[
  {
    "path": ".ci/gpg/README.md",
    "content": "# SDK GPG Keys\n\n## Current *key*pers\n\nThe keys are currently in the hands of [Joe Lanford](https://github.com/joelanford/).\n\n## Transferring keys\n\nIn order to transfer the keys to other members of the Operator SDK admins, following the following:\n\n1. get public GPG key from the person(s) you will transfer to\n2. import their key into your keyring\n\n```\ngpg --import KEY\n```\n\n3. verify their identity, is this really their key. Video call can be useful for this.\n4. sign their key\n\n```\ngpg --sign-key EMAIL-OF-USERS-KEY\n```\n\n5. export the SDK public key\n\n```\ngpg --export --armor  -o 3B2F1481D146238080B346BB052996E2A20B5C7E.pub    .asc 3B2F1481D146238080B346BB052996E2A20B5C7\n```\n6. export the SDK private key\n\n```\ngpg --export-secret-key --armor -o 3B2F1481D146238080B346BB052996E2A2    0B5C7E.priv.asc 3B2F1481D146238080B346BB052996E2A20B5C7E\n```\n7. export the SDK sub key\n\n```\ngpg --export-secret-subkeys --armor -o 3B2F1481D146238080B346BB052996    E2A20B5C7E.sub_priv.asc 3B2F1481D146238080B346BB052996E2A20B5C7E\n```\n\n8. encrypt each key for the person\n\n```\ngpg --encrypt --sign --armor -r EMAIL-OF-USERS-KEY --output 052996E2A20B5C7E.subkey.private.asc.enc 052996E2A20B5C7E.subkey.private.asc\n```\n\n9. send them the encrypted key to the user\n\n10. user should be able to decrypt with their key.\n\n## Updating expiration date\n\nThere will be a few people that have the keys. Those people should be able to update the expiration date. This won't have to be done until November 8, 2025.\n\nYou will want to update the date of the key:\n\n```\ngpg --edit-key (key id)\n```\n\nOnce you're in the gpg console select the key , there are 2, you need to update both. I just pick a 3 year term.\n\n```\ngpg> expire\n(follow prompts)\n3y\ngpg> save\n```\n\nYou can use whatever term the team wants.\n\nOne of the resources I used: [How to change the expiration date of a GPG key](https://www.g-loaded.eu/2010/11/01/change-expiration-date-gpg-key/)\n\n## Sending keys to keyserver\n\nOnce you have the keys updated, you should send them to a keyserver. I have a couple examples, not sure if both are needed.\n\n```\ngpg --keyserver keyserver.ubuntu.com --send-key 3B2F1481D146238080B346BB052996E2A20B5C7E\ngpg --keyserver pgp.mit.edu --send-key 3B2F1481D146238080B346BB052996E2A20B5C7E\n```\n\nI *think* you only need to send it to one server, most of the commands in my shell history use `pgp.mit.edu`\n\n## Updating secring.auto.gpg\n\nOnce you have the keys updated, you need to regenerate the keyrings that are stored in the [SDK repo](https://github.com/operator-framework/operator-sdk/tree/master/.ci/gpg).\n\nUse the SDK key to sign and encrypt it. You need to use `--local-user` to avoid GPG from using your own key.\n\n```\ngpg --cipher-algo AES256 --output secring.auto.gpg --local-user \"cncf-operator-sdk@cncf.io\" --sign --symmetric 3B2F1481D146238080B346BB052996E2A20B5C7E.sub_priv.asc\n```\n\n## Updating pubring.auto\n\nThis is the public keyring. It's simply the public key. Export the public key then rename it as `pubring.auto`\n\n```\ngpg --export --armor -o 3B2F1481D146238080B346BB052996E2A20B5C7E.pub.asc 3B2F1481D146238080B346BB052996E2A20B5C7E\ncp 3B2F1481D146238080B346BB052996E2A20B5C7E.pub.asc pubring.auto\n```\n\n## CI usage of keys\n\nThe GPG keys are stored in [.ci/gpg](https://github.com/operator-framework/operator-sdk/tree/master/.ci/gpg) of the Operator SDK repo.\n\nIn Github settings, there is a `GPG_PASSWORD` environment variable. It is set here in the [Environments](https://github.com/operator-framework/operator-sdk/settings/environments/172302554/edit) tab. You need to be admin.\n\nThe `GPG_PASSWORD` has been encrypted and handed to a few people. These people are the keepers of the password.\n\n## Original process\n\nThe original keys were setup using the following article.\n\nhttps://blogs.itemis.com/en/secure-your-travis-ci-releases-part-2-signature-with-openpgp"
  },
  {
    "path": ".ci/gpg/create-keyring.sh",
    "content": "#!/bin/bash\n\nDIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" >/dev/null 2>&1 && pwd)\"\n\n# Modified from https://blogs.itemis.com/en/secure-your-travis-ci-releases-part-2-signature-with-openpgp\n\nfunction err_exit() {\n  echo \"ERROR: ${1:-\"Unknown Error\"} Exiting.\" 1>&2\n  exit 1\n}\n\ndeclare -r GPG_HOME=\"${DIR}/keyring\"\ndeclare -r SECRING_AUTO=\"${GPG_HOME}/secring.auto\"\ndeclare -r PUBRING_AUTO=\"${GPG_HOME}/pubring.auto\"\n\nmkdir -p --mode 700 \"$GPG_HOME\"\ncp \"${DIR}\"/*.auto* \"${GPG_HOME}\"\n\necho -e \"\\nImporting public keys...\"\n{ gpg --home \"${GPG_HOME}\" --import \"${PUBRING_AUTO}\" ; } || { err_exit \"Could not import public key into gpg.\" ; }\necho \"Success!\"\n\necho -e \"\\nDecrypting secret key...\"\n{\n  # $GPG_PASSWORD is taken from the script's env (injected by CI).\n  echo $GPG_PASSWORD | gpg --home \"${GPG_HOME}\" --decrypt \\\n    --pinentry-mode loopback --batch \\\n    --passphrase-fd 0 \\\n    --output \"${SECRING_AUTO}\" \\\n    \"${SECRING_AUTO}\".gpg ; \\\n} || { err_exit \"Failed to decrypt secret key.\" ; }\necho \"Success!\"\n\necho -e \"\\nImporting private keys...\"\n# { gpg --home \"${GPG_HOME}\" --import \"${PUBRING_AUTO}\" ; } || { err_exit \"Could not import public key into gpg.\" ; }\n{ gpg --home \"${GPG_HOME}\" --import \"${SECRING_AUTO}\" ; } || { err_exit \"Could not import secret key into gpg.\" ; }\necho \"Success!\"\n"
  },
  {
    "path": ".ci/gpg/pubring.auto",
    "content": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBF+clTQBEADMHVz8qS+dcYC0qxlSNe4Yipbr/BtVuWGJay26OAbS4K7sjzs3\nXP+RhjUsJGOnPXn+N/zM6wVNczV7MrdfWNK1UAWBPVC4HjD/ysj/m5lMv/j0RNym\nW6VNdSgV4YWyQHn6eD279gT4p6GAVvQj0eXnWtX7eA0SaITi6dMNqw8QcTOBxzFI\nPXw+4MDJJKDAammtNKgj6LtmYc3o9d8aqbwtPfj3Vvi5d3SWfMx8a+2aSDkVcsva\nbloGUBXYWFzO11T4OYvUYXgQdaKHyT+ZWGCpDsnQV/KqG5S456jmV+Qp+98vwe8k\nXhXhlkjauhbvVR0uGAv0RJ4NZPSmWpie6f7ApQ3XTg3+ZvsrTvi3STCkOKA8/CLm\n/xRhAF/aFZSOLlgzyAxr45j0PRjzX3XJfPePkV1D1cFso3JGDT5Y2oku8bNqYTof\nfV/vw6jxylSNKApn1VyViwZ0+aE9kjMHXytKWWLK+woxrFOG74nGcI+xBOAOHvSU\nGRh5EVXydbyMxqEpq2Su+rHlzfzgPh+hORNQgrag+qdbTVMimCoD+datX4854Hkb\nnah+mq7RtI0k5Nn+ENm4ufbHEKiNb56qFTNgMkquG5vxpA6NOlZ0QfKUxiDU08+g\nPix7+TY7lzNhGipD7QjqfuJJr+1k3p/GrIpoHlU8/8FvlNYBDG3oMUvxNwARAQAB\ntDJPcGVyYXRvciBTREsgKHJlbGVhc2UpIDxjbmNmLW9wZXJhdG9yLXNka0BjbmNm\nLmlvPokCVAQTAQgAPhYhBDsvFIHRRiOAgLNGuwUpluKiC1x+BQJfnJU0AhsBBQkD\nw7iABQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEAUpluKiC1x+P5IQAJXpQMA1\nkIr6S2N9A4TE6z+dhN0g3oPdZqOYwlKpX32H4nLdv219Ns1mwBHUfTFmcbUuQLwH\n1TjF7cVya/tUoyh/P7bBBOy/vC0NvvaOuhRXxeJJD7Q8neuXyCpIoCW8x2Eq47ut\n21AL79ZrzZEBpavJ80S2uNTx7HGKYug491OKkEWO3Y+FOmTV38WsN+lpM+atn1LP\ngWkEhWaxwkfLrYUgZ/lDBAIhPZ7n3gYptmTQdCzlp4dSEwJXesV35aMWfJOM848M\nfVJFyFcMNo6ww0tHD+7btrGc4fHSJC/dKZcYVoiSHmpuAqRBXHWMxKPfijgwWQs5\n6JjxCWt4bwouF0D2uE6SD/MYsxN05yZL6OGfzzQES5Ilt0DS3QRLktN8PdeuS+WN\njLVo7/Q2SUGZcANm+5/ul7Qwj9JeFSK3VloLKY0YFEbnyTHw2TU4oDqyffUWTn+h\nPt34Wy+OWRM+2ykxFP1VklgCN07ESRSZOTN6iUzqets50rKpY3okNiZeMPcblxQo\nuQ5/NFmYV/de87JuSmOKXB2yy/xdr7oxkbw9uYZmBEvw4etxH2yyzVxr0BJ4r0DW\n5DlSxOeHaNa7aUVQnlK+Xf27Pj1XyYvV6G7NWEZYZQ/pclO0rhFH21ZiGo3DHgSo\ncAGv6SWU01nELYYHTn3QFdmdjxmbqjSC0t+EiQJUBBMBCAA+AhsBBQsJCAcCBhUK\nCQgLAgQWAgMBAh4BAheAFiEEOy8UgdFGI4CAs0a7BSmW4qILXH4FAmkUpkMFCQ8b\nq48ACgkQBSmW4qILXH7MSw/+MniPUuEPYy42zuAHP1NGeHRJCWWzDRGwI5QML1LE\nxqDmhzLAxLClZrSjDHRNFMNIYkIjzo1X858jIFgl8l5IdVfy/NZ2VkI46YP8rKFB\n5L/2KJC+zVUF0x57vG72Dyt5fq77ytnSPqNKt7+hB5DlsjA2ZpCPZ9t1QTrw04jD\nNpPjl2OmZKUwN6xh7bebb7RA+p+XmwhP0xKCcJtYbqOl3IdqrVz0Vz4ppvRIPlim\ncVBHS2ufowjPQNR/iS6HGKyVfzMRNFWqP4nz67uzh1rK0vdBnCSf1vFJLFyKi2S+\nOFUUQu2uKibq1n4jGgtY7YQO422GWr9jWyV9NrAgNT+FIKrozLoCjqgbvZpdglA5\ns4CQbBxLXtlRFwTRtv1mZKraou7ybyip+CdB8mySmVmpYpUDv8ABEGReZKVgrI/y\n8D4K+1TmdSvEkoUtuSjm/N/u4PtDZDFOCozEGGTvAjdpvFjdp2Bw3WNmWMNSnkJE\nkqurCAlsqQTF+ckqcn2MrP9oE2v+GPyipN/sx60wNuoIB+xKT2RwO8kP7KBZl1D8\nppRq6oEMx+XJSoekAenR5vXWsV1ZYcG4I33FcwSOgRd842R5dEDG5mXJExBb8Jky\nFbWqq/2uoRT0+AUitOUrd5so58EIvVBxeRYO2C+pJS0vkrbE916h9iVWwhOMsY5Y\nFNa5Ag0EX5yWFgEQAKPVhCFIwrySnVagMvkCzbIWWWOZ2RdOti0wEuMueRRoqjEg\nQZusH9p7KmH08LziIoYuscYLqs0F1WraacbIkJcop4kui8meinPf7ZtM6fKlo52T\nVCGi8XDwJdExWGNF6EN709ZBheTZovuw++0uXlyXDaJQt2PGzYp8EbBKURXp5eMY\nIVQZ8i8wRD+CNtMiJS2SGpowKwS7KsFqWI01+4Fiyac/mke+fvIj+QyI0Hx3QuYj\nw8Jv7N3NlVu72YgPw/QTLLqKZt/DMi1/bU4/vyW8YFUbN3aYf8RjIGzAcRRuWoFx\nv2ZpPPZjLzl1MVcpZTuf46MoIJik4rtJV99AV1HbKVS2/Ym8s4JH+AfVnRpzxkXY\nMQj0L6jCxVL12oyT2Xindw15DOBGyE2qE714/2oZnUsiAQo57IublOBRw8uerj29\nLj94Kj6n5BrUVwYSz5vquojFLPLE3Gy/aVGZRD8DcFOhXfbUN7bN+vnW7WsklWlg\ngS9sw9HKJyJnOQO78Plnl9HWfK2gVxG3eiwUgsjSWKW/OlLPGUeaczjzQkAOJOUo\nbPphOdgbaatkIU7GuYCwD/IM7i/jUiLs7vPRwk7eXeZnV9uqoCqrIdTQQZzFg4CZ\n8zxrNKvGPQw4zaN8YMw9aDeDdJdNciXqrJY5VRZ8/j5AGwesHIdNKkYKDJNbABEB\nAAGJBHIEGAEIACYWIQQ7LxSB0UYjgICzRrsFKZbiogtcfgUCX5yWFgIbAgUJA8O4\ngAJACRAFKZbiogtcfsF0IAQZAQgAHRYhBIYT24eluoJe8/0OviqFnQi/mIbbBQJf\nnJYWAAoJECqFnQi/mIbbHdwP/0qoULqBuHM2ki9nbKuuLWXVIisH48q8J5lI5gOX\nEMndiAC7/f53sTA6i8/wi4RvfjRHzDSiex1gMcIc4MKB1r4+79a9bHHn/BI5vJ3S\nQc8znlEvHkLlQc92W37IonRDCIw8XyACpUNeRzZciCEEgPjKQ/RXmt726DzuFV3Y\nRieuQwNro36Ve2W/Om0VOMElV27et4ykvAepL8YCbGGDAXqRU/FlEdwwgovB4s3Y\nmAZ3ZoVohAGP47jddE6Evmiv4X8TrTBzhlNSn9rxpHElGvOUeA0UFtXqiSfPBNBF\noHUIPRheMVkvaTmsQR+/J9eC4JMPJlOMmNi8I7QwPEv8oj1/ImlxT56e0ah3zc17\nz3ddcJLZKZpNjcu9D6/97322uHibtK2g5DzGbpvXSwjpNuFuA85iC1M8vHDcGV1O\ntTkemHP6y4+twfJsqffnuXtt/3JhN8q2ysAo9U4w0XtAR1HdSV2qgbOROjnmXiia\n8xL3e1ZIb7DjtbtAgBCPBOWoPKNhWDfaXxeV8O1xHST5jo5uC4QxTC2yKQr4W+pV\nLlkI8jK+/iQwIhrMyURahyx++sg2NDggjZb6hC/m8mY7JjfS08Qurfm1of2g4yO1\njcpZlWY/PDr4MZFMDZENH7uqba/eWCWLj03OL+JIG8N5VnFIEdFGMf84vtMpY35b\nALYjjBgP/iKjHX5Zwo+wj7vsdpQu+w+pr5tecptmJ2uypJ6Ns+cuDcz1qfaAOjR3\nrZDGuckuX06G6E5tc/9vMKOtwySD2FgEAdpNdtG1WVIqldgTK7A7odhDtbIeVj3L\n2ysci9xa4Gukj0qB3byuRPhBkHlYkP8KCPiSwkB75OxKZxx3DfMbc5ZZWzge6NCd\naeH41sETtzJiploHIqIOMve8o/7Rl+Mz9MXyedjvOqBKWNDFJxtbv/9TcaIH0MqD\nWv1MQzOZJMO6DC/u7aQz+Jk+Or529Swqoq7JfbdYMpEvLO6wOohYqxGuR36DW8F/\nFJSFbDG3DPLLWsv+01xcYG4s7GNSK30uF2jCMVEb3dOzBpz9DxUY8QHleMGBE2Vb\n29JiDD7nBMd/TVQFaARa0WGXpImcPq4COcwG126pcFeadxMDobPlcHWHvEzfakud\nxYkYd+LFeIlw6Aapb4u/Vjd5o+oIU6bjJ9gN8Ev5Q3xjuxHdatXLVHpS3/xt/iwP\n+LVTIE0pLN43mwGmLsqADrJjs+lUg3sftXVA3jUHD28AblZcI7y+ZjQagIxAAozm\nnTiYy4GvqezDLVb3irq64g3CrqrXJx9hAnKgqFeJ8+F2JzAMxh65bto/tac8hvdX\nB22UTIP7JwGxqTQmyr/7Kui/eleCt0t2UXY7i5Ovh+vApGXbx4YRiQRyBBgBCAAm\nAhsCFiEEOy8UgdFGI4CAs0a7BSmW4qILXH4FAmkU5xUFCQ8b638CQMF0IAQZAQgA\nHRYhBIYT24eluoJe8/0OviqFnQi/mIbbBQJfnJYWAAoJECqFnQi/mIbbHdwP/0qo\nULqBuHM2ki9nbKuuLWXVIisH48q8J5lI5gOXEMndiAC7/f53sTA6i8/wi4RvfjRH\nzDSiex1gMcIc4MKB1r4+79a9bHHn/BI5vJ3SQc8znlEvHkLlQc92W37IonRDCIw8\nXyACpUNeRzZciCEEgPjKQ/RXmt726DzuFV3YRieuQwNro36Ve2W/Om0VOMElV27e\nt4ykvAepL8YCbGGDAXqRU/FlEdwwgovB4s3YmAZ3ZoVohAGP47jddE6Evmiv4X8T\nrTBzhlNSn9rxpHElGvOUeA0UFtXqiSfPBNBFoHUIPRheMVkvaTmsQR+/J9eC4JMP\nJlOMmNi8I7QwPEv8oj1/ImlxT56e0ah3zc17z3ddcJLZKZpNjcu9D6/97322uHib\ntK2g5DzGbpvXSwjpNuFuA85iC1M8vHDcGV1OtTkemHP6y4+twfJsqffnuXtt/3Jh\nN8q2ysAo9U4w0XtAR1HdSV2qgbOROjnmXiia8xL3e1ZIb7DjtbtAgBCPBOWoPKNh\nWDfaXxeV8O1xHST5jo5uC4QxTC2yKQr4W+pVLlkI8jK+/iQwIhrMyURahyx++sg2\nNDggjZb6hC/m8mY7JjfS08Qurfm1of2g4yO1jcpZlWY/PDr4MZFMDZENH7uqba/e\nWCWLj03OL+JIG8N5VnFIEdFGMf84vtMpY35bALYjCRAFKZbiogtcfhHND/9A54vj\n2qrbv58mlK0RLV3PQJPlYlD1uzWXqZi35197b+T8gm5YBJ7d2/Q50DolX2k04AcE\nX4gklwaiV83EpZrMYKeqHrOot6H1FJ86oQmStRzVhgiWZjfCX8Ll4wDNOC0FsIus\nO3kL6p4TNlPlg3rx+kELIYMSzGQipmBSziXC7Xm3/nFGPior1gfy+62SXlVV37zG\n1LCJwVdx+0bgcv/OD9FQx7tOHvrvcJgRcwKq23ElnPQwTmlnqzp7B77Jy4E2QQ6U\nfAo10fcjFu3yjyhTeuLkgei1uRJL7yKoWjok3kOGfxy6sJGY6BIpIHVtWDGWVK5r\nSY+YR9MfnORd2PCEmaNF7mpOTf0Cn1JAXFrAFVYAWVXBQX4y1nx/9UlSi3C3gnpH\nExoFX5Kc/Cvwib4W9md5ZtGKszUAEDZv7Eb4G/o5pWP1C5dyuX8qP95+2Qlwxmom\n40rm8Sk+RBlubBUxPeevxQXIATLPDEKStk/5guFzrOilbDeLaSJYS424eSpDGgvt\n8fJjJxM2Rc+zmFob6vpKGFhGJCxSIFArRO9J3g0G1LGJj+38ZL+LWqcQbjqy2pEF\nDaVoVyi9q09uZ/NOC/JDV+pbTOoShaWPYOoYE4F4A8EXkpRBhQxT6BYEvPLCgiCz\nTsHpyxJ86L++bxtv9JhE6w19geq68spOgobXuw==\n=pKuo\n-----END PGP PUBLIC KEY BLOCK-----\n"
  },
  {
    "path": ".cncf-maintainers",
    "content": "approvers:\n- OchiengEd\n- acornett21\n- anik120\n- camilamacedo86\n- grokspawn\n- jberkhahn\n- joelanford\n- oceanc80\n- rashmigottipati\nreviewers:\n- OchiengEd\n- acornett21\n- anik120\n- camilamacedo86\n- grokspawn\n- jberkhahn\n- joelanford\n- oceanc80\n- rashmigottipati\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.md",
    "content": "---\nname: Bug Report\nabout: If things aren't working as expected.\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n## Bug Report\n\n<!--\nThanks for filing an issue! Before hitting the button, please answer these questions.\nFill in as much of the template below as you can. If you leave out information, we can't help you as well.\n\nNote: Make sure to first check the prerequisites that can be found in the main README.md file!\n-->\n\n#### What did you do?\n\n<!-- A clear and concise description of the steps you took (or insert a code snippet). -->\n\n#### What did you expect to see?\n\n<!-- A clear and concise description of what you expected to happen (or insert a code snippet). -->\n\n#### What did you see instead? Under which circumstances?\n\n<!-- A clear and concise description of what ACTUALLY happened (or insert a code snippet). -->\n\n#### Environment\n\n**Operator type:**\n\n<!-- Uncomment one or more of the following lines corresponding to the language of the operator type -->\n\n<!-- /language go -->\n<!-- /language ansible - For ansible operator related bugs, please create the issue in https://github.com/operator-framework/ansible-operator-plugins -->\n<!-- /language helm -->\n\n**Kubernetes cluster type:**\n\n<!-- The type of cluster used for testing/deployment, ex. \"vanilla\", \"OpenShift\" -->\n\n`$ operator-sdk version`\n\n<!-- Insert the output of `operator-sdk version` here. -->\n\n`$ go version` (if language is Go)\n\n<!-- Insert the output of `go version` here -->\n\n`$ kubectl version`\n\n<!-- Insert the output of `kubectl version` here -->\n\n#### Possible Solution\n\n<!-- Only if you have suggestions on a fix for the bug -->\n\n#### Additional context\n\n<!-- Add any other context about the problem here. -->\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/doc-report.md",
    "content": "---\nname: Doc Report\nabout: Raise an issue with the documentation.\ntitle: ''\nlabels: kind/documentation\nassignees: ''\n\n---\n\n<!-- Please submit only documentation-related issues with this form, or follow the\nContribute to Operator SDK guidelines (https://sdk.operatorframework.io/docs/contribution-guidelines/reporting-issues/) to submit a PR. Use this template while reporting a bug and provide as much info as possible. Not doing so may result in your bug not being addressed in a timely manner. Thanks!\n-->\n\n### What is the URL of the document?\n\n<!-- The URL to help identify the document. -->\n\n### Which section(s) is the issue in?\n\n<!-- The sections(s) within the document that have issue in. -->\n\n### What needs fixing?\n\n<!-- A clear and concise description of what the issue is. -->\n\n#### Additional context\n\n<!-- Add any other context about the problem here. -->\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature-request.md",
    "content": "---\nname: Feature Request\nabout: Suggest a feature\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n## Feature Request\n\n#### Describe the problem you need a feature to resolve.\n\n<!--\nA clear and concise description of what the problem is. Example:\n\nI have an issue when ...\n-->\n\n#### Describe the solution you'd like.\n\n<!-- A clear and concise description of what you want to happen. Add any considered drawbacks. -->\n\n<!-- If your request relates to a particular operator type, uncomment one or more of the following lines corresponding to the language of that type -->\n\n<!-- /language go -->\n<!-- /language ansible For ansible operator related feature requests, please create the issue in https://github.com/operator-framework/ansible-operator-plugins -->\n<!-- /language helm -->\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/support-question.md",
    "content": "---\nname: Support Question\nabout: Any support questions you might have.\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n<!--\nThanks for filing an issue! Before hitting the button, please answer these questions.\n\nFill in as much of the template below as you can. If you leave out information, we can't help you as well.\n\nWe will try our best to answer the question, but we also have a mailing list and slack channel for any other questions.\n-->\n\n## Type of question\n\n<!-- Uncomment one or more of the following lines depending on what you are asking about: -->\n\n<!-- Best practices -->\n<!-- How to implement a specific feature -->\n<!-- General operator-related help -->\n<!-- Open question -->\n\n## Question\n\n#### What did you do?\n\n<!-- A clear and concise description of the steps you took (or insert a code snippet). -->\n\n#### What did you expect to see?\n\n<!-- A clear and concise description of what you expected to happen (or insert a code snippet). -->\n\n#### What did you see instead? Under which circumstances?\n\n<!-- A clear and concise description of what you expected to happen (or insert a code snippet). -->\n\n#### Environment\n\n**Operator type:**\n\n<!-- Uncomment one or more of the following lines corresponding to the language of the operator type -->\n\n<!-- /language go -->\n<!-- /language ansible - For ansible operator related questions, please create the issue in https://github.com/operator-framework/ansible-operator-plugins -->\n<!-- /language helm -->\n\n**Kubernetes cluster type:**\n\n<!-- The type of cluster used for testing/deployment, ex. \"vanilla\", \"OpenShift\" -->\n\n`$ operator-sdk version`\n\n<!-- Insert the output of `operator-sdk version` here. -->\n\n`$ go version` (if language is Go)\n\n<!-- Insert the output of `go version` here -->\n\n`$ kubectl version`\n\n<!-- Insert the output of `kubectl version` here -->\n\n#### Additional context\n\n<!-- Add any other context about the question here. -->\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "content": "<!---\nThanks for filing an issue! Before you submit, please read the following:\n\nCheck the other issue templates if you are trying to submit a bug report, feature request, or question. Search open/closed issues before submitting since someone might have asked the same thing before!\n\nFor ansible operator related requests, please create the issue in https://github.com/operator-framework/ansible-operator-plugins \n-->\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "<!--\n\nWelcome to the Operator SDK! Before contributing, make sure to:\n\n- Read the contributing guidelines https://github.com/operator-framework/operator-sdk/blob/master/CONTRIBUTING.MD\n- Rebase your branch on the latest upstream master\n- Link any relevant issues, PR's, or documentation\n- Check that the commit message is concice and helpful:\n    - When fixing an issue, add \"Closes #<ISSUE_NUMBER>\"\n    - Sign your commit https://github.com/apps/dco\n- Follow the below checklist if making a user-facing change \n\nNote, the location for ansible operator related logic has changed. For ansible operator related changes, please create the Pull Request in https://github.com/operator-framework/ansible-operator-plugins \n\n-->\n\n**Description of the change:**\n\n\n**Motivation for the change:**\n\n\n**Checklist**\n\nIf the pull request includes user-facing changes, extra documentation is required:\n- [ ] Add a new changelog fragment in `changelog/fragments` (see [`changelog/fragments/00-template.yaml`](https://github.com/operator-framework/operator-sdk/tree/master/changelog/fragments/00-template.yaml))\n- [ ] Add or update relevant sections of the docs website in [`website/content/en/docs`](https://github.com/operator-framework/operator-sdk/tree/master/website/content/en/docs)\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n  - package-ecosystem: docker\n    directory: \"/images/custom-scorecard-tests\"\n    schedule:\n      interval: daily\n  - package-ecosystem: docker\n    directory: \"/images/helm-operator\"\n    schedule:\n      interval: daily\n  - package-ecosystem: docker\n    directory: \"/images/operator-sdk\"\n    schedule:\n      interval: daily\n  - package-ecosystem: docker\n    directory: \"/images/scorecard-test\"\n    schedule:\n      interval: daily\n  - package-ecosystem: docker\n    directory: \"/images/scorecard-test-kuttl\"\n    schedule:\n      interval: daily\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule: \n     interval: daily\n  \n"
  },
  {
    "path": ".github/workflows/check-docs-only.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\n# If running in Github actions: this should be set to \"github.base_ref\".\n: ${1?\"the first argument must be set to a commit-ish reference\"}\n\n# Patterns to ignore.\ndeclare -a DOC_PATTERNS\nDOC_PATTERNS=(\n  \"(\\.md)\"\n  \"(\\.MD)\"\n  \"(\\.png)\"\n  \"(\\.pdf)\"\n  \"(netlify\\.toml)\"\n  \"(website/)\"\n  \"(changelog/)\"\n  \"(OWNERS)\"\n  \"(OWNERS_ALIASES)\"\n  \"(LICENSE)\"\n)\n\nif ! git diff --name-only $1 | grep -qvE \"$(IFS=\"|\"; echo \"${DOC_PATTERNS[*]}\")\"; then\n  echo \"true\"\n  exit 0\nfi\n"
  },
  {
    "path": ".github/workflows/clean-unused-disk-space.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\necho \"Removing unused system files to gain more disk space\"\nrm -fr /opt/hostedtoolcache\ncd /opt\nfind . -maxdepth 1 -mindepth 1 '!' -path ./containerd '!' -path ./actionarchivecache '!' -path ./runner '!' -path ./runner-cache -exec rm -rf '{}' ';'"
  },
  {
    "path": ".github/workflows/deploy.yml",
    "content": "name: deploy\n\non:\n  push:\n    branches:\n    - '**'\n    - '!dependabot/**'\n    tags:\n    - 'v*'\n    - 'scorecard-kuttl/v*'\n  pull_request:\n    branches: [ master ]\n\njobs:\n  check_docs_only:\n    name: check_docs_only\n    runs-on: ubuntu-24.04\n    outputs:\n      skip: ${{ steps.check_docs_only.outputs.skip }}\n    steps:\n      - uses: actions/checkout@v6\n        with:\n          fetch-depth: 0\n      - id: check_docs_only\n        # Since PR's are squashed prior to merging to the branch checked out (default branch),\n        # HEAD^ will resolve to the previous point in history.\n        run: |\n          REF=\"HEAD^\"\n          [[ -z \"${{ github.base_ref }}\" ]] || REF=$(git show-ref ${{ github.base_ref }} | head -1 | cut -d' ' -f2)\n          echo \"skip=$(.github/workflows/check-docs-only.sh $REF)\" >> $GITHUB_OUTPUT\n\n  # Job to test release steps. This will only create a release remotely if run on a tagged commit.\n  goreleaser:\n    name: goreleaser\n    needs: check_docs_only\n    # Run this job on a tag like 'vX.Y.Z' or on a branch or pull request with code changes.\n    if: startsWith(github.ref, 'refs/tags/v') || ( needs.check_docs_only.outputs.skip != 'true' && !startsWith(github.ref, 'refs/tags/') )\n    runs-on: ubuntu-24.04\n    environment: deploy\n    steps:\n    - name: checkout\n      uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    - name: install\n      uses: actions/setup-go@v6\n      with:\n        go-version-file: \"go.mod\"\n\n    - name: gpg init\n      if: ${{ github.event_name != 'pull_request' }}\n      run: .ci/gpg/create-keyring.sh\n      env:\n        GPG_PASSWORD: ${{ secrets.GPG_PASSWORD }}\n\n    - name: release\n      run: |\n        if [[ $GITHUB_REF != refs/tags/v* ]]; then\n          export DRY_RUN=1\n        fi\n        make release\n      env:\n        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n\n  # Job matrix for image builds. Only pushes if a tag with prefix \"v\" is present.\n  images:\n    name: images\n    needs: check_docs_only\n    # Run this job on a tag like 'vX.Y.Z' or on a branch or pull request with code changes.\n    if: startsWith(github.ref, 'refs/tags/v') || ( needs.check_docs_only.outputs.skip != 'true' && !startsWith(github.ref, 'refs/tags/') )\n    runs-on: ubuntu-24.04\n    environment: deploy\n    strategy:\n      matrix:\n        id: [\"operator-sdk\", \"helm-operator\", \"scorecard-test\"]\n    steps:\n\n    - name: set up qemu\n      uses: docker/setup-qemu-action@v4\n\n    - name: set up buildx\n      uses: docker/setup-buildx-action@v4\n\n    - name: quay.io login\n      if: ${{ github.event_name != 'pull_request' }}\n      uses: docker/login-action@v4\n      with:\n        username: ${{ secrets.QUAY_USERNAME }}\n        password: ${{ secrets.QUAY_PASSWORD }}\n        registry: quay.io\n\n    # Check out repo before tag step for script.\n    - name: checkout\n      uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    - name: create tags\n      id: tags\n      run: |\n        IMG=quay.io/${{ github.repository_owner }}/${{ matrix.id }}\n        echo tags=$(.github/workflows/get_image_tags.sh \"$IMG\" \"v\") >> $GITHUB_OUTPUT\n\n    - name: build and push\n      uses: docker/build-push-action@v7\n      with:\n        file: ./images/${{ matrix.id }}/Dockerfile\n        context: .\n        platforms: linux/amd64,linux/arm64,linux/ppc64le,linux/s390x\n        # Push on tag, or master or latest branch push.\n        push: ${{ (github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/master' || github.ref == 'refs/heads/latest')) }}\n        tags: ${{ steps.tags.outputs.tags }}\n\n  # scorecard-test-kuttl image build job. Only pushes if a tag with prefix \"scorecard-kuttl/v\" is present.\n  image-scorecard-test-kuttl:\n    name: image-scorecard-test-kuttl\n    needs: check_docs_only\n    # Run this job on a tag like 'scorecard-kuttl/vX.Y.Z' or on a branch or pull request with code changes.\n    if: startsWith(github.ref, 'refs/tags/scorecard-kuttl/v') || ( needs.check_docs_only.outputs.skip != 'true' && !startsWith(github.ref, 'refs/tags/') )\n    runs-on: ubuntu-24.04\n    environment: deploy\n    steps:\n\n    - name: set up qemu\n      uses: docker/setup-qemu-action@v4\n\n    - name: set up buildx\n      uses: docker/setup-buildx-action@v4\n\n    - name: quay.io login\n      if: ${{ github.event_name != 'pull_request' }}\n      uses: docker/login-action@v4\n      with:\n        username: ${{ secrets.QUAY_USERNAME }}\n        password: ${{ secrets.QUAY_PASSWORD }}\n        registry: quay.io\n\n    # Check out repo before tag step for script.\n    - name: checkout\n      uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    - name: create tags\n      id: tags\n      run: |\n        IMG=quay.io/${{ github.repository_owner }}/scorecard-test-kuttl\n        echo tags=$(.github/workflows/get_image_tags.sh \"$IMG\" \"scorecard-kuttl/v\") >> $GITHUB_OUTPUT\n\n    - name: build and push\n      uses: docker/build-push-action@v7\n      with:\n        file: ./images/scorecard-test-kuttl/Dockerfile\n        context: .\n        # s390x is not supported by the scorecard-test-kuttl base image.\n        platforms: linux/amd64,linux/arm64,linux/ppc64le\n        # Push on tag, or master branch push.\n        push: ${{ (github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/master')) }}\n        tags: ${{ steps.tags.outputs.tags }}\n"
  },
  {
    "path": ".github/workflows/freshen-images/build.sh",
    "content": "#!/usr/bin/env bash\n\nDIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" >/dev/null 2>&1 && pwd)\"\n\nsource ${DIR}/lib.sh\n\nset -eu\nset -o pipefail\n\n# Comma-separated list of build platforms, ex. linux/s390x.\n# See 'docker buildx build --help' for --platform flag info.\nDEFAULT_PLATFORMS=\"linux/amd64,linux/arm64,linux/ppc64le,linux/s390x\"\n# TODO(estroz): support scorecard-test-kuttl rebuilds.\n# DEFAULT_SCORECARD_KUTTL_PLATFORMS=\"linux/amd64,linux/arm64,linux/ppc64le\"\nPLATFORMS=\n# Time window to compare image creation times against, relative to now.\n# --timespan should be set to this duration in seconds.\nDEFAULT_TIMESPAN=86400 # 24 hours in seconds\nTIMESPAN=\n# What to do with the image, either load (default) or push.\nIMAGE_DO=--load\n# Space-separated list of git tags.\n# The --tags arg can be comma-separated.\nTAGS=\n# ID of the image, ex. operator-sdk.\nIMAGE_ID=\n# Update all images.\nFORCE=0\nwhile [[ $# -gt 0 ]]; do\n  case $1 in\n  --push)\n  IMAGE_DO=$1\n  ;;\n  --force)\n  FORCE=1\n  ;;\n  --tags)\n    TAGS=($(echo $2 | sed -E 's/,/ /g'))\n  shift\n  ;;\n  --image-id)\n  IMAGE_ID=$2\n  shift\n  ;;\n  --platforms)\n  PLATFORMS=$2\n  shift\n  ;;\n  --timespan)\n  TIMESPAN=$2\n  shift\n  ;;\n  *) echo \"Invalid flag $1\"; exit 1 ;;\n  esac\n  shift\ndone\n\n: ${IMAGE_ID:?--image-id is required}\n: ${TAGS:?--tags is required}\n\n# Set defaults.\ncase $IMAGE_ID in\nscorecard-test-kuttl)\n  # TODO(estroz): support scorecard-test-kuttl rebuilds.\n  # PLATFORMS=${PLATFORMS:-$DEFAULT_SCORECARD_KUTTL_PLATFORMS}\n  echo \"$IMAGE_ID is not supported\"\n  exit 1\n;;\n*)\n  PLATFORMS=${PLATFORMS:-$DEFAULT_PLATFORMS}\n;;\nesac\nTIMESPAN=${TIMESPAN:-$DEFAULT_TIMESPAN}\n\n# Clone the operator-sdk repo into a temp dir with cleanup.\ntmp=$(mktemp -d --tmpdir freshen-images-tmp.XXXXXX)\ngit clone https://github.com/operator-framework/operator-sdk.git $tmp\ntrap \"rm -rf $tmp\" EXIT\npushd $tmp\n\n\n# Build the image defined by IMAGE_ID for each tag for a set of platforms.\nfor i in ${!TAGS[*]}; do\n  if (($i=0)); then\n    build_generic ${TAGS[$i]} $IMAGE_ID \"$PLATFORMS\" true\n  else\n    build_generic ${TAGS[$i]} $IMAGE_ID \"$PLATFORMS\" false\n  fi\ndone\n\npopd\n"
  },
  {
    "path": ".github/workflows/freshen-images/lib.sh",
    "content": "#!/usr/bin/env bash\n\n# _buildx runs \"docker buildx build\" in CI-output mode.\nfunction _buildx() {\n  echo -e \"\\n$ docker buildx build --progress plain $@\"\n  docker buildx build --progress plain $@\n}\n\n# _pull runs \"docker pull\".\nfunction _pull() {\n  echo -e \"\\n$ docker pull $@\"\n  docker pull $@\n}\n\n# cmp_times returns false if time $2 occurred within some timespan defined by TIMESPAN\n# relative to time $1.\nfunction cmp_times() {\n  local base_seconds=$(date -d \"$1\" +%s)\n  local img_time_seconds=$(date -d \"$2\" +%s)\n  if (( $base_seconds - $TIMESPAN < $img_time_seconds )) || (( $FORCE )); then\n    # return false\n    return 1\n  fi\n  # return true\n  return 0\n}\n\n# is_dockerfile_fresh returns false if at least one image in a \"FROM\" directive\n# in the Dockerfile at $1 has been freshly built within TIMESPAN relative to now,\n# or FORCE=1.\nfunction is_dockerfile_fresh() {\n  local dockerfile=$1\n  # Strip flag from FROM to get image, which always precedes this flag if set.\n  local docker_images=$(grep -oP \"FROM (--platform=[^ ]+ )?\\K([^ ]+)\" $dockerfile)\n\n  for img in $docker_images; do\n    _pull $img\n    local img_create_time=$(docker inspect --format '{{.Created}}' $img)\n    if [[ \"$img_create_time\" == \"0001-01-01T00:00:00Z\" ]]; then\n      echo \"image creation time could be found for $img\"\n      exit 1\n    fi\n    if ! cmp_times \"$(date)\" \"$img_create_time\"; then\n      # return false\n      echo \"is_dockerfile_fresh returning 1 (false) for [$img]\"\n      return 1\n    fi\n  done\n}\n\n\n# Build an image at path ./images/$2/Dockerfile checked out at git tag $1\n# for all platforms in $3. Tag is assumed to be \"v\"+semver; the image is tagged\n# with the full semver string and with \"v${major}.${minor}\".\n# The build will only run if the Dockerfile is not fresh.\nfunction build_generic() {\n  local tag=$1\n  local id=$2\n  local platforms=$3\n  local buildlatest=$4\n  local tag_maj_min=\"quay.io/operator-framework/${id}:$(echo $tag | grep -Eo \"v[1-9]+\\.[0-9]+\")\"\n  local tag_full=\"quay.io/operator-framework/${id}:${tag}\"\n  local tag_latest=\"quay.io/operator-framework/${id}:latest\"\n  local dockerfile=./images/${id}/Dockerfile\n\n  git checkout refs/tags/$tag\n  if is_dockerfile_fresh \"$dockerfile\"; then\n    echo \"Skipping build of $dockerfile, it is FRESH!\"\n  else\n    # dockerfile is not fresh, rebuildng image\n    if $buildlatest; then\n      echo \"Rebuilding image [$tag_maj_min] and latest for [$platforms]\"\n      _buildx --builder=container --tag \"$tag_maj_min\" --tag \"$tag_full\"  --tag \"$tag_latest\" --platform \"$platforms\" --file \"$dockerfile\" $IMAGE_DO .\n    else\n      echo \"Rebuilding image [$tag_maj_min] for [$platforms]\"\n      _buildx --builder=container --tag \"$tag_maj_min\" --tag \"$tag_full\"  --platform \"$platforms\" --file \"$dockerfile\" $IMAGE_DO .\n    fi\n  fi\n}\n"
  },
  {
    "path": ".github/workflows/freshen-images/tags.sh",
    "content": "#!/usr/bin/env bash\n\nset -eu\nset -o pipefail\n\n# Major version to select (default 1).\nMAJ=${1:-1}\n# Number of minor versions to select (default 2).\nNUM_MINORS=${2:-2}\n\n# Get unique \"v${major}.${minor}\" tags, then add the greatest patch version for each\n# to a list.\ndeclare -a LATEST_GIT_TAGS\nfor tag in $(git tag --sort=-v:refname -l \"v${MAJ}.*\" | grep -Eo \"v${MAJ}\\.[^\\.]+\" | uniq | head -n $NUM_MINORS); do\n  LATEST_GIT_TAGS+=( $(git tag --sort=-v:refname -l \"$tag*\" | head -n 1) )\ndone\n# Print tags in comma-separated form.\necho ${LATEST_GIT_TAGS[@]} | sed -E 's/[ ]+/,/g'\n"
  },
  {
    "path": ".github/workflows/freshen-images.yml",
    "content": "name: freshen-images\n\non:\n  workflow_dispatch:\n    inputs:\n      force:\n        description: Force rebuild of all images.\n        default: ''\n        required: false\n  schedule:\n  # Run at 11 am UTC every day.\n  - cron: '0 11 * * *'\n\njobs:\n  git_tags:\n    runs-on: ubuntu-24.04\n    outputs:\n      git_tags: ${{ steps.tags.outputs.git_tags }}\n    steps:\n    - name: checkout\n      uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n    - id: tags\n      run: echo \"git_tags=$(.github/workflows/freshen-images/tags.sh)\" >> $GITHUB_OUTPUT\n\n  build:\n    name: build\n    needs: git_tags\n    runs-on: ubuntu-24.04\n    environment: deploy\n    strategy:\n      matrix:\n        # TODO(estroz): support scorecard-test-kuttl rebuilds.\n        id: [\"operator-sdk\", \"helm-operator\", \"scorecard-test\"]\n    steps:\n    - name: set up qemu\n      uses: docker/setup-qemu-action@v4\n    - name: set up buildx\n      uses: docker/setup-buildx-action@v4\n    - name: quay.io login\n      uses: docker/login-action@v4\n      with:\n        username: ${{ secrets.QUAY_USERNAME }}\n        password: ${{ secrets.QUAY_PASSWORD }}\n        registry: quay.io\n    - name: checkout\n      uses: actions/checkout@v6\n      with:\n        fetch-depth: 1\n    - name: build and push\n      id: build_ids\n      run: |\n        .github/workflows/freshen-images/build.sh --push \\\n          --image-id ${{ matrix.id }} \\\n          --tags ${{ needs.git_tags.outputs.git_tags }} \\\n          ${{ github.event.inputs.force != '' && '--force' || '' }}\n"
  },
  {
    "path": ".github/workflows/get_image_tags.sh",
    "content": "#!/usr/bin/env bash\n\nIMG=\"$1\"\nTAG_PREFIX=\"$2\"\n\n: ${IMG:?\"\\$1 must be set to an image tag\"}\n: ${TAG_PREFIX:?\"\\$2 must be set to some tag prefix to pass to refs/tags/{prefix}*\"}\n: ${GITHUB_REF:?\"GITHUB_REF must be set to a git 'refs/' path in the environment (typically set by the Actions runner)\"}\n\nif [[ $GITHUB_REF == refs/tags/${TAG_PREFIX}* ]]; then\n  # Release tags.\n  TAG=\"${GITHUB_REF#refs/tags/${TAG_PREFIX}}\"\n  # Prepend \"v\" if removed by the above variable operation, since $TAG should always be semver.\n  [[ $TAG == v* ]] || TAG=\"v${TAG}\"\n  MAJOR_MINOR=\"${TAG%.*}\"\n  echo \"${IMG}:${TAG},${IMG}:${MAJOR_MINOR}\"\n\nelif [[ $GITHUB_REF == refs/tags/* ]]; then\n  # Any other tag, which will not be pushed.\n  TAG=\"$(echo \"${GITHUB_REF#refs/tags/}\" | sed -r 's|/+|-|g')-local\"\n  echo \"${IMG}:${TAG}\"\n\nelif [[ $GITHUB_REF == refs/heads/* ]]; then\n  # Branch build.\n  TAG=\"$(echo \"${GITHUB_REF#refs/heads/}\" | sed -r 's|/+|-|g')\"\n  echo \"${IMG}:${TAG}\"\n\nelif [[ $GITHUB_REF == refs/pull/* ]]; then\n  # PR build.\n  TAG=\"pr-$(echo \"${GITHUB_REF}\" | sed -E 's|refs/pull/([^/]+)/?.*|\\1|')\"\n  echo \"${IMG}:${TAG}\"\nfi\n"
  },
  {
    "path": ".github/workflows/integration.yml",
    "content": "name: integration\non:\n  pull_request: {}\n\njobs:\n  check_docs_only:\n    name: check_docs_only\n    runs-on: ubuntu-24.04\n    outputs:\n      skip: ${{ steps.check_docs_only.outputs.skip }}\n    steps:\n      - uses: actions/checkout@v6\n        with:\n          fetch-depth: 0\n      - id: check_docs_only\n        # Since PR's are squashed prior to merging to the branch checked out (default branch),\n        # HEAD^ will resolve to the previous point in history.\n        run: |\n          REF=\"HEAD^\"\n          [[ -z \"${{ github.base_ref }}\" ]] || REF=$(git show-ref ${{ github.base_ref }} | head -1 | cut -d' ' -f2)\n          echo \"skip=$(.github/workflows/check-docs-only.sh $REF)\" >> $GITHUB_OUTPUT\n\n  integration:\n    name: integration\n    runs-on: ubuntu-24.04\n    needs: check_docs_only\n    if: needs.check_docs_only.outputs.skip != 'true'\n    steps:\n      - uses: actions/checkout@v6\n        with:\n          fetch-depth: 0\n\n      - name: Cleanup Unused Disk Space\n        run: |\n          .github/workflows/clean-unused-disk-space.sh\n\n      - uses: actions/setup-go@v6\n        with:\n         go-version-file: \"go.mod\"\n      - run: make test-e2e-integration\n"
  },
  {
    "path": ".github/workflows/markdown-link-check-config.json",
    "content": "{\n    \"ignorePatterns\": [\n        { \"pattern\": \"^https://github.com/.+\" },\n        { \"pattern\": \"^mailto:\" }\n    ],\n\n    \"httpHeaders\": [\n        {\n            \"urls\": [\"https://docs.github.com\"],\n            \"headers\": {\n                \"User-Agent\": \"Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:98.0) Gecko/20100101 Firefox/98.0\"\n            }\n        }\n    ]\n}\n"
  },
  {
    "path": ".github/workflows/olm-check.yml",
    "content": "name: olm-check\n\non:\n pull_request:\n   branches:\n    - 'release-*'\n workflow_dispatch:\n   \n\njobs:\n  check-olm-minor-releases:\n    name: check-olm-minor-releases\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n      - id: run-check-olm\n        run: ./hack/check-olm.sh\n    \n    "
  },
  {
    "path": ".github/workflows/rerun.yml",
    "content": "on:\n  issue_comment:\n    types: [created]\n\njobs:\n  rerun_tests:\n    name: rerun_pr_tests\n    if: ${{ github.event.issue.pull_request }}\n    runs-on: ubuntu-24.04\n    steps:\n    - uses: operator-framework/rerun-actions@v0.4.0\n      with:\n        repo_token: ${{ secrets.GITHUB_TOKEN }}\n        comment_id: ${{ github.event.comment.id }}\n"
  },
  {
    "path": ".github/workflows/test-go.yml",
    "content": "name: go\non:\n  pull_request: {}\n\nenv:\n  MEMCACHED_IMAGE: \"memcached:1.4.36-alpine\"\n\njobs:\n  check_docs_only:\n    name: check_docs_only\n    runs-on: ubuntu-24.04\n    outputs:\n      skip: ${{ steps.check_docs_only.outputs.skip }}\n    steps:\n      - uses: actions/checkout@v6\n        with:\n          fetch-depth: 0\n      - id: check_docs_only\n        # Since PR's are squashed prior to merging to the branch checked out (default branch),\n        # HEAD^ will resolve to the previous point in history.\n        run: |\n          REF=\"HEAD^\"\n          [[ -z \"${{ github.base_ref }}\" ]] || REF=$(git show-ref ${{ github.base_ref }} | head -1 | cut -d' ' -f2)\n          echo \"skip=$(.github/workflows/check-docs-only.sh $REF)\" >> $GITHUB_OUTPUT\n\n  e2e:\n    name: e2e\n    runs-on: ubuntu-24.04\n    needs: check_docs_only\n    if: needs.check_docs_only.outputs.skip != 'true'\n    steps:\n      - uses: actions/checkout@v6\n        with:\n          fetch-depth: 0\n\n      - name: Cleanup Unused Disk Space\n        run: |\n          .github/workflows/clean-unused-disk-space.sh\n\n      - uses: actions/setup-go@v6\n        with:\n          go-version-file: \"go.mod\"\n      - run: sudo rm -rf /usr/local/bin/kustomize\n      - run: make test-e2e-go\n\n  unit:\n    name: unit\n    runs-on: ubuntu-24.04\n    needs: check_docs_only\n    if: needs.check_docs_only.outputs.skip != 'true'\n    steps:\n      - uses: actions/checkout@v6\n        with:\n          fetch-depth: 0\n\n      - name: Cleanup Unused Disk Space\n        run: |\n          .github/workflows/clean-unused-disk-space.sh\n\n      - uses: actions/setup-go@v6\n        with:\n          go-version-file: \"go.mod\"\n      - run: make test-unit\n      - uses: shogo82148/actions-goveralls@v1\n        with:\n          path-to-profile: coverage.out\n"
  },
  {
    "path": ".github/workflows/test-helm.yml",
    "content": "name: helm\non:\n  pull_request: {}\n\njobs:\n  check_docs_only:\n    name: check_docs_only\n    runs-on: ubuntu-24.04\n    outputs:\n      skip: ${{ steps.check_docs_only.outputs.skip }}\n    steps:\n      - uses: actions/checkout@v6\n        with:\n          fetch-depth: 0\n      - id: check_docs_only\n        # Since PR's are squashed prior to merging to the branch checked out (default branch),\n        # HEAD^ will resolve to the previous point in history.\n        run: |\n          REF=\"HEAD^\"\n          [[ -z \"${{ github.base_ref }}\" ]] || REF=$(git show-ref ${{ github.base_ref }} | head -1 | cut -d' ' -f2)\n          echo \"skip=$(.github/workflows/check-docs-only.sh $REF)\" >> $GITHUB_OUTPUT\n\n  e2e:\n    name: e2e\n    runs-on: ubuntu-24.04\n    needs: check_docs_only\n    if: needs.check_docs_only.outputs.skip != 'true'\n    steps:\n      - uses: actions/checkout@v6\n        with:\n          fetch-depth: 0\n\n      - name: Cleanup Unused Disk Space\n        run: |\n          .github/workflows/clean-unused-disk-space.sh\n\n      - uses: actions/setup-go@v6\n        with:\n          go-version-file: \"go.mod\"\n      - run: sudo rm -rf /usr/local/bin/kustomize\n      - run: make test-e2e-helm\n"
  },
  {
    "path": ".github/workflows/test-sample-go.yml",
    "content": "name: memcached-sample\non:\n  pull_request: {}\n\njobs:\n  check_docs_only:\n    name: check_docs_only\n    runs-on: ubuntu-24.04\n    outputs:\n      skip: ${{ steps.check_docs_only.outputs.skip }}\n    steps:\n      - uses: actions/checkout@v6\n        with:\n          fetch-depth: 0\n      - id: check_docs_only\n        # Since PR's are squashed prior to merging to the branch checked out (default branch),\n        # HEAD^ will resolve to the previous point in history.\n        run: |\n          REF=\"HEAD^\"\n          [[ -z \"${{ github.base_ref }}\" ]] || REF=$(git show-ref ${{ github.base_ref }} | head -1 | cut -d' ' -f2)\n          echo \"skip=$(.github/workflows/check-docs-only.sh $REF)\" >> $GITHUB_OUTPUT\n\n  e2e:\n    name: e2e\n    runs-on: ubuntu-24.04\n    needs: check_docs_only\n    if: needs.check_docs_only.outputs.skip != 'true'\n    steps:\n      - uses: actions/checkout@v6\n        with:\n          fetch-depth: 0\n\n      - name: Cleanup Unused Disk Space\n        run: |\n          .github/workflows/clean-unused-disk-space.sh\n\n      - uses: actions/setup-go@v6\n        with:\n          go-version-file: \"go.mod\"\n      - run: sudo rm -rf /usr/local/bin/kustomize\n      - run: make test-e2e-sample-go\n"
  },
  {
    "path": ".github/workflows/test-sanity.yml",
    "content": "name: sanity\non:\n  pull_request: {}\n\njobs:\n  check_docs_only:\n    name: check_docs_only\n    runs-on: ubuntu-24.04\n    outputs:\n      skip: ${{ steps.check_docs_only.outputs.skip }}\n    steps:\n    - uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n    - id: check_docs_only\n      # Since PR's are squashed prior to merging to the branch checked out (default branch),\n      # HEAD^ will resolve to the previous point in history.\n      run: |\n        REF=\"HEAD^\"\n        [[ -z \"${{ github.base_ref }}\" ]] || REF=$(git show-ref ${{ github.base_ref }} | head -1 | cut -d' ' -f2)\n        echo \"skip=$(.github/workflows/check-docs-only.sh $REF)\" >> $GITHUB_OUTPUT\n\n  sanity:\n    name: sanity\n    runs-on: ubuntu-24.04\n    needs: check_docs_only\n    if: needs.check_docs_only.outputs.skip != 'true'\n    steps:\n    - uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n\n    - name: Cleanup Unused Disk Space\n      run: |\n        .github/workflows/clean-unused-disk-space.sh    \n\n    - uses: actions/setup-go@v6\n      with:\n        go-version-file: \"go.mod\"\n      id: go\n    - run: sudo rm -rf /usr/local/bin/kustomize\n    - run: make test-sanity\n\n  docs:\n    name: docs\n    runs-on: ubuntu-24.04\n    steps:\n    - uses: actions/checkout@v6\n      with:\n        fetch-depth: 0\n        submodules: recursive\n    - run: make test-docs\n    - uses: gaurav-nelson/github-action-markdown-link-check@v1\n      with:\n        max-depth: 1\n        config-file: '.github/workflows/markdown-link-check-config.json'\n"
  },
  {
    "path": ".gitignore",
    "content": "# Folders\n.idea\n\n# Build artifacts\n/build\n/dist\n**/bin/\n\n# Test artifacts\n**/testbin/\n\n# CI GPG keyring\n/.ci/gpg/keyring\n\n# Website\nwebsite/public/\nwebsite/resources/\nwebsite/node_modules/\nwebsite/tech-doc-hugo\n\n# Ignore molecule samples testdata if it be generated in the testdata/ diretory\ntestdata/ansible/memcached-molecule-operator\ntestdata/ansible/advanced-molecule-operator\n\n# Trash files\n*\\.DS_Store\n\n# Created by https://www.toptal.com/developers/gitignore/api/go,vim,emacs,visualstudiocode\n# Edit at https://www.toptal.com/developers/gitignore?templates=go,vim,emacs,visualstudiocode\n\n### Emacs ###\n# -*- mode: gitignore; -*-\n*~\n\\#*\\#\n/.emacs.desktop\n/.emacs.desktop.lock\n*.elc\nauto-save-list\ntramp\n.\\#*\n\n# Org-mode\n.org-id-locations\n*_archive\n\n# flymake-mode\n*_flymake.*\n\n# eshell files\n/eshell/history\n/eshell/lastdir\n\n# elpa packages\n/elpa/\n\n# reftex files\n*.rel\n\n# AUCTeX auto folder\n/auto/\n\n# cask packages\n.cask/\ndist/\n\n# Flycheck\nflycheck_*.el\n\n# server auth directory\n/server/\n\n# projectiles files\n.projectile\n\n# directory configuration\n.dir-locals.el\n\n# network security\n/network-security.data\n\n\n### Go ###\n# Binaries for programs and plugins\n*.exe\n*.exe~\n*.dll\n*.so\n*.dylib\n\n# Test binary, built with `go test -c`\n*.test\n\n# Output of the go coverage tool, specifically when used with LiteIDE\n*.out\n\n### Vim ###\n# Swap\n[._]*.s[a-v][a-z]\n!*.svg  # comment out if you don't need vector files\n[._]*.sw[a-p]\n[._]s[a-rt-v][a-z]\n[._]ss[a-gi-z]\n[._]sw[a-p]\n\n# Session\nSession.vim\nSessionx.vim\n\n# Temporary\n.netrwhist\n# Auto-generated tag files\ntags\n# Persistent undo\n[._]*.un~\n\n### VisualStudioCode ###\n.vscode/*\n!.vscode/settings.json\n!.vscode/tasks.json\n!.vscode/launch.json\n!.vscode/extensions.json\n*.code-workspace\n\n### VisualStudioCode Patch ###\n# Ignore all local history of files\n.history\n.ionide\n\n# End of https://www.toptal.com/developers/gitignore/api/go,vim,emacs,visualstudiocode\n\n# Python cache (Ansible molecule)\ntest/ansible/plugins/filter/__pycache__/\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"website/themes/docsy\"]\n\tpath = website/themes/docsy\n\turl = https://github.com/asmacdo/docsy.git\n\n"
  },
  {
    "path": ".golangci.yml",
    "content": "version: \"2\"\nlinters:\n  enable:\n    - dupl\n    - ginkgolinter\n    - goconst\n    - gocyclo\n    - gosec\n    - misspell\n    - nakedret\n    - revive\n    - unconvert\n    - unparam\n  exclusions:\n    generated: lax\n    presets:\n      - comments\n      - common-false-positives\n      - legacy\n      - std-error-handling\n    rules:\n      - linters:\n          - revive\n        text: should not use dot imports\n        source: ginkgo|gomega\n      - linters:\n          - gosec\n        text: G110|G601|G404|G204|G306\n    paths:\n      - third_party$\n      - builtin$\n      - examples$\n  settings:\n    revive:\n      rules:\n        - name: var-naming\n          disabled: true\nformatters:\n  enable:\n    - goimports\n  exclusions:\n    generated: lax\n    paths:\n      - third_party$\n      - builtin$\n      - examples$\n"
  },
  {
    "path": ".goreleaser.yml",
    "content": "# Global environment variables for builds.\nenv:\n  - CGO_ENABLED=0\n  - GO111MODULE=on\n  - GOPROXY=https://proxy.golang.org|direct\n  - REPO=github.com/operator-framework/operator-sdk\n  - GO_BUILD_TAGS=containers_image_openpgp\n\n# Hooks to run before any build is run.\nbefore:\n  hooks:\n    - go version | grep --quiet \"go1\\.15\\.5\" || echo \"Go binary version must be 1.15.5\"\n    - go mod download\n\n# Binary builds.\nbuilds:\n  # operator-sdk build steps\n  - id: operator-sdk\n    main: ./cmd/operator-sdk\n    binary: operator-sdk\n    mod_timestamp: \"{{ .CommitTimestamp }}\"\n    # containers_image_openpgp for containers/image\n    flags: &build-flags\n      - -tags=containers_image_openpgp\n    asmflags: &build-asmflags\n      - all=-trimpath={{ .Env.PWD }}\n    gcflags: &build-gcflags\n      - all=-trimpath={{ .Env.PWD }}\n    ldflags: &build-ldflags\n      - -X {{ .Env.REPO }}/internal/version.Version={{ .Env.SIMPLE_VERSION }}\n      - -X {{ .Env.REPO }}/internal/version.GitVersion={{ .Env.GIT_VERSION }}\n      - -X {{ .Env.REPO }}/internal/version.GitCommit={{ .Env.GIT_COMMIT }}\n      - -X {{ .Env.REPO }}/internal/version.KubernetesVersion={{ .Env.K8S_VERSION }}\n      - -X {{ .Env.REPO }}/internal/version.ImageVersion={{ .Env.IMAGE_VERSION }}\n    targets: &build-targets\n      - darwin_amd64\n      - darwin_arm64\n      - linux_amd64\n      - linux_arm64\n      - linux_ppc64le\n      - linux_s390x\n\n  # helm-operator build steps\n  - id: helm-operator\n    main: ./cmd/helm-operator\n    binary: helm-operator\n    mod_timestamp: \"{{ .CommitTimestamp }}\"\n    flags: *build-flags\n    asmflags: *build-asmflags\n    gcflags: *build-gcflags\n    ldflags: *build-ldflags\n    targets: *build-targets\n\n# Use most recent tag and short commit for snapshot version.\nsnapshot:\n  name_template: \"{{ .Env.GIT_VERSION }}\"\n\n# We don't use archives, so skip creating them.\narchives:\n  - format: binary\n    name_template: \"{{ .Binary }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}{{ if .Mips }}_{{ .Mips }}{{ end }}\"\n\nchecksum:\n  name_template: \"checksums.txt\"\n\n# Sign the checksum file with the CI GPG key.\nsigns:\n  - signature: \"${artifact}.asc\"\n    artifacts: checksum\n    # Use the CI signing subkey A20B5C7E decrypted into .ci/gpg/keyring to sign the release.\n    args: [\"--home\", \".ci/gpg/keyring\", \"-u\", \"A20B5C7E\", \"--output\", \"${signature}\", \"--detach-sign\", \"${artifact}\"]\n\n# We use a custom changelog generator.\nchangelog:\n\n# TODO(estroz): configure homebrew publishing\n# brews:\n#   - name: operator-sdk\n#     ids:\n#     - operator-sdk\n\n# Uncomment for testing\n# release:\n#   github:\n#     owner: <your-github-namespace>\n#     name: operator-sdk\n"
  },
  {
    "path": "CONTRIBUTING.MD",
    "content": "# How to contribute\n\nOperator SDK is Apache 2.0 licensed and accepts contributions via GitHub pull requests. This document outlines some of the conventions on commit message formatting, contact points for developers, and other resources to help get contributions into operator-sdk.\n\n# Email and Chat\n\n- Email: [operator-framework][operator_framework]  \n\n## Getting started\n\n- Fork the repository on GitHub\n- See the [developer guide][developer-guide] for build instructions\n\n## Reporting bugs and creating issues\n\nReporting bugs is one of the best ways to contribute. However, a good bug report has some very specific qualities, so please read over our short document on [reporting issues][reporting-issues] before submitting a bug report. This document might contain links to known issues, another good reason to take a look there before reporting a bug.\n\n## Contribution flow\n\nThis is a rough outline of what a contributor's workflow looks like:\n\n- Create a topic branch from where to base the contribution. This is usually master.\n- Make commits of logical units.\n- Make sure commit messages are in the proper format (see below).\n- Push changes in a topic branch to a personal fork of the repository.\n- Submit a pull request to operator-framework/operator-sdk.\n- The PR must receive a LGTM from two maintainers found in the MAINTAINERS file.\n\nThanks for contributing!\n\n### Code style\n\nThe coding style suggested by the Go community is used in operator-sdk. See the [style doc][golang-style-doc] for details.\n\nPlease follow this style to make operator-sdk easy to review, maintain and develop.\n\n### Format of the commit message\n\nWe follow a rough convention for commit messages that is designed to answer two\nquestions: what changed and why. The subject line should feature the what and\nthe body of the commit should describe the why.\n\n```\nscripts: add the test-cluster command\n\nthis uses tmux to setup a test cluster that can easily be killed and started for debugging.\n\nFixes #38\n```\n\nThe format can be described more formally as follows:\n\n```\n<subsystem>: <what changed>\n<BLANK LINE>\n<why this change was made>\n<BLANK LINE>\n<footer>\n```\n\nThe first line is the subject and should be no longer than 70 characters, the second line is always blank, and other lines should be wrapped at 80 characters. This allows the message to be easier to read on GitHub as well as in various git tools.\n\n## Documentation\n\nMost contributions involve some sort of documentation. See our [doc contribution guidelines][doc-contrib] for details.\n\n## Changelog\n\nThe operator-sdk maintains a changelog and most contributions should involve a changelog entry. See our [changelog contribution guidelines][changelog-contrib] for details.\n\n[operator_framework]: https://groups.google.com/forum/#!forum/operator-framework\n[developer-guide]: https://sdk.operatorframework.io/docs/contribution-guidelines/developer-guide/\n[reporting-issues]: https://sdk.operatorframework.io/docs/contribution-guidelines/reporting-issues/\n[golang-style-doc]: https://github.com/golang/go/wiki/CodeReviewComments\n[doc-contrib]: https://sdk.operatorframework.io/docs/contribution-guidelines/documentation\n[changelog-contrib]:https://master.sdk.operatorframework.io/docs/contribution-guidelines/changelog\n"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "Makefile",
    "content": "SHELL = /bin/bash\n\n# IMAGE_VERSION represents the helm-operator, and scorecard subproject versions.\n# This value must be updated to the release tag of the most recent release, a change that must\n# occur in the release commit. IMAGE_VERSION will be removed once each subproject that uses this\n# version is moved to a separate repo and release process.\nexport IMAGE_VERSION = v1.42.2\n# Build-time variables to inject into binaries\nexport SIMPLE_VERSION = $(shell (test \"$(shell git describe --tags)\" = \"$(shell git describe --tags --abbrev=0)\" && echo $(shell git describe --tags)) || echo $(shell git describe --tags --abbrev=0)+git)\nexport GIT_VERSION = $(shell git describe --dirty --tags --always)\nexport GIT_COMMIT = $(shell git rev-parse HEAD)\nexport K8S_VERSION = 1.33.1\nexport KIND_VERSION = 0.29.0\n\n# Build settings\nexport TOOLS_DIR = tools/bin\nexport SCRIPTS_DIR = tools/scripts\nGO := $(shell type -P go)\nREPO = $(shell $(GO) list -m)\nBUILD_DIR = build\nGO_ASMFLAGS = -asmflags \"all=-trimpath=$(shell dirname $(PWD))\"\nGO_GCFLAGS = -gcflags \"all=-trimpath=$(shell dirname $(PWD))\"\nGO_BUILD_ARGS = \\\n  $(GO_GCFLAGS) $(GO_ASMFLAGS) \\\n  -ldflags \" \\\n    -X '$(REPO)/internal/version.Version=$(SIMPLE_VERSION)' \\\n    -X '$(REPO)/internal/version.GitVersion=$(GIT_VERSION)' \\\n    -X '$(REPO)/internal/version.GitCommit=$(GIT_COMMIT)' \\\n    -X '$(REPO)/internal/version.KubernetesVersion=v$(K8S_VERSION)' \\\n    -X '$(REPO)/internal/version.ImageVersion=$(IMAGE_VERSION)' \\\n  \" \\\n# containers_image_openpgp for containers/image\nGO_BUILD_TAGS = containers_image_openpgp\n\nexport GO111MODULE = on\nexport CGO_ENABLED = 0\nexport PATH := $(PWD)/$(BUILD_DIR):$(PWD)/$(TOOLS_DIR):$(PATH)\n\n##@ Development\n\n.PHONY: generate\ngenerate: build # Generate CLI docs and samples\n\trm -rf testdata\n\t$(GO) run ./hack/generate/cncf-maintainers/main.go\n\t$(GO) run -tags=$(GO_BUILD_TAGS) ./hack/generate/cli-doc/gen-cli-doc.go\n\t$(GO) run ./hack/generate/samples/generate_testdata.go\n\t$(GO) generate ./...\n\n.PHONY: bindata\nOLM_VERSIONS = 0.26.0 0.27.0 0.28.0\nbindata: ## Update project bindata\n\t./hack/generate/olm_bindata.sh $(OLM_VERSIONS)\n\t$(MAKE) fix\n\n.PHONY: fix\nfix: ## Fixup files in the repo.\n\t$(GO) mod tidy\n\t$(GO) fmt ./...\n\tmake setup-lint\n\t$(TOOLS_DIR)/golangci-lint run --fix --build-tags $(GO_BUILD_TAGS)\n\n.PHONY: setup-lint\nsetup-lint: ## Setup the lint\n\t$(SCRIPTS_DIR)/fetch golangci-lint 2.6.2\n\n.PHONY: lint\nlint: setup-lint ## Run the lint check\n\t$(TOOLS_DIR)/golangci-lint run --build-tags $(GO_BUILD_TAGS)\n\n\n.PHONY: clean\nclean: ## Cleanup build artifacts and tool binaries.\n\trm -rf $(BUILD_DIR) dist $(TOOLS_DIR)\n\n##@ Build\n\n# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)\nifeq (,$(shell go env GOBIN))\nGOBIN=$(shell go env GOPATH)/bin\nelse\nGOBIN=$(shell go env GOBIN)\nendif\n\n.PHONY: install\ninstall: ## Install operator-sdk and helm-operator.\n\t@if [ -z \"$(GOBIN)\" ]; then \\\n\t\techo \"Error: GOBIN is not set\"; \\\n\t\texit 1; \\\n\tfi\n\t$(GO) install $(GO_BUILD_ARGS) -tags=$(GO_BUILD_TAGS) ./cmd/{operator-sdk,helm-operator}\n\n.PHONY: build\nbuild: ## Build operator-sdk and helm-operator.\n\t@mkdir -p $(BUILD_DIR)\n\t$(GO) build $(GO_BUILD_ARGS) -tags=$(GO_BUILD_TAGS) -o $(BUILD_DIR) ./cmd/{operator-sdk,helm-operator}\n\n.PHONY: build/operator-sdk build/helm-operator\nbuild/operator-sdk build/helm-operator:\n\t$(GO) build $(GO_BUILD_ARGS) -tags=$(GO_BUILD_TAGS) -o $(BUILD_DIR)/$(@F) ./cmd/$(@F)\n\n# Build scorecard binaries.\n.PHONY: build/scorecard-test build/scorecard-test-kuttl build/custom-scorecard-tests\nbuild/scorecard-test build/scorecard-test-kuttl build/custom-scorecard-tests:\n\t$(GO) build $(GO_GCFLAGS) $(GO_ASMFLAGS) -o $(BUILD_DIR)/$(@F) ./images/$(@F)\n\n##@ Dev image build\n\n# Convenience wrapper for building all remotely hosted images.\n.PHONY: image-build\nIMAGE_TARGET_LIST = operator-sdk helm-operator scorecard-test scorecard-test-kuttl\nimage-build: $(foreach i,$(IMAGE_TARGET_LIST),image/$(i)) ## Build all images.\n\n\n# Build an image.\nBUILD_IMAGE_REPO = quay.io/operator-framework\n# When running in a terminal, this will be false. If true (ex. CI), print plain progress.\nifneq ($(shell test -t 0; echo $$?),0)\nDOCKER_PROGRESS = --progress plain\nendif\nimage/%: export DOCKER_CLI_EXPERIMENTAL = enabled\nimage/%:\n\tdocker buildx build $(DOCKER_PROGRESS) -t $(BUILD_IMAGE_REPO)/$*:dev -f ./images/$*/Dockerfile --load .\n\nimage-base/%: export DOCKER_CLI_EXPERIMENTAL = enabled\nimage-base/%:\n\tdocker buildx build $(DOCKER_PROGRESS) -t $(BUILD_IMAGE_REPO)/$*-base:dev -f ./images/$*/base.Dockerfile --load images/$*\n##@ Release\n\n.PHONY: release\nrelease: ## Release target. See 'make -f release/Makefile help' for more information.\n\t$(MAKE) -f release/Makefile $@\n\n.PHONY: prerelease\nprerelease: generate ## Write release commit changes. See 'make -f release/Makefile help' for more information.\nifneq ($(RELEASE_VERSION),$(IMAGE_VERSION))\n\t$(error \"IMAGE_VERSION \"$(IMAGE_VERSION)\" must be updated to match RELEASE_VERSION \"$(RELEASE_VERSION)\" prior to creating a release commit\")\nendif\n\t$(MAKE) -f release/Makefile $@\n\n.PHONY: tag\ntag: ## Tag a release commit. See 'make -f release/Makefile help' for more information.\n\t$(MAKE) -f release/Makefile $@\n\n##@ Test\n\n.PHONY: test-all\ntest-all: test-static test-e2e ## Run all tests\n\n.PHONY: test-static\ntest-static: test-sanity test-unit test-docs ## Run all non-cluster-based tests\n\n.PHONY: test-sanity\ntest-sanity: generate fix ## Test repo formatting, linting, etc.\n\tgit diff --exit-code # fast-fail if generate or fix produced changes\n\t./hack/check-license.sh\n\t./hack/check-error-log-msg-format.sh\n\t$(GO) vet -tags=$(GO_BUILD_TAGS) ./...\n\tmake setup-lint\n\tmake lint\n\tgit diff --exit-code # diff again to ensure other checks don't change repo\n\n.PHONY: test-docs\ntest-docs: ## Test doc links\n\t$(GO) run ./release/changelog/gen-changelog.go -validate-only\n\tgit submodule update --init --recursive website/\n\t./hack/check-links.sh\n\n.PHONY: test-unit\nTEST_PKGS = $(shell $(GO) list ./... | grep -v -E 'github.com/operator-framework/operator-sdk/test/')\ntest-unit: ## Run unit tests\n\tCGO_ENABLED=1 $(GO) test -race -tags=$(GO_BUILD_TAGS) -coverprofile=coverage.out -covermode=atomic -short $(TEST_PKGS)\n\ne2e_tests := test-e2e-go test-e2e-helm test-e2e-integration\ne2e_targets := test-e2e $(e2e_tests)\n.PHONY: $(e2e_targets)\n\n.PHONY: test-e2e-setup\nexport KIND_CLUSTER := osdk-test\n\nKUBEBUILDER_ASSETS = $(PWD)/$(shell $(GO) install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest && $(shell $(GO) env GOPATH)/bin/setup-envtest use $(K8S_VERSION) --bin-dir tools/bin/ -p path)\ntest-e2e-setup:: build dev-install cluster-create\n\n.PHONY: cluster-create\ncluster-create::\n\t[[ \"`$(TOOLS_DIR)/kind get clusters`\" =~ \"$(KIND_CLUSTER)\" ]] || $(TOOLS_DIR)/kind create cluster --image=\"kindest/node:v$(K8S_VERSION)\" --name $(KIND_CLUSTER)\n\n.PHONY: dev-install\ndev-install::\n\t$(SCRIPTS_DIR)/fetch kind $(KIND_VERSION)\n\t$(SCRIPTS_DIR)/fetch kubectl $(K8S_VERSION) # Install kubectl AFTER envtest because envtest includes its own kubectl binary\n\n.PHONY: test-e2e-teardown\ntest-e2e-teardown:\n\t$(SCRIPTS_DIR)/fetch kind $(KIND_VERSION)\n\t$(TOOLS_DIR)/kind delete cluster --name $(KIND_CLUSTER)\n\trm -f $(KUBECONFIG)\n\n# Double colon rules allow repeated rule declarations.\n# Repeated rules are executed in the order they appear.\n$(e2e_targets):: test-e2e-setup image/scorecard-test\ntest-e2e:: $(e2e_tests) ## Run e2e tests\n\ntest-e2e-sample-go:: dev-install cluster-create ## Run Memcached Operator Sample e2e tests\n\tmake test-e2e -C ./testdata/go/v4/memcached-operator/\ntest-e2e-go:: image/custom-scorecard-tests ## Run Go e2e tests\n\t$(GO) test ./test/e2e/go -v -ginkgo.v\ntest-e2e-helm:: image/helm-operator ## Run Helm e2e tests\n\t$(GO) test ./test/e2e/helm -v -ginkgo.v\ntest-e2e-integration:: ## Run integration tests\n\t$(GO) test ./test/integration -v -ginkgo.v\n\t./hack/tests/subcommand-olm-install.sh\n\n.DEFAULT_GOAL := help\n.PHONY: help\nhelp: ## Show this help screen.\n\t@echo 'Usage: make <OPTIONS> ... <TARGETS>'\n\t@echo ''\n\t@echo 'Available targets are:'\n\t@echo ''\n\t@awk 'BEGIN {FS = \":.*##\"; printf \"\\nUsage:\\n  make \\033[36m<target>\\033[0m\\n\"} /^[a-zA-Z0-9_-]+:.*?##/ { printf \"  \\033[36m%-25s\\033[0m %s\\n\", $$1, $$2 } /^##@/ { printf \"\\n\\033[1m%s\\033[0m\\n\", substr($$0, 5) } ' $(MAKEFILE_LIST)\n"
  },
  {
    "path": "OWNERS",
    "content": "approvers:\n- sdk-admins\n- sdk-approvers\nreviewers:\n- sdk-admins\n- sdk-approvers\n- sdk-reviewers\n"
  },
  {
    "path": "OWNERS_ALIASES",
    "content": "\n# See the OWNERS docs: https://git.k8s.io/community/contributors/guide/owners.md\n\naliases:\n  # Contributors who can be contacted to perform admin-related tasks on the repo.\n  # This role is a subset of the approver role.\n  sdk-admins:\n  - joelanford\n  - oceanc80\n\n  # Contributors who can approve any PRs in the repo.\n  sdk-approvers:\n  - camilamacedo86\n  - jberkhahn\n  - rashmigottipati\n  - grokspawn\n  - anik120\n  - acornett21\n  - OchiengEd\n\n  # Contributors who can review and LGTM any PRs in the repo.\n  sdk-reviewers:\n\n  # Contributors who were approvers that are no longer directly involved with the project.\n  # This role is symbolic.\n  sdk-emeritus-admins:\n  - everettraven\n  sdk-emeritus-approvers:\n  - bharathi-tenneti\n  - fabianvf\n  - hasbro17\n  - shawn-hurley\n  - estroz\n  - marc-obrien\n  - asmacdo\n  - jmrodri\n  - theishshah\n  - varshaprasad96"
  },
  {
    "path": "README.md",
    "content": "<img src=\"website/static/operator_logo_sdk_color.svg\" height=\"125px\"></img>\n\n> ⚠️ **IMPORTANT NOTICE:** Images under `gcr.io/kubebuilder/` Will Be Unavailable Soon\n>\n> **If your project uses `gcr.io/kubebuilder/kube-rbac-proxy`** it will be affected.\n> Your project may fail to work if the image cannot be pulled. **You must move as soon as possible**, sometime from early 2025, the GCR will go away.\n>\n> The usage of the project [kube-rbac-proxy](https://github.com/brancz/kube-rbac-proxy) was discontinued from Kubebuilder and Operator-SDK.\n> It was replaced for similar protection using `authn/authz` via Controller-Runtime's feature [WithAuthenticationAndAuthorization](https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.18.4/pkg/metrics/filters#WithAuthenticationAndAuthorization).\n>\n> For more information and guidance see the discussion https://github.com/kubernetes-sigs/kubebuilder/discussions/3907\n\n[![Build Status](https://github.com/operator-framework/operator-sdk/workflows/deploy/badge.svg)](https://github.com/operator-framework/operator-sdk/actions)\n[![License](http://img.shields.io/:license-apache-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0.html)\n\n## Documentation\n\nDocs can be found on the [Operator SDK website][sdk-docs].\n\n## Overview\n\nThis project is a component of the [Operator Framework][of-home], an\nopen source toolkit to manage Kubernetes native applications, called\nOperators, in an effective, automated, and scalable way. Read more in\nthe [introduction blog post][of-blog].\n\n[Operators][operator-link] make it easy to manage complex stateful\napplications on top of Kubernetes. However writing an Operator today can\nbe difficult because of challenges such as using low level APIs, writing\nboilerplate, and a lack of modularity which leads to duplication.\n\nThe Operator SDK is a framework that uses the\n[controller-runtime][controller-runtime] library to make writing\noperators easier by providing:\n\n- High level APIs and abstractions to write the operational logic more intuitively\n- Tools for scaffolding and code generation to bootstrap a new project fast\n- Extensions to cover common Operator use cases\n\n## Dependency and platform support\n\n### Go version\n\nRelease binaries will be built with the Go compiler version specified in the [developer guide][dev-guide-prereqs].\nA Go Operator project's Go version can be found in its `go.mod` file.\n\n[dev-guide-prereqs]:https://sdk.operatorframework.io/docs/contribution-guidelines/developer-guide#prerequisites\n\n### Kubernetes versions\n\nSupported Kubernetes versions for your Operator project or relevant binary can be determined\nby following this [compatibility guide][k8s-compat].\n\n[k8s-compat]:https://sdk.operatorframework.io/docs/overview#kubernetes-version-compatibility\n\n### Platforms\n\nThe set of supported platforms for all binaries and images can be found in [these tables][platforms].\n\n[platforms]:https://sdk.operatorframework.io/docs/overview#platform-support\n\n## Community and how to get involved\n\n- [Operator framework community][operator-framework-community]\n- [Communication channels][operator-framework-communication]\n- [Project meetings][operator-framework-meetings]\n\n## How to contribute\n\nCheck out the [contributor documentation][contribution-docs].\n\n## License\n\nOperator SDK is under Apache 2.0 license. See the [LICENSE][license_file] file for details.\n\n[controller-runtime]: https://github.com/kubernetes-sigs/controller-runtime\n[license_file]:./LICENSE\n[of-home]: https://github.com/operator-framework\n[of-blog]: https://www.openshift.com/blog/introducing-the-operator-framework\n[operator-link]: https://kubernetes.io/docs/concepts/extend-kubernetes/operator/\n[sdk-docs]: https://sdk.operatorframework.io\n[operator-framework-community]: https://github.com/operator-framework/community\n[operator-framework-communication]: https://github.com/operator-framework/community#get-involved\n[operator-framework-meetings]: https://github.com/operator-framework/community#meetings\n[contribution-docs]: https://sdk.operatorframework.io/docs/contribution-guidelines/\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Security Policy\n\n## Supported Versions\n\nOperator SDK makes a constant stream of releases. In general, this means that security\nupdates will be made in minor releases for the most recent major release only.\n\n## Reporting a Vulnerability\n\nTo report a vulnerability, please follow the instructions at\nhttps://access.redhat.com/security/team/contact\n"
  },
  {
    "path": "changelog/fragments/00-template.yaml",
    "content": "# entries is a list of entries to include in\n# release notes and/or the migration guide\nentries:\n  - description: >\n      Description is the line that shows up in the CHANGELOG. This\n      should be formatted as markdown and be on a single line. Using\n      the YAML string '>' operator means you can write your entry\n      multiple lines and it will still be parsed as a single line.\n\n      If an operator type's plugin is being changed then prefix the description with\n      \"(<operator language>/<plugin version>)\", ex. \"(go/v2)\".\n      If an operator type's runtime is being changed, use then prefix the description\n      with \"For <operator language>-based operators,\", ex. \"For Go-based operators\".\n\n    # kind is one of:\n    # - addition\n    # - change\n    # - deprecation\n    # - removal\n    # - bugfix\n    kind: \"\"\n\n    # Is this a breaking change?\n    breaking: false\n\n    # NOTE: ONLY USE `pull_request_override` WHEN ADDING THIS\n    # FILE FOR A PREVIOUSLY MERGED PULL_REQUEST!\n    #\n    # The generator auto-detects the PR number from the commit\n    # message in which this file was originally added.\n    #\n    # What is the pull request number (without the \"#\")?\n    # pull_request_override: 0\n\n\n    # Migration can be defined to automatically add a section to\n    # the migration guide. This is required for breaking changes.\n    migration:\n      header: Header text for the migration section\n      body: |\n        Body of the migration section. This should be formatted as markdown and can\n        span multiple lines.\n\n        Using the YAML string '|' operator means that newlines in this string will\n        be honored and interpretted as newlines in the rendered markdown.\n"
  },
  {
    "path": "changelog/generated/v1.10.0.md",
    "content": "## v1.10.0\n\n### Additions\n\n- Provide XML formatting option for scorecard users. Additionally transforms scorecard result types to xunit testsuite/testcase layout. ([#5048](https://github.com/operator-framework/operator-sdk/pull/5048))\n\n### Changes\n\n- **Breaking change**: (ansible/v1) Bumped Kustomize version in ansible project scaffolding to 3.8.7. ([#5057](https://github.com/operator-framework/operator-sdk/pull/5057))\n\n### Bug Fixes\n\n- Fixed the `operator-sdk generate bundle` command to specify the right path of bundle metadata in bundle.Dockerfile. ([#5030](https://github.com/operator-framework/operator-sdk/pull/5030))\n- For Helm-based operators, fixed release equality comparison such that number values are compared and not their types to avoid unnecessary reconciliations. ([#5042](https://github.com/operator-framework/operator-sdk/pull/5042))\n- Bump java-operator-plugins. Adds `namespaced` plugin attribute and fixes resource version generation. ([#5020](https://github.com/operator-framework/operator-sdk/pull/5020))\n- In the `pkgman-to-bundle` command, changed the default channel name used for CSV's not specified in `package.yaml` to `defaultChannel` instead of \"candidate\". ([#5062](https://github.com/operator-framework/operator-sdk/pull/5062))\n"
  },
  {
    "path": "changelog/generated/v1.11.0.md",
    "content": "## v1.11.0\n\n### Additions\n\n- (go/v3, ansible/v1, helm/v1) Added `containerPort` protocol field required for server-side apply in manifests. ([#4863](https://github.com/operator-framework/operator-sdk/pull/4863))\n- For helm based operators, added a predicate that filters resources based on selectors specified in `watches.yaml`. Only the resources that contain the labels specified by selectors will be reconciled. ([#4997](https://github.com/operator-framework/operator-sdk/pull/4997))\n- For helm-based operators, support go `text/template` expansion of override values. ([#5105](https://github.com/operator-framework/operator-sdk/pull/5105))\n\n### Changes\n\n- (go/v3) Fixed a bug in `make test` caused by incorrect envtest asset setup. ([#4863](https://github.com/operator-framework/operator-sdk/pull/4863))\n- (go/v3, ansible/v1, helm/v1) Increased resource limits for controller manager. ([#4863](https://github.com/operator-framework/operator-sdk/pull/4863))\n- Updated operator-framework dependency to 0.10.5. This specific update includes a fix for bundle validation when checking for invalid service accounts. ([#5119](https://github.com/operator-framework/operator-sdk/pull/5119))\n- For helm-based operators, reverted #5042 and #4937  which modified helm release equality comparison. ([#5097](https://github.com/operator-framework/operator-sdk/pull/5097))\n\n### Bug Fixes\n\n- (ansible/v1) Previously, when scaffolding an Ansible-based operator with both Roles and Playbooks, the roles imported by the playbook could not be found when running locally (`make run`). This change prepends the `ANSIBLE_ROLES_PATH` environment variable with the path to the local roles directory. ([#5118](https://github.com/operator-framework/operator-sdk/pull/5118))\n- For Ansible-based operators, if a request is sent without a body in the metadata it will now be extracted from the request URL and properly set owner references/dependent watches. ([#5064](https://github.com/operator-framework/operator-sdk/pull/5064))\n- In `generate bundle`, exclude ServiceAccounts already in a CSV from generated bundle. ([#5120](https://github.com/operator-framework/operator-sdk/pull/5120))\n"
  },
  {
    "path": "changelog/generated/v1.12.0.md",
    "content": "## v1.12.0\n\n### Additions\n\n- If an optional UniqueID is provided by a user in the scorecard config and the user generates XML output the UID will be appended to the test result output. ([#5092](https://github.com/operator-framework/operator-sdk/pull/5092))\n\n### Bug Fixes\n\n- Preserve the order of `webhookdefinitions` while generating bundles,  by sorting `webhookDescriptions` in CSV generator. ([#5177](https://github.com/operator-framework/operator-sdk/pull/5177))\n"
  },
  {
    "path": "changelog/generated/v1.13.0.md",
    "content": "## v1.13.0\n\n### Additions\n\n- Added new optional validator `alpha-deprecated-apis` for the command bundle validate to help you verify if your bundle uses Kubernetes deprecated APIs. ([#5216](https://github.com/operator-framework/operator-sdk/pull/5216))\n- Added support for configuring Scorecard Service Accounts using config files alongside the CLI. ([#5245](https://github.com/operator-framework/operator-sdk/pull/5245))\n\n### Changes\n\n- (quarkus/v1alpha) Bumped java-operator-plugins to v0.1.0. This is the first release of the java-operator-plugins repo. There are no other changes besides pointing to a specific tag. ([#5206](https://github.com/operator-framework/operator-sdk/pull/5206))\n- For ansible-based operators, we have bumped `ansible-runner` dependency to >= 2.0.2. ([#5205](https://github.com/operator-framework/operator-sdk/pull/5205))\n- Updated default base image used in `run bundle` and `run bundle-upgrade` to the multi-arch `quay.io/operator-framework/opm:latest` image to support non-amd64 clusters. ([#5171](https://github.com/operator-framework/operator-sdk/pull/5171))\n- Replaced busybox with UBI8.4 for Scorecard Un-Tar image. ([#5191](https://github.com/operator-framework/operator-sdk/pull/5191))\n"
  },
  {
    "path": "changelog/generated/v1.14.0.md",
    "content": "## v1.14.0\n\n### Additions\n\n- Added new flag options `--storage-image` and `--untar-image` to the Scorecard command to allow overwrite its default values. These options are useful for disconnect environments and to prevent an impact of the external registry's pull limits. ([#5306](https://github.com/operator-framework/operator-sdk/pull/5306))\n- Added information to the errors raised by scorecard basic tests to allow easily identify the scenarios. ([#5273](https://github.com/operator-framework/operator-sdk/pull/5273))\n\n### Changes\n\n- - Upgrade the Kubernetes dependencies from `1.21` to `1.22`. - Upgrade the controller-gen dependency from `v0.6.2` to `v0.7.0`. More info: https://github.com/kubernetes-sigs/controller-tools/releases - Upgrade the sigs.k8s.io/controller-runtime dependency from `v0.9.2` to `v0.10.0`. More info: https://github.com/kubernetes-sigs/controller-runtime/releases - Upgrade the Env Test used from `1.21` to `1.22`. ([#5228](https://github.com/operator-framework/operator-sdk/pull/5228))\n- Bumped community.kubernetes to kubernetes.core >= 2.2.0. Added the kubernetes.core collection to requirements. ([#5249](https://github.com/operator-framework/operator-sdk/pull/5249))\n- Reformat xml output to support in-line attributes. ([#5241](https://github.com/operator-framework/operator-sdk/pull/5241))\n\n### Removals\n\n- Helm operator reconciliation diffs are now logged only at the zap debug level. ([#5307](https://github.com/operator-framework/operator-sdk/pull/5307))\n\n### Bug Fixes\n\n- scorecard will now print out the failed CR when the basic test fails. ([#5255](https://github.com/operator-framework/operator-sdk/pull/5255))\n- For Ansible-based Operators, adds documented `Successful` condition, and no longer removes conditions from the status in updates. Users can now wait for a successful reconciliation by waiting for the `Successful` type condition to be `True`. ([#5262](https://github.com/operator-framework/operator-sdk/pull/5262))\n- Fixed an error where `bundle validate` would return a \"duplicate service account\" error when an object and service account have the same `.metadata.name` in a bundle. ([#5282](https://github.com/operator-framework/operator-sdk/pull/5282))\n- The list of webhooks in `webhookdescription` was previously sorted based on `webhookType`. It is now being sorted based on webhook names. ([#5301](https://github.com/operator-framework/operator-sdk/pull/5301))\n"
  },
  {
    "path": "changelog/generated/v1.15.0.md",
    "content": "## v1.15.0\n\n### Changes\n\n- Bumped community.kubernetes to kubernetes.core >= 2.2.0. Added the kubernetes.core collection to requirements. ([#5249](https://github.com/operator-framework/operator-sdk/pull/5249))\n\n### Bug Fixes\n\n- For Ansible operators, if an API endpoint has a \"/\" in server path component the ansible binary will no longer throw error. ([#5308](https://github.com/operator-framework/operator-sdk/pull/5308))\n"
  },
  {
    "path": "changelog/generated/v1.16.0.md",
    "content": "## v1.16.0\n\n### Additions\n\n- For Ansible-based operators, add default resource limits for the manager. ([#5274](https://github.com/operator-framework/operator-sdk/pull/5274))\n- Add annotation to specify the default container. More info [here](https://kubernetes.io/docs/reference/labels-annotations-taints/#kubectl-kubernetes-io-default-container). ([#5330](https://github.com/operator-framework/operator-sdk/pull/5330))\n- Add PHONY targets to Makefile. ([#5330](https://github.com/operator-framework/operator-sdk/pull/5330))\n- Add `# TODO(user): Configure the resources accordingly based on the project requirements.` into the file `config/manager/manager.yaml` to make this requirement clear for users. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/. ([#5330](https://github.com/operator-framework/operator-sdk/pull/5330))\n- For Golang-based projects, added `ignore-not-found` flag to the `uninstall` and `undeploy` Makefile targets.  This change allows `make undeploy` and  `make install` to continue if Kustomize encounters a missing resource. You can invoke this feature by calling `make undeploy ignore-not-found=true`. ([#5330](https://github.com/operator-framework/operator-sdk/pull/5330))\n- Add new optional validator Good Practices. You are able to test your bundle against good practices defined under operator framework solutions by running:\n```sh \n$ operator-sdk bundle validate ./bundle --select-optional name=good-practices OR $ operator-sdk bundle validate ./bundle --select-optional suite=operatorframework \n```.\n([#5448](https://github.com/operator-framework/operator-sdk/pull/5448))\n- Add the deprecated APIs optional checker, `alpha-deprecated-apis`, to the `operatorframework` suite. ([#5407](https://github.com/operator-framework/operator-sdk/pull/5407))\n\n### Changes\n\n- Upgrade OPM version that is used by default to 1.19.1 in the generated Makefile so `make catalog-build` also works on OSX. ([#5099](https://github.com/operator-framework/operator-sdk/pull/5099))\n- For Ansible-based operators, bumped the `operator_sdk.util` ansible module to 0.3.1. ([#5462](https://github.com/operator-framework/operator-sdk/pull/5462))\n- For a more consistent user experience, ensure that all areas that require to be changed are marked by `TODO(user)`. ([#5330](https://github.com/operator-framework/operator-sdk/pull/5330))\n- For Helm-based Operators, adopted the same default resource limit values used to scaffold Golang-based projects. ([#5330](https://github.com/operator-framework/operator-sdk/pull/5330))\n- For Golang-based Operators, increase the values used in the default scaffold to define the resource limits usage and make clear the need to optimize its values based on the Operator requirements. ([#5330](https://github.com/operator-framework/operator-sdk/pull/5330))\n\n### Deprecations\n\n- Deprecation of the Optional(stage: alpha) Community Operator bundle validation. Its checks were moved to the [external validator](https://github.com/redhat-openshift-ecosystem/ocp-olm-catalog-validator/). ([#5414](https://github.com/operator-framework/operator-sdk/pull/5414))\n\n### Bug Fixes\n\n- Optional `OperatorHub.io` validator called by `operator-sdk bundle validate ./bundle --select-optional name=operatorhub` now includes a previously missing category `Modernization & Migration`. ([#5375](https://github.com/operator-framework/operator-sdk/pull/5375))\n- Improves the validate bundle spec error message to provide a better explanation when invalid service accounts are found. ([#5375](https://github.com/operator-framework/operator-sdk/pull/5375))\n- Improve scaffolding to filter existing multiline code fragments. More info [kubernetes-sigs/kubebuilder#2343](https://github.com/kubernetes-sigs/kubebuilder/pull/2343/files). ([#5330](https://github.com/operator-framework/operator-sdk/pull/5330))\n"
  },
  {
    "path": "changelog/generated/v1.17.0.md",
    "content": "## v1.17.0\n\n### Additions\n\n- Now operator-sdk bundle validate also ensures that the `alm-examples` annotation has a valid JSON ([More info](https://github.com/operator-framework/api/pull/207)) Introduction done by upgrading operator-framework/api from the commit `54878ea280f7c7402549dae568916dfb330b9262` to the release `v0.11.1`. ([#5495](https://github.com/operator-framework/operator-sdk/pull/5495))\n- Added the `hybrid.helm.sdk.operatorframework.io/v1-alpha` plugin, which scaffolds a hybrid helm based operator.  For more details on the plugin, please refer https://github.com/operator-framework/helm-operator-plugins/blob/main/docs/tutorial.md. This plugin is alpha and subject to breaking changes. ([#5504](https://github.com/operator-framework/operator-sdk/pull/5504))\n- Add resource requests and limits to kube-rbac-proxy. ([#5505](https://github.com/operator-framework/operator-sdk/pull/5505))\n\n### Changes\n\n- (go/v3) upgrade go version from 1.16 to 1.17 and the following dependencies: - upgrade controller-runtime from `0.10.0` to `0.11.0` - k8s from `1.22` to `1.23` - controller-gen from `v0.0.7` to `v0.8.0`. ([#5505](https://github.com/operator-framework/operator-sdk/pull/5505))\n- The debug log level for the sidecar container kube-rbac-proxy was reduced from 10 to 0. ([#5505](https://github.com/operator-framework/operator-sdk/pull/5505))\n"
  },
  {
    "path": "changelog/generated/v1.18.0.md",
    "content": "## v1.18.0\n\n### Additions\n\n- Add bundle size validator check for the command `operator-sdk bundle validate` check if the bundle is not bigger than ~4MB and warning the authors if the bundle size is closer to this amount. [More info](https://github.com/operator-framework/api/pull/210). ([#5552](https://github.com/operator-framework/operator-sdk/pull/5552))\n- Add warning check for properties defined in the CSV for the command `operator-sdk bundle validate` warning when found properties annotations in the CSV recommending define these properties in `metadata/properties.yaml` instead. [More info](https://github.com/operator-framework/api/pull/217). ([#5552](https://github.com/operator-framework/operator-sdk/pull/5552))\n- Add support to check for the manifests using the APIs which will be removed in [1.25](https://kubernetes.io/docs/reference/using-api/deprecation-guide/#v1-25) and [1.26](https://kubernetes.io/docs/reference/using-api/deprecation-guide/#v1-26) Kubernetes versions in the bundle manifests via the commands `operator-sdk bundle validate ./bundle --select-optional name=alpha-deprecated-apis` and consequently to `operator-sdk bundle validate ./bundle --select-optional suite=operatorframework`. Note that is unlike these APIs be present on the bundle. [More info](https://github.com/operator-framework/api/pull/208). ([#5552](https://github.com/operator-framework/operator-sdk/pull/5552))\n- Adds support to bundle operators using image digests instead of tags. ([#5567](https://github.com/operator-framework/operator-sdk/pull/5567))\n\n### Changes\n\n- (java/v1alpha) bumping the java-operator-plugins dependency to v0.2.0. This release includes the following items.\n### Additions - chore: bump go 1.17, k8s 1.23, and kubebuilder 3.3 (#69) - chore(deps): update to Quarkus SDK extension 3.0.2 and Quarkus 2.6.3 (#70) - chore(deps): update to use Quarkus JOSDK extension 3.0.1 (#67) - Remove useless file (#65) - chore: bump k8s 1.22.2 and kubebuilder 3.2 (#64) - exposed endpoints for micrometer metrics (#45) - modified the Quarkus operator SDK version and tutorial too (#40) - chore: bump fabric8 5.8.0 & quarkus 2.4.0 (#42) - modified the doc file and removed file after generation (#41) - release: fix release script to understand release branches (#38)\n### Bug Fixes - Fix for wrongly generated file name (#73). ([#5542](https://github.com/operator-framework/operator-sdk/pull/5542))\n\n### Bug Fixes\n\n- Fixed a bug in `generate kustomze manifest` that quotes from interactive input were not trimmed properly. ([#5545](https://github.com/operator-framework/operator-sdk/pull/5545))\n- Add requirement cloud.common for Ansible-based operators. ([#5505](https://github.com/operator-framework/operator-sdk/pull/5505))\n"
  },
  {
    "path": "changelog/generated/v1.19.0.md",
    "content": "## v1.19.0\n\n### Additions\n\n- Add official binary builds for `darwin/arm64`. ([#5581](https://github.com/operator-framework/operator-sdk/pull/5581))\n- User is not able to run the `operator-sdk run bundle` in local kind-registry as `--skip-tls` flag is deprecated. OPM introduced new flags `--skip-tls-verify and --use-http`. This fix will enable the newly introduced flags. ([#5617](https://github.com/operator-framework/operator-sdk/pull/5617))\n- For the helm/v1 plugin, parsed the \"helm.sdk.operatorframework.io/reconcile-period\"  value from the custom resource annotations for helm operators. This value is then  set to the 'ReconcilePeriod' field of the reconciler to reconcile the cluster in the specified intervals of time. ([#5585](https://github.com/operator-framework/operator-sdk/pull/5585))\n- Added log so that URL verification errors when starting the ansible-operator are not silently swallowed. ([#5595](https://github.com/operator-framework/operator-sdk/pull/5595))\n- Reverted removal of  `--skip-tls` flag and mark the flag as deprecated. ([#5633](https://github.com/operator-framework/operator-sdk/pull/5633))\n\n### Changes\n\n- scorecard will now printout test results, if any, even when there is a context timeout. This will allow underlying errors from a test to be shown helping users address the issues. ([#5628](https://github.com/operator-framework/operator-sdk/pull/5628))\n\n### Bug Fixes\n\n- (java/v1alpha) bumped the java-operator-plugins dependency to [v0.3.0](https://github.com/operator-framework/java-operator-plugins/releases/tag/v0.3.0). ([#5588](https://github.com/operator-framework/operator-sdk/pull/5588))\n- Add the labels defined in the Manager (Operator Deployment) to the ClusterServiceVersions [`DeploymentSpecs`](https://github.com/operator-framework/api/blob/master/pkg/operators/v1alpha1/clusterserviceversion_types.go#L78) to ensure that they will also be provided to the integration with OLM (CSV). ([#5533](https://github.com/operator-framework/operator-sdk/pull/5533))\n"
  },
  {
    "path": "changelog/generated/v1.20.0.md",
    "content": "## v1.20.0\n\n### Additions\n\n- New check to warning authors when the CRD description is empty was added to the Good Practices validator. You are able to check it by running `operator-sdk bundle validate ./bundle --select-optional name=good-practices` or `$ operator-sdk bundle validate ./bundle --select-optional suite=operatorframework` ([More info](https://github.com/operator-framework/api/pull/234)). ([#5552](https://github.com/operator-framework/operator-sdk/pull/5552))\n- For ansible-based operators, proxy server port can be changed with the new `proxy-port` flag, which still defaults to 8888. ([#5669](https://github.com/operator-framework/operator-sdk/pull/5669))\n- Previously we added this error to show the user that the Path component is part of proxy server. Now, kubectl made this fix that handles this case and there is no need to throw this error anymore. ([#5648](https://github.com/operator-framework/operator-sdk/pull/5648))\n\n### Changes\n\n- Update the supported OLM versions to 0.18.3, 0.19.1, 0.20.0. ([#5684](https://github.com/operator-framework/operator-sdk/pull/5684))\n\n### Bug Fixes\n\n- Fix: channel naming validator check and move it for the Good Practices validator. You are able to check it by running `operator-sdk bundle validate ./bundle --select-optional name=good-practices` or `$ operator-sdk bundle validate ./bundle --select-optional suite=operatorframework` ([More info](https://github.com/operator-framework/api/pull/231)). ([#5552](https://github.com/operator-framework/operator-sdk/pull/5552))\n- For ansible-based operators, this change fixes an issue that caused finalizers to fail to run if the watched resource (CR) is deleted during reconciliation. ([#5678](https://github.com/operator-framework/operator-sdk/pull/5678))\n- The related image discovery feature currently only reads environment variables from the manager container. This was causing an error when the deployment labels or container name that was expected were not present. This fixes that by collecting related images from all containers across all deployments.\nThis change also enables users to use related images in other containers since related images from everywhere will be considered. ([#5639](https://github.com/operator-framework/operator-sdk/pull/5639))\n"
  },
  {
    "path": "changelog/generated/v1.21.0.md",
    "content": "## v1.21.0\n\n### Additions\n\n- (declarative/v1): For Golang-based operators, copy the channels directory in the Dockerfile ([More info](https://github.com/kubernetes-sigs/kubebuilder/pull/2507/files)). ([#4863](https://github.com/operator-framework/operator-sdk/pull/4863))\n- (go/v3):For Golang-based operators, new README.md will begin to be scaffolded. ([#4863](https://github.com/operator-framework/operator-sdk/pull/4863))\n\n### Changes\n\n- The validate package was inadvertantly exposed, it should be internal as all the other packages are in operator-sdk. The package was moved from `pkg/validate` to `internal/validate`. ([#5726](https://github.com/operator-framework/operator-sdk/pull/5726))\n- Changed the default reconcile period of Ansible-based operators to 10h instead of 1m. ([#5781](https://github.com/operator-framework/operator-sdk/pull/5781))\n- Bump the helm-operator-plugins dependency version to v0.0.10. ([#5772](https://github.com/operator-framework/operator-sdk/pull/5772))\n- (go/v3):For Golang-based operators, upgrade controller-runtime and Kubernetes deps. ([#4863](https://github.com/operator-framework/operator-sdk/pull/4863))\n- (kustomize/v1):For Golang/Helm/Ansible-based operators, upgrade kube-rbac-proxy image from v0.8.0 to v0.11.0. ([#4863](https://github.com/operator-framework/operator-sdk/pull/4863))\n- (config-gen alpha command): Updated the image `gcr.io/kubebuilder/kube-rbac-proxy` from v0.5.0 to v0.11.0. ([#4863](https://github.com/operator-framework/operator-sdk/pull/4863))\n- (config-gen alpha command): upgrade sigs.k8s.io/controller-tools from v0.7.0 to v0.8.0. ([#4863](https://github.com/operator-framework/operator-sdk/pull/4863))\n- For Golang-based operators, change Makefile targets to replace go get with go install in order to remove deprecation and begin to be prepared to support go 1.18 in the future releases (IMPORTANT: Golang projects still not supporting versions >= 1.18. To know more about what needs to be done in order to support Golang 1.18, see [here](https://github.com/kubernetes-sigs/kubebuilder/issues/2559) ). ([#4863](https://github.com/operator-framework/operator-sdk/pull/4863))\n- Update the `operator-sdk run bundle` command to have a more detailed help output, stating the intent of the command and that index-images passed via the `--index-image` flag should not already contain the bundle. ([#5727](https://github.com/operator-framework/operator-sdk/pull/5727))\n\n### Bug Fixes\n\n- (go/v3): For Golang-based operators, fix suite test using global cfg ([More info](https://github.com/kubernetes-sigs/kubebuilder/pull/2602)). ([#4863](https://github.com/operator-framework/operator-sdk/pull/4863))\n- (go/v3): For Golang-based operators, ensure that the plugin can only be used with its go supported version >= 1.17 (IMPORTANT: Golang projects still not supporting versions >= 1.18. To know more about what needs to be done in order to support Golang 1.18, see [here](https://github.com/kubernetes-sigs/kubebuilder/issues/2559) ). ([#4863](https://github.com/operator-framework/operator-sdk/pull/4863))\n- (kustomize/v1): For Golang-based operators, fix the issue to scaffold the same Kind for different groups with multi-group support by using group name in crd/patches and rbac editor/viewer manifests ([More info](https://github.com/kubernetes-sigs/kubebuilder/pull/2500)). ([#4863](https://github.com/operator-framework/operator-sdk/pull/4863))\n- (kustomize/v1): For Golang-based operators, fix the issue to scaffold the same Kind for different groups with multi-group support by using group name in crd/patches and rbac editor/viewer manifests ([More info](https://github.com/kubernetes-sigs/kubebuilder/pull/2500)). ([#4863](https://github.com/operator-framework/operator-sdk/pull/4863))\n- (go/v3): For Golang-based operators, avoid adding duplicated code fragments ([More info](https://github.com/kubernetes-sigs/kubebuilder/pull/2619)). ([#4863](https://github.com/operator-framework/operator-sdk/pull/4863))\n"
  },
  {
    "path": "changelog/generated/v1.22.0.md",
    "content": "## v1.22.0\n\n### Additions\n\n- For Go (go/v3) and Hybrid Helm (hybrid.helm/v1-alpha) language based operators: Add support for Go 1.18. ([#5843](https://github.com/operator-framework/operator-sdk/pull/5843))\n- For `operator-sdk bundle validate` command and GoodPractices validator (`--select-optional name=good-practices`): Add CRD description check validation [More info](https://github.com/operator-framework/api/pull/234). ([#5843](https://github.com/operator-framework/operator-sdk/pull/5843))\n- For `operator-sdk bundle validate` command and GoodPractices validator (`--select-optional name=good-practices`): Add a new check to warn authors when permissions to create CRDs are found [More info](https://github.com/operator-framework/api/pull/241). ([#5843](https://github.com/operator-framework/operator-sdk/pull/5843))\n- For Quarkus (quarkus/v1-alpha) language based operator: add bundle generation [More info](https://github.com/operator-framework/java-operator-plugins/pull/84). ([#5843](https://github.com/operator-framework/operator-sdk/pull/5843))\n- For operator-sdk run bundle and bundle-upgrade subcommands: improve message from common scenario faced to add a new bundle [More info](https://github.com/operator-framework/operator-registry/pull/954). ([#5843](https://github.com/operator-framework/operator-sdk/pull/5843))\n- For operator-sdk run bundle and bundle-upgrade subcommands: adds some extra text context to sql statement errors [More info](https://github.com/operator-framework/operator-registry/pull/953). ([#5843](https://github.com/operator-framework/operator-sdk/pull/5843))\n- For Golang/Ansible/Helm/HybridHelm language-based operators (go/v3, ansible/v1, helm/v1, hybrid.helm/v1-alpha, add a new comment with the option `leaderElectionReleaseOnCancel` [More info] (https://github.com/kubernetes-sigs/kubebuilder/pull/2596]). ([#5814](https://github.com/operator-framework/operator-sdk/pull/5814))\n\n### Changes\n\n- **Breaking change**: For Ansible-based language operators, upgrade `community.kubernetes` from `1.2.1` to `2.0.1`. **IMPORTANT** The `community.kubernetes` collection is being renamed to kubernetes.core. As of version 2.0.0, the collection has been replaced by deprecated redirects for all content to kubernetes.core. If you are using FQCNs starting with `community.kubernetes`, please update them to `kubernetes.core`. ([#5846](https://github.com/operator-framework/operator-sdk/pull/5846))\n- For Ansible-based language operators, upgrade `kubernetes.core` from `2.2.0` to `2.3.1`. **IMPORTANT** The `community.kubernetes` collection is being renamed to kubernetes.core. As of version 2.0.0, the collection has been replaced by deprecated redirects for all content to kubernetes.core. If you are using FQCNs starting with `community.kubernetes`, please update them to `kubernetes.core`. ([#5846](https://github.com/operator-framework/operator-sdk/pull/5846))\n- For Ansible-based language operators, upgrade `community.kubernetes` from `1.2.1` to `2.0.1`. **IMPORTANT** The `community.kubernetes` collection is being renamed to kubernetes.core. As of version 2.0.0, the collection has been replaced by deprecated redirects for all content to kubernetes.core. If you are using FQCNs starting with `community.kubernetes`, please update them to `kubernetes.core`. ([#5846](https://github.com/operator-framework/operator-sdk/pull/5846))\n- Scorecard details got generated for the bundle even if no details were present for the scorecard in the java plugin. This change will add scorecard changes on conditional basis. ([#5800](https://github.com/operator-framework/operator-sdk/pull/5800))\n- Hide --skip-tls flag as it is deprecated. ([#5830](https://github.com/operator-framework/operator-sdk/pull/5830))\n- For Go (go/v3) and Helm Hybrid (hybrid.helm/v1-alpha) language based operators: Upgrade Kubernetes dependencies from `1.23` to `1.24` and controller-gen from `v0.8.0` to `v0.9.0`. ([#5843](https://github.com/operator-framework/operator-sdk/pull/5843))\n- For Helm (helm/v1) and Hybrid Helm (hybrid.helm/v1-alpha) language based operators: Upgrade helm from `v3.6.2` to `v3.9.0`. ([#5843](https://github.com/operator-framework/operator-sdk/pull/5843))\n- For Ansible (ansible/v1) and Helm (helm/v1) language based operators: change the default value for the manager.option LeaderElectionResourceLock from `comfigmaps` to `configmapsleases` to allow a safe transition to use the leases option on the future. [More info](https://github.com/kubernetes-sigs/controller-runtime/pull/1903). ([#5843](https://github.com/operator-framework/operator-sdk/pull/5843))\n- For Quarkus (quarkus/v1-alpha) language based operator: upgrade dependency from `v0.0.3` to `v0.5.1` [More info](https://github.com/operator-framework/java-operator-plugins/releases). ([#5843](https://github.com/operator-framework/operator-sdk/pull/5843))\n- For Helm Hybrid (hybrid.helm/v1-alpha) language based operator: Upgrade dependency from `v0.0.10` to `v0.0.11`. [More info](https://github.com/operator-framework/helm-operator-plugins/releases). ([#5843](https://github.com/operator-framework/operator-sdk/pull/5843))\n- For Go (go/v3, go/v2), Ansible (ansible/v1), Helm (helm/v1), and Helm Hybrid (hybrid.helm/v1-alpha) language based operators: Bump OPM version from `v1.19.1` to `v1.23.0`. ([#5843](https://github.com/operator-framework/operator-sdk/pull/5843))\n- For Docker images: Bump Go from 1.17 to 1.18. ([#5843](https://github.com/operator-framework/operator-sdk/pull/5843))\n- Docs: Update Go 1.17 references to Go 1.18. ([#5843](https://github.com/operator-framework/operator-sdk/pull/5843))\n- For HybridHelm based-language (hybrid.helm/v1-alpha), update its version from v0.0.10 to [v0.0.11-0.20220607145946-5b29693d1612](https://github.com/operator-framework/helm-operator-plugins/commit/5b29693d1612f87797e1e91e6cf1253842a5714e). [More info](https://github.com/operator-framework/helm-operator-plugins/compare/v0.0.8...5b29693d1612). ([#5814](https://github.com/operator-framework/operator-sdk/pull/5814))\n- Add support for File-Based Catalog to the subcommands [operator-sdk run bundle](https://sdk.operatorframework.io/docs/cli/operator-sdk_run_bundle/#m-docsclioperator-sdk_run_bundle)  and [run bundle-upgrade](https://sdk.operatorframework.io/docs/cli/operator-sdk_run_bundle-upgrade/) so that  new indexes created by these subcommands are using the new format.  Users are able to pass in an index catalog with FBC format via the flag option `--index-image`. ([#5809](https://github.com/operator-framework/operator-sdk/pull/5809))\n\n### Deprecations\n\n- For Ansible/Helm based-operators (ansible/v1, helm/v1), deprecate the flag `crd-version` since `v1beta1` APIs is not longer offered from k8s 1.22 and this flag is deprecated for Golang. ([#5815](https://github.com/operator-framework/operator-sdk/pull/5815))\n\n### Bug Fixes\n\n- Enable `run bundle` command to handle large File-Based Catalog index images  by generating the extra FBC with the bundle contents and mounting a ConfigMap with that extra FBC, without regenerating the entire index. ([#5868](https://github.com/operator-framework/operator-sdk/pull/5868))\n- For `operator-sdk bundle validate` command and GoodPractices validator (`--select-optional name=good-practices`): fix channel naming validation [More info](https://github.com/operator-framework/api/pull/231). ([#5843](https://github.com/operator-framework/operator-sdk/pull/5843))\n- For Golang-based language (go/v2), fix issue introduced by removing the GO111MODULE=on from Dockerfile. ([More info](https://github.com/kubernetes-sigs/kubebuilder/pull/2678))\n**IMPORTANT NOTE**: If you are using `go/v2` we highly recommend to upgrade your project to latest `go/v3` plugin (default operator-sdk scaffold). Please be aware that `go/v2` is a plugin which was kept to ensure the backwards compatibility with old Kubebuilder layout produced using its CLI versions < `3.0.0`. ([More info](https://book.kubebuilder.io/plugins/go-v2-plugin.html)) Therefore, we are unable to upgrade this plugin continuously and solve tech-debts as it is very likely that it would soon be deprecated by the Kubebuilder community. Note that projects built with this plugin do not produce CRDs for example using v1 APIs so that cannot work on Kubernetes cluster >= `1.22`). Please, ensure that you follow our migration guide [Migrating from pre-v1.0.0 to latest](https://sdk.operatorframework.io/docs/building-operators/golang/migration/). ([#5814](https://github.com/operator-framework/operator-sdk/pull/5814))\n"
  },
  {
    "path": "changelog/generated/v1.23.0.md",
    "content": "## v1.23.0\n\n### Additions\n\n- (Alpha) New optional validator to help verify if a bundle matches criteria for multiple architecture support. More info: https://olm.operatorframework.io/docs/advanced-tasks/ship-operator-supporting-multiarch/. You can test it out by running `$ operator-sdk bundle validate ./bundle --select-optional name=multiarch`. ([#5908](https://github.com/operator-framework/operator-sdk/pull/5908))\n- Add an option, `WatchAnnotationsChanges`, to trigger reconciliations on annotation changes on watched resources. ([#5611](https://github.com/operator-framework/operator-sdk/pull/5611))\n- Add a plugin (deploy-image/v1-alpha) for Golang projects that scaffolds the code to deploy and manage an Operand(image). You can test it out by running `operator-sdk --group=example.com --version=v1alpha1 --kind=Memcached --image=memcached:1.6.15-alpine --image-container-command=\"memcached,-m=64,modern,-v\" --image-container-port=\"11211\" --run-as-user=\"1001\" --plugins=\"deploy-image/v1-alpha\"` [More info](https://master.book.kubebuilder.io/plugins/deploy-image-plugin-v1-alpha.html). ([#5965](https://github.com/operator-framework/operator-sdk/pull/5965))\n- Add a plugin (grafana/v1-alpha) valid for all languages to help you generate Grafana dashboards. You can test it out by running `operator-sdk edit --plugins=grafana.kubebuilder.io/v1-alpha` [More info](https://master.book.kubebuilder.io/plugins/grafana-v1-alpha.html). ([#5965](https://github.com/operator-framework/operator-sdk/pull/5965))\n- Add new golang plugin `go/v4-alpha` which adds support for Apple Silicon(`darwin/arm64`). ([#5965](https://github.com/operator-framework/operator-sdk/pull/5965))\n- Test containers defined by `config.yaml` can now read the environment variable `SCORECARD_STORAGE` to get a storage path defined in the `config.yaml`. ([#5829](https://github.com/operator-framework/operator-sdk/pull/5829))\n- (deploy-image/v1alpha plugin) Add support to generate SDK bundle manifests. ([#5997](https://github.com/operator-framework/operator-sdk/pull/5997))\n- (ansible/v1,helm/v1) Add support for Apple Silicon(`darwin/arm64`). [Release Notes](https://github.com/kubernetes-sigs/kustomize/releases/tag/kustomize%2Fv4.0.0). ([#5965](https://github.com/operator-framework/operator-sdk/pull/5965))\n\n### Changes\n\n- Upgrade kube rbac proxy image `gcr.io/kubebuilder/kube-rbac-proxy` from `v0.11.0` to `v0.12.0`. [More info](https://github.com/brancz/kube-rbac-proxy/releases/tag/v0.12.0). ([#5903](https://github.com/operator-framework/operator-sdk/pull/5903))\n- (go/v3) Update `controller-tools` from `0.9.0` to `0.9.2`. [More info](https://github.com/kubernetes-sigs/controller-tools/releases/tag/v0.9.2). ([#5965](https://github.com/operator-framework/operator-sdk/pull/5965))\n- (go/v3) Update `controller-runtime` from `v0.12.1` to `v0.12.2` and Kubernetes dependencies from `v0.24.0` to `v0.24.2`. [More info](https://github.com/kubernetes-sigs/controller-runtime/releases/tag/v0.12.2). ([#5965](https://github.com/operator-framework/operator-sdk/pull/5965))\n- (go/v3,ansible/v1,helm/v1) Update `gcr.io/kubebuilder/kube-rbac-proxy` from `0.12.0` to `0.13.0`. [More info](https://github.com/brancz/kube-rbac-proxy/releases/tag/v0.13.0). ([#5965](https://github.com/operator-framework/operator-sdk/pull/5965))\n- **Breaking change**: (ansible/v1,helm/v1) Upgraded `kustomize` version from `v3.8.7` to `v4.5.5`. [Release Notes](https://github.com/kubernetes-sigs/kustomize/releases/tag/kustomize%2Fv4.0.0). ([#5965](https://github.com/operator-framework/operator-sdk/pull/5965))\n- Update the supported OLM versions to 0.20.0, 0.21.2, 0.22.0. ([#6000](https://github.com/operator-framework/operator-sdk/pull/6000))\n- Moved bundle name validation check to the good-practices validator. You can test it out by running `$ operator-sdk bundle validate ./bundle --select-optional name=good-practices`. ([#5908](https://github.com/operator-framework/operator-sdk/pull/5908))\n\n### Deprecations\n\n- Legacy layout \"Kubebuilder 2.x\" provided via the go/v2 plugin is officially deprecated. Be aware that since `Apr 2021`, the default layout produced is done via the `go/v3`. ([More info](https://github.com/kubernetes-sigs/kubebuilder/discussions/2842)) Check your `PROJECT` file to make sure that your project layout is `go.kubebuilder.io/v3`, if not please follow the [migration guide](https://sdk.operatorframework.io/docs/building-operators/golang/migration/) to upgrade your project. ([#5965](https://github.com/operator-framework/operator-sdk/pull/5965))\n- Dropped support for installing `olm` version `0.19.1`. ([#6000](https://github.com/operator-framework/operator-sdk/pull/6000))\n\n### Bug Fixes\n\n- For Hybrid Helm (hybrid.helm/v1-alpha) language based operators: Bump Dockerfile Go version to 1.18. ([#5772](https://github.com/operator-framework/operator-sdk/pull/5772))\n- Fix Makefile targets to not download binaries when they are found already. ([#5965](https://github.com/operator-framework/operator-sdk/pull/5965))\n- Remove the option to call `kustomize/v1` plugin alone. If you are looking to use this project as a base for you to generate other plugins, please use [Kubebuilder](https://github.com/kubernetes-sigs/kubebuilder) instead. ([#5965](https://github.com/operator-framework/operator-sdk/pull/5965))\n- Fix operator-sdk run bundle and upgrade bundle subCommands to allow them to work against Kubernetes versions < 1.19 and vendors like Openshift. ([#5973](https://github.com/operator-framework/operator-sdk/pull/5973))\n- Fixed scorecard testOutput tightly coupling with scorecard storage mountPath. ([#5714](https://github.com/operator-framework/operator-sdk/pull/5714))\n- Fix operator-sdk generate kustomize manifests to respect changes made by users in the config/manifests. ([#5960](https://github.com/operator-framework/operator-sdk/pull/5960))\n- For `operator-sdk run bundle-upgrade`: fix a bug that caused `InstallPlan`s occasionally not being approved when attempting to upgrade a bundle. ([#5901](https://github.com/operator-framework/operator-sdk/pull/5901))\n- For run bundle-upgrade, generate just the extra FBC of the bundle instead of rendering the entire index and appending bundle contents to it. ([#5891](https://github.com/operator-framework/operator-sdk/pull/5891))\n- Honor `--skip-tls-verify` and `--use-http` flags from run bundle(-upgrade). ([#5921](https://github.com/operator-framework/operator-sdk/pull/5921))\n"
  },
  {
    "path": "changelog/generated/v1.24.0.md",
    "content": "## v1.24.0\n\n### Changes\n\n- Bumping java-operator-plugins to v0.6.0. ([#6007](https://github.com/operator-framework/operator-sdk/pull/6007))\n\n### Bug Fixes\n\n- Support test selectors in scorecard-kuttl. This only works if you supply a test name in the config for the entrypoint in the scorecard test config.yaml\nIn the `stages.tests`section add an `entrypoint`, in this entrypoint you add the name of the test you want to associate with the selector.\nIf you have a kuttl test directory called `smoke` your entrypoint should have `- smoke` as an entry. That way scorecard can pass that into the image and kuttl will run the single test. ([#6015](https://github.com/operator-framework/operator-sdk/pull/6015))\n- `operator-sdk run bundle(-upgrade)`: fixed bug that made it so bundles weren't properly upgraded if the  channel used in the bundle wasn't in the same channel as the bundle installed via `operator-sdk run bundle`. Using `operator-sdk run bundle` will now use a default channel instead of the one in the bundle. ([#6042](https://github.com/operator-framework/operator-sdk/pull/6042))\n- `operator-sdk run bundle(-upgrade)`: fixed bug causing `operator-sdk run bundle-upgrade` and `operator-sdk run bundle ... --index-image=...` to stall indefinitely. ([#6040](https://github.com/operator-framework/operator-sdk/pull/6040))\n- For Ansible & Helm-based operators, the generated `Makefile` does not handle converting `aarch64` to `arm64`. This prevents it from downloading the appropriate binaries.\nThis change simply adds a call to `sed` to convert `aarch64` to `arm64`. ([#5480](https://github.com/operator-framework/operator-sdk/pull/5480))\n"
  },
  {
    "path": "changelog/generated/v1.25.0.md",
    "content": "## v1.25.0\n\n### Changes\n\n- (ansible/v1): Modified ansible scaffolding in order to incorporate  changes with Kubebuilder on `--component-config` flag changes.  Previously, the changes with `--component-config` flag were not  considered by default.\nThe following are the modifications: 1. If the `--component-config` flag is passed then look for `- /manager`  in `manager.yaml` in order to add leader election id. If the component  config flag is not passed then check for `--leader-elect` flag. 2. In `manager_proxy_patch.yaml` file, look for `memory: 64Mi`  if the component flag is passed flag is passed. If not then look  for `--leader-elect`. 3. Repeat the same logic for replacing the port number from the file. 4. At the end, update the `manager.yaml` file to avoid lint errors. ([#6047](https://github.com/operator-framework/operator-sdk/pull/6047))\n- (go/v3, hybrid.helm/v1-alpha, and quarkus/v1-alpha): Upgrade Kubernetes dependencies from `1.24` to `1.25`. ([#6044](https://github.com/operator-framework/operator-sdk/pull/6044))\n- This PR bumped Kubebuilder to 3.7.1,  with this version comes the addition of the `--component-config` flag.\nThis flag is passed through `operator-sdk init` command.  If this flag is passed through the command line as an argument then only the  `controller_manager_config.yaml` file will be scaffolded in the  manifest.  If it is not passed then it will not scaffold out this file.  The command for passing the flag is:  operator-sdk init --domain example.com --repo github.com/example/memcached-operator --component-config. ([#6047](https://github.com/operator-framework/operator-sdk/pull/6047))\n- (ansible/v1): updates the base ansible base operator event api, api server,  and proxy to now have a 5 second timeout when reading the request headers.  This is to prevent the possibility of a [Slowloris attack](https://www.cloudflare.com/learning/ddos/ddos-attack-tools/slowloris/). ([#6088](https://github.com/operator-framework/operator-sdk/pull/6088))\n- Modified go version to 1.19 and Kubebuilder to 3.7.1. The `config-gen` is  completely removed from Kubebuilder. As part of this bump, the  website content of SDK was updated where the doc is referring to  `config-gen`. ([#6047](https://github.com/operator-framework/operator-sdk/pull/6047))\n- Updated ginkgo to ginkgo/v2 in all of the files. ([#6047](https://github.com/operator-framework/operator-sdk/pull/6047))\n- Updated: - ginko to `ginko/v2` - `io/ioutil` packages to either `io` or `os` since its not longer supported in go1.19. ([#6047](https://github.com/operator-framework/operator-sdk/pull/6047))\n- (helm/v1): Modified helm scaffolding in order to incorporate changes with Kubebuilder on `--component-config` flag changes. Previously,  the changes with `--component-config` flag were not considered by  default.\nThe following are the modifications: 1. If the `--component-config` flag is passed then look for `- /manager`  in `manager.yaml` in order to add leader election id. If the component  config flag is not passed then check for `--leader-elect` flag. 2. In `manager_proxy_patch.yaml` file, look for `memory: 64Mi`  if the component flag is passed flag is passed. If not then look  for `--leader-elect`. 3. Repeat the same logic for replacing the port number from the file. 4. At the end, update the `manager.yaml` file to avoid lint errors. ([#6047](https://github.com/operator-framework/operator-sdk/pull/6047))\n- (ansible/v1, helm/v1): Added support to build multi-arch images from the project Makefile. A docker-buildx target will build the images for the platforms specified by the PLATFORMS variable. ([#6093](https://github.com/operator-framework/operator-sdk/pull/6093))\n\n### Bug Fixes\n\n- (docs) Update the go version in the developer guide.  The documentation wasn't updated when the go version was bumped to v1.18. ([#6101](https://github.com/operator-framework/operator-sdk/pull/6101))\n- For operator-sdk run bundle and bundle-upgrade subcommands: Added --security-context-config flag to enable seccompprofile. It defaults to restricted to support k8s 1.25. You can disable it with --security-context-config=legacy. ([#6062](https://github.com/operator-framework/operator-sdk/pull/6062))\n"
  },
  {
    "path": "changelog/generated/v1.26.0.md",
    "content": "## v1.26.0\n\n### Additions\n\n- For `operator-sdk bundle validate`: When checking for Kubernetes APIs deprecated in Kubernetes v1.25.0 the ClusterServiceVersion's CustomResourceDefinitions,  ClusterPermissions, and Permissions are now validated to ensure no references to  deprecated APIs are being made. ([#6119](https://github.com/operator-framework/operator-sdk/pull/6119))\n\n### Changes\n\n- (images): Bumps all Operator SDK maintained images to now use ubi(-minimal) tag 8.7. ([#6175](https://github.com/operator-framework/operator-sdk/pull/6175))\n\n### Bug Fixes\n\n- ansible: fixed \"make run\" so it finds local roles. ([#6110](https://github.com/operator-framework/operator-sdk/pull/6110))\n- For `operator-sdk run bundle(-upgrade)`: fix a bug in the logic that would attempt to create a `ConfigMap` that contained the entire contents of an FBC. Now if the FBC contents are to large to fit into a single `ConfigMap`, the FBC contents will be partitioned and split amongst multiple `ConfigMap` resources. ([#6182](https://github.com/operator-framework/operator-sdk/pull/6182))\n"
  },
  {
    "path": "changelog/generated/v1.27.0.md",
    "content": "## v1.27.0\n\n### Changes\n\n- `operator-sdk run bundle(-upgrade)`: Change default of the `--security-context-config` flag to be `legacy` instead of `restricted`. ([#6210](https://github.com/operator-framework/operator-sdk/pull/6210))\n- `operator-sdk run bundle`: When creating the CatalogSource, we now set the `grpcPodConfig.SecurityContextConfig` to the value of the  `--security-context-config` flag. ([#6210](https://github.com/operator-framework/operator-sdk/pull/6210))\n- The `scorecard-test-kuttl` image always prints the kuttl logs in case there is an error processing the kuttl report. ([#6225](https://github.com/operator-framework/operator-sdk/pull/6225))\n\n### Bug Fixes\n\n- `operator-sdk bundle validate`: Fix a bug in the Kubernetes 1.25 validation logic that would warn that a Kubernetes resource was deprecated without checking the group that contains the resource.  (i.e if apps/deployments was deprecated and you used other/deployments you would receive a warning)\". The validation logic will now verify the group and resource before issuing a warning. ([#6227](https://github.com/operator-framework/operator-sdk/pull/6227))\n- `operator-sdk run bundle(-upgrade)`: Fix a bug where SQLite bundle images were failing to be run properly due to a change in the default channel that is used by `run bundle(-upgrade)` when creating a subscription. ([#6210](https://github.com/operator-framework/operator-sdk/pull/6210))\n- `operator-sdk run bundle(-upgrade)`: Update the logic used to set a Registry Pod's PSA configuration to fix a bug where a Pod's containers still had a restrictive SecurityContext even when setting `--security-context-config=legacy`. ([#6210](https://github.com/operator-framework/operator-sdk/pull/6210))\n- For `operator-sdk bundle validate`: Fix a bug that would make the command exit with a 0 exit code even if there were validation failures. ([#6274](https://github.com/operator-framework/operator-sdk/pull/6274))\n- (scorecard): Fixes a bug where an error would be thrown if a Custom Resource did not have a `.spec` field, which is a perfectly valid scenario.  Instead of throwing an error scorecard will now issue a suggestion. ([#6245](https://github.com/operator-framework/operator-sdk/pull/6245))\n"
  },
  {
    "path": "changelog/generated/v1.28.0.md",
    "content": "## v1.28.0\n\n### Changes\n\n- (ansible): Revert the cryptography package unpinning and repin to v3.3.2. ([#6348](https://github.com/operator-framework/operator-sdk/pull/6348))\n- - Upgrade Kubernetes dependencies from `1.25` to `1.26`. - Upgrade `sigs.k8s.io/controller-tools` from `v0.10.0` to `v0.11.3`. More info: https://github.com/kubernetes-sigs/controller-tools/releases - Upgrade `sigs.k8s.io/controller-runtime` dependency from `v0.13.0` to `v0.14.5`. More info: https://github.com/kubernetes-sigs/controller-runtime/releases - Upgrade `k8s.io/client-go` dependency from `v0.25.3` to `v0.26.2`. - Upgrade `controller-gen` dependency from `v0.10.0` to `v0.11.1`. - Upgrade `kube-rbac-proxy` from `v0.13.0` to `v0.13.1` - Modify gov4alpha plugin to use `go/v4-alpha` from Kubebuilder. ([#6352](https://github.com/operator-framework/operator-sdk/pull/6352))\n\n### Bug Fixes\n\n- For ansible operators: fix a JSON parsing bug by updating the kubernetes.core collection to v2.4.0. ([#6334](https://github.com/operator-framework/operator-sdk/pull/6334))\n- (scorecard): update default storage and untar images to images that run as non-root users by default. This ensures full compliance with restricted PSA guidelines when using `--pod-security=restricted`. ([#6335](https://github.com/operator-framework/operator-sdk/pull/6335))\n"
  },
  {
    "path": "changelog/generated/v1.29.0.md",
    "content": "## v1.29.0\n\n### Changes\n\n- (scorecard): Update kuttl to v0.15.0 in the scorecard-test-kuttl image. ([#6401](https://github.com/operator-framework/operator-sdk/pull/6401))\n- (ansible/v1): Bump the golang base image version in the ansible-operator Dockerfiles from 1.18 to 1.19. ([#6398](https://github.com/operator-framework/operator-sdk/pull/6398))\n- (operator-sdk run bundle): Compress the bundle content, to avoid the configMap exceed max length error. The error will look like this: \n`... ConfigMap ... is invalid: []: Too long: must have at most 1048576 bytes`.\nFixes issue [#6323](https://github.com/operator-framework/operator-sdk/issues/6323). ([#6408](https://github.com/operator-framework/operator-sdk/pull/6408))\n\n### Bug Fixes\n\n- (docs): Update the go version in the developer guide.  The documentation wasn't updated when the go version was bumped to v1.19. ([#6101](https://github.com/operator-framework/operator-sdk/pull/6101))\n"
  },
  {
    "path": "changelog/generated/v1.3.0.md",
    "content": "## v1.3.0\n\n### Additions\n\n- Added OLM bindata for the 0.17.0 release version. ([#4242](https://github.com/operator-framework/operator-sdk/pull/4242))\n- Added [`order=<int>`](https://sdk.operatorframework.io/docs/building-operators/golang/references/markers/#usage) marker fields to CSV markers. ([#4254](https://github.com/operator-framework/operator-sdk/pull/4254))\n- In Ansible-based operators, added the `ansible_operator_build_info` metric to instrument commit and version information. ([#4220](https://github.com/operator-framework/operator-sdk/pull/4220))\n- In Helm-based operators, added the `helm_operator_build_info` metric to instrument commit and version information. ([#4220](https://github.com/operator-framework/operator-sdk/pull/4220))\n- Added the `--package <name>` flag to all `generate` subcommands. This flag is required by `generate <bundle|packagemanifests>` when run outside of a project. ([#4074](https://github.com/operator-framework/operator-sdk/pull/4074))\n- Added the `run bundle-upgrade` subcommand to automate testing upgrades of an operator from one version to another using OLM. ([#4271](https://github.com/operator-framework/operator-sdk/pull/4271))\n- (go/v2) Added the command `òperator-sdk edit` which allows users edit the project layout to support [multi-group](https://book.kubebuilder.io/migration/multi-group.html). ([#4156](https://github.com/operator-framework/operator-sdk/pull/4156))\n\n### Changes\n\n- (go/v2) Bumped controller-runtime from v0.6.3 to v0.6.4. ([#4282](https://github.com/operator-framework/operator-sdk/pull/4282))\n- Go CLI plugin go/v3 is now the default. ([#4307](https://github.com/operator-framework/operator-sdk/pull/4307))\n- Bumped `operator-sdk` binary dependencies to their k8s v1.19 equivalents. ([#4294](https://github.com/operator-framework/operator-sdk/pull/4294))\n- Updated helm-operator's Helm dependency to v3.4.1. ([#4259](https://github.com/operator-framework/operator-sdk/pull/4259))\n\n### Bug Fixes\n\n- Made the `cleanup` command's error handling more robust on deletion and \"not found\" events. ([#4303](https://github.com/operator-framework/operator-sdk/pull/4303))\n- Fixed the documented `packagemanifests` make recipe. ([#4303](https://github.com/operator-framework/operator-sdk/pull/4303))\n- `generate kustomize manifests` will now (re)generate a base `ClusterServiceVersion` manifest with a valid name. ([#4276](https://github.com/operator-framework/operator-sdk/pull/4276))\n- (ansible/v1) Pinned all top level Python requirements. This fixes a bug that erroneously installed Ansible 2.10.z instead of Ansible 2.9.z. ([#4321](https://github.com/operator-framework/operator-sdk/pull/4321))\n- Refactored the `generate bundle|packagemanifest` commands to generate bundles/package manifest data outside of projects. ([#4074](https://github.com/operator-framework/operator-sdk/pull/4074))\n- (go/v2) Removed unused import for defaulting webhooks scaffolded by `create webhook` ([kubebuilder#1718](https://github.com/kubernetes-sigs/kubebuilder/pull/1718)). ([#4156](https://github.com/operator-framework/operator-sdk/pull/4156))\n- (go/v2) Allow owner to not be specified in generated licenses ([kubebuilder#1749](https://github.com/kubernetes-sigs/kubebuilder/pull/1749)). ([#4156](https://github.com/operator-framework/operator-sdk/pull/4156))\n- (go/v2) Fixed controller imports scaffolded by `create api` when `--resource=false` ([kubebuilder#1770](https://github.com/kubernetes-sigs/kubebuilder/pull/1770)). ([#4215](https://github.com/operator-framework/operator-sdk/pull/4215))\n"
  },
  {
    "path": "changelog/generated/v1.30.0.md",
    "content": "## v1.30.0\n\n### Additions\n\n- Add a Parameter to the Makefile to allow modifying the 'operator-sdk' binary before running any commands. If necessary, a specific version of the SDK can be downloaded for cases when the project has yet to upgrade to a later or latest version. ([#6443](https://github.com/operator-framework/operator-sdk/pull/6443))\n- Currently, the operator SDK for the Ansible operator lacks options to customize the leader election resource lock behavior. This limits the flexibility of the operator and prevents users from adjusting lease duration and renew deadline according to their specific needs.\nChanges: Implemented enhancements to the operator SDK to include additional flags for configuring leader election resource lock options. These changes provide users with the ability to specify the type of resource object used for locking during leader election and customize the lease duration and renew deadline.\nIntroduced --leader-elect-lease-duration flag to allow users to define the duration that non-leader candidates will wait to force acquire leadership. The default duration is set to 15 seconds.\nIntroduced --leader-elect-renew-deadline flag, enabling users to set the renew deadline, which determines the duration that the acting control plane will retry refreshing leadership before giving up. The default duration is set to 10 seconds.\nIntroduced --leader-elect-resource-lock flag to allow users to define the type of resource object that is used for locking during leader election. Supported options are 'leases', 'endpointsleases', and 'configmapsleases'. The default option is 'leases'.\nThese changes provide more flexibility and control over leader election behavior, allowing operators to adapt to various deployment scenarios and specific requirements. ([#6426](https://github.com/operator-framework/operator-sdk/pull/6426))\n\n### Changes\n\n- Currently, when setting `overrideValues` in your `watches.yaml`, every entry is logged with its key and its value. When working with confidential information such as credentials, logging those information would not be optimal nor desirable. Therefore, there should be a way to silence/suppress these values.\nThis feature introduces the `--suppress-override-values` boolean-flag for the `helm-operator`. When set to true, the value of the overrideValues entry is sanitized with this value \"****\".\nThis is a simple example of `overrideValues` of the `watches.yaml` ```yaml overrideValues:\n  x: y\n```\nThe default-value of `--suppress-override-values` is `false` so therefore we would get this warning logged: `Chart value x overridden to y by operator's watches.yaml`\nWhen setting `--suppress-override-values` `true` the warning will be logged in the following manner: `Chart value x overridden to **** by operator's watches.yaml`. ([#6469](https://github.com/operator-framework/operator-sdk/pull/6469))\n- (images): Bumps all Operator SDK maintained images to now use ubi(-minimal) tag 8.8. ([#6466](https://github.com/operator-framework/operator-sdk/pull/6466))\n\n### Bug Fixes\n\n- In `run bundle-upgrade`, hash the cache directory name to avoid error of too long file name. ([#6477](https://github.com/operator-framework/operator-sdk/pull/6477))\n"
  },
  {
    "path": "changelog/generated/v1.31.0.md",
    "content": "## v1.31.0\n\n### Changes\n\n- (ansible): Update the `quay.io/operator-framework/ansible-operator` base image to now use Ansible 2.15.0.  Removes pre-installed Python modules that are not required to build and run the `testdata/ansible/memcached-operator` sample. Updates Python to 3.9 to work with Ansible 2.15.0. ([#6483](https://github.com/operator-framework/operator-sdk/pull/6483))\n- (ansible/v1): Updates the `ansible/v1` plugin scaffolding to: - Remove the `community.kubernetes` collection - Update the `operator_sdk.util` collection from `v0.4.0` --> `v0.5.0` - Update the `molecule.yaml` files to work with `molecule v5.1.0`. ([#6483](https://github.com/operator-framework/operator-sdk/pull/6483))\n- (helm): Use informer to list helm secrets to improve performance. ([#6354](https://github.com/operator-framework/operator-sdk/pull/6354))\n- Updated Reference from \"to_be_owned.namespace\" to \"to_be_owned.metadata.namespace \" in the ansible reference documentation. ([#6409](https://github.com/operator-framework/operator-sdk/pull/6409))\n\n### Removals\n\n- (ansible): Remove the `quay.io/operator-framework/ansible-operator-2.11-preview` image. This image will no longer be built after Operator-SDK v1.30.0. ([#6483](https://github.com/operator-framework/operator-sdk/pull/6483))\n\n### Bug Fixes\n\n- Fix a bug where `olm install` command is failed for \"no-match\" error.\nThe output in this case is something like:\n```$ operator-sdk olm install --verbose ... FATA[0001] Failed to install OLM version \"latest\": failed to create CRDs and resources: no matches for kind \"OLMConfig\" in version \"operators.coreos.com/v1\"```. Now, in this case, operator-sdk tries to create the resource again, until it succeeds (or until the timeout exceeded). ([#6490](https://github.com/operator-framework/operator-sdk/pull/6490))\n- Fix a bug where `run bundle` command does not copy all FBC manifests into the new catalog image if custom index-image is passed. ([#6512](https://github.com/operator-framework/operator-sdk/pull/6512))\n- `markUnsafe` now correctly marks as unsafe the all variables passed in `spec`. ([#6376](https://github.com/operator-framework/operator-sdk/pull/6376))\n"
  },
  {
    "path": "changelog/generated/v1.32.0.md",
    "content": "## v1.32.0\n\n### Additions\n\n- For Helm-based operators, whenever the operator encounters an  error during reconcilliation, it would attempt to rollback the changes with the `--force` option. This behavior could have  undesired side effects in some scenario.\nThis change allows the users to change this behavior by adding the  annotation, `helm.sdk.operatorframework.io/rollback-force: false`\n to the custom resource. ([#6546](https://github.com/operator-framework/operator-sdk/pull/6546))\n\n### Bug Fixes\n\n- (helm): Use informer cache label selectors to reduce memory consumption. ([#6377](https://github.com/operator-framework/operator-sdk/pull/6377))\n- (helm): Fix bug with detection of owner reference support when setting up dynamic watches. ([#6377](https://github.com/operator-framework/operator-sdk/pull/6377))\n"
  },
  {
    "path": "changelog/generated/v1.33.0.md",
    "content": "## v1.33.0\n\n### Changes\n\n- Bump supported Kubernetes version to 1.27. ([#6613](https://github.com/operator-framework/operator-sdk/pull/6613))\n- **Breaking change**: (go/v4-alpha): go/v4 is now stable and is the default version used when scaffolding a Go based operator. ([#6613](https://github.com/operator-framework/operator-sdk/pull/6613))\n- **Breaking change**: (kustomize/v2-alpha): kustomize/v2 is now stable and is the default version used in the plugin chain when using go/v4, ansible/v1, helm/v1, and hybrid/v1-alpha plugins. ([#6613](https://github.com/operator-framework/operator-sdk/pull/6613))\n- Updated the supported OLM versions to 0.24.0, 0.25.0, and 0.26.0. ([#6613](https://github.com/operator-framework/operator-sdk/pull/6613))\n\n### Deprecations\n\n- (helm/v1): Deprecate the `--config` flag due to the controller-runtime ComponentConfig package being deprecated with the planned removal of support for loading manager options from a file. ([#6613](https://github.com/operator-framework/operator-sdk/pull/6613))\n\n### Bug Fixes\n\n- `operator-sdk olm install`: fix a bug where the retry logic would not retry until the command's timeout was reached, resulting in early exiting of the command before the specified timeout was reached. ([#6613](https://github.com/operator-framework/operator-sdk/pull/6613))\n"
  },
  {
    "path": "changelog/generated/v1.34.0.md",
    "content": "## v1.34.0\n\n### Bug Fixes\n\n- (helm/v1) Fix an issue that multi-arch images cannot be built from the project Makefile. ([#6661](https://github.com/operator-framework/operator-sdk/pull/6661))\n"
  },
  {
    "path": "changelog/generated/v1.35.0.md",
    "content": "## v1.35.0\n\n### Changes\n\n- For Ansible-based operators, upgrade the version of the Ansible Operator Plugin used in operator-sdk to v1.34.2. ([#6749](https://github.com/operator-framework/operator-sdk/pull/6749))\n\n### Bug Fixes\n\n- (helm/v1) Fix broken helm-operator role scaffolding which causes reconciler to hang due to lack of permissions. ([#6769](https://github.com/operator-framework/operator-sdk/pull/6769))\n"
  },
  {
    "path": "changelog/generated/v1.36.0.md",
    "content": "## v1.36.0\n\n### Changes\n\n- - Upgrade Kubernetes dependencies from `1.28` to `1.29`. ([#6736](https://github.com/operator-framework/operator-sdk/pull/6736))\n"
  },
  {
    "path": "changelog/generated/v1.37.0.md",
    "content": "## v1.37.0\n\n### Removals\n\n- **Breaking change**: Remove the Quarkus plugin (java-operator-plugins integration). ([#6824](https://github.com/operator-framework/operator-sdk/pull/6824))\n- **Breaking change**: (hybrid.helm/v1-alpha) Remove hybrid-helm v1-alpha support, due to low adoption, in favor of maintenance simplicity. ([#6833](https://github.com/operator-framework/operator-sdk/pull/6833))\n"
  },
  {
    "path": "changelog/generated/v1.38.0.md",
    "content": "## v1.38.0\n\n### Changes\n\n- For Go-based, Helm-based and Ansible-based operators this release moves to Kubernetes 1.30 API's and Kubebuilder v4 Scaffolding, specifically utilizing the v4.1.1 version. The update to Kubebuiler results in some scaffolding changes which more information can be found below: - Discontinue usage of [kube-rbac-proxy](https://github.com/brancz/kube-rbac-proxy) in the default scaffolding of new projects. For further information, see: [Action Required: Ensure that you no longer use gcr.io/kubebuilder images](https://github.com/kubernetes-sigs/kubebuilder/discussions/3907) - The `go/v2` or `go/v3` layouts have been removed, you must upgrade to `go/v4` to be compatible with this release and future updates. To know how to upgrade,check the [migration documentation](https://book.kubebuilder.io/migration/v3vsv4). - Re-introduces authn/authz protection for the metrics endpoint using [`WithAuthenticationAndAuthorization`](https://github.com/kubernetes-sigs/controller-runtime/blob/v0.18.4/pkg/metrics/filters/filters.go#L35)  provided by controller-runtime instead of kube-rbac-proxy; which usage was [discontinued in the project](https://github.com/kubernetes-sigs/kubebuilder/discussions/3907).  Please, ensure that you no longer use the image `gcr.io/kubebuilder/kube-rbac-proxy`. Images provided under `gcr.io/kubebuilder/` will be unavailable from **March 18, 2025**. To learn more about any of the metrics changes please look at the Kubebuilder book [metrics](https://book.kubebuilder.io/reference/metrics) page.\nFor `Helm-based` and `Ansible-based` operators, a new flag called `metrics-require-rbac` was introduced into the runtime/binary, to control adding  [`WithAuthenticationAndAuthorization`](https://github.com/kubernetes-sigs/controller-runtime/blob/v0.18.4/pkg/metrics/filters/filters.go#L35) to `Metrics.FilterProvider` of controller-runtime. This was done to ensure forwards and backwards compatibility of the binary and images with any scaffolded content. ([#6862](https://github.com/operator-framework/operator-sdk/pull/6862))\n\n### Bug Fixes\n\n- An additional condition is included for matching `apiVersion` of example CRs with CRD `version` when searching for the CRD in the CSV.  Previously, The `olm-spec-descriptors` scorecard test failed when multiple versions of CRD is included in the CSV.  The CR specified in `alm-examples` annotations are validated only against the first matched CRD (by name), which is incorrect.  This ensures the correct CRD version is selected for validations. ([#6784](https://github.com/operator-framework/operator-sdk/pull/6784))\n- Fix naive YAML split in `run bundle` command. ([#6829](https://github.com/operator-framework/operator-sdk/pull/6829))\n"
  },
  {
    "path": "changelog/generated/v1.39.0.md",
    "content": "## v1.39.0\n\n### Changes\n\n- For Go-based, Helm-based and Ansible-based operators this release moves to Kubernetes 1.31 API's and Kubebuilder v4 Scaffolding, specifically utilizing the v4.2.0 version. The update to Kubebuiler results in some scaffolding changes which more information can be found below: - Add support to protect project with [network policies](https://kubernetes.io/docs/concepts/services-networking/network-policies/) ([#3853](https://github.com/kubernetes-sigs/kubebuilder/pull/3853)). ([#6878](https://github.com/operator-framework/operator-sdk/pull/6878))\n"
  },
  {
    "path": "changelog/generated/v1.39.1.md",
    "content": "## v1.39.1\n\nNo changes for this release!\n"
  },
  {
    "path": "changelog/generated/v1.39.2.md",
    "content": "## v1.39.2\n\nNo changes for this release!\n"
  },
  {
    "path": "changelog/generated/v1.4.0.md",
    "content": "## v1.4.0\n\n### Additions\n\n- For Helm-based operators, added Liveness and Readiness probe by default using [`healthz.Ping`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/healthz#CheckHandler). ([#4326](https://github.com/operator-framework/operator-sdk/pull/4326))\n- For Ansible-based operators, added Liveness and Readiness probe by default using [`healthz.Ping`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/healthz#CheckHandler). ([#4326](https://github.com/operator-framework/operator-sdk/pull/4326))\n- For Ansible/Helm-based operators, added new flag `--health-probe-bind-address` to set the health probe address. ([#4326](https://github.com/operator-framework/operator-sdk/pull/4326))\n- (ansible/v1, helm/v1) Added plugin objects for the `manifests` and `scorecard` phase 2 plugins. ([#4419](https://github.com/operator-framework/operator-sdk/pull/4419))\n- For Ansible-based and Helm-based operators, as well as for the Operator SDK and the (custom) scorecard tests, the Docker base images are pinned to improve the reproducibility of builds using Docker. ([#4417](https://github.com/operator-framework/operator-sdk/pull/4417))\n\n### Changes\n\n- Changed the suggested finalizer format to `<qualified-group>/<finalizer-name>`. ([#4472](https://github.com/operator-framework/operator-sdk/pull/4472))\n- Upgraded the `kudobuilder/kuttl` base image version in the `scorecard-test-kuttl` image to v0.8.0. ([#4391](https://github.com/operator-framework/operator-sdk/pull/4391))\n- (go/v2) Changed `go` PROJECT plugin object to `manifests` and `scorecard` objects (`.sdk.operatorframework.io` suffix). ([#4419](https://github.com/operator-framework/operator-sdk/pull/4419))\n- (ansible/v1, helm/v1) Post-fixed positional directory argument `.` in `docker-build` make target to align with `podman`. ([#4466](https://github.com/operator-framework/operator-sdk/pull/4466))\n- For Ansible-based operators, the Python version has been updated to a newer version, from 3.6 to 3.8 to take advantage of performance improvements, language additions, security updates and generally better availability for local development. ([#4413](https://github.com/operator-framework/operator-sdk/pull/4413))\n\n### Deprecations\n\n- For Ansible-based operators, the `/ping` endpoint is deprecated. Use `/healthz` instead. ([#4326](https://github.com/operator-framework/operator-sdk/pull/4326))\n\n### Bug Fixes\n\n- Project version now determines how package name is retrieved for a project. ([#4431](https://github.com/operator-framework/operator-sdk/pull/4431))\n- `run bundle-upgrade` now handles error gracefully when a previous operator version doesn't exist. ([#4451](https://github.com/operator-framework/operator-sdk/pull/4451))\n- `run bundle` and `run bundle-upgrade` now validate the value passed to the hidden flag `--mode` before running a bundle. ([#4462](https://github.com/operator-framework/operator-sdk/pull/4462))\n- For Go-based projects, `generate <bundle|packagemanifests>` subcommands now consider package and type names when parsing Go API types files to generate a CSV's `owned.customresourcedefinitions`, such that types in different packages and files will not overwrite each other. ([#4445](https://github.com/operator-framework/operator-sdk/pull/4445))\n- Bumped operator-framework/api to prevent `operator-sdk bundle validate` from exiting non-0 when validation emits only warnings. ([#4458](https://github.com/operator-framework/operator-sdk/pull/4458))\n- Fixed panic when \"operator-sdk bundle validate\" fails. ([#4386](https://github.com/operator-framework/operator-sdk/pull/4386))\n- Update containerd dependency to correctly handle running the Operator SDK CLI on Apple Silicon. ([#4359](https://github.com/operator-framework/operator-sdk/pull/4359))\n- Fixed invalid object names generated for long package names passed to `run packagemanifests` & `run bundle`. ([#4471](https://github.com/operator-framework/operator-sdk/pull/4471))\n- Corrected the download URL for helm-operator and ansible-operator in their respective project types. ([#4407](https://github.com/operator-framework/operator-sdk/pull/4407))\n- Fixed the order of helm-operator, ansible-operator, and kustomize binary checks in the Makefile. ([#4407](https://github.com/operator-framework/operator-sdk/pull/4407))\n- Fixed a bug that caused the Helm operator to remove the finalizer without doing a helm uninstall. ([#3431](https://github.com/operator-framework/operator-sdk/pull/3431))\n- For Helm-based operators, do not add owner references to resources that contain the Helm annotation: 'helm.sh/resource-policy: keep'. ([#4389](https://github.com/operator-framework/operator-sdk/pull/4389))\n"
  },
  {
    "path": "changelog/generated/v1.40.0.md",
    "content": "## v1.40.0\n\n### Additions\n\n- (go/v4) For Go-based operators, a devcontainer is now available to allow users to develop and test the operator in a local environment and leverage on solutions such as VS Code Remote Containers and GitHub Codespaces to have a consistent development environment. ([#6928](https://github.com/operator-framework/operator-sdk/pull/6928))\n- (go/v4) For Go-based operators, new GitHub Actions are available to ensure better quality of their code. ([#6928](https://github.com/operator-framework/operator-sdk/pull/6928))\n- (go/v4) For Go-based operators, controllers now use `.Named(\"<Kind>\")` in  `SetupWithManager` to prevent naming conflicts in multi-group projects. ([More info](https://github.com/kubernetes-sigs/kubebuilder/pull/4162)). ([#6928](https://github.com/operator-framework/operator-sdk/pull/6928))\n- (go/v4) For Go-based operators, a new Makefile target named `lint-config` has been added to verify that your `.golangci.yaml` configuration file is valid. This helps catch issues early when customizing lint rules.\n([More info](https://github.com/kubernetes-sigs/kubebuilder/pull/4462)). ([#6928](https://github.com/operator-framework/operator-sdk/pull/6928))\n- For ALL-based operators, scaffolded resources now include the `app.kubernetes.io/name` label to support Kubernetes best practices for app identification. ([More info](https://github.com/kubernetes-sigs/kubebuilder/pull/4437/files)). ([#6928](https://github.com/operator-framework/operator-sdk/pull/6928))\n- For ALL-based operators, new role manifests are now scaffolded under the `config/rbac/` directory to assist cluster administrators. For each API defined in the project, three role files are generated: `<kind>_admin_role.yaml`, `<kind>_editor_role.yaml`, and `<kind>_viewer_role.yaml`.\nThese roles are not applied by default. Instead, they are provided as helpers, allowing cluster administrators to customize and apply appropriate permissions as needed.\nThe primary motivation for scaffolding these roles is to simplify integration with Kubernetes' aggregated roles mechanism. By including annotations such as `rbac.authorization.k8s.io/aggregate-to-admin: \"true\"`, `rbac.authorization.k8s.io/aggregate-to-edit: \"true\"`, and `rbac.authorization.k8s.io/aggregate-to-view: \"true\"`, these role definitions can automatically contribute permissions to the default admin, edit, and view roles in a cluster when applied.\nFor more information on Kubernetes RBAC and aggregated roles, see: https://kubernetes.io/docs/reference/access-authn-authz/rbac/. ([#6928](https://github.com/operator-framework/operator-sdk/pull/6928))\n- For ALL-based operators, new role manifests are now scaffolded under the `config/rbac/` directory to assist cluster administrators. For each API defined in the project, three role files are generated: `<kind>_admin_role.yaml`, `<kind>_editor_role.yaml`, and `<kind>_viewer_role.yaml`.\nThese roles are not applied by default. Instead, they are provided as helpers, allowing cluster administrators to customize and apply appropriate permissions as needed.\nThe primary motivation for scaffolding these roles is to simplify integration with Kubernetes' aggregated roles mechanism. By including annotations such as `rbac.authorization.k8s.io/aggregate-to-admin: \"true\"`, `rbac.authorization.k8s.io/aggregate-to-edit: \"true\"`, and `rbac.authorization.k8s.io/aggregate-to-view: \"true\"`, these role definitions can automatically contribute permissions to the default admin, edit, and view roles in a cluster when applied.\nFor more information on Kubernetes RBAC and aggregated roles, see: https://kubernetes.io/docs/reference/access-authn-authz/rbac/. ([#6928](https://github.com/operator-framework/operator-sdk/pull/6928))\n\n### Changes\n\n- The bundle build target now respects the CONTAINER_TOOL variable, allowing users to use alternative container tools like podman instead of docker. ([#6932](https://github.com/operator-framework/operator-sdk/pull/6932))\n- For All-based Operators, upgrade OPM to version from `v1.23.0` to `v1.55.0`, which includes several bug fixes and  improvements. For further information, see: https://github.com/operator-framework/operator-registry/releases. ([#6953](https://github.com/operator-framework/operator-sdk/pull/6953))\n- (go/v4) For Go-based Operators, the `main.go` file has been enhanced to support real TLS certificates for both webhooks and the metrics server, with automated certificate rotation via cert-manager. This change improves security and aligns with production-grade best practices.\nPreviously, setups relied on kube-rbac-proxy (deprecated in Operator SDK and Kubebuilder, see: [kubebuilder/discussions/3907](https://github.com/kubernetes-sigs/kubebuilder/discussions/3907)), which generated TLS certificates dynamically — a method no longer recommended for secure environments. The updated approach adopts static certificates managed by cert-manager.\nAdditionally, integrations with Prometheus now support scraping metrics using the cert-manager generated certificates. A related fix was introduced to ensure that CA injection patches are only applied to CRDs with a conversion webhook, avoiding unnecessary annotations.\nTo support these improvements, changes to `config/default/kustomization.yaml` are required. These include: configuring webhook and metrics server certificates, enabling Prometheus scraping with TLS, and correcting CA injection behavior.\nThese updates also introduce flexible opt-in mechanisms, allowing users to selectively enable or disable: - TLS for the metrics server via cert-manager - TLS for webhooks via cert-manager - TLS configuration for Prometheus scraping\nTogether, these changes are part of a broader effort to elevate the default security posture and configurability of Go-based operators. ([#6928](https://github.com/operator-framework/operator-sdk/pull/6928))\n- (go/v4) For Go-based operators, a fix has been implemented to ensure that the Prometheus configuration can properly scrape metrics from the operator's metrics server when TLS is enabled. ([#6928](https://github.com/operator-framework/operator-sdk/pull/6928))\n- (go/v4) For Go-based operators, a fix has been implemented to ensure that CA injection patches are applied only to CRDs that define a conversion webhook.\nPreviously, the CA injection patch logic was overly broad — applying injection annotations to all CRDs whenever a webhook was scaffolded with the `--conversion` flag. This behavior was introduced in Kubebuilder release `v3.5.0` when replacements were introduced in place of legacy vars and the `kustomize/v2-alpha` plugin was adopted.\nThe incorrect behavior likely went unnoticed due to incomplete support for conversion webhooks in earlier versions. This release addresses that gap, enabling proper scaffolding and CA injection behavior specifically for CRDs with conversion webhooks.\nTo support this improvement, a new marker has been introduced: `+kubebuilder:scaffold:crdkustomizecainjectionns`. This marker ensures that the correct replacements are generated in `config/default/kustomization.yaml` for CA injection. Additionally, the `kubebuilder:scaffold:crdkustomizewebhookpatch` marker was created to ensure that the webhook patch is only applied to CRDs that have a conversion webhook in the `config/crd/kustomization.yaml` file.\nFor more information on this and other scaffolding markers, refer to the official Kubebuilder documentation: https://book.kubebuilder.io/reference/markers/scaffold. ([#6928](https://github.com/operator-framework/operator-sdk/pull/6928))\n- (go/v4) For Go-based operators, ENVTEST version management is now automated by  deriving values from `go.mod`, and controller tests now locate binaries dynamically.  ([More info](https://github.com/kubernetes-sigs/kubebuilder/pull/4401))\nThese updates improve the developer experience by: - Reducing manual configuration for ENVTEST. - Ensuring IDEs or test runners can locate the binaries reliably. - Making controller test scaffolding more robust and portable. ([#6928](https://github.com/operator-framework/operator-sdk/pull/6928))\n- (go/v4) For Go-based operators, updated GolangCI-Lint configuration to replace  the deprecated `exportloopref` linter with the `copyloopvar` linter. ([#6928](https://github.com/operator-framework/operator-sdk/pull/6928))\n- (go/v4) For Go-based operators, upgraded project scaffolding to Go 1.23,  Kubernetes v0.32.1, and controller-runtime v0.20.4.\nThe default project scaffolding for Go-based operators has been updated to use:\n  - **Go 1.23**\n  - **Kubernetes modules v0.32.1**\n  - **controller-runtime v0.20.4**\n  - **Ginkgo v2.22.0** and **Gomega v1.36.1**. ([#6928](https://github.com/operator-framework/operator-sdk/pull/6928))\n- **Breaking change**: (go/v4) For Go-based operators, upgraded controller-runtime from `v0.19.4` to `v0.20.0` and added support for Kubernetes 1.32.  Removed deprecated `webhook.Validator` and `webhook.Defaulter` interfaces from the runtime. Webhooks should no longer reside under the `api/` directory—this has been the default behavior since Kubebuilder rlease [v4.3.0)(https://github.com/kubernetes-sigs/kubebuilder/releases/tag/v4.3.0). \nA `--legacy=true` flag was added to support scaffolding webhooks in the old layout when needed. ([More info](https://github.com/kubernetes-sigs/kubebuilder/pull/4492) ·  [Migration guide](https://github.com/kubernetes-sigs/kubebuilder/releases/tag/v4.3.0)). ([#6928](https://github.com/operator-framework/operator-sdk/pull/6928))\n"
  },
  {
    "path": "changelog/generated/v1.41.0.md",
    "content": "## v1.41.0\n\n### Additions\n\n- For Go-based operators, add new target to setup/teardown Kind cluster for E2E tests  and remove Kind setup from CI workflows. ([#6954](https://github.com/operator-framework/operator-sdk/pull/6954))\n\n### Changes\n\n- **Breaking change**: For Go-based operators, upgrade the Go version from `1.23` to `1.24`. ([#6954](https://github.com/operator-framework/operator-sdk/pull/6954))\n- For Go-based operators, upgrade golangci-lint to `v2.1.0` and update `.golangci.yml`  to the v2 config format with enhanced structure and controls. ([#6954](https://github.com/operator-framework/operator-sdk/pull/6954))\n- For Go-based operators, upgrade controller-gen from `v0.17.2` to `v0.18.0`. ([#6954](https://github.com/operator-framework/operator-sdk/pull/6954))\n- For Go-based operators, upgrade controller-runtime from `v0.20.4` to `v0.21.0`  and kubernetes dependencies to `v0.33`. ([#6954](https://github.com/operator-framework/operator-sdk/pull/6954))\n"
  },
  {
    "path": "changelog/generated/v1.42.0.md",
    "content": "## v1.42.0\n\nNo changes for this release!\n"
  },
  {
    "path": "changelog/generated/v1.42.1.md",
    "content": "## v1.42.1\n\nNo changes for this release!\n"
  },
  {
    "path": "changelog/generated/v1.42.2.md",
    "content": "## v1.42.2\n\nNo changes for this release!\n"
  },
  {
    "path": "changelog/generated/v1.5.0.md",
    "content": "## v1.5.0\n\n### Additions\n\n- Added support for markers for files with the `yml` extension. More info: [kubernetes-sigs/kubebuilder#1907](https://github.com/kubernetes-sigs/kubebuilder/pull/1907). ([#4402](https://github.com/operator-framework/operator-sdk/pull/4402))\n- (go/v3) Added the `--force` option to the `create webhook` command. More info: [kubernetes-sigs/kubebuilder#1903](https://github.com/kubernetes-sigs/kubebuilder/pull/1903). ([#4402](https://github.com/operator-framework/operator-sdk/pull/4402))\n- (go/v3) Added `ErrorIfCRDPathMissing` config by default to controller's `suite_tests.go`. More info: [kubernetes-sigs/kubebuilder#1910](https://github.com/kubernetes-sigs/kubebuilder/pull/1910). ([#4402](https://github.com/operator-framework/operator-sdk/pull/4402))\n- For Ansible-based operators, allow passing a `--graceful-shutdown-timeout` to configure the duration the manager should wait before stopping. ([#4571](https://github.com/operator-framework/operator-sdk/pull/4571))\n- (go/v3) Create and bind to a non-default service account ([kubernetes-sigs/kubebuilder#2070](https://github.com/kubernetes-sigs/kubebuilder/pull/2070)). ([#4626](https://github.com/operator-framework/operator-sdk/pull/4626))\n\n### Changes\n\n- (go/v3) Upgraded the `sigs.k8s.io/kubebuilder-declarative-pattern` dependency used by `create api --pattern=addon`. More info: [kubernetes-sigs/kubebuilder#1946](https://github.com/kubernetes-sigs/kubebuilder/pull/1946). ([#4402](https://github.com/operator-framework/operator-sdk/pull/4402))\n- (go/v2, go/v3) Added Makefile help. ([#4402](https://github.com/operator-framework/operator-sdk/pull/4402))\n- (go/v3) Changed the manager pod template's security context `runAsUser: 65532` to `runAsNonRoot: true`. More info: [kubernetes-sigs/kubebuilder#1978](https://github.com/kubernetes-sigs/kubebuilder/pull/1978). ([#4402](https://github.com/operator-framework/operator-sdk/pull/4402))\n- **Breaking change**: PROJECT config version 3-alpha has been upgraded to version 3. ([#4613](https://github.com/operator-framework/operator-sdk/pull/4613))\n- Improved `generate bundle` and `generate packagemanifests` handling and help text for use outside of a project. ([#4514](https://github.com/operator-framework/operator-sdk/pull/4514))\n- (go/v3) Pinned controller-runtime to v0.7.2. ([#4626](https://github.com/operator-framework/operator-sdk/pull/4626))\n- For Ansible-based operators, change the level of the proxy skipping cache logs to debug level. ([#4511](https://github.com/operator-framework/operator-sdk/pull/4511))\n\n### Bug Fixes\n\n- For Go-based operators, fixed `create api --force` such that it actually overwrites all files. More info: [kubernetes-sigs/kubebuilder#1903](https://github.com/kubernetes-sigs/kubebuilder/pull/1903). ([#4402](https://github.com/operator-framework/operator-sdk/pull/4402))\n- Upgraded the `gcr.io/kubebuilder/kube-rbac-proxy` image version from `0.5.0` to `0.8.0` to support rootless run mode. More info [kubernetes-sigs/kubebuilder#1955](https://github.com/kubernetes-sigs/kubebuilder/pull/1955). ([#4402](https://github.com/operator-framework/operator-sdk/pull/4402))\n- (go/v3) Correctly named health/readiness endpoints as `healthz` and `readyz`, respectively. More info [kubernetes-sigs/kubebuilder#1910](https://github.com/kubernetes-sigs/kubebuilder/pull/1910). ([#4402](https://github.com/operator-framework/operator-sdk/pull/4402))\n- (go/v3) Tolerate `.` directories when checking if dir is empty in `init`. More info: [kubernetes-sigs/kubebuilder#1944](https://github.com/kubernetes-sigs/kubebuilder/pull/1944). ([#4402](https://github.com/operator-framework/operator-sdk/pull/4402))\n- Properly consider all Go files when generating a CSV's `spec.customresourcedefinitions.owned`. ([#4507](https://github.com/operator-framework/operator-sdk/pull/4507))\n- Fixed samples kustomization.yaml generation on `operator-sdk init --plugins=helm --helm-chart=<chart>`, caused by out-of-order operations in plugin code. ([#4584](https://github.com/operator-framework/operator-sdk/pull/4584))\n- Skip CSV definitions parsing in `generate kustomize manifests` if the APIs dir does not exist, as projects may use only required APIs. ([#4624](https://github.com/operator-framework/operator-sdk/pull/4624))\n- Bump cryptography dependency in ansible-operator to `3.3.2`. This will fix a potential security bug related to update() calls. Ref: https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst#332---2021-02-07. ([#4539](https://github.com/operator-framework/operator-sdk/pull/4539))\n- Fixed ambiguous `--input-dir` and `--deploy-dir` flag semantics for `generate bundle`. ([#4514](https://github.com/operator-framework/operator-sdk/pull/4514))\n- (ansible/v1, helm/v1) Upgraded the `gcr.io/kubebuilder/kube-rbac-proxy` image version from `0.5.0` to `0.8.0` to support rootless run mode. ([#4498](https://github.com/operator-framework/operator-sdk/pull/4498))\n- For Ansible/Helm-based operators, fix swapped readinessProbe/livenessProbe in manager. ([#4546](https://github.com/operator-framework/operator-sdk/pull/4546))\n"
  },
  {
    "path": "changelog/generated/v1.6.0.md",
    "content": "## v1.6.0\n\n### Additions\n\n- For Golang-based operators, added the `declarative.go/v1` plugin which customizes initialized projects with patterns from [kubernetes-sigs/kubebuilder-declarative-pattern](https://github.com/kubernetes-sigs/kubebuilder-declarative-pattern). (e.g `operator-sdk create api --plugins=go/v3,declarative`). ([#4731](https://github.com/operator-framework/operator-sdk/pull/4731))\n- Added `kustomize.common/v1` plugin which scaffolds the a commonly used project base that leverages `kustomize`. ([#4730](https://github.com/operator-framework/operator-sdk/pull/4730))\n- (ansible/v1, helm/v1) Added the option to configure `ansible-operator` and `helm-operator` with a [component config](https://master.book.kubebuilder.io/component-config-tutorial/tutorial.html). ([#4701](https://github.com/operator-framework/operator-sdk/pull/4701))\n- (ansible/v1, helm/v1) Add rules for leader election. ([#4701](https://github.com/operator-framework/operator-sdk/pull/4701))\n- Added [`alpha config-gen`](https://github.com/kubernetes-sigs/kubebuilder/tree/master/pkg/cli/alpha/config-gen), a kustomize plugin to specialize configuration for kubebuilder-style projects. This feature is *alpha* and subject to breaking changes. ([#4670](https://github.com/operator-framework/operator-sdk/pull/4670))\n- (helm/v1, ansible/v1) Added Makefile `help` target. ([#4660](https://github.com/operator-framework/operator-sdk/pull/4660))\n- (ansible/v1, helm/v1) Added `securityContext`'s to the manager's Deployment to disallow running as root user. ([#4655](https://github.com/operator-framework/operator-sdk/pull/4655))\n- Added `--ca-secret-name` to `run bundle` and `run bundle-upgrade` to configure the registry Pod with an in-cluster certificate Secret to use TLS with a private registry. ([#4703](https://github.com/operator-framework/operator-sdk/pull/4703))\n- For Helm based-operators, added annotation `helm.sdk.operatorframework.io/uninstall-wait: \"true\"` to allow all resources to be deleted before removing the custom resource's finalizer. ([#4487](https://github.com/operator-framework/operator-sdk/pull/4487))\n- (go/v2, go/v3, ansible/v1, helm/v1) Added the `opm` and `catalog-build` Makefile targets to download [`opm`](https://github.com/operator-framework/operator-registry/blob/v1.15.1/docs/design/opm-tooling.md) and build operator catalogs either from scratch or an existing catalog. ([#4406](https://github.com/operator-framework/operator-sdk/pull/4406))\n- Added new optional flags `--delete-all`, `--delete-crds` and `--delete-operator-groups` to the cleanup command. ([#4619](https://github.com/operator-framework/operator-sdk/pull/4619))\n- Added `--service-account` to `run bundle` and `run bundle-upgrade` to bind registry objects to a non-default service account. ([#4694](https://github.com/operator-framework/operator-sdk/pull/4694))\n- Added `--pull-secret-name` to `run bundle` and `run bundle-upgrade` to configure the registry Pod with an in-cluster docker config Secret to pull bundle images from private registries. ([#4694](https://github.com/operator-framework/operator-sdk/pull/4694))\n- (ansible/v1, helm/v1) Create and bind controller-manager to a non-default service account ([kubebuilder#2070](https://github.com/kubernetes-sigs/kubebuilder/pull/2070)). ([#4653](https://github.com/operator-framework/operator-sdk/pull/4653))\n\n### Changes\n\n- For Ansible-based Operators: Update Python dependencies.\n  - openshift (0.11.2 -> 0.12.0)\n  - kubernetes (11.0.0 -> 12.0.1)\n  - ansible-runner (1.4.6 -> 1.4.7)\n  - ansible (2.9.15 -> 2.9.19). ([#4734](https://github.com/operator-framework/operator-sdk/pull/4734))\n- (ansible/v1) Update scaffolded requirements.yml to pull in newer versions of the Ansible collections.\n  - community.kubernetes (1.1.1 -> 1.2.1)\n  - operator_sdk.util (0.1.0 -> 0.2.0). ([#4734](https://github.com/operator-framework/operator-sdk/pull/4734))\n- (helm/v1) Explicitly set `--health-probe-bind-address` in the manager's auth proxy patch. ([#4654](https://github.com/operator-framework/operator-sdk/pull/4654))\n- (ansible/v1) Explicitly set `--health-probe-bind-address` in the manager's auth proxy patch. ([#4654](https://github.com/operator-framework/operator-sdk/pull/4654))\n- (go/v2, go/v3, ansible/v1, helm/v1) Changed `BUNDLE_IMG` and added `IMAGE_TAG_BASE` Makefile variables to allow one line bundle and catalog image builds. ([#4406](https://github.com/operator-framework/operator-sdk/pull/4406))\n- For Ansible-based operators, collections as main dependencies for the operator installed with ansible-galaxy are pinned to specific versions to prevent hard to track bugs. ([#4529](https://github.com/operator-framework/operator-sdk/pull/4529))\n- Update community Kubernetes Ansible collection to version 1.1.1. ([#4594](https://github.com/operator-framework/operator-sdk/pull/4594))\n- Bumped urllib3 in ansible-operator-base and ansible-operator images to 1.26.4 for a security fix. ([#4723](https://github.com/operator-framework/operator-sdk/pull/4723))\n- For Ansible-based operators, Python package installation in the Docker image is delegated to a pipenv managed Pipfile and Pipfile.lock, pinning both the main installed packages and their subdependencies. This prevents installing conflicting (sub)dependencies. ([#4543](https://github.com/operator-framework/operator-sdk/pull/4543))\n- For Ansible-based operators, Python package installation in the Docker image is delegated to a pipenv managed Pipfile and Pipfile.lock, pinning both the main installed packages and their subdependencies. This prevents installing conflicting (sub)dependencies. ([#4543](https://github.com/operator-framework/operator-sdk/pull/4543))\n\n### Deprecations\n\n- (ansible/v1, helm/v1) The flags `--enable-leader-election` and `--metrics-addr` were deprecated in favor of `--leader-elect` and `--metrics-bind-address`, respectively, to follow upstream conventions. ([#4654](https://github.com/operator-framework/operator-sdk/pull/4654))\n\n### Bug Fixes\n\n- (go/v3) Create webhook manifests in `config/` on running `create webhook`, not `init`. ([#4701](https://github.com/operator-framework/operator-sdk/pull/4701))\n- (manifests/v2) Added a `config/manifests` kustomize patch to remove the cert-manager volume and volumeMount from manifests destined for `generate <bundle|packagemanifests>`. ([#4623](https://github.com/operator-framework/operator-sdk/pull/4623))\n- For Helm-based operators, fixed handling of `kind: List` whereby the operator fails when trying to set watch on the object. Watches are created for objects in the list instead. ([#4682](https://github.com/operator-framework/operator-sdk/pull/4682))\n- (go/v2, go/v3, ansible/v1, helm/v1) Fixed the Prometheus `ServiceMonitor` metrics endpoint, which was not configured to be scraped correctly. ([#4680](https://github.com/operator-framework/operator-sdk/pull/4680))\n- In Ansible-based operators, mark the input variables from custom resources as unsafe by default. ([#4566](https://github.com/operator-framework/operator-sdk/pull/4566))\n"
  },
  {
    "path": "changelog/generated/v1.6.1.md",
    "content": "## v1.6.1\n\n### Additions\n\n- For Golang-based operators, added the `declarative.go/v1` plugin which customizes initialized projects with patterns from [kubernetes-sigs/kubebuilder-declarative-pattern](https://github.com/kubernetes-sigs/kubebuilder-declarative-pattern). (e.g `operator-sdk create api --plugins=go/v3,declarative`). ([#4731](https://github.com/operator-framework/operator-sdk/pull/4731))\n- Added `kustomize.common/v1` plugin which scaffolds the a commonly used project base that leverages `kustomize`. ([#4730](https://github.com/operator-framework/operator-sdk/pull/4730))\n- (ansible/v1, helm/v1) Added the option to configure `ansible-operator` and `helm-operator` with a [component config](https://master.book.kubebuilder.io/component-config-tutorial/tutorial.html). ([#4701](https://github.com/operator-framework/operator-sdk/pull/4701))\n- (ansible/v1, helm/v1) Add rules for leader election. ([#4701](https://github.com/operator-framework/operator-sdk/pull/4701))\n- Added [`alpha config-gen`](https://github.com/kubernetes-sigs/kubebuilder/tree/master/pkg/cli/alpha/config-gen), a kustomize plugin to specialize configuration for kubebuilder-style projects. This feature is *alpha* and subject to breaking changes. ([#4670](https://github.com/operator-framework/operator-sdk/pull/4670))\n- (helm/v1, ansible/v1) Added Makefile `help` target. ([#4660](https://github.com/operator-framework/operator-sdk/pull/4660))\n- (ansible/v1, helm/v1) Added `securityContext`'s to the manager's Deployment to disallow running as root user. ([#4655](https://github.com/operator-framework/operator-sdk/pull/4655))\n- Added `--ca-secret-name` to `run bundle` and `run bundle-upgrade` to configure the registry Pod with an in-cluster certificate Secret to use TLS with a private registry. ([#4703](https://github.com/operator-framework/operator-sdk/pull/4703))\n- For Helm based-operators, added annotation `helm.sdk.operatorframework.io/uninstall-wait: \"true\"` to allow all resources to be deleted before removing the custom resource's finalizer. ([#4487](https://github.com/operator-framework/operator-sdk/pull/4487))\n- (go/v2, go/v3, ansible/v1, helm/v1) Added the `opm` and `catalog-build` Makefile targets to download [`opm`](https://github.com/operator-framework/operator-registry/blob/v1.15.1/docs/design/opm-tooling.md) and build operator catalogs either from scratch or an existing catalog. ([#4406](https://github.com/operator-framework/operator-sdk/pull/4406))\n- Added new optional flags `--delete-all`, `--delete-crds` and `--delete-operator-groups` to the cleanup command. ([#4619](https://github.com/operator-framework/operator-sdk/pull/4619))\n- Added `--service-account` to `run bundle` and `run bundle-upgrade` to bind registry objects to a non-default service account. ([#4694](https://github.com/operator-framework/operator-sdk/pull/4694))\n- Added `--pull-secret-name` to `run bundle` and `run bundle-upgrade` to configure the registry Pod with an in-cluster docker config Secret to pull bundle images from private registries. ([#4694](https://github.com/operator-framework/operator-sdk/pull/4694))\n- (ansible/v1, helm/v1) Create and bind controller-manager to a non-default service account ([kubebuilder#2070](https://github.com/kubernetes-sigs/kubebuilder/pull/2070)). ([#4653](https://github.com/operator-framework/operator-sdk/pull/4653))\n\n### Changes\n\n- For Ansible-based Operators: Update Python dependencies.\n  - openshift (0.11.2 -> 0.12.0)\n  - kubernetes (11.0.0 -> 12.0.1)\n  - ansible-runner (1.4.6 -> 1.4.7)\n  - ansible (2.9.15 -> 2.9.19). ([#4734](https://github.com/operator-framework/operator-sdk/pull/4734))\n- (ansible/v1) Update scaffolded requirements.yml to pull in newer versions of the Ansible collections.\n  - community.kubernetes (1.1.1 -> 1.2.1)\n  - operator_sdk.util (0.1.0 -> 0.2.0). ([#4734](https://github.com/operator-framework/operator-sdk/pull/4734))\n- (helm/v1) Explicitly set `--health-probe-bind-address` in the manager's auth proxy patch. ([#4654](https://github.com/operator-framework/operator-sdk/pull/4654))\n- (ansible/v1) Explicitly set `--health-probe-bind-address` in the manager's auth proxy patch. ([#4654](https://github.com/operator-framework/operator-sdk/pull/4654))\n- (go/v2, go/v3, ansible/v1, helm/v1) Changed `BUNDLE_IMG` and added `IMAGE_TAG_BASE` Makefile variables to allow one line bundle and catalog image builds. ([#4406](https://github.com/operator-framework/operator-sdk/pull/4406))\n- For Ansible-based operators, collections as main dependencies for the operator installed with ansible-galaxy are pinned to specific versions to prevent hard to track bugs. ([#4529](https://github.com/operator-framework/operator-sdk/pull/4529))\n- Update community Kubernetes Ansible collection to version 1.1.1. ([#4594](https://github.com/operator-framework/operator-sdk/pull/4594))\n- Bumped urllib3 in ansible-operator-base and ansible-operator images to 1.26.4 for a security fix. ([#4723](https://github.com/operator-framework/operator-sdk/pull/4723))\n- For Ansible-based operators, Python package installation in the Docker image is delegated to a pipenv managed Pipfile and Pipfile.lock, pinning both the main installed packages and their subdependencies. This prevents installing conflicting (sub)dependencies. ([#4543](https://github.com/operator-framework/operator-sdk/pull/4543))\n- For Ansible-based operators, Python package installation in the Docker image is delegated to a pipenv managed Pipfile and Pipfile.lock, pinning both the main installed packages and their subdependencies. This prevents installing conflicting (sub)dependencies. ([#4543](https://github.com/operator-framework/operator-sdk/pull/4543))\n\n### Deprecations\n\n- (ansible/v1, helm/v1) The flags `--enable-leader-election` and `--metrics-addr` were deprecated in favor of `--leader-elect` and `--metrics-bind-address`, respectively, to follow upstream conventions. ([#4654](https://github.com/operator-framework/operator-sdk/pull/4654))\n\n### Bug Fixes\n\n- (go/v3) Create webhook manifests in `config/` on running `create webhook`, not `init`. ([#4701](https://github.com/operator-framework/operator-sdk/pull/4701))\n- (manifests/v2) Added a `config/manifests` kustomize patch to remove the cert-manager volume and volumeMount from manifests destined for `generate <bundle|packagemanifests>`. ([#4623](https://github.com/operator-framework/operator-sdk/pull/4623))\n- For Helm-based operators, fixed handling of `kind: List` whereby the operator fails when trying to set watch on the object. Watches are created for objects in the list instead. ([#4682](https://github.com/operator-framework/operator-sdk/pull/4682))\n- (go/v2, go/v3, ansible/v1, helm/v1) Fixed the Prometheus `ServiceMonitor` metrics endpoint, which was not configured to be scraped correctly. ([#4680](https://github.com/operator-framework/operator-sdk/pull/4680))\n- In Ansible-based operators, mark the input variables from custom resources as unsafe by default. ([#4566](https://github.com/operator-framework/operator-sdk/pull/4566))"
  },
  {
    "path": "changelog/generated/v1.7.0.md",
    "content": "## v1.7.0\n\n### Additions\n\n- Added `operator-sdk pkgman-to-bundle` command to support migration of packagemanifests to bundle format. Refer  https://github.com/operator-framework/enhancements/blob/master/enhancements/sdk-migrate-bundle.md  for more details. ([#4718](https://github.com/operator-framework/operator-sdk/pull/4718))\n- For Ansible-based operators, added log messages for each event that is received. This will make debugging excessive reconciliations much more straightforward. ([#4779](https://github.com/operator-framework/operator-sdk/pull/4779))\n- Added new optional flag `--optional-values` to the command `operator-sdk bundle validate`. This option allows to inform a list of key and values to the validators. (e.g. `operator-sdk bundle validate ./bundle --optional-values=k8s-version=1.22 --select-optional suite=operatorframework`). ([#4693](https://github.com/operator-framework/operator-sdk/pull/4693))\n\n### Deprecations\n\n- Deprecated `operator-sdk generate packagemanifests` and `operator-sdk run packagemanifests` commands, packagemanifests support in general in favour of operator bundles. ([#4838](https://github.com/operator-framework/operator-sdk/pull/4838))\n\n### Bug Fixes\n\n- For Ansible- and Helm-based operators, added the `--config` flag, which was mistakenly not added to either ansible-/helm-operator binary when file support was originally added. ([#4776](https://github.com/operator-framework/operator-sdk/pull/4776))\n- Format ansible-operator and helm-operator `run` command logs correctly. ([#4844](https://github.com/operator-framework/operator-sdk/pull/4844))\n- (go/v3, ansible/v1, helm/v1) Moved `leases.coordination.k8s.io` to its own proxy-role rule. ([#4835](https://github.com/operator-framework/operator-sdk/pull/4835))\n- (go/v3) Set the Makefile's `SHELL` variable to the system's `bash` binary with shell opts. ([#4835](https://github.com/operator-framework/operator-sdk/pull/4835))\n- The `generate kustomize manifests` command no longer adds non-served CRD versions to a CSV's `.spec.customresourcedefinitions.owned`. ([#4842](https://github.com/operator-framework/operator-sdk/pull/4842))\n"
  },
  {
    "path": "changelog/generated/v1.7.1.md",
    "content": "## v1.7.1\n\n### Additions\n\n- Added `operator-sdk pkgman-to-bundle` command to support migration of packagemanifests to bundle format. Refer  https://github.com/operator-framework/enhancements/blob/master/enhancements/sdk-migrate-bundle.md  for more details. ([#4718](https://github.com/operator-framework/operator-sdk/pull/4718))\n- For Ansible-based operators, added log messages for each event that is received. This will make debugging excessive reconciliations much more straightforward. ([#4779](https://github.com/operator-framework/operator-sdk/pull/4779))\n- Added new optional flag `--optional-values` to the command `operator-sdk bundle validate`. This option allows to inform a list of key and values to the validators. (e.g. `operator-sdk bundle validate ./bundle --optional-values=k8s-version=1.22 --select-optional suite=operatorframework`). ([#4693](https://github.com/operator-framework/operator-sdk/pull/4693))\n\n### Changes\n\n- (go/v3, ansible/v1, helm/v1) Bumped controller-runtime to v0.8.3 (kubernetes 1.20). ([#4863](https://github.com/operator-framework/operator-sdk/pull/4863))\n\n### Deprecations\n\n- Deprecated `operator-sdk generate packagemanifests` and `operator-sdk run packagemanifests` commands, packagemanifests support in general in favour of operator bundles. ([#4838](https://github.com/operator-framework/operator-sdk/pull/4838))\n\n### Bug Fixes\n\n- For Ansible- and Helm-based operators, added the `--config` flag, which was mistakenly not added to either ansible-/helm-operator binary when file support was originally added. ([#4776](https://github.com/operator-framework/operator-sdk/pull/4776))\n- Format ansible-operator and helm-operator `run` command logs correctly. ([#4844](https://github.com/operator-framework/operator-sdk/pull/4844))\n- (go/v3, ansible/v1, helm/v1) Moved `leases.coordination.k8s.io` to its own proxy-role rule. ([#4835](https://github.com/operator-framework/operator-sdk/pull/4835))\n- (go/v3) Set the Makefile's `SHELL` variable to the system's `bash` binary with shell opts. ([#4835](https://github.com/operator-framework/operator-sdk/pull/4835))\n- The `generate kustomize manifests` command no longer adds non-served CRD versions to a CSV's `.spec.customresourcedefinitions.owned`. ([#4842](https://github.com/operator-framework/operator-sdk/pull/4842))\n- For Anible-based operators, fixed a bug that prevented owner reference annotations from being added to cluster-scoped and multi-namespace resources, which had to be applied manually to correctly reconcile them. ([#4850](https://github.com/operator-framework/operator-sdk/pull/4850))\n"
  },
  {
    "path": "changelog/generated/v1.8.0.md",
    "content": "## v1.8.0\n\n### Additions\n\n- Added new bundle validator to check the bundle against the Community Operator criteria. For further information run `operator-sdk bundle validate --list-optional` and `operator-sdk bundle validate --help`. This validator is in alpha and subject to breaking changes. ([#4939](https://github.com/operator-framework/operator-sdk/pull/4939))\n- Added --extra-service-accounts flag to `generate bundle` to consider roles bound to service accounts not specified in the operator's Deployment. ([#4826](https://github.com/operator-framework/operator-sdk/pull/4826))\n- Added the `quarkus/v1-alpha` Java plugin, which supports `init` and `create api` commands. This plugin is alpha and subject to breaking changes. ([#4871](https://github.com/operator-framework/operator-sdk/pull/4871))\n- Add new optional flag `--skip-tls` to the commands `operator-sdk run bundle` and `operator-sdk run bundle-upgrade`. This option allows to install the operator from a bundle image stored at an insecure docker registry. (e.g. `operator-sdk run bundle localhost:5000/my-operator-bundle:latest --skip-tls`). ([#4816](https://github.com/operator-framework/operator-sdk/pull/4816))\n\n### Changes\n\n- `generate bundle` adds ClusterRoles bound by RoleBindings to a CSV's `.spec.permissions`, since these become namespace-scoped at runtime. They will also be added to `.spec.clusterPermissions` if bound by a ClusterRoleBinding. ([#4826](https://github.com/operator-framework/operator-sdk/pull/4826))\n- Images built from the operator-sdk repository for the latest two minor version's latest patch version will now be rebuilt whenever a constituent base image has a new patch version published. For example, running `docker pull quay.io/operator-framework/ansible-operator:v1.7.2` after a rebuild will result in a fully compatible, patched image. ([#4917](https://github.com/operator-framework/operator-sdk/pull/4917))\n- (go/v3) Upgraded Go version to 1.16. ([#4927](https://github.com/operator-framework/operator-sdk/pull/4927))\n\n### Bug Fixes\n\n- Bumped operator-framework/api to v0.8.1, which properly defaults a CRD conversion's service port to 443. ([#4903](https://github.com/operator-framework/operator-sdk/pull/4903))\n- Detect and report ansible-runner binary failures early and prevent symliking to artifacts. ([#4944](https://github.com/operator-framework/operator-sdk/pull/4944))\n- For Helm-based operators, fixed a bug where deployed and candidate release comparison was always false when an RNG was used to derive some manifest value, resulting in the chart release constantly upgrading. ([#4937](https://github.com/operator-framework/operator-sdk/pull/4937))\n- Bumped operator-lib to v0.4.1 for several bugfixes in ansible-operator and helm-operator binaries. ([#4888](https://github.com/operator-framework/operator-sdk/pull/4888))\n- Pinned pip3 to 21.1 in the ansible-operator image to fix https://github.com/pypa/pip/pull/9827. ([#4877](https://github.com/operator-framework/operator-sdk/pull/4877))\n- Pinned base images of ansible-operator to ubi:8.3-297.1618432833, and helm-operator and scorecard to ubi-minimal:8.3-298.1618432845. ([#4873](https://github.com/operator-framework/operator-sdk/pull/4873))\n"
  },
  {
    "path": "changelog/generated/v1.9.0.md",
    "content": "## v1.9.0\n\n### Changes\n\n- **Breaking change**: For Ansible operators, if an API endpoint has path component in it then the ansible-operator binary will terminate early with an error, due to a bug in the proxy that would cause the operator to target the wrong cluster. ([#4987](https://github.com/operator-framework/operator-sdk/pull/4987))\n\n### Bug Fixes\n\n- For helm-based operators, empty patch requests generated from the 3-way merge are filtered to avoid unnecessary requests to the kube apiserver. ([#4957](https://github.com/operator-framework/operator-sdk/pull/4957))\n"
  },
  {
    "path": "cmd/helm-operator/main.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage main\n\nimport (\n\t\"log\"\n\n\t\"github.com/spf13/cobra\"\n\t_ \"k8s.io/client-go/plugin/pkg/client/auth\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/cmd/helm-operator/run\"\n\t\"github.com/operator-framework/operator-sdk/internal/cmd/helm-operator/version\"\n)\n\nfunc main() {\n\troot := cobra.Command{\n\t\tShort: \"Reconcile an Helm operator project using helm\",\n\t\tLong: `This binary runs a Helm operator that reconciles Kubernetes resources\nmanaged by the helm program. It can be run either directly or from a Helm operator\nproject's image entrypoint\n`,\n\t\tUse: \"helm-operator\",\n\t}\n\n\troot.AddCommand(run.NewCmd())\n\troot.AddCommand(version.NewCmd())\n\n\tif err := root.Execute(); err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n"
  },
  {
    "path": "cmd/operator-sdk/main.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage main\n\nimport (\n\t// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)\n\t// to ensure that `exec-entrypoint` and `run` can make use of them.\n\t_ \"k8s.io/client-go/plugin/pkg/client/auth\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/cli\"\n)\n\nfunc main() {\n\tif err := cli.Run(); err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n"
  },
  {
    "path": "code-of-conduct.md",
    "content": "## Red Hat Community Code of Conduct\n\n### Contributor Code of Conduct\n\nAs contributors and maintainers of this project, and in the interest of\nfostering an open and welcoming community, we pledge to respect all people who\ncontribute through reporting issues, posting feature requests, updating\ndocumentation, submitting pull requests or patches, and other activities.\n\nWe are committed to making participation in this project a harassment-free\nexperience for everyone, regardless of level of experience, gender, gender\nidentity and expression, sexual orientation, disability, personal appearance,\nbody size, race, ethnicity, age, religion, or nationality.\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery\n* Personal attacks\n* Trolling or insulting/derogatory comments\n* Public or private harassment\n* Publishing others' private information, such as physical or electronic addresses, without explicit permission\n* Other unethical or unprofessional conduct.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct. By adopting this Code of Conduct,\nproject maintainers commit themselves to fairly and consistently applying these\nprinciples to every aspect of managing this project. Project maintainers who do\nnot follow or enforce the Code of Conduct may be permanently removed from the\nproject team.\n\nThis code of conduct applies both within project spaces and in public spaces\nwhen an individual is representing the project or its community.\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting a project maintainer or the Operator SDK team <aos-operator-sdk@redhat.com>.\n\nThis Code of Conduct is adapted from the Contributor Covenant\n(http://contributor-covenant.org), version 1.2.0, available at\nhttp://contributor-covenant.org/version/1/2/0/\n\n### Red Hat Events Code of Conduct\n\nRed Hat events are working conferences intended for professional networking and\ncollaboration in the Red Hat community. Attendees are expected to behave\naccording to professional standards and in accordance with their employer’s\npolicies on appropriate workplace behavior.\n\nWhile at Red Hat events or related social networking opportunities, attendees\nshould not engage in discriminatory or offensive speech or actions including\nbut not limited to gender, sexuality, race, age, disability, or religion.\nSpeakers should be especially aware of these concerns.\n\nRed Hat does not condone any statements by speakers contrary to these standards.\nRed Hat reserves the right to deny entrance and/or eject from an event (without\nrefund) any individual found to be engaging in discriminatory or offensive\nspeech or actions.\n\nPlease bring any concerns to the immediate attention of designated on-site\nstaff, or the Operator SDK team <aos-operator-sdk@redhat.com>.\n"
  },
  {
    "path": "config/crd/bases/_.yaml",
    "content": "\n---\napiVersion: apiextensions.k8s.io/v1beta1\nkind: CustomResourceDefinition\nmetadata:\n  annotations:\n    controller-gen.kubebuilder.io/version: v0.3.0\n  creationTimestamp: null\nspec:\n  group: \"\"\n  names:\n    kind: \"\"\n    plural: \"\"\n  scope: \"\"\nstatus:\n  acceptedNames:\n    kind: \"\"\n    plural: \"\"\n  conditions: null\n  storedVersions: null\n"
  },
  {
    "path": "go.mod",
    "content": "module github.com/operator-framework/operator-sdk\n\ngo 1.25.7\n\nrequire (\n\tgithub.com/blang/semver/v4 v4.0.0\n\tgithub.com/fatih/structtag v1.2.0\n\tgithub.com/go-logr/logr v1.4.3\n\tgithub.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572\n\tgithub.com/iancoleman/strcase v0.3.0\n\tgithub.com/kr/text v0.2.0\n\tgithub.com/markbates/inflect v1.0.4\n\tgithub.com/maxbrunsfeld/counterfeiter/v6 v6.12.1\n\tgithub.com/onsi/ginkgo/v2 v2.28.1\n\tgithub.com/onsi/gomega v1.39.1\n\tgithub.com/operator-framework/ansible-operator-plugins v1.42.2\n\tgithub.com/operator-framework/api v0.34.0\n\tgithub.com/operator-framework/operator-lib v0.19.0\n\tgithub.com/operator-framework/operator-manifest-tools v0.10.0\n\tgithub.com/operator-framework/operator-registry v1.59.0\n\tgithub.com/prometheus/client_golang v1.23.2\n\tgithub.com/sergi/go-diff v1.4.0\n\tgithub.com/sirupsen/logrus v1.9.4\n\tgithub.com/spf13/afero v1.15.0\n\tgithub.com/spf13/cobra v1.10.2\n\tgithub.com/spf13/pflag v1.0.10\n\tgithub.com/spf13/viper v1.21.0\n\tgithub.com/stretchr/testify v1.11.1\n\tgithub.com/thoas/go-funk v0.9.3\n\tgolang.org/x/mod v0.32.0\n\tgolang.org/x/text v0.34.0\n\tgolang.org/x/tools v0.41.0\n\tgomodules.xyz/jsonpatch/v3 v3.0.1\n\thelm.sh/helm/v3 v3.18.6\n\tk8s.io/api v0.33.9\n\tk8s.io/apiextensions-apiserver v0.33.9\n\tk8s.io/apimachinery v0.33.9\n\tk8s.io/cli-runtime v0.33.9\n\tk8s.io/client-go v0.33.9\n\tk8s.io/kubectl v0.33.9\n\tk8s.io/utils v0.0.0-20251002143259-bc988d571ff4\n\tsigs.k8s.io/controller-runtime v0.21.0\n\tsigs.k8s.io/controller-tools v0.18.0\n\tsigs.k8s.io/kubebuilder/v4 v4.6.0\n\tsigs.k8s.io/yaml v1.6.0\n)\n\nrequire (\n\tcel.dev/expr v0.25.1 // indirect\n\tdario.cat/mergo v1.0.2 // indirect\n\tgithub.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect\n\tgithub.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect\n\tgithub.com/BurntSushi/toml v1.5.0 // indirect\n\tgithub.com/MakeNowJust/heredoc v1.0.0 // indirect\n\tgithub.com/Masterminds/goutils v1.1.1 // indirect\n\tgithub.com/Masterminds/semver/v3 v3.4.0 // indirect\n\tgithub.com/Masterminds/sprig/v3 v3.3.0 // indirect\n\tgithub.com/Masterminds/squirrel v1.5.4 // indirect\n\tgithub.com/Microsoft/go-winio v0.6.2 // indirect\n\tgithub.com/Microsoft/hcsshim v0.13.0 // indirect\n\tgithub.com/VividCortex/ewma v1.2.0 // indirect\n\tgithub.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect\n\tgithub.com/antlr4-go/antlr/v4 v4.13.1 // indirect\n\tgithub.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect\n\tgithub.com/beorn7/perks v1.0.1 // indirect\n\tgithub.com/bshuster-repo/logrus-logstash-hook v1.0.0 // indirect\n\tgithub.com/cenkalti/backoff/v5 v5.0.3 // indirect\n\tgithub.com/cespare/xxhash/v2 v2.3.0 // indirect\n\tgithub.com/chai2010/gettext-go v1.0.2 // indirect\n\tgithub.com/containerd/cgroups/v3 v3.0.5 // indirect\n\tgithub.com/containerd/containerd v1.7.29 // indirect\n\tgithub.com/containerd/containerd/api v1.9.0 // indirect\n\tgithub.com/containerd/continuity v0.4.5 // indirect\n\tgithub.com/containerd/errdefs v1.0.0 // indirect\n\tgithub.com/containerd/errdefs/pkg v0.3.0 // indirect\n\tgithub.com/containerd/log v0.1.0 // indirect\n\tgithub.com/containerd/platforms v0.2.1 // indirect\n\tgithub.com/containerd/stargz-snapshotter/estargz v0.18.1 // indirect\n\tgithub.com/containerd/ttrpc v1.2.7 // indirect\n\tgithub.com/containerd/typeurl/v2 v2.2.3 // indirect\n\tgithub.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 // indirect\n\tgithub.com/containers/ocicrypt v1.2.1 // indirect\n\tgithub.com/coreos/go-systemd/v22 v22.6.0 // indirect\n\tgithub.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect\n\tgithub.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467 // indirect\n\tgithub.com/cyphar/filepath-securejoin v0.4.1 // indirect\n\tgithub.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect\n\tgithub.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect\n\tgithub.com/distribution/distribution/v3 v3.0.0 // indirect\n\tgithub.com/distribution/reference v0.6.0 // indirect\n\tgithub.com/docker/cli v29.2.0+incompatible // indirect\n\tgithub.com/docker/distribution v2.8.3+incompatible // indirect\n\tgithub.com/docker/docker v28.5.2+incompatible // indirect\n\tgithub.com/docker/docker-credential-helpers v0.9.3 // indirect\n\tgithub.com/docker/go-connections v0.6.0 // indirect\n\tgithub.com/docker/go-events v0.0.0-20250114142523-c867878c5e32 // indirect\n\tgithub.com/docker/go-metrics v0.0.1 // indirect\n\tgithub.com/docker/go-units v0.5.0 // indirect\n\tgithub.com/emicklei/go-restful/v3 v3.12.2 // indirect\n\tgithub.com/evanphx/json-patch v5.9.11+incompatible // indirect\n\tgithub.com/evanphx/json-patch/v5 v5.9.11 // indirect\n\tgithub.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect\n\tgithub.com/fatih/color v1.18.0 // indirect\n\tgithub.com/felixge/httpsnoop v1.0.4 // indirect\n\tgithub.com/fsnotify/fsnotify v1.9.0 // indirect\n\tgithub.com/fxamacker/cbor/v2 v2.8.0 // indirect\n\tgithub.com/go-errors/errors v1.4.2 // indirect\n\tgithub.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect\n\tgithub.com/go-git/go-billy/v5 v5.6.2 // indirect\n\tgithub.com/go-git/go-git/v5 v5.16.5 // indirect\n\tgithub.com/go-gorp/gorp/v3 v3.1.0 // indirect\n\tgithub.com/go-jose/go-jose/v4 v4.1.3 // indirect\n\tgithub.com/go-logr/stdr v1.2.2 // indirect\n\tgithub.com/go-logr/zapr v1.3.0 // indirect\n\tgithub.com/go-openapi/jsonpointer v0.21.1 // indirect\n\tgithub.com/go-openapi/jsonreference v0.21.0 // indirect\n\tgithub.com/go-openapi/swag v0.23.1 // indirect\n\tgithub.com/go-sql-driver/mysql v1.9.2 // indirect\n\tgithub.com/go-task/slim-sprig/v3 v3.0.0 // indirect\n\tgithub.com/go-viper/mapstructure/v2 v2.4.0 // indirect\n\tgithub.com/gobuffalo/envy v1.6.5 // indirect\n\tgithub.com/gobuffalo/flect v1.0.3 // indirect\n\tgithub.com/gobwas/glob v0.2.3 // indirect\n\tgithub.com/gogo/protobuf v1.3.2 // indirect\n\tgithub.com/golang-migrate/migrate/v4 v4.19.0 // indirect\n\tgithub.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect\n\tgithub.com/golang/mock v1.7.0-rc.1 // indirect\n\tgithub.com/golang/protobuf v1.5.4 // indirect\n\tgithub.com/google/btree v1.1.3 // indirect\n\tgithub.com/google/cel-go v0.26.0 // indirect\n\tgithub.com/google/gnostic-models v0.6.9 // indirect\n\tgithub.com/google/go-cmp v0.7.0 // indirect\n\tgithub.com/google/go-containerregistry v0.20.7 // indirect\n\tgithub.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 // indirect\n\tgithub.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect\n\tgithub.com/google/uuid v1.6.0 // indirect\n\tgithub.com/gorilla/handlers v1.5.2 // indirect\n\tgithub.com/gorilla/mux v1.8.1 // indirect\n\tgithub.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect\n\tgithub.com/gosuri/uitable v0.0.4 // indirect\n\tgithub.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect\n\tgithub.com/grpc-ecosystem/grpc-gateway/v2 v2.27.4 // indirect\n\tgithub.com/h2non/filetype v1.1.3 // indirect\n\tgithub.com/h2non/go-is-svg v0.0.0-20160927212452-35e8c4b0612c // indirect\n\tgithub.com/hashicorp/errwrap v1.1.0 // indirect\n\tgithub.com/hashicorp/go-multierror v1.1.1 // indirect\n\tgithub.com/hashicorp/golang-lru/arc/v2 v2.0.7 // indirect\n\tgithub.com/hashicorp/golang-lru/v2 v2.0.7 // indirect\n\tgithub.com/huandu/xstrings v1.5.0 // indirect\n\tgithub.com/inconshreveable/mousetrap v1.1.0 // indirect\n\tgithub.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect\n\tgithub.com/jmoiron/sqlx v1.4.0 // indirect\n\tgithub.com/joelanford/ignore v0.1.1 // indirect\n\tgithub.com/joho/godotenv v1.3.0 // indirect\n\tgithub.com/josharian/intern v1.0.0 // indirect\n\tgithub.com/json-iterator/go v1.1.12 // indirect\n\tgithub.com/klauspost/compress v1.18.1 // indirect\n\tgithub.com/klauspost/pgzip v1.2.6 // indirect\n\tgithub.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect\n\tgithub.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect\n\tgithub.com/lib/pq v1.10.9 // indirect\n\tgithub.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect\n\tgithub.com/mailru/easyjson v0.9.0 // indirect\n\tgithub.com/mattn/go-colorable v0.1.14 // indirect\n\tgithub.com/mattn/go-isatty v0.0.20 // indirect\n\tgithub.com/mattn/go-runewidth v0.0.16 // indirect\n\tgithub.com/mattn/go-sqlite3 v1.14.32 // indirect\n\tgithub.com/miekg/dns v1.1.61 // indirect\n\tgithub.com/miekg/pkcs11 v1.1.1 // indirect\n\tgithub.com/mitchellh/copystructure v1.2.0 // indirect\n\tgithub.com/mitchellh/go-homedir v1.1.0 // indirect\n\tgithub.com/mitchellh/go-wordwrap v1.0.1 // indirect\n\tgithub.com/mitchellh/reflectwalk v1.0.2 // indirect\n\tgithub.com/moby/locker v1.0.1 // indirect\n\tgithub.com/moby/spdystream v0.5.0 // indirect\n\tgithub.com/moby/sys/capability v0.4.0 // indirect\n\tgithub.com/moby/sys/mountinfo v0.7.2 // indirect\n\tgithub.com/moby/sys/sequential v0.6.0 // indirect\n\tgithub.com/moby/sys/user v0.4.0 // indirect\n\tgithub.com/moby/sys/userns v0.1.0 // indirect\n\tgithub.com/moby/term v0.5.2 // indirect\n\tgithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect\n\tgithub.com/modern-go/reflect2 v1.0.2 // indirect\n\tgithub.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect\n\tgithub.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect\n\tgithub.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect\n\tgithub.com/nxadm/tail v1.4.11 // indirect\n\tgithub.com/opencontainers/go-digest v1.0.0 // indirect\n\tgithub.com/opencontainers/image-spec v1.1.1 // indirect\n\tgithub.com/opencontainers/runtime-spec v1.2.1 // indirect\n\tgithub.com/otiai10/copy v1.14.1 // indirect\n\tgithub.com/otiai10/mint v1.6.3 // indirect\n\tgithub.com/pelletier/go-toml/v2 v2.2.4 // indirect\n\tgithub.com/peterbourgon/diskv v2.0.1+incompatible // indirect\n\tgithub.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 // indirect\n\tgithub.com/pkg/errors v0.9.1 // indirect\n\tgithub.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect\n\tgithub.com/proglottis/gpgme v0.1.5 // indirect\n\tgithub.com/prometheus/client_model v0.6.2 // indirect\n\tgithub.com/prometheus/common v0.67.5 // indirect\n\tgithub.com/prometheus/procfs v0.16.1 // indirect\n\tgithub.com/redis/go-redis/extra/rediscmd/v9 v9.10.0 // indirect\n\tgithub.com/redis/go-redis/extra/redisotel/v9 v9.10.0 // indirect\n\tgithub.com/redis/go-redis/v9 v9.10.0 // indirect\n\tgithub.com/rivo/uniseg v0.4.7 // indirect\n\tgithub.com/rubenv/sql-migrate v1.8.0 // indirect\n\tgithub.com/russross/blackfriday/v2 v2.1.0 // indirect\n\tgithub.com/sagikazarmark/locafero v0.11.0 // indirect\n\tgithub.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect\n\tgithub.com/secure-systems-lab/go-securesystemslib v0.9.1 // indirect\n\tgithub.com/shopspring/decimal v1.4.0 // indirect\n\tgithub.com/sigstore/fulcio v1.8.5 // indirect\n\tgithub.com/sigstore/protobuf-specs v0.5.0 // indirect\n\tgithub.com/sigstore/sigstore v1.10.4 // indirect\n\tgithub.com/smallstep/pkcs7 v0.2.1 // indirect\n\tgithub.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect\n\tgithub.com/spf13/cast v1.10.0 // indirect\n\tgithub.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 // indirect\n\tgithub.com/stoewer/go-strcase v1.3.1 // indirect\n\tgithub.com/subosito/gotenv v1.6.0 // indirect\n\tgithub.com/ulikunitz/xz v0.5.15 // indirect\n\tgithub.com/vbatts/tar-split v0.12.2 // indirect\n\tgithub.com/vbauerster/mpb/v8 v8.10.2 // indirect\n\tgithub.com/x448/float16 v0.8.4 // indirect\n\tgithub.com/xlab/treeprint v1.2.0 // indirect\n\tgo.etcd.io/bbolt v1.4.3 // indirect\n\tgo.etcd.io/etcd/client/pkg/v3 v3.6.0 // indirect\n\tgo.etcd.io/etcd/client/v3 v3.6.0 // indirect\n\tgo.opencensus.io v0.24.0 // indirect\n\tgo.opentelemetry.io/auto/sdk v1.2.1 // indirect\n\tgo.opentelemetry.io/contrib/bridges/prometheus v0.61.0 // indirect\n\tgo.opentelemetry.io/contrib/exporters/autoexport v0.61.0 // indirect\n\tgo.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect\n\tgo.opentelemetry.io/otel v1.40.0 // indirect\n\tgo.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.12.2 // indirect\n\tgo.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.12.2 // indirect\n\tgo.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.36.0 // indirect\n\tgo.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.36.0 // indirect\n\tgo.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 // indirect\n\tgo.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 // indirect\n\tgo.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0 // indirect\n\tgo.opentelemetry.io/otel/exporters/prometheus v0.58.0 // indirect\n\tgo.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.12.2 // indirect\n\tgo.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.36.0 // indirect\n\tgo.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.36.0 // indirect\n\tgo.opentelemetry.io/otel/log v0.12.2 // indirect\n\tgo.opentelemetry.io/otel/metric v1.40.0 // indirect\n\tgo.opentelemetry.io/otel/sdk v1.40.0 // indirect\n\tgo.opentelemetry.io/otel/sdk/log v0.12.2 // indirect\n\tgo.opentelemetry.io/otel/sdk/metric v1.40.0 // indirect\n\tgo.opentelemetry.io/otel/trace v1.40.0 // indirect\n\tgo.opentelemetry.io/proto/otlp v1.7.1 // indirect\n\tgo.podman.io/common v0.65.0 // indirect\n\tgo.podman.io/image/v5 v5.37.0 // indirect\n\tgo.podman.io/storage v1.60.0 // indirect\n\tgo.uber.org/multierr v1.11.0 // indirect\n\tgo.uber.org/zap v1.27.1 // indirect\n\tgo.yaml.in/yaml/v2 v2.4.3 // indirect\n\tgo.yaml.in/yaml/v3 v3.0.4 // indirect\n\tgolang.org/x/crypto v0.47.0 // indirect\n\tgolang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect\n\tgolang.org/x/net v0.49.0 // indirect\n\tgolang.org/x/oauth2 v0.34.0 // indirect\n\tgolang.org/x/sync v0.19.0 // indirect\n\tgolang.org/x/sys v0.40.0 // indirect\n\tgolang.org/x/term v0.39.0 // indirect\n\tgolang.org/x/time v0.14.0 // indirect\n\tgolang.org/x/tools/go/packages/packagestest v0.1.1-deprecated // indirect\n\tgomodules.xyz/jsonpatch/v2 v2.4.0 // indirect\n\tgomodules.xyz/orderedmap v0.1.0 // indirect\n\tgoogle.golang.org/genproto v0.0.0-20251202230838-ff82c1b0f217 // indirect\n\tgoogle.golang.org/genproto/googleapis/api v0.0.0-20251222181119-0a764e51fe1b // indirect\n\tgoogle.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b // indirect\n\tgoogle.golang.org/grpc v1.79.3 // indirect\n\tgoogle.golang.org/protobuf v1.36.11 // indirect\n\tgopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect\n\tgopkg.in/inf.v0 v0.9.1 // indirect\n\tgopkg.in/warnings.v0 v0.1.2 // indirect\n\tgopkg.in/yaml.v2 v2.4.0 // indirect\n\tgopkg.in/yaml.v3 v3.0.1 // indirect\n\tk8s.io/apiserver v0.33.9 // indirect\n\tk8s.io/component-base v0.33.9 // indirect\n\tk8s.io/klog/v2 v2.130.1 // indirect\n\tk8s.io/kube-openapi v0.0.0-20250610211856-8b98d1ed966a // indirect\n\toras.land/oras-go/v2 v2.6.0 // indirect\n\tsigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.33.0 // indirect\n\tsigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect\n\tsigs.k8s.io/kustomize/api v0.19.0 // indirect\n\tsigs.k8s.io/kustomize/kyaml v0.19.0 // indirect\n\tsigs.k8s.io/randfill v1.0.0 // indirect\n\tsigs.k8s.io/structured-merge-diff/v4 v4.7.0 // indirect\n)\n"
  },
  {
    "path": "go.sum",
    "content": "cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4=\ncel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4=\ncloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ndario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=\ndario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=\nfilippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=\nfilippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=\ngithub.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=\ngithub.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=\ngithub.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=\ngithub.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=\ngithub.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=\ngithub.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=\ngithub.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=\ngithub.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=\ngithub.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=\ngithub.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=\ngithub.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=\ngithub.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=\ngithub.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=\ngithub.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=\ngithub.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=\ngithub.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs=\ngithub.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=\ngithub.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM=\ngithub.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10=\ngithub.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=\ngithub.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=\ngithub.com/Microsoft/hcsshim v0.13.0 h1:/BcXOiS6Qi7N9XqUcv27vkIuVOkBEcWstd2pMlWSeaA=\ngithub.com/Microsoft/hcsshim v0.13.0/go.mod h1:9KWJ/8DgU+QzYGupX4tzMhRQE8h6w90lH6HAaclpEok=\ngithub.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow=\ngithub.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4=\ngithub.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=\ngithub.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=\ngithub.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=\ngithub.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=\ngithub.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ=\ngithub.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw=\ngithub.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=\ngithub.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=\ngithub.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=\ngithub.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=\ngithub.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=\ngithub.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=\ngithub.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=\ngithub.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=\ngithub.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=\ngithub.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=\ngithub.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70=\ngithub.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=\ngithub.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=\ngithub.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=\ngithub.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=\ngithub.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=\ngithub.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=\ngithub.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=\ngithub.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=\ngithub.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=\ngithub.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=\ngithub.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk=\ngithub.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA=\ngithub.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=\ngithub.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=\ngithub.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo=\ngithub.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=\ngithub.com/containerd/containerd v1.7.29 h1:90fWABQsaN9mJhGkoVnuzEY+o1XDPbg9BTC9QTAHnuE=\ngithub.com/containerd/containerd v1.7.29/go.mod h1:azUkWcOvHrWvaiUjSQH0fjzuHIwSPg1WL5PshGP4Szs=\ngithub.com/containerd/containerd/api v1.9.0 h1:HZ/licowTRazus+wt9fM6r/9BQO7S0vD5lMcWspGIg0=\ngithub.com/containerd/containerd/api v1.9.0/go.mod h1:GhghKFmTR3hNtyznBoQ0EMWr9ju5AqHjcZPsSpTKutI=\ngithub.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4=\ngithub.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=\ngithub.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=\ngithub.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=\ngithub.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=\ngithub.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=\ngithub.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=\ngithub.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=\ngithub.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A=\ngithub.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=\ngithub.com/containerd/stargz-snapshotter/estargz v0.18.1 h1:cy2/lpgBXDA3cDKSyEfNOFMA/c10O1axL69EU7iirO8=\ngithub.com/containerd/stargz-snapshotter/estargz v0.18.1/go.mod h1:ALIEqa7B6oVDsrF37GkGN20SuvG/pIMm7FwP7ZmRb0Q=\ngithub.com/containerd/ttrpc v1.2.7 h1:qIrroQvuOL9HQ1X6KHe2ohc7p+HP/0VE6XPU7elJRqQ=\ngithub.com/containerd/ttrpc v1.2.7/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o=\ngithub.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40=\ngithub.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk=\ngithub.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 h1:Qzk5C6cYglewc+UyGf6lc8Mj2UaPTHy/iF2De0/77CA=\ngithub.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=\ngithub.com/containers/ocicrypt v1.2.1 h1:0qIOTT9DoYwcKmxSt8QJt+VzMY18onl9jUXsxpVhSmM=\ngithub.com/containers/ocicrypt v1.2.1/go.mod h1:aD0AAqfMp0MtwqWgHM1bUwe1anx0VazI108CRrSKINQ=\ngithub.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=\ngithub.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=\ngithub.com/coreos/go-systemd/v22 v22.6.0 h1:aGVa/v8B7hpb0TKl0MWoAavPDmHvobFe5R5zn0bCJWo=\ngithub.com/coreos/go-systemd/v22 v22.6.0/go.mod h1:iG+pp635Fo7ZmV/j14KUcmEyWF+0X7Lua8rrTWzYgWU=\ngithub.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=\ngithub.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo=\ngithub.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=\ngithub.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=\ngithub.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=\ngithub.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=\ngithub.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467 h1:uX1JmpONuD549D73r6cgnxyUu18Zb7yHAy5AYU0Pm4Q=\ngithub.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw=\ngithub.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=\ngithub.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=\ngithub.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=\ngithub.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=\ngithub.com/distribution/distribution/v3 v3.0.0 h1:q4R8wemdRQDClzoNNStftB2ZAfqOiN6UX90KJc4HjyM=\ngithub.com/distribution/distribution/v3 v3.0.0/go.mod h1:tRNuFoZsUdyRVegq8xGNeds4KLjwLCRin/tTo6i1DhU=\ngithub.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=\ngithub.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=\ngithub.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=\ngithub.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=\ngithub.com/docker/cli v29.2.0+incompatible h1:9oBd9+YM7rxjZLfyMGxjraKBKE4/nVyvVfN4qNl9XRM=\ngithub.com/docker/cli v29.2.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=\ngithub.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=\ngithub.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=\ngithub.com/docker/docker v28.5.2+incompatible h1:DBX0Y0zAjZbSrm1uzOkdr1onVghKaftjlSWt4AFexzM=\ngithub.com/docker/docker v28.5.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=\ngithub.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8=\ngithub.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo=\ngithub.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=\ngithub.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE=\ngithub.com/docker/go-events v0.0.0-20250114142523-c867878c5e32 h1:EHZfspsnLAz8Hzccd67D5abwLiqoqym2jz/jOS39mCk=\ngithub.com/docker/go-events v0.0.0-20250114142523-c867878c5e32/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=\ngithub.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=\ngithub.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=\ngithub.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=\ngithub.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=\ngithub.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU=\ngithub.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=\ngithub.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=\ngithub.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=\ngithub.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=\ngithub.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=\ngithub.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=\ngithub.com/evanphx/json-patch v5.9.11+incompatible h1:ixHHqfcGvxhWkniF1tWxBHA0yb4Z+d1UQi45df52xW8=\ngithub.com/evanphx/json-patch v5.9.11+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=\ngithub.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU=\ngithub.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM=\ngithub.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4=\ngithub.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc=\ngithub.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=\ngithub.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=\ngithub.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=\ngithub.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=\ngithub.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=\ngithub.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=\ngithub.com/foxcpp/go-mockdns v1.1.0 h1:jI0rD8M0wuYAxL7r/ynTrCQQq0BVqfB99Vgk7DlmewI=\ngithub.com/foxcpp/go-mockdns v1.1.0/go.mod h1:IhLeSFGed3mJIAXPH2aiRQB+kqz7oqu8ld2qVbOu7Wk=\ngithub.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=\ngithub.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=\ngithub.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=\ngithub.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=\ngithub.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=\ngithub.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU=\ngithub.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=\ngithub.com/gkampitakis/ciinfo v0.3.2 h1:JcuOPk8ZU7nZQjdUhctuhQofk7BGHuIy0c9Ez8BNhXs=\ngithub.com/gkampitakis/ciinfo v0.3.2/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo=\ngithub.com/gkampitakis/go-diff v1.3.2 h1:Qyn0J9XJSDTgnsgHRdz9Zp24RaJeKMUHg2+PDZZdC4M=\ngithub.com/gkampitakis/go-diff v1.3.2/go.mod h1:LLgOrpqleQe26cte8s36HTWcTmMEur6OPYerdAAS9tk=\ngithub.com/gkampitakis/go-snaps v0.5.15 h1:amyJrvM1D33cPHwVrjo9jQxX8g/7E2wYdZ+01KS3zGE=\ngithub.com/gkampitakis/go-snaps v0.5.15/go.mod h1:HNpx/9GoKisdhw9AFOBT1N7DBs9DiHo/hGheFGBZ+mc=\ngithub.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=\ngithub.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=\ngithub.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=\ngithub.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=\ngithub.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM=\ngithub.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=\ngithub.com/go-git/go-git/v5 v5.16.5 h1:mdkuqblwr57kVfXri5TTH+nMFLNUxIj9Z7F5ykFbw5s=\ngithub.com/go-git/go-git/v5 v5.16.5/go.mod h1:QOMLpNf1qxuSY4StA/ArOdfFR2TrKEjJiye2kel2m+M=\ngithub.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs=\ngithub.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw=\ngithub.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs=\ngithub.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=\ngithub.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=\ngithub.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=\ngithub.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=\ngithub.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=\ngithub.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=\ngithub.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=\ngithub.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=\ngithub.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=\ngithub.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=\ngithub.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg=\ngithub.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic=\ngithub.com/go-openapi/jsonpointer v0.21.1/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk=\ngithub.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=\ngithub.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=\ngithub.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU=\ngithub.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0=\ngithub.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=\ngithub.com/go-sql-driver/mysql v1.9.2 h1:4cNKDYQ1I84SXslGddlsrMhc8k4LeDVj6Ad6WRjiHuU=\ngithub.com/go-sql-driver/mysql v1.9.2/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=\ngithub.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=\ngithub.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=\ngithub.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=\ngithub.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=\ngithub.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=\ngithub.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=\ngithub.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=\ngithub.com/gobuffalo/envy v1.6.5 h1:X3is06x7v0nW2xiy2yFbbIjwHz57CD6z6MkvqULTCm8=\ngithub.com/gobuffalo/envy v1.6.5/go.mod h1:N+GkhhZ/93bGZc6ZKhJLP6+m+tCNPKwgSpH9kaifseQ=\ngithub.com/gobuffalo/flect v1.0.3 h1:xeWBM2nui+qnVvNM4S3foBhCAL2XgPU+a7FdpelbTq4=\ngithub.com/gobuffalo/flect v1.0.3/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs=\ngithub.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=\ngithub.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=\ngithub.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=\ngithub.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=\ngithub.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=\ngithub.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=\ngithub.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=\ngithub.com/golang-migrate/migrate/v4 v4.19.0 h1:RcjOnCGz3Or6HQYEJ/EEVLfWnmw9KnoigPSjzhCuaSE=\ngithub.com/golang-migrate/migrate/v4 v4.19.0/go.mod h1:9dyEcu+hO+G9hPSw8AIg50yg622pXJsoHItQnDGZkI0=\ngithub.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=\ngithub.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=\ngithub.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=\ngithub.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=\ngithub.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=\ngithub.com/golang/mock v1.7.0-rc.1 h1:YojYx61/OLFsiv6Rw1Z96LpldJIy31o+UHmwAUMJ6/U=\ngithub.com/golang/mock v1.7.0-rc.1/go.mod h1:s42URUywIqd+OcERslBJvOjepvNymP31m3q8d/GkuRs=\ngithub.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=\ngithub.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=\ngithub.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=\ngithub.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=\ngithub.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=\ngithub.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=\ngithub.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=\ngithub.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=\ngithub.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=\ngithub.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=\ngithub.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=\ngithub.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=\ngithub.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=\ngithub.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=\ngithub.com/google/cel-go v0.26.0 h1:DPGjXackMpJWH680oGY4lZhYjIameYmR+/6RBdDGmaI=\ngithub.com/google/cel-go v0.26.0/go.mod h1:A9O8OU9rdvrK5MQyrqfIxo1a0u4g3sF8KB6PUIaryMM=\ngithub.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=\ngithub.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw=\ngithub.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=\ngithub.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=\ngithub.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=\ngithub.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=\ngithub.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=\ngithub.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=\ngithub.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=\ngithub.com/google/go-containerregistry v0.20.7 h1:24VGNpS0IwrOZ2ms2P1QE3Xa5X9p4phx0aUgzYzHW6I=\ngithub.com/google/go-containerregistry v0.20.7/go.mod h1:Lx5LCZQjLH1QBaMPeGwsME9biPeo1lPx6lbGj/UmzgM=\ngithub.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=\ngithub.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=\ngithub.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=\ngithub.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 h1:z2ogiKUYzX5Is6zr/vP9vJGqPwcdqsWjOt+V8J7+bTc=\ngithub.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI=\ngithub.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=\ngithub.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=\ngithub.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=\ngithub.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE=\ngithub.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w=\ngithub.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=\ngithub.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=\ngithub.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=\ngithub.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=\ngithub.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY=\ngithub.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo=\ngithub.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA=\ngithub.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=\ngithub.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20210315223345-82c243799c99 h1:JYghRBlGCZyCF2wNUJ8W0cwaQdtpcssJ4CgC406g+WU=\ngithub.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20210315223345-82c243799c99/go.mod h1:3bDW6wMZJB7tiONtC/1Xpicra6Wp5GgbTbQWCbI5fkc=\ngithub.com/grpc-ecosystem/grpc-gateway/v2 v2.27.4 h1:kEISI/Gx67NzH3nJxAmY/dGac80kKZgZt134u7Y/k1s=\ngithub.com/grpc-ecosystem/grpc-gateway/v2 v2.27.4/go.mod h1:6Nz966r3vQYCqIzWsuEl9d7cf7mRhtDmm++sOxlnfxI=\ngithub.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg=\ngithub.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY=\ngithub.com/h2non/go-is-svg v0.0.0-20160927212452-35e8c4b0612c h1:fEE5/5VNnYUoBOj2I9TP8Jc+a7lge3QWn9DKE7NCwfc=\ngithub.com/h2non/go-is-svg v0.0.0-20160927212452-35e8c4b0612c/go.mod h1:ObS/W+h8RYb1Y7fYivughjxojTmIu5iAIjSrSLCLeqE=\ngithub.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=\ngithub.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=\ngithub.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=\ngithub.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=\ngithub.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=\ngithub.com/hashicorp/golang-lru/arc/v2 v2.0.7 h1:QxkVTxwColcduO+LP7eJO56r2hFiG8zEbfAAzRv52KQ=\ngithub.com/hashicorp/golang-lru/arc/v2 v2.0.7/go.mod h1:Pe7gBlGdc8clY5LJ0LpJXMt5AmgmWNH1g+oFFVUHOEc=\ngithub.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=\ngithub.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=\ngithub.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI=\ngithub.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=\ngithub.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI=\ngithub.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=\ngithub.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=\ngithub.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=\ngithub.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=\ngithub.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=\ngithub.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=\ngithub.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=\ngithub.com/joelanford/ignore v0.1.1 h1:vKky5RDoPT+WbONrbQBgOn95VV/UPh4ejlyAbbzgnQk=\ngithub.com/joelanford/ignore v0.1.1/go.mod h1:8eho/D8fwQ3rIXrLwE23AaeaGDNXqLE9QJ3zJ4LIPCw=\ngithub.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=\ngithub.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=\ngithub.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=\ngithub.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=\ngithub.com/joshdk/go-junit v1.0.0 h1:S86cUKIdwBHWwA6xCmFlf3RTLfVXYQfvanM5Uh+K6GE=\ngithub.com/joshdk/go-junit v1.0.0/go.mod h1:TiiV0PqkaNfFXjEiyjWM3XXrhVyCa1K4Zfga6W52ung=\ngithub.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=\ngithub.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=\ngithub.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=\ngithub.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=\ngithub.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=\ngithub.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=\ngithub.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=\ngithub.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co=\ngithub.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0=\ngithub.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=\ngithub.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=\ngithub.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=\ngithub.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=\ngithub.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=\ngithub.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=\ngithub.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=\ngithub.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=\ngithub.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=\ngithub.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=\ngithub.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=\ngithub.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=\ngithub.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=\ngithub.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw=\ngithub.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o=\ngithub.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk=\ngithub.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw=\ngithub.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=\ngithub.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=\ngithub.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0=\ngithub.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE=\ngithub.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=\ngithub.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=\ngithub.com/markbates/inflect v1.0.4 h1:5fh1gzTFhfae06u3hzHYO9xe3l3v3nW5Pwt3naLTP5g=\ngithub.com/markbates/inflect v1.0.4/go.mod h1:1fR9+pO2KHEO9ZRtto13gDwwZaAKstQzferVeWqbgNs=\ngithub.com/maruel/natural v1.1.1 h1:Hja7XhhmvEFhcByqDoHz9QZbkWey+COd9xWfCfn1ioo=\ngithub.com/maruel/natural v1.1.1/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg=\ngithub.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=\ngithub.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=\ngithub.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=\ngithub.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=\ngithub.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=\ngithub.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=\ngithub.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=\ngithub.com/mattn/go-sqlite3 v1.14.32 h1:JD12Ag3oLy1zQA+BNn74xRgaBbdhbNIDYvQUEuuErjs=\ngithub.com/mattn/go-sqlite3 v1.14.32/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=\ngithub.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=\ngithub.com/maxbrunsfeld/counterfeiter/v6 v6.12.1 h1:D4O2wLxB384TS3ohBJMfolnxb4qGmoZ1PnWNtit8LYo=\ngithub.com/maxbrunsfeld/counterfeiter/v6 v6.12.1/go.mod h1:RuJdxo0oI6dClIaMzdl3hewq3a065RH65dofJP03h8I=\ngithub.com/mfridman/tparse v0.18.0 h1:wh6dzOKaIwkUGyKgOntDW4liXSo37qg5AXbIhkMV3vE=\ngithub.com/mfridman/tparse v0.18.0/go.mod h1:gEvqZTuCgEhPbYk/2lS3Kcxg1GmTxxU7kTC8DvP0i/A=\ngithub.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs=\ngithub.com/miekg/dns v1.1.61/go.mod h1:mnAarhS3nWaW+NVP2wTkYVIZyHNJ098SJZUki3eykwQ=\ngithub.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU=\ngithub.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=\ngithub.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=\ngithub.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=\ngithub.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=\ngithub.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=\ngithub.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=\ngithub.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=\ngithub.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=\ngithub.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=\ngithub.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=\ngithub.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=\ngithub.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU=\ngithub.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=\ngithub.com/moby/sys/capability v0.4.0 h1:4D4mI6KlNtWMCM1Z/K0i7RV1FkX+DBDHKVJpCndZoHk=\ngithub.com/moby/sys/capability v0.4.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I=\ngithub.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg=\ngithub.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4=\ngithub.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=\ngithub.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko=\ngithub.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs=\ngithub.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=\ngithub.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=\ngithub.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=\ngithub.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ=\ngithub.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc=\ngithub.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=\ngithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=\ngithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=\ngithub.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=\ngithub.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=\ngithub.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=\ngithub.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=\ngithub.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=\ngithub.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=\ngithub.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=\ngithub.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=\ngithub.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=\ngithub.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=\ngithub.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=\ngithub.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY=\ngithub.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc=\ngithub.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=\ngithub.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=\ngithub.com/onsi/ginkgo/v2 v2.28.1 h1:S4hj+HbZp40fNKuLUQOYLDgZLwNUVn19N3Atb98NCyI=\ngithub.com/onsi/ginkgo/v2 v2.28.1/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE=\ngithub.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28=\ngithub.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg=\ngithub.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=\ngithub.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=\ngithub.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=\ngithub.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=\ngithub.com/opencontainers/runtime-spec v1.2.1 h1:S4k4ryNgEpxW1dzyqffOmhI1BHYcjzU8lpJfSlR0xww=\ngithub.com/opencontainers/runtime-spec v1.2.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=\ngithub.com/operator-framework/ansible-operator-plugins v1.42.2 h1:wACG1NLD93Cri5oaC9h+amjr12Upl0DktObjfpCT/0k=\ngithub.com/operator-framework/ansible-operator-plugins v1.42.2/go.mod h1:HfNrz3ek3tcdyIicPyOzSN4G4yb40aNvPB4wCcItT5M=\ngithub.com/operator-framework/api v0.34.0 h1:REiEaYhG1CWmDoajdcAdZqtgoljWG+ixMY59vUX5pFI=\ngithub.com/operator-framework/api v0.34.0/go.mod h1:eGncUNIYvWtfGCCKmLzGXvoi3P0TDf3Yd/Z0Sn9E6SQ=\ngithub.com/operator-framework/operator-lib v0.19.0 h1:az6ogYj21rtU0SF9uYctRLyKp2dtlqTsmpfehFy6Ce8=\ngithub.com/operator-framework/operator-lib v0.19.0/go.mod h1:KxycAjFnHt0DBtHmH3Jm7yHcY5sdrshPKTqM/HKAQ08=\ngithub.com/operator-framework/operator-manifest-tools v0.10.0 h1:+vtIElvGQ5e43gCD6fF65a0HNH3AD3LGnukUhpl9kjc=\ngithub.com/operator-framework/operator-manifest-tools v0.10.0/go.mod h1:eB/wnr0BOhMLNXPeceE+0p3vudP16zDNWP60Hvn3KaM=\ngithub.com/operator-framework/operator-registry v1.59.0 h1:SQhT0qMTYJXqStNhBOYXmLAMpS3eszzbcXAg5NLgJu8=\ngithub.com/operator-framework/operator-registry v1.59.0/go.mod h1:QE1RRQGe+iau8sfY10DbP3+eoahH0G0l+coYrnEzJgI=\ngithub.com/otiai10/copy v1.14.1 h1:5/7E6qsUMBaH5AnQ0sSLzzTg1oTECmcCmT6lvF45Na8=\ngithub.com/otiai10/copy v1.14.1/go.mod h1:oQwrEDDOci3IM8dJF0d8+jnbfPDllW6vUjNc3DoZm9I=\ngithub.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs=\ngithub.com/otiai10/mint v1.6.3/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM=\ngithub.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=\ngithub.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=\ngithub.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=\ngithub.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=\ngithub.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=\ngithub.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=\ngithub.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=\ngithub.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=\ngithub.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY=\ngithub.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg=\ngithub.com/proglottis/gpgme v0.1.5 h1:KCGyOw8sQ+SI96j6G8D8YkOGn+1TwbQTT9/zQXoVlz0=\ngithub.com/proglottis/gpgme v0.1.5/go.mod h1:5LoXMgpE4bttgwwdv9bLs/vwqv3qV7F4glEEZ7mRKrM=\ngithub.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=\ngithub.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=\ngithub.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=\ngithub.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=\ngithub.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=\ngithub.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=\ngithub.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=\ngithub.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=\ngithub.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=\ngithub.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=\ngithub.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=\ngithub.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=\ngithub.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4=\ngithub.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw=\ngithub.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=\ngithub.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=\ngithub.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=\ngithub.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=\ngithub.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=\ngithub.com/redis/go-redis/extra/rediscmd/v9 v9.10.0 h1:uTiEyEyfLhkw678n6EulHVto8AkcXVr8zUcBJNZ0ark=\ngithub.com/redis/go-redis/extra/rediscmd/v9 v9.10.0/go.mod h1:eFYL/99JvdLP4T9/3FZ5t2pClnv7mMskc+WstTcyVr4=\ngithub.com/redis/go-redis/extra/redisotel/v9 v9.10.0 h1:4z7/hCJ9Jft8EBb2tDmK38p2WjyIEJ1ShhhwAhjOCps=\ngithub.com/redis/go-redis/extra/redisotel/v9 v9.10.0/go.mod h1:B0thqLh4hB8MvvcUKSwyP5YiIcCCp8UrQ0cA9gEqyjk=\ngithub.com/redis/go-redis/v9 v9.10.0 h1:FxwK3eV8p/CQa0Ch276C7u2d0eNC9kCmAYQ7mCXCzVs=\ngithub.com/redis/go-redis/v9 v9.10.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw=\ngithub.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=\ngithub.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=\ngithub.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=\ngithub.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=\ngithub.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=\ngithub.com/rubenv/sql-migrate v1.8.0 h1:dXnYiJk9k3wetp7GfQbKJcPHjVJL6YK19tKj8t2Ns0o=\ngithub.com/rubenv/sql-migrate v1.8.0/go.mod h1:F2bGFBwCU+pnmbtNYDeKvSuvL6lBVtXDXUUv5t+u1qw=\ngithub.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=\ngithub.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=\ngithub.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=\ngithub.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=\ngithub.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ=\ngithub.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=\ngithub.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8=\ngithub.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM=\ngithub.com/secure-systems-lab/go-securesystemslib v0.9.1 h1:nZZaNz4DiERIQguNy0cL5qTdn9lR8XKHf4RUyG1Sx3g=\ngithub.com/secure-systems-lab/go-securesystemslib v0.9.1/go.mod h1:np53YzT0zXGMv6x4iEWc9Z59uR+x+ndLwCLqPYpLXVU=\ngithub.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw=\ngithub.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=\ngithub.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=\ngithub.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=\ngithub.com/sigstore/fulcio v1.8.5 h1:HYTD1/L5wlBp8JxsWxUf8hmfaNBBF/x3r3p5l6tZwbA=\ngithub.com/sigstore/fulcio v1.8.5/go.mod h1:tSLYK3JsKvJpDW1BsIsVHZgHj+f8TjXARzqIUWSsSPQ=\ngithub.com/sigstore/protobuf-specs v0.5.0 h1:F8YTI65xOHw70NrvPwJ5PhAzsvTnuJMGLkA4FIkofAY=\ngithub.com/sigstore/protobuf-specs v0.5.0/go.mod h1:+gXR+38nIa2oEupqDdzg4qSBT0Os+sP7oYv6alWewWc=\ngithub.com/sigstore/sigstore v1.10.4 h1:ytOmxMgLdcUed3w1SbbZOgcxqwMG61lh1TmZLN+WeZE=\ngithub.com/sigstore/sigstore v1.10.4/go.mod h1:tDiyrdOref3q6qJxm2G+JHghqfmvifB7hw+EReAfnbI=\ngithub.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=\ngithub.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w=\ngithub.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g=\ngithub.com/smallstep/pkcs7 v0.2.1 h1:6Kfzr/QizdIuB6LSv8y1LJdZ3aPSfTNhTLqAx9CTLfA=\ngithub.com/smallstep/pkcs7 v0.2.1/go.mod h1:RcXHsMfL+BzH8tRhmrF1NkkpebKpq3JEM66cOFxanf0=\ngithub.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw=\ngithub.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U=\ngithub.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=\ngithub.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=\ngithub.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=\ngithub.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=\ngithub.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=\ngithub.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=\ngithub.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=\ngithub.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=\ngithub.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=\ngithub.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU=\ngithub.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY=\ngithub.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 h1:pnnLyeX7o/5aX8qUQ69P/mLojDqwda8hFOCBTmP/6hw=\ngithub.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6/go.mod h1:39R/xuhNgVhi+K0/zst4TLrJrVmbm6LVgl4A0+ZFS5M=\ngithub.com/stoewer/go-strcase v1.3.1 h1:iS0MdW+kVTxgMoE1LAZyMiYJFKlOzLooE4MxjirtkAs=\ngithub.com/stoewer/go-strcase v1.3.1/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=\ngithub.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=\ngithub.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=\ngithub.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=\ngithub.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=\ngithub.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=\ngithub.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=\ngithub.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=\ngithub.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=\ngithub.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=\ngithub.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=\ngithub.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=\ngithub.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=\ngithub.com/thoas/go-funk v0.9.3 h1:7+nAEx3kn5ZJcnDm2Bh23N2yOtweO14bi//dvRtgLpw=\ngithub.com/thoas/go-funk v0.9.3/go.mod h1:+IWnUfUmFO1+WVYQWQtIJHeRRdaIyyYglZN7xzUPe4Q=\ngithub.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=\ngithub.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=\ngithub.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=\ngithub.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=\ngithub.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=\ngithub.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=\ngithub.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=\ngithub.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=\ngithub.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY=\ngithub.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=\ngithub.com/vbatts/tar-split v0.12.2 h1:w/Y6tjxpeiFMR47yzZPlPj/FcPLpXbTUi/9H7d3CPa4=\ngithub.com/vbatts/tar-split v0.12.2/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA=\ngithub.com/vbauerster/mpb/v8 v8.10.2 h1:2uBykSHAYHekE11YvJhKxYmLATKHAGorZwFlyNw4hHM=\ngithub.com/vbauerster/mpb/v8 v8.10.2/go.mod h1:+Ja4P92E3/CorSZgfDtK46D7AVbDqmBQRTmyTqPElo0=\ngithub.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=\ngithub.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=\ngithub.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ=\ngithub.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=\ngithub.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=\ngithub.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=\ngithub.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=\ngithub.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=\ngo.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo=\ngo.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E=\ngo.etcd.io/etcd/api/v3 v3.6.0 h1:vdbkcUBGLf1vfopoGE/uS3Nv0KPyIpUV/HM6w9yx2kM=\ngo.etcd.io/etcd/api/v3 v3.6.0/go.mod h1:Wt5yZqEmxgTNJGHob7mTVBJDZNXiHPtXTcPab37iFOw=\ngo.etcd.io/etcd/client/pkg/v3 v3.6.0 h1:nchnPqpuxvv3UuGGHaz0DQKYi5EIW5wOYsgUNRc365k=\ngo.etcd.io/etcd/client/pkg/v3 v3.6.0/go.mod h1:Jv5SFWMnGvIBn8o3OaBq/PnT0jjsX8iNokAUessNjoA=\ngo.etcd.io/etcd/client/v3 v3.6.0 h1:/yjKzD+HW5v/3DVj9tpwFxzNbu8hjcKID183ug9duWk=\ngo.etcd.io/etcd/client/v3 v3.6.0/go.mod h1:Jzk/Knqe06pkOZPHXsQ0+vNDvMQrgIqJ0W8DwPdMJMg=\ngo.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=\ngo.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=\ngo.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=\ngo.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=\ngo.opentelemetry.io/contrib/bridges/prometheus v0.61.0 h1:RyrtJzu5MAmIcbRrwg75b+w3RlZCP0vJByDVzcpAe3M=\ngo.opentelemetry.io/contrib/bridges/prometheus v0.61.0/go.mod h1:tirr4p9NXbzjlbruiRGp53IzlYrDk5CO2fdHj0sSSaY=\ngo.opentelemetry.io/contrib/exporters/autoexport v0.61.0 h1:XfzKtKSrbtYk9TNCF8dkO0Y9M7IOfb4idCwBOTwGBiI=\ngo.opentelemetry.io/contrib/exporters/autoexport v0.61.0/go.mod h1:N6otC+qXTD5bAnbK2O1f/1SXq3cX+3KYSWrkBUqG0cw=\ngo.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 h1:YH4g8lQroajqUwWbq/tr2QX1JFmEXaDLgG+ew9bLMWo=\ngo.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ=\ngo.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18=\ngo.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg=\ngo.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms=\ngo.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g=\ngo.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.12.2 h1:06ZeJRe5BnYXceSM9Vya83XXVaNGe3H1QqsvqRANQq8=\ngo.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.12.2/go.mod h1:DvPtKE63knkDVP88qpatBj81JxN+w1bqfVbsbCbj1WY=\ngo.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.12.2 h1:tPLwQlXbJ8NSOfZc4OkgU5h2A38M4c9kfHSVc4PFQGs=\ngo.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.12.2/go.mod h1:QTnxBwT/1rBIgAG1goq6xMydfYOBKU6KTiYF4fp5zL8=\ngo.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.36.0 h1:zwdo1gS2eH26Rg+CoqVQpEK1h8gvt5qyU5Kk5Bixvow=\ngo.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.36.0/go.mod h1:rUKCPscaRWWcqGT6HnEmYrK+YNe5+Sw64xgQTOJ5b30=\ngo.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.36.0 h1:gAU726w9J8fwr4qRDqu1GYMNNs4gXrU+Pv20/N1UpB4=\ngo.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.36.0/go.mod h1:RboSDkp7N292rgu+T0MgVt2qgFGu6qa1RpZDOtpL76w=\ngo.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 h1:GqRJVj7UmLjCVyVJ3ZFLdPRmhDUp2zFmQe3RHIOsw24=\ngo.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0/go.mod h1:ri3aaHSmCTVYu2AWv44YMauwAQc0aqI9gHKIcSbI1pU=\ngo.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 h1:lwI4Dc5leUqENgGuQImwLo4WnuXFPetmPpkLi2IrX54=\ngo.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0/go.mod h1:Kz/oCE7z5wuyhPxsXDuaPteSWqjSBD5YaSdbxZYGbGk=\ngo.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0 h1:nRVXXvf78e00EwY6Wp0YII8ww2JVWshZ20HfTlE11AM=\ngo.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0/go.mod h1:r49hO7CgrxY9Voaj3Xe8pANWtr0Oq916d0XAmOoCZAQ=\ngo.opentelemetry.io/otel/exporters/prometheus v0.58.0 h1:CJAxWKFIqdBennqxJyOgnt5LqkeFRT+Mz3Yjz3hL+h8=\ngo.opentelemetry.io/otel/exporters/prometheus v0.58.0/go.mod h1:7qo/4CLI+zYSNbv0GMNquzuss2FVZo3OYrGh96n4HNc=\ngo.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.12.2 h1:12vMqzLLNZtXuXbJhSENRg+Vvx+ynNilV8twBLBsXMY=\ngo.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.12.2/go.mod h1:ZccPZoPOoq8x3Trik/fCsba7DEYDUnN6yX79pgp2BUQ=\ngo.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.36.0 h1:rixTyDGXFxRy1xzhKrotaHy3/KXdPhlWARrCgK+eqUY=\ngo.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.36.0/go.mod h1:dowW6UsM9MKbJq5JTz2AMVp3/5iW5I/TStsk8S+CfHw=\ngo.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.36.0 h1:G8Xec/SgZQricwWBJF/mHZc7A02YHedfFDENwJEdRA0=\ngo.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.36.0/go.mod h1:PD57idA/AiFD5aqoxGxCvT/ILJPeHy3MjqU/NS7KogY=\ngo.opentelemetry.io/otel/log v0.12.2 h1:yob9JVHn2ZY24byZeaXpTVoPS6l+UrrxmxmPKohXTwc=\ngo.opentelemetry.io/otel/log v0.12.2/go.mod h1:ShIItIxSYxufUMt+1H5a2wbckGli3/iCfuEbVZi/98E=\ngo.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g=\ngo.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc=\ngo.opentelemetry.io/otel/sdk v1.40.0 h1:KHW/jUzgo6wsPh9At46+h4upjtccTmuZCFAc9OJ71f8=\ngo.opentelemetry.io/otel/sdk v1.40.0/go.mod h1:Ph7EFdYvxq72Y8Li9q8KebuYUr2KoeyHx0DRMKrYBUE=\ngo.opentelemetry.io/otel/sdk/log v0.12.2 h1:yNoETvTByVKi7wHvYS6HMcZrN5hFLD7I++1xIZ/k6W0=\ngo.opentelemetry.io/otel/sdk/log v0.12.2/go.mod h1:DcpdmUXHJgSqN/dh+XMWa7Vf89u9ap0/AAk/XGLnEzY=\ngo.opentelemetry.io/otel/sdk/log/logtest v0.0.0-20250521073539-a85ae98dcedc h1:uqxdywfHqqCl6LmZzI3pUnXT1RGFYyUgxj0AkWPFxi0=\ngo.opentelemetry.io/otel/sdk/log/logtest v0.0.0-20250521073539-a85ae98dcedc/go.mod h1:TY/N/FT7dmFrP/r5ym3g0yysP1DefqGpAZr4f82P0dE=\ngo.opentelemetry.io/otel/sdk/metric v1.40.0 h1:mtmdVqgQkeRxHgRv4qhyJduP3fYJRMX4AtAlbuWdCYw=\ngo.opentelemetry.io/otel/sdk/metric v1.40.0/go.mod h1:4Z2bGMf0KSK3uRjlczMOeMhKU2rhUqdWNoKcYrtcBPg=\ngo.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZYblVjw=\ngo.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA=\ngo.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4=\ngo.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE=\ngo.podman.io/common v0.65.0 h1:8JNl25U4VpKDkFHSymSPm4te7ZQHJbfAB/l2FqtmYEg=\ngo.podman.io/common v0.65.0/go.mod h1:+lJu8KHeoDQsD9HDdiFaMaOUiqPLQnK406WuLnqM7Z0=\ngo.podman.io/image/v5 v5.37.0 h1:yzgQybwuWIIeK63hu+mQqna/wOh96XD5cpVc6j8Dg5M=\ngo.podman.io/image/v5 v5.37.0/go.mod h1:+s2Sx5dia/jVeT8tI3r2NAPrARMiDdbEq3QPIQogx3I=\ngo.podman.io/storage v1.60.0 h1:bWNSrR58nxg39VNFDSx3m0AswbvyzPGOo5XsUfomTao=\ngo.podman.io/storage v1.60.0/go.mod h1:NK+rsWJVuQeCM7ifv7cxD3abegWxwtW/3OkuSUJJoE4=\ngo.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=\ngo.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=\ngo.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=\ngo.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=\ngo.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=\ngo.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=\ngo.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=\ngo.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=\ngo.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=\ngo.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=\ngolang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=\ngolang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=\ngolang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=\ngolang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=\ngolang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=\ngolang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=\ngolang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=\ngolang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=\ngolang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=\ngolang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=\ngolang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o=\ngolang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8=\ngolang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=\ngolang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=\ngolang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=\ngolang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=\ngolang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=\ngolang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=\ngolang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=\ngolang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=\ngolang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=\ngolang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=\ngolang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=\ngolang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c=\ngolang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU=\ngolang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=\ngolang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=\ngolang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=\ngolang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=\ngolang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=\ngolang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=\ngolang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=\ngolang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=\ngolang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=\ngolang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=\ngolang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=\ngolang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=\ngolang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=\ngolang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw=\ngolang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=\ngolang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=\ngolang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=\ngolang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=\ngolang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=\ngolang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=\ngolang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=\ngolang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=\ngolang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=\ngolang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=\ngolang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=\ngolang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=\ngolang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=\ngolang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=\ngolang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=\ngolang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=\ngolang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=\ngolang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=\ngolang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=\ngolang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=\ngolang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=\ngolang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY=\ngolang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww=\ngolang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=\ngolang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=\ngolang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=\ngolang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=\ngolang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=\ngolang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=\ngolang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=\ngolang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=\ngolang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=\ngolang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=\ngolang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=\ngolang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=\ngolang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=\ngolang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=\ngolang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=\ngolang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=\ngolang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=\ngolang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=\ngolang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=\ngolang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=\ngolang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=\ngolang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=\ngolang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=\ngolang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc=\ngolang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg=\ngolang.org/x/tools/go/expect v0.1.0-deprecated h1:jY2C5HGYR5lqex3gEniOQL0r7Dq5+VGVgY1nudX5lXY=\ngolang.org/x/tools/go/expect v0.1.0-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY=\ngolang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM=\ngolang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8=\ngolang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw=\ngomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=\ngomodules.xyz/jsonpatch/v3 v3.0.1 h1:Te7hKxV52TKCbNYq3t84tzKav3xhThdvSsSp/W89IyI=\ngomodules.xyz/jsonpatch/v3 v3.0.1/go.mod h1:CBhndykehEwTOlEfnsfJwvkFQbSN8YZFr9M+cIHAJto=\ngomodules.xyz/orderedmap v0.1.0 h1:fM/+TGh/O1KkqGR5xjTKg6bU8OKBkg7p0Y+x/J9m8Os=\ngomodules.xyz/orderedmap v0.1.0/go.mod h1:g9/TPUCm1t2gwD3j3zfV8uylyYhVdCNSi+xCEIu7yTU=\ngonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=\ngonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=\ngoogle.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=\ngoogle.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=\ngoogle.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=\ngoogle.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=\ngoogle.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=\ngoogle.golang.org/genproto v0.0.0-20251202230838-ff82c1b0f217 h1:GvESR9BIyHUahIb0NcTum6itIWtdoglGX+rnGxm2934=\ngoogle.golang.org/genproto v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:yJ2HH4EHEDTd3JiLmhds6NkJ17ITVYOdV3m3VKOnws0=\ngoogle.golang.org/genproto/googleapis/api v0.0.0-20251222181119-0a764e51fe1b h1:uA40e2M6fYRBf0+8uN5mLlqUtV192iiksiICIBkYJ1E=\ngoogle.golang.org/genproto/googleapis/api v0.0.0-20251222181119-0a764e51fe1b/go.mod h1:Xa7le7qx2vmqB/SzWUBa7KdMjpdpAHlh5QCSnjessQk=\ngoogle.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b h1:Mv8VFug0MP9e5vUxfBcE3vUkV6CImK3cMNMIDFjmzxU=\ngoogle.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=\ngoogle.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=\ngoogle.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=\ngoogle.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=\ngoogle.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=\ngoogle.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=\ngoogle.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE=\ngoogle.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=\ngoogle.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=\ngoogle.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=\ngoogle.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=\ngoogle.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=\ngoogle.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=\ngoogle.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=\ngoogle.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=\ngoogle.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=\ngoogle.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=\ngoogle.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=\ngoogle.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=\ngopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=\ngopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=\ngopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=\ngopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=\ngopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=\ngopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=\ngopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=\ngopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=\ngopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=\ngopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=\ngopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=\ngopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=\ngopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=\ngopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=\ngotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=\nhelm.sh/helm/v3 v3.18.6 h1:S/2CqcYnNfLckkHLI0VgQbxgcDaU3N4A/46E3n9wSNY=\nhelm.sh/helm/v3 v3.18.6/go.mod h1:L/dXDR2r539oPlFP1PJqKAC1CUgqHJDLkxKpDGrWnyg=\nhonnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=\nhonnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=\nk8s.io/api v0.33.9 h1:QoLQgQzazgHUK3C7SzakD+QlfgSoppNNStUXHPRFAg0=\nk8s.io/api v0.33.9/go.mod h1:bzXsnmnU3fJS7sqS0/B7yuR++M0VEEcb0xbntSxLrzU=\nk8s.io/apiextensions-apiserver v0.33.9 h1:p5Ao3yrNWmdoVtqEdfhU9ujTNde7PtSgxPPTOh/jHEA=\nk8s.io/apiextensions-apiserver v0.33.9/go.mod h1:LqqV//JrmiZ3k5EX8loTQFELYROprV0bZcstPi16fso=\nk8s.io/apimachinery v0.33.9 h1:axzrsWm3cbGIlzMAMrN+FY0VZ3Y/0zGJLVBdge1GUMo=\nk8s.io/apimachinery v0.33.9/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=\nk8s.io/apiserver v0.33.9 h1:7pVTaj4Llf652oHZEA1WaWwTkVIRbZwZkjeSOU1CHV0=\nk8s.io/apiserver v0.33.9/go.mod h1:uwDR3UtZ201iSNiEnFay8huQtccygneqWjnzsUzzWjo=\nk8s.io/cli-runtime v0.33.9 h1:+wfn402vwycirwoUgi1Qhkv/66ZFXCY0QZ1/o1gl/j0=\nk8s.io/cli-runtime v0.33.9/go.mod h1:sKkwL+mK4yBcQMBkj0oRMkr8MICb2vmIo+W6LbcTN6A=\nk8s.io/client-go v0.33.9 h1:eKERuku85ZVS2vatHNvbGZBSjUN0b3aDBZZwG/8pSzs=\nk8s.io/client-go v0.33.9/go.mod h1:GR4liooJGOd/cQrYpohyOWaoZbE4l9oPw2KZzpUZA74=\nk8s.io/component-base v0.33.9 h1:hE7jBcCH43udsELSJxfN4JEKR/WkFP6REUHe2+ZyWME=\nk8s.io/component-base v0.33.9/go.mod h1:ptjJCkb60xUJ3cAWtuqi5bWYXKqF/cwHnc/2eT9qzak=\nk8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=\nk8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=\nk8s.io/kube-openapi v0.0.0-20250610211856-8b98d1ed966a h1:ZV3Zr+/7s7aVbjNGICQt+ppKWsF1tehxggNfbM7XnG8=\nk8s.io/kube-openapi v0.0.0-20250610211856-8b98d1ed966a/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8=\nk8s.io/kubectl v0.33.9 h1:E2TxYlknKaSQWK/fVyuU9v67/BC1YWGzHHaU6NLOrnk=\nk8s.io/kubectl v0.33.9/go.mod h1:ezz1y1xXaQ+NL10iGl9lk9IQU5ZB5K4fHVlNRxwTdEc=\nk8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck=\nk8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=\noras.land/oras-go/v2 v2.6.0 h1:X4ELRsiGkrbeox69+9tzTu492FMUu7zJQW6eJU+I2oc=\noras.land/oras-go/v2 v2.6.0/go.mod h1:magiQDfG6H1O9APp+rOsvCPcW1GD2MM7vgnKY0Y+u1o=\nsigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.33.0 h1:qPrZsv1cwQiFeieFlRqT627fVZ+tyfou/+S5S0H5ua0=\nsigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.33.0/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=\nsigs.k8s.io/controller-runtime v0.21.0 h1:CYfjpEuicjUecRk+KAeyYh+ouUBn4llGyDYytIGcJS8=\nsigs.k8s.io/controller-runtime v0.21.0/go.mod h1:OSg14+F65eWqIu4DceX7k/+QRAbTTvxeQSNSOQpukWM=\nsigs.k8s.io/controller-tools v0.18.0 h1:rGxGZCZTV2wJreeRgqVoWab/mfcumTMmSwKzoM9xrsE=\nsigs.k8s.io/controller-tools v0.18.0/go.mod h1:gLKoiGBriyNh+x1rWtUQnakUYEujErjXs9pf+x/8n1U=\nsigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=\nsigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=\nsigs.k8s.io/kubebuilder/v4 v4.6.0 h1:SBc37jghs3L2UaEL91A1t5K5dANrEviUDuNic9hMQSw=\nsigs.k8s.io/kubebuilder/v4 v4.6.0/go.mod h1:zlXrnLiJPDPpK4hKCUrlgzzLOusfA8Sd8tpYGIrvD00=\nsigs.k8s.io/kustomize/api v0.19.0 h1:F+2HB2mU1MSiR9Hp1NEgoU2q9ItNOaBJl0I4Dlus5SQ=\nsigs.k8s.io/kustomize/api v0.19.0/go.mod h1:/BbwnivGVcBh1r+8m3tH1VNxJmHSk1PzP5fkP6lbL1o=\nsigs.k8s.io/kustomize/kyaml v0.19.0 h1:RFge5qsO1uHhwJsu3ipV7RNolC7Uozc0jUBC/61XSlA=\nsigs.k8s.io/kustomize/kyaml v0.19.0/go.mod h1:FeKD5jEOH+FbZPpqUghBP8mrLjJ3+zD3/rf9NNu1cwY=\nsigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=\nsigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=\nsigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=\nsigs.k8s.io/structured-merge-diff/v4 v4.7.0 h1:qPeWmscJcXP0snki5IYF79Z8xrl8ETFxgMd7wez1XkI=\nsigs.k8s.io/structured-merge-diff/v4 v4.7.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=\nsigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=\nsigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=\nsigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=\n"
  },
  {
    "path": "hack/check-error-log-msg-format.sh",
    "content": "#!/bin/bash\n\nset -o nounset\nset -o pipefail\n\nsource \"hack/lib/common.sh\"\n\necho \"Checking format of error and log messages...\"\nallfiles=$(listFiles|grep -v ./internal/bindata/...)\nlog_case_output=$(grep -PRn '(Error\\((.*[Ee]rr|nil), |^(?!.*(fmt|errors)).+\\.Error(f)?\\(|Fatal(f)?\\(|Info(f)?\\(|Warn(f)?\\()\"[[:lower:]]' $allfiles | sort -u)\nif [ -n \"${log_case_output}\" ]; then\n  echo -e \"Log messages do not begin with upper case:\\n${log_case_output}\"\nfi\nerr_case_output=$(grep -ERn '(errors\\.New|fmt\\.Errorf)\\(\"[[:upper:]]' $allfiles | sort -u)\nif [ -n \"${err_case_output}\" ]; then\n  echo -e \"Error messages do not begin with lower case:\\n${err_case_output}\"\nfi\nerr_punct_output=$(grep -ERn '(errors\\.New|fmt\\.Errorf)\\(\".*\\.\"' $allfiles | sort -u)\nif [ -n \"${err_punct_output}\" ]; then\n  echo -e \"Error messages should not have ending punctuation:\\n${err_punct_output}\"\nfi\n\nif [[ -n \"$log_case_output\" || -n \"$err_case_output\" || -n \"$err_punct_output\" ]]; then\n  exit 255\nfi\n"
  },
  {
    "path": "hack/check-license.sh",
    "content": "#!/bin/bash\n\nset -o errexit\nset -o nounset\nset -o pipefail\n\nsource \"hack/lib/common.sh\"\n\necho \"Checking for license header...\"\nallfiles=$(listFiles|grep -v ./internal/bindata/...)\nlicRes=\"\"\nfor file in $allfiles; do\n  if ! head -n3 \"${file}\" | grep -Eq \"(Copyright|generated|GENERATED|Licensed)\" ; then\n    licRes=\"${licRes}\\n\"$(echo -e \"  ${file}\")\n  fi\ndone\nif [ -n \"${licRes}\" ]; then\n  echo -e \"license header checking failed:\\n${licRes}\"\n  exit 255\nfi\n"
  },
  {
    "path": "hack/check-links.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\nsource ./hack/lib/common.sh\n\nheader_text \"Building the website\"\ndocker volume create sdk-html\ntrap_add \"docker volume rm sdk-html\" EXIT\ndocker run --rm -v \"$(pwd):/src\" -v sdk-html:/src/website/public klakegg/hugo:0.73.0-ext-ubuntu -s website\n\nheader_text \"Checking links\"\n# For config explanation: https://github.com/gjtorikian/html-proofer#special-cases-for-the-command-line\ndocker run --rm -v sdk-html:/target klakegg/html-proofer:3.19.2 /target \\\n  --empty-alt-ignore \\\n  --http-status-ignore 429 \\\n  --allow_hash_href \\\n  --typhoeus-config='{\"ssl_verifypeer\":false,\"followlocation\":true,\"connecttimeout\":600,\"timeout\":600}' \\\n  --hydra-config='{\"max_concurrency\":5}' \\\n  --url-ignore \"/github.com\\/operator-framework\\/operator-sdk\\/edit\\/master\\//,https://docs.github.com/en/get-started/quickstart/fork-a-repo,https://github.com/operator-framework/operator-sdk/settings/access\"\n"
  },
  {
    "path": "hack/check-olm.sh",
    "content": "#!/bin/bash\n\nFAILED=\"false\"\n\n# Get list of unique release versions sorted highest to lowest\nRELEASES=($(curl https://api.github.com/repos/operator-framework/operator-lifecycle-manager/releases | jq '.[] | .name' | tr -d '\"'))\n\n# Get unique release versions ignoring patch versions\nRELEASES_UNIQUE_NO_PATCH=($(printf '%s\\n' \"${RELEASES[@]}\" | awk -F. '{ print $1 \".\" $2 \".\" }' | sort -ur))\n\n# Get highest patch version for each unique minor version\n# Loop through the latest 3 unique release versions\nVERSIONS_STRING=\"\"\nfor i in {2..0}\ndo\n    MINOR_VERSION=$(echo \"${RELEASES_UNIQUE_NO_PATCH[i]}\")\n    PATCH_ARRAY=($(printf '%s\\n' \"${RELEASES[@]}\" | grep ${RELEASES_UNIQUE_NO_PATCH[i]} | awk -F. '{ print $1 \".\" $2 \".\" $3 }' | sort -ur))\n    VERSIONS_STRING+=$(echo \" ${PATCH_ARRAY[0]}\" | tr -d 'v')\ndone\n\nVERSIONS_ARRAY=($(echo \"$VERSIONS_STRING\" | tr ' ' '\\n'))\n\n# check Makefile OLM_VERSIONS\nEXPECTED=\"OLM_VERSIONS =$VERSIONS_STRING\"\nACTUAL=$(cat Makefile | grep \"OLM_VERSIONS =\")\n\nif [[ $ACTUAL != $EXPECTED ]]\nthen\n    echo -e \"\\nMakefile does not have the most up to date OLM release versions.\\nEXPECTED: $EXPECTED | ACTUAL: $ACTUAL\"\n    FAILED=\"true\"\nfi\n\n# check internal/bindata/olm/versions.go\nAVAILABLE_VERSIONS=($(cat internal/bindata/olm/versions.go | awk '/var availableVersions/,/},\\n}/' | tr -d '\\t' | tr -d ' \":{},'))\n\nACTUAL=\"\"\nfor i in {1..3}\ndo \n    ACTUAL+=\" ${AVAILABLE_VERSIONS[i]}\"\ndone\n\nif [[ $ACTUAL != $VERSIONS_STRING ]]\nthen\n    echo -e \"\\ninternal/bindata/olm/versions.go does not have the most up to date OLM release versions as availableVersions.\\nEXPECTED: $VERSIONS_STRING | ACTUAL: $ACTUAL\"\n    FAILED=\"true\"\nfi\n\n# check internal/testutils/olm.go\nEXPECTED=\"OlmVersionForTestSuite = \\\"${VERSIONS_ARRAY[2]}\\\"\"\nACTUAL=$(cat internal/testutils/olm.go | grep \"OlmVersionForTestSuite =\" | tr -d '\\t')\n\nif [[ $ACTUAL != $EXPECTED ]]\nthen\n    echo -e \"\\ninternal/testutils/olm.go does not have the most up to date OLM release versions.\\nEXPECTED: $EXPECTED | ACTUAL: $ACTUAL\"\n    FAILED=\"true\"\nfi\n\n# check docs - website/content/en/docs/overview/_index.md\nEXPECTED=\"Currently, the officially supported OLM Versions are: ${VERSIONS_ARRAY[0]}, ${VERSIONS_ARRAY[1]}, and ${VERSIONS_ARRAY[2]}\"\nACTUAL=$(cat website/content/en/docs/overview/_index.md | grep \"Currently, the officially supported OLM Versions are:\")\n\nif [[ $ACTUAL != $EXPECTED ]]\nthen\n    echo -e \"\\nDocs (website/content/en/docs/overview/_index.md) does not have the most up to date OLM release versions.\\nEXPECTED: $EXPECTED | ACTUAL: $ACTUAL\"\n    FAILED=\"true\"\nfi\n\n# State pass or fail result\nif [[ $FAILED != \"false\" ]]\nthen\n    echo -e \"\\nOLM Version Check - \\033[0;31mFAILED\\033[0m\"\n    exit 1\nelse\n    echo -e \"\\nOLM Version Check - \\033[0;32mPASSED\\033[0m\"\nfi\n"
  },
  {
    "path": "hack/generate/cli-doc/gen-cli-doc.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/cobra\"\n\t\"github.com/spf13/cobra/doc\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/cli\"\n)\n\nconst fmTemplate = `---\ntitle: \"%s\"\n---\n`\n\nfunc main() {\n\tcurrentDir, err := os.Getwd()\n\tif err != nil {\n\t\tlog.Fatalf(\"Failed to get current directory: %v\", err)\n\t}\n\n\tcliDocsPath := filepath.Join(currentDir, \"website\", \"content\", \"en\", \"docs\", \"cli\")\n\t_, cliRoot := cli.GetPluginsCLIAndRoot()\n\tcliRoot.DisableAutoGenTag = true\n\trecreateDocDir(cliRoot, cliDocsPath)\n}\n\n// htmlFormatter will replace angular brackets (`<` and `>`) with its character entitites\n// `&lt;` and `&gt;`\nfunc htmlFormatter(rootCmd *cobra.Command) {\n\n\tfor _, cmds := range rootCmd.Commands() {\n\t\tif len(cmds.Commands()) > 0 {\n\t\t\thtmlFormatter(cmds)\n\t\t}\n\n\t\tcmds.Long = strings.ReplaceAll(cmds.Long, \"<\", \"&lt;\")\n\t\tcmds.Long = strings.ReplaceAll(cmds.Long, \">\", \"&gt;\")\n\t}\n\n}\n\n// recreateDocDir removes and recreates the CLI doc directory for rootCmd\n// at docPath to ensure that stale files (e.g. from renamed or removed CLI subcommands)\n// are removed.\nfunc recreateDocDir(rootCmd *cobra.Command, docPath string) {\n\tcurrentDir, err := os.Getwd()\n\tif err != nil {\n\t\tlog.Fatalf(\"Failed to get current directory: %v\", err)\n\t}\n\n\tif err := os.Rename(docPath+\"/_index.md\", currentDir+\"/tmp_index.md\"); err != nil {\n\t\tlog.Fatalf(\"Failed to move existing index: %v\", err)\n\t}\n\tif err := os.RemoveAll(docPath); err != nil {\n\t\tlog.Fatalf(\"Failed to remove existing generated docs: %v\", err)\n\t}\n\tif err := os.MkdirAll(docPath, 0755); err != nil {\n\t\tlog.Fatalf(\"Failed to re-create docs directory: %v\", err)\n\t}\n\n\tfilePrepender := func(filename string) string {\n\t\tname := filepath.Base(filename)\n\t\tbase := strings.TrimSuffix(name, path.Ext(name))\n\t\treturn fmt.Sprintf(fmTemplate, strings.ReplaceAll(base, \"_\", \" \"))\n\t}\n\tlinkHandler := func(name string) string {\n\t\tbase := strings.TrimSuffix(name, path.Ext(name))\n\t\treturn \"../\" + base\n\t}\n\n\thtmlFormatter(rootCmd)\n\n\terr = doc.GenMarkdownTreeCustom(rootCmd, docPath, filePrepender, linkHandler)\n\tif err != nil {\n\t\tlog.Fatalf(\"Failed to generate documentation: %v\", err)\n\t}\n\n\tif err := os.Rename(currentDir+\"/tmp_index.md\", docPath+\"/_index.md\"); err != nil {\n\t\tlog.Fatalf(\"Failed to move existing index: %v\", err)\n\t}\n}\n"
  },
  {
    "path": "hack/generate/cncf-maintainers/main.go",
    "content": "package main\n\nimport (\n\t\"log\"\n\t\"os\"\n\n\t\"k8s.io/utils/set\"\n\t\"sigs.k8s.io/yaml\"\n)\n\ntype ownersMap map[string][]string\ntype aliasesMap struct {\n\tAliases map[string][]string `json:\"aliases,omitempty\"`\n}\n\nfunc main() {\n\townersData, err := os.ReadFile(\"OWNERS\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\taliasData, err := os.ReadFile(\"OWNERS_ALIASES\")\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tvar owners ownersMap\n\tif err := yaml.Unmarshal(ownersData, &owners); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tvar aliases aliasesMap\n\tif err := yaml.Unmarshal(aliasData, &aliases); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\texpandedOwners := make(map[string]set.Set[string])\n\tfor group, ownersAliases := range owners {\n\t\texpandedOwners[group] = set.New[string]()\n\t\tfor _, alias := range ownersAliases {\n\t\t\tif members, ok := aliases.Aliases[alias]; ok {\n\t\t\t\texpandedOwners[group].Insert(members...)\n\t\t\t} else {\n\t\t\t\tlog.Fatalf(\"alias %q is listed in OWNERS group %q but was not found in OWNERS_ALIASES\", alias, group)\n\t\t\t}\n\t\t}\n\t}\n\n\toutOwners := make(map[string][]string)\n\tfor g, m := range expandedOwners {\n\t\toutOwners[g] = m.SortedList()\n\t}\n\n\tout, err := yaml.Marshal(outOwners)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tif err := os.WriteFile(\".cncf-maintainers\", out, 0644); err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n"
  },
  {
    "path": "hack/generate/migrate-markers.sh",
    "content": "#!/usr/bin/env bash\n\n# Migrate old CSV annotations to new markers.\n# Example:\n# $ ./migrate-markers.sh *.go\n\nOLD_MARKER_BASE=\"operator-sdk:gen-csv:customresourcedefinitions\"\nNEW_MARKER_BASE=\"operator-sdk:csv:customresourcedefinitions\"\n\nSPEC_TYPE=\"spec\"\nSTATUS_TYPE=\"status\"\n\nfunction migrate_displayName() {\n  local old_marker_pattern=\"${OLD_MARKER_BASE}\"'\\.displayName=\"([^\"]+)\"'\n  local new_marker_pattern=\"${NEW_MARKER_BASE}\"':displayName=\"\\1\"'\n\n  sed -i -E 's/'$old_marker_pattern'/'$new_marker_pattern'/g' \"$1\"\n}\n\nfunction migrate_resources() {\n  local old_marker_pattern_1=\"${OLD_MARKER_BASE}\"'\\.resources=\"([^\\,]+)\\,([^\\,]+)\\,\\\\\"([^\\\\]+)\\\\\"\"'\n  local old_marker_pattern_2=\"${OLD_MARKER_BASE}\"'\\.resources=\"([^\\,]+)\\,([^\\,]+)\\,\"'\n  local new_marker_pattern_1=\"${NEW_MARKER_BASE}\"':resources={\\1,\\2,\"\\3\"}'\n  local new_marker_pattern_2=\"${NEW_MARKER_BASE}\"':resources={\\1,\\2,}'\n\n  sed -i -E 's/'$old_marker_pattern_1'/'$new_marker_pattern_1'/g' \"$1\"\n  sed -i -E 's/'$old_marker_pattern_2'/'$new_marker_pattern_2'/g' \"$1\"\n}\n\nfunction migrate_typeDescriptors() {\n  local type=$2\n  local old_marker_true_pattern=\"${OLD_MARKER_BASE}\\.${type}Descriptors=true\"\n  local old_marker_false_pattern=\"${OLD_MARKER_BASE}\\.${type}Descriptors=false\"\n  local new_marker_pattern=\"${NEW_MARKER_BASE}:type=${type}\"\n\n  sed -i -E 's/'$old_marker_true_pattern'/'$new_marker_pattern'/g' \"$1\"\n  sed -i -E 's/'$old_marker_false_pattern'//g' \"$1\"\n}\n\nfunction migrate_typeDescriptors_displayName() {\n  local type=$2\n  local old_marker_pattern=\"${OLD_MARKER_BASE}\\.${type}Descriptors\"'\\.displayName=\"([^\"]+)\"'\n  local new_marker_pattern=\"${NEW_MARKER_BASE}:type=${type}\"',displayName=\"\\1\"'\n\n  sed -i -E 's/'$old_marker_pattern'/'$new_marker_pattern'/g' \"$1\"\n}\n\nfunction migrate_typeDescriptors_xDescriptors() {\n  local type=$2\n  local old_marker_pattern=\"${OLD_MARKER_BASE}\\.${type}Descriptors\"'\\.x-descriptors=\"([^\"]+)\"'\n  local new_marker_pattern=\"${NEW_MARKER_BASE}:type=${type}\"',xDescriptors=\"\\1\"'\n\n  sed -i -E 's/'$old_marker_pattern'/'$new_marker_pattern'/g' \"$1\"\n}\n\nset -eu\nshopt -s extglob nullglob\nFILES=$*\nshopt -u extglob nullglob\n\nfor file in $FILES; do\n  if ! [[ \"$file\" =~ .*\\.go ]]; then\n    continue\n  fi\n  # Globals\n  migrate_displayName \"$file\"\n  migrate_resources \"$file\"\n  # Spec descriptors\n  migrate_typeDescriptors \"$file\" $SPEC_TYPE\n  migrate_typeDescriptors_displayName \"$file\" $SPEC_TYPE\n  migrate_typeDescriptors_xDescriptors \"$file\" $SPEC_TYPE\n  # Status descriptors\n  migrate_typeDescriptors \"$file\" $STATUS_TYPE\n  migrate_typeDescriptors_displayName \"$file\" $STATUS_TYPE\n  migrate_typeDescriptors_xDescriptors \"$file\" $STATUS_TYPE\ndone\n"
  },
  {
    "path": "hack/generate/olm_bindata.sh",
    "content": "#!/usr/bin/env bash\n\nbase_version=0.16.1\n\nfunction version_gt() {\n    test \"$(printf '%s\\n' \"$@\" | sort -V | head -n 1)\" != \"$1\";\n}\n\nfunction get_olm_manifests() {\n    echo \"downloading olm manifests for version ${1}\"\n    tag=$1\n    if version_gt ${1} $base_version; then\n        tag=\"v\"$1\n    fi\n    echo \"using the olm tag ${tag}\"\n    curl -L -o olm-manifests/$1-olm.yaml \"https://github.com/operator-framework/operator-lifecycle-manager/releases/download/${tag}/olm.yaml\"\n    curl -L -o olm-manifests/$1-crds.yaml \"https://github.com/operator-framework/operator-lifecycle-manager/releases/download/${tag}/crds.yaml\"\n}\n\nfunction remove_olm_manifests {\n    rm -rf olm-manifests\n}\n\n# check for files starting with the name \"manifests\" inside internal/bindata/olm folder\nfunction delete_old_olmbindata {\n    echo \"Deleting previous versions of olm-bindata files if they exist\"\n    find internal/bindata/olm -maxdepth 1 -type f -name manifests* -exec rm {} \\;\n}\n\nfunction generate_bindata() {\n    $(go env GOPATH)/bin/go-bindata -o manifests.go -pkg olm olm-manifests/\n    mv manifests.go internal/bindata/olm/\n\n    remove_olm_manifests\n}\n\n# delete bindata if it already exists\ndelete_old_olmbindata\n\n# get go-bindata tool\ngo install github.com/go-bindata/go-bindata/...@latest\n\nmkdir olm-manifests\nfor v in $@; do\n    echo \"processing version $v\"\n    get_olm_manifests $v\ndone\n\ngenerate_bindata\nremove_olm_manifests\n\ngo mod tidy\n"
  },
  {
    "path": "hack/generate/samples/generate_testdata.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage main\n\nimport (\n\t\"flag\"\n\t\"os\"\n\t\"path/filepath\"\n\n\t\"github.com/operator-framework/operator-sdk/hack/generate/samples/internal/helm\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\n\tgolang \"github.com/operator-framework/operator-sdk/hack/generate/samples/internal/go\"\n\t\"github.com/operator-framework/operator-sdk/internal/testutils\"\n)\n\nfunc main() {\n\t// binaryPath allow inform the binary that should be used.\n\t// By default it is operator-sdk\n\tvar binaryPath string\n\n\tflag.StringVar(&binaryPath, \"bin\", testutils.BinaryName, \"Binary path that should be used\")\n\tflag.Parse()\n\n\t// Make the binary path absolute if pathed, for reproducibility and debugging purposes.\n\tif dir, _ := filepath.Split(binaryPath); dir != \"\" {\n\t\ttmp, err := filepath.Abs(binaryPath)\n\t\tif err != nil {\n\t\t\tlog.Fatalf(\"Failed to make binary path %q absolute: %v\", binaryPath, err)\n\t\t}\n\t\tbinaryPath = tmp\n\t}\n\n\twd, err := os.Getwd()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// samplesPath is the path where all samples should be generated\n\tsamplesPath := filepath.Join(wd, \"testdata\")\n\tlog.Infof(\"writing sample directories under %s\", samplesPath)\n\n\tlog.Infof(\"creating Helm Memcached Sample\")\n\thelm.GenerateMemcachedSamples(binaryPath, samplesPath)\n\n\tlog.Infof(\"creating Go Memcached Sample with Webhooks\")\n\tgolang.GenerateMemcachedSamples(binaryPath, samplesPath)\n}\n"
  },
  {
    "path": "hack/generate/samples/internal/go/generate.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage golang\n\nimport (\n\t\"path/filepath\"\n\n\twithcustomization \"github.com/operator-framework/operator-sdk/hack/generate/samples/internal/go/memcached-with-customization\"\n)\n\nfunc GenerateMemcachedSamples(binaryPath, rootPath string) {\n\n\t// TODO: replace the Memcached implementation and update the tutorial\n\t// to use the deploy.image/v1-alpha plugin to do the scaffold instead\n\t// to create an empty scaffold add all code. So that, we can also\n\t// ensure that the tutorial follows the good practices\n\twithcustomization.GenerateSample(binaryPath, filepath.Join(rootPath, \"go\", \"v4\"))\n\twithcustomization.GenerateSample(binaryPath, filepath.Join(rootPath, \"go\", \"v4\", \"monitoring\"))\n}\n"
  },
  {
    "path": "hack/generate/samples/internal/go/memcached-with-customization/e2e_test_code.go",
    "content": "package v3\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\tkbutil \"sigs.k8s.io/kubebuilder/v4/pkg/plugin/util\"\n\n\t\"github.com/operator-framework/operator-sdk/hack/generate/samples/internal/pkg\"\n)\n\n// implementingE2ETests will add e2e test for the sample\n// so that users are able to know how the can create their own e2e tests\nfunc (mh *Memcached) implementingE2ETests() {\n\tlog.Infof(\"implementing example e2e tests\")\n\n\t// testDir is testdata/go/v3/memcached-operator/test\n\ttestDir := filepath.Join(mh.ctx.Dir, \"test\")\n\t// testE2eDir is testdata/go/v3/memcached-operator/test/e2e\n\ttestE2eDir := filepath.Join(testDir, \"e2e\")\n\t// testUtilsDir is testdata/go/v3/memcached-operator/test/utils\n\ttestUtilsDir := filepath.Join(testDir, \"utils\")\n\n\t// Following we will create the directories\n\t// Create the golang files with a string replace inside only\n\t// Then, replace the string replace by the template contents\n\tmh.createDirs(testDir, testE2eDir, testUtilsDir)\n\tmh.createGoFiles(testE2eDir, testUtilsDir)\n\tmh.addContent(testE2eDir, testUtilsDir)\n\n\t// Add a target to run the tests into the Makefile\n\tmh.addTestE2eMakefileTarget()\n}\n\nfunc (mh *Memcached) addTestE2eMakefileTarget() {\n\terr := kbutil.ReplaceInFile(filepath.Join(mh.ctx.Dir, \"Makefile\"),\n\t\t`KUBEBUILDER_ASSETS=\"$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)\" go test $$(go list ./... | grep -v /e2e) -coverprofile cover.out`,\n\t\t`KUBEBUILDER_ASSETS=\"$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)\"  go test $(go list ./... | grep -v /test/) -coverprofile cover.out`,\n\t)\n\tpkg.CheckError(\"replacing test target\", err)\n\n}\n\nfunc (mh *Memcached) addContent(testE2eDir string, testUtilsDir string) {\n\terr := kbutil.ReplaceInFile(filepath.Join(testE2eDir, \"e2e_suite_test.go\"),\n\t\t\"replace\",\n\t\te2eSuiteTemplate,\n\t)\n\tpkg.CheckError(\"replacing e2eSuiteTemplate\", err)\n\n\terr = kbutil.ReplaceInFile(filepath.Join(testUtilsDir, \"utils.go\"),\n\t\t\"replace\",\n\t\tutilsTemplate,\n\t)\n\tpkg.CheckError(\"replacing utils\", err)\n\n\tif generateWithMonitoring {\n\t\terr = kbutil.ReplaceInFile(filepath.Join(testE2eDir, \"e2e_test.go\"),\n\t\t\t\"replace\",\n\t\t\te2eWithMonitoringTemplate,\n\t\t)\n\t\tpkg.CheckError(\"replacing e2eWithMonitoringTemplate tests\", err)\n\n\t} else {\n\t\terr = kbutil.ReplaceInFile(filepath.Join(testE2eDir, \"e2e_test.go\"),\n\t\t\t\"replace\",\n\t\t\te2eTemplate,\n\t\t)\n\t\tpkg.CheckError(\"replacing e2eTemplate tests\", err)\n\t}\n}\n\nfunc (mh *Memcached) createGoFiles(testE2eDir string, testUtilsDir string) {\n\terr := os.WriteFile(filepath.Join(testE2eDir, \"e2e_suite_test.go\"), []byte(\"replace\"), 0644)\n\tpkg.CheckError(\"error to create file to add e2e_suite_test.go\", err)\n\n\terr = os.WriteFile(filepath.Join(testE2eDir, \"e2e_test.go\"), []byte(\"replace\"), 0644)\n\tpkg.CheckError(\"error to create file to add e2e_test.go\", err)\n\n\terr = os.WriteFile(filepath.Join(testUtilsDir, \"utils.go\"), []byte(\"replace\"), 0644)\n\tpkg.CheckError(\"error to create file to add utils.go\", err)\n}\n\nfunc (mh *Memcached) createDirs(testDir string, testE2eDir string, testUtilsDir string) {\n\terr := os.Mkdir(testDir, os.ModePerm)\n\tif !os.IsExist(err) {\n\t\tpkg.CheckError(\"error to create test dir\", err)\n\t}\n\terr = os.Mkdir(testE2eDir, os.ModePerm)\n\tif !os.IsExist(err) {\n\t\tpkg.CheckError(\"error to create test e2e dir\", err)\n\t}\n\terr = os.Mkdir(testUtilsDir, os.ModePerm)\n\tif !os.IsExist(err) {\n\t\tpkg.CheckError(\"error to create test utils dir\", err)\n\t}\n}\n\nconst e2eSuiteTemplate = `/*\nCopyright 2022.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage e2e\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\n// Run e2e tests using the Ginkgo runner.\nfunc TestE2E(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tfmt.Fprintf(GinkgoWriter, \"Starting Memcached Operator suite\\n\")\n\tRunSpecs(t, \"Memcached e2e suite\")\n}\n`\n\nconst e2eTemplate = `/*\nCopyright 2022.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage e2e\n\nimport (\n\t\"fmt\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"time\"\n\n\t//nolint:golint\n\t//nolint:revive\n\t. \"github.com/onsi/ginkgo/v2\"\n\n\t//nolint:golint\n\t//nolint:revive\n\t. \"github.com/onsi/gomega\"\n\n\t\"github.com/example/memcached-operator/test/utils\"\n)\n\n// constant parts of the file\nconst namespace = \"memcached-operator-system\"\n\nvar _ = Describe(\"memcached\", Ordered, func() {\n\tBeforeAll(func() {\n\t\t// The prometheus and the certmanager are installed in this test\n\t\t// because the Memcached sample has this option enable and\n\t\t// when we try to apply the manifests both will be required to be installed\n\t\tBy(\"installing prometheus operator\")\n\t\tExpect(utils.InstallPrometheusOperator()).To(Succeed())\n\n\t\tBy(\"installing the cert-manager\")\n\t\tExpect(utils.InstallCertManager()).To(Succeed())\n\n\t\t// The namespace can be created when we run make install\n\t\t// However, in this test we want ensure that the solution\n\t\t// can run in a ns labeled as restricted. Therefore, we are\n\t\t// creating the namespace an lebeling it.\n\t\tBy(\"creating manager namespace\")\n\t\tcmd := exec.Command(\"kubectl\", \"create\", \"ns\", namespace)\n\t\t_, _ = utils.Run(cmd)\n\n\t\t// Now, let's ensure that all namespaces can raise an Warn when we apply the manifests\n\t\t// and that the namespace where the Operator and Operand will run are enforced as\n\t\t// restricted so that we can ensure that both can be admitted and run with the enforcement\n\t\tBy(\"labeling all namespaces to warn when we apply the manifest if would violate the PodStandards\")\n\t\tcmd = exec.Command(\"kubectl\", \"label\", \"--overwrite\", \"ns\", \"--all\",\n\t\t\t\"pod-security.kubernetes.io/audit=restricted\",\n\t\t\t\"pod-security.kubernetes.io/enforce-version=v1.24\",\n\t\t\t\"pod-security.kubernetes.io/warn=restricted\")\n\t\t_, err := utils.Run(cmd)\n\t\tExpectWithOffset(1, err).NotTo(HaveOccurred())\n\n\t\tBy(\"labeling enforce the namespace where the Operator and Operand(s) will run\")\n\t\tcmd = exec.Command(\"kubectl\", \"label\", \"--overwrite\", \"ns\", namespace,\n\t\t\t\"pod-security.kubernetes.io/audit=restricted\",\n\t\t\t\"pod-security.kubernetes.io/enforce-version=v1.24\",\n\t\t\t\"pod-security.kubernetes.io/enforce=restricted\")\n\t\t_, err = utils.Run(cmd)\n\t\tExpect(err).To(Not(HaveOccurred()))\n\t})\n\n\tAfterAll(func() {\n\t\tBy(\"uninstalling the Prometheus manager bundle\")\n\t\tutils.UninstallPrometheusOperator()\n\n\t\tBy(\"uninstalling the cert-manager bundle\")\n\t\tutils.UninstallCertManager()\n\n\t\tBy(\"removing manager namespace\")\n\t\tcmd := exec.Command(\"kubectl\", \"create\", \"ns\", namespace)\n\t\t_, _ = utils.Run(cmd)\n\t})\n\n\tContext(\"Memcached Operator\", func() {\n\t\tIt(\"should run successfully\", func() {\n\t\t\tvar controllerPodName string\n\t\t\tvar err error\n\t\t\tprojectDir, _ := utils.GetProjectDir()\n\n\t\t\t// operatorImage stores the name of the image used in the example\n\t\t\tvar operatorImage = \"example.com/memcached-operator:v0.0.1\"\n\n\t\t\tBy(\"building the manager(Operator) image\")\n\t\t\tcmd := exec.Command(\"make\", \"docker-build\", fmt.Sprintf(\"IMG=%s\", operatorImage))\n\t\t\t_, err = utils.Run(cmd)\n\t\t\tExpectWithOffset(1, err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"loading the manager(Operator) image on Kind\")\n\t\t\terr = utils.LoadImageToKindClusterWithName(operatorImage)\n\t\t\tExpectWithOffset(1, err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"installing CRDs\")\n\t\t\tcmd = exec.Command(\"make\", \"install\")\n\t\t\t_, err = utils.Run(cmd)\n\t\t\tExpectWithOffset(1, err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"deploying the controller-manager\")\n\t\t\tcmd = exec.Command(\"make\", \"deploy\", fmt.Sprintf(\"IMG=%s\", operatorImage))\n\t\t\toutputMake, err := utils.Run(cmd)\n\t\t\tExpectWithOffset(1, err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"validating that manager Pod/container(s) are restricted\")\n\t\t\tExpectWithOffset(1, outputMake).NotTo(ContainSubstring(\"Warning: would violate PodSecurity\"))\n\n\t\t\tBy(\"validating that the controller-manager pod is running as expected\")\n\t\t\tverifyControllerUp := func() error {\n\t\t\t\t// Get pod name\n\t\t\t\tcmd = exec.Command(\"kubectl\", \"get\",\n\t\t\t\t\t\"pods\", \"-l\", \"control-plane=controller-manager\",\n\t\t\t\t\t\"-o\", \"go-template={{ range .items }}{{ if not .metadata.deletionTimestamp }}{{ .metadata.name }}\"+\n\t\t\t\t\t\t\"{{ \\\"\\\\n\\\" }}{{ end }}{{ end }}\",\n\t\t\t\t\t\"-n\", namespace,\n\t\t\t\t)\n\t\t\t\tpodOutput, err := utils.Run(cmd)\n\t\t\t\tExpectWithOffset(2, err).NotTo(HaveOccurred())\n\t\t\t\tpodNames := utils.GetNonEmptyLines(string(podOutput))\n\t\t\t\tif len(podNames) != 1 {\n\t\t\t\t\treturn fmt.Errorf(\"expect 1 controller pods running, but got %d\", len(podNames))\n\t\t\t\t}\n\t\t\t\tcontrollerPodName = podNames[0]\n\t\t\t\tExpectWithOffset(2, controllerPodName).Should(ContainSubstring(\"controller-manager\"))\n\n\t\t\t\t// Validate pod status\n\t\t\t\tcmd = exec.Command(\"kubectl\", \"get\",\n\t\t\t\t\t\"pods\", controllerPodName, \"-o\", \"jsonpath={.status.phase}\",\n\t\t\t\t\t\"-n\", namespace,\n\t\t\t\t)\n\t\t\t\tstatus, err := utils.Run(cmd)\n\t\t\t\tExpectWithOffset(2, err).NotTo(HaveOccurred())\n\t\t\t\tif string(status) != \"Running\" {\n\t\t\t\t\treturn fmt.Errorf(\"controller pod in %s status\", status)\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tEventuallyWithOffset(1, verifyControllerUp, time.Minute, time.Second).Should(Succeed())\n\n\t\t\tBy(\"creating an instance of the Memcached Operand(CR)\")\n\t\t\tEventuallyWithOffset(1, func() error {\n\t\t\t\tcmd = exec.Command(\"kubectl\", \"apply\", \"-f\", filepath.Join(projectDir,\n\t\t\t\t\t\"config/samples/cache_v1alpha1_memcached.yaml\"), \"-n\", namespace)\n\t\t\t\t_, err = utils.Run(cmd)\n\t\t\t\treturn err\n\t\t\t}, time.Minute, time.Second).Should(Succeed())\n\n\t\t\tBy(\"validating that pod(s) status.phase=Running\")\n\t\t\tgetMemcachedPodStatus := func() error {\n\t\t\t\tcmd = exec.Command(\"kubectl\", \"get\",\n\t\t\t\t\t\"pods\", \"-l\", \"app.kubernetes.io/name=memcached-operator\",\n\t\t\t\t\t\"-o\", \"jsonpath={.items[*].status}\", \"-n\", namespace,\n\t\t\t\t)\n\t\t\t\tstatus, err := utils.Run(cmd)\n\t\t\t\tfmt.Println(string(status))\n\t\t\t\tExpectWithOffset(2, err).NotTo(HaveOccurred())\n\t\t\t\tif !strings.Contains(string(status), \"\\\"phase\\\":\\\"Running\\\"\") {\n\t\t\t\t\treturn fmt.Errorf(\"memcached pod in %s status\", status)\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tEventuallyWithOffset(1, getMemcachedPodStatus, time.Minute, time.Second).Should(Succeed())\n\n\t\t\tBy(\"validating that the status of the custom resource created is updated or not\")\n\t\t\tgetStatus := func() error {\n\t\t\t\tcmd = exec.Command(\"kubectl\", \"get\", \"memcached\",\n\t\t\t\t\t\"memcached-sample\", \"-o\", \"jsonpath={.status.conditions}\",\n\t\t\t\t\t\"-n\", namespace,\n\t\t\t\t)\n\t\t\t\tstatus, err := utils.Run(cmd)\n\t\t\t\tfmt.Println(string(status))\n\t\t\t\tExpectWithOffset(2, err).NotTo(HaveOccurred())\n\t\t\t\tif !strings.Contains(string(status), \"Available\") {\n\t\t\t\t\treturn fmt.Errorf(\"status condition with type Available should be set\")\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tEventually(getStatus, time.Minute, time.Second).Should(Succeed())\n\t\t})\n\t})\n})\n`\n\nconst e2eWithMonitoringTemplate = `/*\nCopyright 2022.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage e2e\n\nimport (\n\t\"bufio\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t//nolint:golint\n\t//nolint:revive\n\t. \"github.com/onsi/ginkgo/v2\"\n\n\t//nolint:golint\n\t//nolint:revive\n\t. \"github.com/onsi/gomega\"\n\n\t\"github.com/example/memcached-operator/test/utils\"\n)\n\n// constant parts of the file\nconst (\n\tnamespace                                      = \"memcached-operator-system\"\n\tmemcachedDeploymentSizeUndesiredCountTotalName = \"memcached_deployment_size_undesired_count_total\"\n\ttokenRequestRawString                          = \"{\\\"apiVersion\\\": \\\"authentication.k8s.io/v1\\\", \\\"kind\\\": \\\"TokenRequest\\\"}\"\n)\n\n// tokenRequest is a trimmed down version of the authentication.k8s.io/v1/TokenRequest Type\n// that we want to use for extracting the token.\ntype tokenRequest struct {\n\tStatus struct {\n\t\tToken string \"json:\\\"token\\\"\"\n\t} \"json:\\\"status\\\"\"\n}\n\nvar _ = Describe(\"memcached\", Ordered, func() {\n\tBeforeAll(func() {\n\t\t// The prometheus and the certmanager are installed in this test\n\t\t// because the Memcached sample has this option enable and\n\t\t// when we try to apply the manifests both will be required to be installed\n\t\tBy(\"installing prometheus operator\")\n\t\tExpect(utils.InstallPrometheusOperator()).To(Succeed())\n\n\t\tBy(\"installing the cert-manager\")\n\t\tExpect(utils.InstallCertManager()).To(Succeed())\n\n\t\t// The namespace can be created when we run make install\n\t\t// However, in this test we want ensure that the solution\n\t\t// can run in a ns labeled as restricted. Therefore, we are\n\t\t// creating the namespace an lebeling it.\n\t\tBy(\"creating manager namespace\")\n\t\tcmd := exec.Command(\"kubectl\", \"create\", \"ns\", namespace)\n\t\t_, _ = utils.Run(cmd)\n\n\t\t// Now, let's ensure that all namespaces can raise an Warn when we apply the manifests\n\t\t// and that the namespace where the Operator and Operand will run are enforced as\n\t\t// restricted so that we can ensure that both can be admitted and run with the enforcement\n\t\tBy(\"labeling all namespaces to warn when we apply the manifest if would violate the PodStandards\")\n\t\tcmd = exec.Command(\"kubectl\", \"label\", \"--overwrite\", \"ns\", \"--all\",\n\t\t\t\"pod-security.kubernetes.io/audit=restricted\",\n\t\t\t\"pod-security.kubernetes.io/enforce-version=v1.24\",\n\t\t\t\"pod-security.kubernetes.io/warn=restricted\")\n\t\t_, err := utils.Run(cmd)\n\t\tExpectWithOffset(1, err).NotTo(HaveOccurred())\n\n\t\tBy(\"labeling enforce the namespace where the Operator and Operand(s) will run\")\n\t\tcmd = exec.Command(\"kubectl\", \"label\", \"--overwrite\", \"ns\", namespace,\n\t\t\t\"pod-security.kubernetes.io/audit=restricted\",\n\t\t\t\"pod-security.kubernetes.io/enforce-version=v1.24\",\n\t\t\t\"pod-security.kubernetes.io/enforce=restricted\")\n\t\t_, err = utils.Run(cmd)\n\t\tExpect(err).To(Not(HaveOccurred()))\n\t})\n\n\tAfterAll(func() {\n\t\tBy(\"uninstalling the Prometheus manager bundle\")\n\t\tutils.UninstallPrometheusOperator()\n\n\t\tBy(\"uninstalling the cert-manager bundle\")\n\t\tutils.UninstallCertManager()\n\n\t\tBy(\"removing manager namespace\")\n\t\tcmd := exec.Command(\"kubectl\", \"create\", \"ns\", namespace)\n\t\t_, _ = utils.Run(cmd)\n\t})\n\n\tContext(\"Memcached Operator\", func() {\n\t\tIt(\"should run successfully\", func() {\n\t\t\tvar controllerPodName string\n\t\t\tvar err error\n\t\t\tprojectDir, _ := utils.GetProjectDir()\n\n\t\t\t// operatorImage stores the name of the image used in the example\n\t\t\tvar operatorImage = \"example.com/memcached-operator:v0.0.1\"\n\n\t\t\tBy(\"building the manager(Operator) image\")\n\t\t\tcmd := exec.Command(\"make\", \"docker-build\", fmt.Sprintf(\"IMG=%s\", operatorImage))\n\t\t\t_, err = utils.Run(cmd)\n\t\t\tExpectWithOffset(1, err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"loading the manager(Operator) image on Kind\")\n\t\t\terr = utils.LoadImageToKindClusterWithName(operatorImage)\n\t\t\tExpectWithOffset(1, err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"installing CRDs\")\n\t\t\tcmd = exec.Command(\"make\", \"install\")\n\t\t\t_, err = utils.Run(cmd)\n\t\t\tExpectWithOffset(1, err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"deploying the controller-manager\")\n\t\t\tcmd = exec.Command(\"make\", \"deploy\", fmt.Sprintf(\"IMG=%s\", operatorImage))\n\t\t\toutputMake, err := utils.Run(cmd)\n\t\t\tExpectWithOffset(1, err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"validating that manager Pod/container(s) are restricted\")\n\t\t\tExpectWithOffset(1, outputMake).NotTo(ContainSubstring(\"Warning: would violate PodSecurity\"))\n\n\t\t\tBy(\"validating that the controller-manager pod is running as expected\")\n\t\t\tverifyControllerUp := func() error {\n\t\t\t\t// Get pod name\n\t\t\t\tcmd = exec.Command(\"kubectl\", \"get\",\n\t\t\t\t\t\"pods\", \"-l\", \"control-plane=controller-manager\",\n\t\t\t\t\t\"-o\", \"go-template={{ range .items }}{{ if not .metadata.deletionTimestamp }}{{ .metadata.name }}\"+\n\t\t\t\t\t\t\"{{ \\\"\\\\n\\\" }}{{ end }}{{ end }}\",\n\t\t\t\t\t\"-n\", namespace,\n\t\t\t\t)\n\t\t\t\tpodOutput, err := utils.Run(cmd)\n\t\t\t\tExpectWithOffset(2, err).NotTo(HaveOccurred())\n\t\t\t\tpodNames := utils.GetNonEmptyLines(string(podOutput))\n\t\t\t\tif len(podNames) != 1 {\n\t\t\t\t\treturn fmt.Errorf(\"expect 1 controller pods running, but got %d\", len(podNames))\n\t\t\t\t}\n\t\t\t\tcontrollerPodName = podNames[0]\n\t\t\t\tExpectWithOffset(2, controllerPodName).Should(ContainSubstring(\"controller-manager\"))\n\n\t\t\t\t// Validate pod status\n\t\t\t\tcmd = exec.Command(\"kubectl\", \"get\",\n\t\t\t\t\t\"pods\", controllerPodName, \"-o\", \"jsonpath={.status.phase}\",\n\t\t\t\t\t\"-n\", namespace,\n\t\t\t\t)\n\t\t\t\tstatus, err := utils.Run(cmd)\n\t\t\t\tExpectWithOffset(2, err).NotTo(HaveOccurred())\n\t\t\t\tif string(status) != \"Running\" {\n\t\t\t\t\treturn fmt.Errorf(\"controller pod in %s status\", status)\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tEventuallyWithOffset(1, verifyControllerUp, time.Minute, time.Second).Should(Succeed())\n\n\t\t\tBy(\"creating an instance of the Memcached Operand(CR)\")\n\t\t\tEventuallyWithOffset(1, func() error {\n\t\t\t\tcmd = exec.Command(\"kubectl\", \"apply\", \"-f\", filepath.Join(projectDir,\n\t\t\t\t\t\"config/samples/cache_v1alpha1_memcached.yaml\"), \"-n\", namespace)\n\t\t\t\t_, err = utils.Run(cmd)\n\t\t\t\treturn err\n\t\t\t}, time.Minute, time.Second).Should(Succeed())\n\n\t\t\tBy(\"validating that pod(s) status.phase=Running\")\n\t\t\tgetMemcachedPodStatus := func() error {\n\t\t\t\tcmd = exec.Command(\"kubectl\", \"get\",\n\t\t\t\t\t\"pods\", \"-l\", \"app.kubernetes.io/name=memcached-operator\",\n\t\t\t\t\t\"-o\", \"jsonpath={.items[*].status}\", \"-n\", namespace,\n\t\t\t\t)\n\t\t\t\tstatus, err := utils.Run(cmd)\n\t\t\t\tfmt.Println(string(status))\n\t\t\t\tExpectWithOffset(2, err).NotTo(HaveOccurred())\n\t\t\t\tif !strings.Contains(string(status), \"\\\"phase\\\":\\\"Running\\\"\") {\n\t\t\t\t\treturn fmt.Errorf(\"memcached pod in %s status\", status)\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tEventuallyWithOffset(1, getMemcachedPodStatus, time.Minute, time.Second).Should(Succeed())\n\n\t\t\tBy(\"validating that the status of the custom resource created is updated or not\")\n\t\t\tgetStatus := func() error {\n\t\t\t\tcmd = exec.Command(\"kubectl\", \"get\", \"memcached\",\n\t\t\t\t\t\"memcached-sample\", \"-o\", \"jsonpath={.status.conditions}\",\n\t\t\t\t\t\"-n\", namespace,\n\t\t\t\t)\n\t\t\t\tstatus, err := utils.Run(cmd)\n\t\t\t\tfmt.Println(string(status))\n\t\t\t\tExpectWithOffset(2, err).NotTo(HaveOccurred())\n\t\t\t\tif !strings.Contains(string(status), \"Available\") {\n\t\t\t\t\treturn fmt.Errorf(\"status condition with type Available should be set\")\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tEventually(getStatus, time.Minute, time.Second).Should(Succeed())\n\t\t})\n\t})\n\n\tContext(\"Memcached Operator metrics\", Ordered, func() {\n\t\tBeforeAll(func() {\n\t\t\tBy(\"granting permissions to access the metrics\")\n\t\t\tcmd := exec.Command(\"kubectl\",\n\t\t\t\t\"create\", \"clusterrolebinding\", \"metrics-memcached-operator\",\n\t\t\t\t\"--clusterrole=memcached-operator-metrics-reader\",\n\t\t\t\tfmt.Sprintf(\"--serviceaccount=%s:memcached-operator-controller-manager\", namespace))\n\t\t\t_, err := utils.Run(cmd)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t})\n\n\t\tAfterAll(func() {\n\t\t\tBy(\"removing permissions to access the metrics\")\n\t\t\tcmd := exec.Command(\"kubectl\", \"delete\",\n\t\t\t\t\"clusterrolebinding\", \"metrics-memcached-operator\")\n\t\t\t_, err := utils.Run(cmd)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t})\n\n\t\tIt(\"MemcachedDeploymentSizeUndesiredCountTotal should be increased when scaling the Memcached deployment\", func() {\n\t\t\tinitialMetricValue := getMetricValue(memcachedDeploymentSizeUndesiredCountTotalName)\n\n\t\t\tnumberOfScales := 5\n\t\t\tBy(fmt.Sprintf(\"scaling memcached-samle deployment %d times\", numberOfScales))\n\t\t\tscaleMemcachedSampleDeployment(numberOfScales)\n\n\t\t\tBy(fmt.Sprintf(\"validating MemcachedDeploymentSizeUndesiredCountTotal has increased by %d\", numberOfScales))\n\t\t\tfinalMetricValue := getMetricValue(memcachedDeploymentSizeUndesiredCountTotalName)\n\t\t\tExpect(finalMetricValue).Should(BeNumerically(\">=\", initialMetricValue+numberOfScales))\n\t\t})\n\t})\n})\n\n// getMetricValue will reach the Memcached operator metrics endpoint, validate the metric and extract its value\nfunc getMetricValue(metricName string) int {\n\t// reach the metrics endpoint and validate the metric exists\n\tmetricsEndpoint := curlMetrics()\n\tExpectWithOffset(1, metricsEndpoint).Should(ContainSubstring(metricName))\n\n\t// extract the metric value\n\tmetricValue, err := strconv.Atoi(parseMetricValue(metricsEndpoint, metricName))\n\tExpectWithOffset(1, err).NotTo(HaveOccurred())\n\n\treturn metricValue\n}\n\n// curlMetrics curl's the /metrics endpoint, returning all logs once a 200 status is returned.\nfunc curlMetrics() string {\n\tBy(\"reading the metrics token\")\n\t// Filter token query by service account in case more than one exists in a namespace.\n\ttoken, err := serviceAccountToken()\n\tExpectWithOffset(2, err).NotTo(HaveOccurred())\n\tExpectWithOffset(2, len(token)).To(BeNumerically(\">\", 0))\n\n\tBy(\"creating a curl pod\")\n\tcmd := exec.Command(\"kubectl\", \"run\", \"curl\", \"--image=curlimages/curl:7.68.0\",\n\t\t\"--restart=OnFailure\", \"-n\", \"default\", \"--\", \"curl\", \"-v\", \"-k\", \"-H\",\n\t\tfmt.Sprintf(\"Authorization: Bearer %s\", strings.TrimSpace(token)),\n\t\tfmt.Sprintf(\"https://memcached-operator-controller-manager-metrics-service.%s.svc:8443/metrics\", namespace))\n\t_, err = utils.Run(cmd)\n\tExpectWithOffset(2, err).NotTo(HaveOccurred())\n\n\tBy(\"validating that the curl pod is running as expected\")\n\tverifyCurlUp := func() error {\n\t\t// Validate pod status\n\t\tcmd := exec.Command(\"kubectl\", \"get\", \"pods\", \"curl\",\n\t\t\t\"-o\", \"jsonpath={.status.phase}\", \"-n\", \"default\")\n\t\tstatusOutput, err := utils.Run(cmd)\n\t\tstatus := string(statusOutput)\n\t\tExpectWithOffset(3, err).NotTo(HaveOccurred())\n\t\tif status != \"Completed\" && status != \"Succeeded\" {\n\t\t\treturn fmt.Errorf(\"curl pod in %s status\", status)\n\t\t}\n\t\treturn nil\n\t}\n\tEventuallyWithOffset(2, verifyCurlUp, 240*time.Second, time.Second).Should(Succeed())\n\n\tBy(\"validating that the metrics endpoint is serving as expected\")\n\tvar metricsEndpoint string\n\tgetCurlLogs := func() string {\n\t\tcmd = exec.Command(\"kubectl\", \"logs\", \"curl\", \"-n\", \"default\")\n\t\tmetricsEndpointOutput, err := utils.Run(cmd)\n\t\tExpectWithOffset(3, err).NotTo(HaveOccurred())\n\t\tmetricsEndpoint = string(metricsEndpointOutput)\n\t\treturn metricsEndpoint\n\t}\n\tEventuallyWithOffset(2, getCurlLogs, 10*time.Second, time.Second).Should(ContainSubstring(\"< HTTP/2 200\"))\n\n\tBy(\"cleaning up the curl pod\")\n\tcmd = exec.Command(\"kubectl\", \"delete\",\n\t\t\"pods/curl\", \"-n\", \"default\")\n\t_, err = utils.Run(cmd)\n\tExpectWithOffset(3, err).NotTo(HaveOccurred())\n\n\treturn metricsEndpoint\n}\n\n// serviceAccountToken provides a helper function that can provide you with a service account\n// token that you can use to interact with the service. This function leverages the k8s'\n// TokenRequest API in raw format in order to make it generic for all version of the k8s that\n// is currently being supported in kubebuilder test infra.\n// TokenRequest API returns the token in raw JWT format itself. There is no conversion required.\nfunc serviceAccountToken() (out string, err error) {\n\tBy(\"Creating the ServiceAccount token\")\n\tsecretName := \"memcached-operator-controller-manager-token-request\"\n\tprojectDir, _ := utils.GetProjectDir()\n\ttokenRequestFile := filepath.Join(projectDir, \"/test/e2e/\", secretName)\n\terr = os.WriteFile(tokenRequestFile, []byte(tokenRequestRawString), os.FileMode(0o755))\n\tif err != nil {\n\t\treturn out, err\n\t}\n\tvar rawJson string\n\tEventually(func() error {\n\t\t// Output of this is already a valid JWT token. No need to covert this from base64 to string format\n\t\tcmd := exec.Command(\"kubectl\", \"create\", \"--raw\",\n\t\t\tfmt.Sprintf(\"/api/v1/namespaces/%s/serviceaccounts/memcached-operator-controller-manager/token\", namespace),\n\t\t\t\"-f\", tokenRequestFile,\n\t\t)\n\t\trawJsonOutput, err := utils.Run(cmd)\n\t\trawJson = string(rawJsonOutput)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tvar token tokenRequest\n\t\terr = json.Unmarshal([]byte(rawJson), &token)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tout = token.Status.Token\n\t\treturn nil\n\t}, time.Minute, time.Second).Should(Succeed())\n\n\treturn out, err\n}\n\n// parseMetricValue will parse the metric value from the metrics endpoint\nfunc parseMetricValue(metricsEndpoint string, metricName string) string {\n\tr := strings.NewReader(metricsEndpoint)\n\tscan := bufio.NewScanner(r)\n\tfor scan.Scan() {\n\t\tmetricLine := scan.Text()\n\t\tif strings.HasPrefix(metricLine, metricName) {\n\t\t\tsplit := strings.Split(metricLine, \" \")\n\t\t\treturn split[1]\n\t\t}\n\t}\n\treturn \"\"\n}\n\n// scaleMemcachedSampleDeployment will scale memcached-sample deployment 'numberOfScales' times\nfunc scaleMemcachedSampleDeployment(numberOfScales int) {\n\tfor i := 1; i <= numberOfScales; i++ {\n\t\tcmd := exec.Command(\"kubectl\", \"scale\", \"--replicas=3\",\n\t\t\t\"deployment\", \"memcached-sample\", \"-n\", namespace)\n\t\t_, err := utils.Run(cmd)\n\t\tExpectWithOffset(1, err).NotTo(HaveOccurred())\n\t\ttime.Sleep(10 * time.Second)\n\t}\n}\n\nconst monitoringImportFragment = \"\\\"github.com/example/memcached-operator/monitoring\\\"\"\n\nconst incMemcachedDeploymentSizeUndesiredCountTotalFragment = \"monitoring.MemcachedDeploymentSizeUndesiredCountTotal.Inc()\"\n\nconst registerMetricsFragment = \"monitoring.RegisterMetrics()\"\n`\n\nconst utilsTemplate = `/*\nCopyright 2022.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage utils\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strings\"\n\n\t. \"github.com/onsi/ginkgo/v2\" //nolint:golint,revive\n)\n\nconst (\n\tprometheusOperatorVersion = \"0.51\"\n\tprometheusOperatorURL     = \"https://raw.githubusercontent.com/prometheus-operator/\" +\n\t\t\"prometheus-operator/release-%s/bundle.yaml\"\n\n\tcertmanagerVersion = \"v1.5.3\"\n\tcertmanagerURLTmpl = \"https://github.com/jetstack/cert-manager/releases/download/%s/cert-manager.yaml\"\n)\n\nfunc warnError(err error) {\n\tfmt.Fprintf(GinkgoWriter, \"warning: %v\\n\", err)\n}\n\n// InstallPrometheusOperator installs the prometheus Operator to be used to export the enabled metrics.\nfunc InstallPrometheusOperator() error {\n\turl := fmt.Sprintf(prometheusOperatorURL, prometheusOperatorVersion)\n\tcmd := exec.Command(\"kubectl\", \"apply\", \"-f\", url)\n\t_, err := Run(cmd)\n\treturn err\n}\n\n// Run executes the provided command within this context\nfunc Run(cmd *exec.Cmd) ([]byte, error) {\n\tdir, _ := GetProjectDir()\n\tcmd.Dir = dir\n\tfmt.Fprintf(GinkgoWriter, \"running dir: %s\\n\", cmd.Dir)\n\n\t// To allow make commands be executed from the project directory which is subdir on SDK repo\n\t// TODO:(user) You might not need the following code\n\tif err := os.Chdir(cmd.Dir); err != nil {\n\t\tfmt.Fprintf(GinkgoWriter, \"chdir dir: %s\\n\", err)\n\t}\n\n\tcmd.Env = append(os.Environ(), \"GO111MODULE=on\")\n\tcommand := strings.Join(cmd.Args, \" \")\n\tfmt.Fprintf(GinkgoWriter, \"running: %s\\n\", command)\n\toutput, err := cmd.CombinedOutput()\n\tif err != nil {\n\t\treturn output, fmt.Errorf(\"%s failed with error: (%v) %s\", command, err, string(output))\n\t}\n\n\treturn output, nil\n}\n\n// UninstallPrometheusOperator uninstalls the prometheus\nfunc UninstallPrometheusOperator() {\n\turl := fmt.Sprintf(prometheusOperatorURL, prometheusOperatorVersion)\n\tcmd := exec.Command(\"kubectl\", \"delete\", \"-f\", url)\n\tif _, err := Run(cmd); err != nil {\n\t\twarnError(err)\n\t}\n}\n\n// UninstallCertManager uninstalls the cert manager\nfunc UninstallCertManager() {\n\turl := fmt.Sprintf(certmanagerURLTmpl, certmanagerVersion)\n\tcmd := exec.Command(\"kubectl\", \"delete\", \"-f\", url)\n\tif _, err := Run(cmd); err != nil {\n\t\twarnError(err)\n\t}\n}\n\n// InstallCertManager installs the cert manager bundle.\nfunc InstallCertManager() error {\n\turl := fmt.Sprintf(certmanagerURLTmpl, certmanagerVersion)\n\tcmd := exec.Command(\"kubectl\", \"apply\", \"-f\", url)\n\tif _, err := Run(cmd); err != nil {\n\t\treturn err\n\t}\n\t// Wait for cert-manager-webhook to be ready, which can take time if cert-manager\n\t// was re-installed after uninstalling on a cluster.\n\tcmd = exec.Command(\"kubectl\", \"wait\", \"deployment.apps/cert-manager-webhook\",\n\t\t\"--for\", \"condition=Available\",\n\t\t\"--namespace\", \"cert-manager\",\n\t\t\"--timeout\", \"5m\",\n\t)\n\n\t_, err := Run(cmd)\n\treturn err\n}\n\n// LoadImageToKindCluster loads a local docker image to the kind cluster\nfunc LoadImageToKindClusterWithName(name string) error {\n\tcluster := \"kind\"\n\tif v, ok := os.LookupEnv(\"KIND_CLUSTER\"); ok {\n\t\tcluster = v\n\t}\n\tkindOptions := []string{\"load\", \"docker-image\", name, \"--name\", cluster}\n\tcmd := exec.Command(\"kind\", kindOptions...)\n\t_, err := Run(cmd)\n\treturn err\n}\n\n// GetNonEmptyLines converts given command output string into individual objects\n// according to line breakers, and ignores the empty elements in it.\nfunc GetNonEmptyLines(output string) []string {\n\tvar res []string\n\telements := strings.Split(output, \"\\n\")\n\tfor _, element := range elements {\n\t\tif element != \"\" {\n\t\t\tres = append(res, element)\n\t\t}\n\t}\n\n\treturn res\n}\n\n// GetProjectDir will return the directory where the project is\nfunc GetProjectDir() (string, error) {\n\twd, err := os.Getwd()\n\tif err != nil {\n\t\treturn wd, err\n\t}\n\twd = strings.Replace(wd, \"/test/e2e\", \"\", -1)\n\treturn wd, nil\n}\n\n// ReplaceInFile replaces all instances of old with new in the file at path.\nfunc ReplaceInFile(path, old, new string) error {\n\tinfo, err := os.Stat(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\t// false positive\n\t// nolint:gosec\n\tb, err := os.ReadFile(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif !strings.Contains(string(b), old) {\n\t\treturn errors.New(\"unable to find the content to be replaced\")\n\t}\n\ts := strings.Replace(string(b), old, new, -1)\n\terr = os.WriteFile(path, []byte(s), info.Mode())\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n`\n"
  },
  {
    "path": "hack/generate/samples/internal/go/memcached-with-customization/memcached_with_customization.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage v3\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\tkbutil \"sigs.k8s.io/kubebuilder/v4/pkg/plugin/util\"\n\n\t\"github.com/operator-framework/operator-sdk/hack/generate/samples/internal/pkg\"\n)\n\n// monitoringString is appended to logs and error messages to signify the inclusion of monitoring\nconst monitoringString = \" and monitoring\"\n\n// Memcached defines the Memcached Sample in GO using webhooks or webhooks and monitoring code\ntype Memcached struct {\n\tctx *pkg.SampleContext\n}\n\nvar generateWithMonitoring bool\nvar goFilesHeader string\nvar prometheusAPIVersion = \"v0.59.0\"\n\n// GenerateSample will call all actions to create the directory and generate the sample\n// Note that it should NOT be called in the e2e tests.\nfunc GenerateSample(binaryPath, samplesPath string) {\n\tgenerateWithMonitoring = strings.HasSuffix(samplesPath, \"monitoring\")\n\n\tlogInfo := \"starting to generate Go memcached sample with webhooks\"\n\terrorInfo := \"generating Go memcached with context: webhooks\"\n\n\tif generateWithMonitoring {\n\t\tlogInfo += monitoringString\n\t\terrorInfo += monitoringString\n\t}\n\n\tlog.Info(logInfo)\n\tctx, err := pkg.NewSampleContext(binaryPath, filepath.Join(samplesPath, \"memcached-operator\"), \"GO111MODULE=on\")\n\tpkg.CheckError(errorInfo, err)\n\n\tmemcached := Memcached{&ctx}\n\tmemcached.Prepare()\n\tmemcached.Run()\n}\n\n// Prepare the Context for the Memcached with webhooks or with webhooks and monitoring Go Sample\n// Note that sample directory will be re-created and the context data for the sample\n// will be set such as the domain and GVK.\nfunc (mh *Memcached) Prepare() {\n\tlogInfo := \"destroying directory for Go Memcached sample with webhooks\"\n\n\tif generateWithMonitoring {\n\t\tlogInfo += monitoringString\n\t}\n\n\tlog.Info(logInfo)\n\tmh.ctx.Destroy()\n\n\tlog.Infof(\"creating directory\")\n\terr := mh.ctx.Prepare()\n\tpkg.CheckError(\"creating directory for Go Sample\", err)\n\n\tlog.Infof(\"setting domain and GVK\")\n\tmh.ctx.Domain = \"example.com\"\n\tmh.ctx.Version = \"v1alpha1\"\n\tmh.ctx.Group = \"cache\"\n\tmh.ctx.Kind = \"Memcached\"\n}\n\n// Run the steps to create the Memcached with webhooks or with webhooks and monitoring Go Sample\nfunc (mh *Memcached) Run() {\n\n\tlog.Infof(\"creating the go/v3 project\")\n\terr := mh.ctx.Init(\n\t\t\"--plugins\", \"go/v4\",\n\t\t\"--project-version\", \"3\",\n\t\t\"--repo\", \"github.com/example/memcached-operator\",\n\t\t\"--domain\", mh.ctx.Domain)\n\tpkg.CheckError(\"creating the project\", err)\n\n\terr = mh.ctx.CreateAPI(\n\t\t\"--group\", mh.ctx.Group,\n\t\t\"--version\", mh.ctx.Version,\n\t\t\"--kind\", mh.ctx.Kind,\n\t\t\"--plugins\", \"deploy-image/v1-alpha\",\n\t\t\"--image\", \"memcached:1.4.36-alpine\",\n\t\t\"--image-container-command\", \"memcached,-m=64,-o,modern,-v\",\n\t\t\"--image-container-port\", \"11211\",\n\t\t\"--run-as-user\", \"1001\",\n\t\t\"--make=false\",\n\t\t\"--manifests=false\")\n\tpkg.CheckError(\"scaffolding apis\", err)\n\n\terr = mh.ctx.UncommentRestrictivePodStandards()\n\tpkg.CheckError(\"creating the bundle\", err)\n\n\tlog.Infof(\"implementing the API markers\")\n\tmh.implementingAPIMarkers()\n\n\tlog.Infof(\"implementing the Controller\")\n\tmh.implementingController()\n\n\tif generateWithMonitoring {\n\t\tgoGetcmd := exec.Command(\"go\", \"get\", fmt.Sprintf(\"%s@%s\", \"github.com/prometheus-operator/prometheus-operator\", prometheusAPIVersion))\n\t\tgoGetcmd.Dir = mh.ctx.Dir\n\t\tif _, err := mh.ctx.Run(goGetcmd); err != nil {\n\t\t\tpkg.CheckError(\"error getting prometheus dependency\", err)\n\t\t}\n\n\t\tlog.Infof(\"implementing Monitoring\")\n\t\tmh.implementingMonitoring()\n\t}\n\n\tlog.Infof(\"scaffolding webhook\")\n\terr = mh.ctx.CreateWebhook(\n\t\t\"--group\", mh.ctx.Group,\n\t\t\"--version\", mh.ctx.Version,\n\t\t\"--kind\", mh.ctx.Kind,\n\t\t\"--defaulting\")\n\tpkg.CheckError(\"scaffolding webhook\", err)\n\n\tmh.implementingWebhooks()\n\n\tmh.uncommentDefaultKustomizationV4()\n\tmh.uncommentManifestsKustomizationv4()\n\n\tmh.customizingMain()\n\n\tmh.implementingE2ETests()\n\n\tcmd := exec.Command(\"go\", \"mod\", \"tidy\")\n\tcmd.Dir = mh.ctx.Dir\n\t_, err = mh.ctx.Run(cmd)\n\tpkg.CheckError(\"Running go mod tidy\", err)\n\n\tif generateWithMonitoring {\n\t\tcmd := exec.Command(\"make\", \"generate-metricsdocs\")\n\t\tcmd.Dir = mh.ctx.Dir\n\t\t_, err = mh.ctx.Run(cmd)\n\t\tpkg.CheckError(\"Running make generate-metricsdocs\", err)\n\t}\n\n\tlog.Infof(\"creating the bundle\")\n\terr = mh.ctx.GenerateBundle()\n\tpkg.CheckError(\"creating the bundle\", err)\n\n\tlog.Infof(\"setting createdAt annotation\")\n\tcsv := filepath.Join(mh.ctx.Dir, \"bundle\", \"manifests\", mh.ctx.ProjectName+\".clusterserviceversion.yaml\")\n\terr = kbutil.ReplaceRegexInFile(csv, \"createdAt:.*\", createdAt)\n\tpkg.CheckError(\"setting createdAt annotation\", err)\n\n\tlog.Infof(\"stripping bundle annotations\")\n\terr = mh.ctx.StripBundleAnnotations()\n\tpkg.CheckError(\"stripping bundle annotations\", err)\n\n\tpkg.CheckError(\"formatting project\", mh.ctx.Make(\"fmt\"))\n\n\t// Clean up built binaries, if any.\n\tpkg.CheckError(\"cleaning up\", os.RemoveAll(filepath.Join(mh.ctx.Dir, \"bin\")))\n\n\t// TODO: remove when this is fixed\n\t// Update the test make target to properly shell out\n\t// to the go list command\n\tpkg.CheckError(\"fixing \\\"test\\\" make target\", kbutil.ReplaceInFile(filepath.Join(mh.ctx.Dir, \"Makefile\"),\n\t\t\"KUBEBUILDER_ASSETS=\\\"$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)\\\"  go test $(go list ./... | grep -v /test/) -coverprofile cover.out\",\n\t\t\"KUBEBUILDER_ASSETS=\\\"$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)\\\"  go test $(shell go list ./... | grep -v /test/) -coverprofile cover.out\"))\n\n}\n\n// uncommentDefaultKustomizationV4 will uncomment code in config/default/kustomization.yaml\nfunc (mh *Memcached) uncommentDefaultKustomizationV4() {\n\tvar err error\n\tkustomization := filepath.Join(mh.ctx.Dir, \"config\", \"default\", \"kustomization.yaml\")\n\tlog.Info(\"uncommenting config/default/kustomization.yaml to enable webhooks and ca injection\")\n\n\terr = kbutil.UncommentCode(kustomization, \"#- ../certmanager\", \"#\")\n\tpkg.CheckError(\"uncomment certmanager\", err)\n\n\terr = kbutil.UncommentCode(kustomization, \"#- ../prometheus\", \"#\")\n\tpkg.CheckError(\"uncomment prometheus\", err)\n\n\terr = kbutil.UncommentCode(kustomization, `#- path: cert_metrics_manager_patch.yaml\n#  target:\n#    kind: Deployment`, \"#\")\n\tpkg.CheckError(\"uncomment metrics with certmanager\", err)\n\n\terr = kbutil.UncommentCode(kustomization,\n\t\t`#replacements:\n# - source: # Uncomment the following block to enable certificates for metrics\n#     kind: Service\n#     version: v1\n#     name: controller-manager-metrics-service\n#     fieldPath: metadata.name\n#   targets:\n#     - select:\n#         kind: Certificate\n#         group: cert-manager.io\n#         version: v1\n#         name: metrics-certs\n#       fieldPaths:\n#         - spec.dnsNames.0\n#         - spec.dnsNames.1\n#       options:\n#         delimiter: '.'\n#         index: 0\n#         create: true\n#     - select: # Uncomment the following to set the Service name for TLS config in Prometheus ServiceMonitor\n#         kind: ServiceMonitor\n#         group: monitoring.coreos.com\n#         version: v1\n#         name: controller-manager-metrics-monitor\n#       fieldPaths:\n#         - spec.endpoints.0.tlsConfig.serverName\n#       options:\n#         delimiter: '.'\n#         index: 0\n#         create: true\n#\n# - source:\n#     kind: Service\n#     version: v1\n#     name: controller-manager-metrics-service\n#     fieldPath: metadata.namespace\n#   targets:\n#     - select:\n#         kind: Certificate\n#         group: cert-manager.io\n#         version: v1\n#         name: metrics-certs\n#       fieldPaths:\n#         - spec.dnsNames.0\n#         - spec.dnsNames.1\n#       options:\n#         delimiter: '.'\n#         index: 1\n#         create: true\n#     - select: # Uncomment the following to set the Service namespace for TLS in Prometheus ServiceMonitor\n#         kind: ServiceMonitor\n#         group: monitoring.coreos.com\n#         version: v1\n#         name: controller-manager-metrics-monitor\n#       fieldPaths:\n#         - spec.endpoints.0.tlsConfig.serverName\n#       options:\n#         delimiter: '.'\n#         index: 1\n#         create: true\n#\n# - source: # Uncomment the following block if you have any webhook\n#     kind: Service\n#     version: v1\n#     name: webhook-service\n#     fieldPath: .metadata.name # Name of the service\n#   targets:\n#     - select:\n#         kind: Certificate\n#         group: cert-manager.io\n#         version: v1\n#         name: serving-cert\n#       fieldPaths:\n#         - .spec.dnsNames.0\n#         - .spec.dnsNames.1\n#       options:\n#         delimiter: '.'\n#         index: 0\n#         create: true\n# - source:\n#     kind: Service\n#     version: v1\n#     name: webhook-service\n#     fieldPath: .metadata.namespace # Namespace of the service\n#   targets:\n#     - select:\n#         kind: Certificate\n#         group: cert-manager.io\n#         version: v1\n#         name: serving-cert\n#       fieldPaths:\n#         - .spec.dnsNames.0\n#         - .spec.dnsNames.1\n#       options:\n#         delimiter: '.'\n#         index: 1\n#         create: true\n#`, \"#\")\n\tpkg.CheckError(\"uncommented kustomize default config for webhooks and certmanager\", err)\n\n\terr = kbutil.UncommentCode(kustomization, `# - source: # Uncomment the following block if you have a DefaultingWebhook (--defaulting )\n#     kind: Certificate\n#     group: cert-manager.io\n#     version: v1\n#     name: serving-cert\n#     fieldPath: .metadata.namespace # Namespace of the certificate CR\n#   targets:\n#     - select:\n#         kind: MutatingWebhookConfiguration\n#       fieldPaths:\n#         - .metadata.annotations.[cert-manager.io/inject-ca-from]\n#       options:\n#         delimiter: '/'\n#         index: 0\n#         create: true\n# - source:\n#     kind: Certificate\n#     group: cert-manager.io\n#     version: v1\n#     name: serving-cert\n#     fieldPath: .metadata.name\n#   targets:\n#     - select:\n#         kind: MutatingWebhookConfiguration\n#       fieldPaths:\n#         - .metadata.annotations.[cert-manager.io/inject-ca-from]\n#       options:\n#         delimiter: '/'\n#         index: 1\n#         create: true\n#`, \"#\")\n\tpkg.CheckError(\"uncommented kustomize default config for defaulting webhooks \", err)\n}\n\n// uncommentManifestsKustomization will uncomment code in config/manifests/kustomization.yaml\nfunc (mh *Memcached) uncommentManifestsKustomizationv4() {\n\tvar err error\n\tkustomization := filepath.Join(mh.ctx.Dir, \"config\", \"manifests\", \"kustomization.yaml\")\n\tlog.Info(\"uncommenting config/manifests/kustomization.yaml to enable webhooks in OLM\")\n\n\terr = kbutil.UncommentCode(kustomization,\n\t\t`#patches:\n#- target:\n#    group: apps\n#    version: v1\n#    kind: Deployment\n#    name: controller-manager\n#    namespace: system\n#  patch: |-\n#    # Remove the manager container's \"cert\" volumeMount, since OLM will create and mount a set of certs.\n#    # Update the indices in this path if adding or removing containers/volumeMounts in the manager's Deployment.\n#    - op: remove\n\n#      path: /spec/template/spec/containers/0/volumeMounts/0\n#    # Remove the \"cert\" volume, since OLM will create and mount a set of certs.\n#    # Update the indices in this path if adding or removing volumes in the manager's Deployment.\n#    - op: remove\n#      path: /spec/template/spec/volumes/0`, \"#\")\n\tpkg.CheckError(\"uncommented webhook volume removal patch\", err)\n}\n\n// implementingWebhooks will customize the kind wekbhok file\nfunc (mh *Memcached) implementingWebhooks() {\n\tlog.Infof(\"implementing webhooks\")\n\twebhookPath := filepath.Join(mh.ctx.Dir, \"internal\", \"webhook\", mh.ctx.Version, fmt.Sprintf(\"%s_webhook.go\",\n\t\tstrings.ToLower(mh.ctx.Kind)))\n\n\terr := kbutil.ReplaceInFile(webhookPath,\n\t\t\"// TODO(user): fill in your defaulting logic.\",\n\t\t\"if memcached.Spec.Size == 0 {\\n\\t\\tmemcached.Spec.Size = 3\\n\\t}\")\n\tpkg.CheckError(\"injecting defaulting logic\", err)\n}\n\n// implementingController will customizations in the Controller\nfunc (mh *Memcached) implementingController() {\n\tcontrollerPath := filepath.Join(mh.ctx.Dir, \"internal\", \"controller\", fmt.Sprintf(\"%s_controller.go\",\n\t\tstrings.ToLower(mh.ctx.Kind)))\n\n\terr := kbutil.InsertCode(controllerPath,\n\t\t`\t\t\t\t\t\tSecurityContext: &corev1.SecurityContext{`, userIDWarningFragment)\n\tpkg.CheckError(\"adding warning comment for UserID\", err)\n\n\terr = kbutil.InsertCode(controllerPath,\n\t\t`\t\t\t\t\t\tRunAsNonRoot: ptr.To(true),`, runAsUserCommentFragment)\n\tpkg.CheckError(\"adding comment regarding RunAsUser field in Security Context\", err)\n}\n\n// implementingMonitoring will customize monitoring\nfunc (mh *Memcached) implementingMonitoring() {\n\terr := os.Mkdir(filepath.Join(mh.ctx.Dir, \"monitoring\"), os.ModePerm)\n\tpkg.CheckError(\"creating monitoring directory\", err)\n\n\theader, err := os.ReadFile((filepath.Join(mh.ctx.Dir, \"hack\", \"boilerplate.go.txt\")))\n\tgoFilesHeader = string(header)\n\tpkg.CheckError(\"reading go files header\", err)\n\n\tlog.Infof(\"implementing metrics\")\n\tmh.implementingMetrics()\n\n\tlog.Infof(\"implementing alerts\")\n\tmh.implementingAlerts()\n\n\tlog.Infof(\"implementing prom-rule-ci\")\n\tmh.implementingPromRuleCi()\n\n\tlog.Infof(\"implementing runbooks\")\n\tmh.implementingRunbooks()\n\n\tlog.Infof(\"implementing prometheus RBAC\")\n\tmh.implementingPrometheusRBAC()\n\n\tlog.Infof(\"customizing the Controller\")\n\tmh.customizingController()\n\n\tlog.Infof(\"customizing Main\")\n\tmh.customizingMainMonitoring()\n\n\tlog.Infof(\"customizing Dockerfile\")\n\tmh.customizingDockerfile()\n\n\tlog.Infof(\"customizing Makefile\")\n\tmh.customizingMakefile()\n}\n\n// nolint:gosec\n// implementingAPI will customize the API\nfunc (mh *Memcached) implementingAPIMarkers() {\n\terr := kbutil.InsertCode(\n\t\tfilepath.Join(mh.ctx.Dir, \"api\", mh.ctx.Version, fmt.Sprintf(\"%s_types.go\", strings.ToLower(mh.ctx.Kind))),\n\t\t\"// Port defines the port that will be used to init the container with the image\",\n\t\t`\n\t// +operator-sdk:csv:customresourcedefinitions:type=spec`)\n\tpkg.CheckError(\"inserting Port spec marker\", err)\n\n\terr = kbutil.InsertCode(\n\t\tfilepath.Join(mh.ctx.Dir, \"api\", mh.ctx.Version, fmt.Sprintf(\"%s_types.go\", strings.ToLower(mh.ctx.Kind))),\n\t\t\"// +kubebuilder:validation:ExclusiveMaximum=false\",\n\t\t`\n\t// +operator-sdk:csv:customresourcedefinitions:type=spec`)\n\tpkg.CheckError(\"inserting spec Status\", err)\n\n\tlog.Infof(\"implementing MemcachedStatus marker\")\n\terr = kbutil.ReplaceInFile(\n\t\tfilepath.Join(mh.ctx.Dir, \"api\", mh.ctx.Version, fmt.Sprintf(\"%s_types.go\", strings.ToLower(mh.ctx.Kind))),\n\t\t`\t// For further information see: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties\n`,\n\t\t`\t// For further information see: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties\n\n\t// Conditions store the status conditions of the Memcached instances\n\t// +operator-sdk:csv:customresourcedefinitions:type=status`,\n\t)\n\tpkg.CheckError(\"inserting Status marker\", err)\n\n\terr = kbutil.ReplaceInFile(\n\t\tfilepath.Join(mh.ctx.Dir, \"api\", mh.ctx.Version, fmt.Sprintf(\"%s_types.go\", strings.ToLower(mh.ctx.Kind))),\n\t\t`\n\t// Size defines the number of Memcached instances\n\t// The following markers will use OpenAPI v3 schema to validate the value\n\t// More info: https://book.kubebuilder.io/reference/markers/crd-validation.html\n\t// +kubebuilder:validation:Minimum=1\n\t// +kubebuilder:validation:Maximum=3\n\t// +kubebuilder:validation:ExclusiveMaximum=false\n\t// +operator-sdk:csv:customresourcedefinitions:type=spec`,\n\t\t`\n\t// The following markers will use OpenAPI v3 schema to validate the value\n\t// More info: https://book.kubebuilder.io/reference/markers/crd-validation.html\n\t// +kubebuilder:validation:Minimum=1\n\t// +kubebuilder:validation:Maximum=3\n\t// +kubebuilder:validation:ExclusiveMaximum=false\n\n\t// Size defines the number of Memcached instances\n\t// +operator-sdk:csv:customresourcedefinitions:type=spec`,\n\t)\n\tpkg.CheckError(\"updating Size spec marker\", err)\n\n\t// Add CSV marker that shows CRD owned resources\n\terr = kbutil.InsertCode(\n\t\tfilepath.Join(mh.ctx.Dir, \"api\", mh.ctx.Version, fmt.Sprintf(\"%s_types.go\", strings.ToLower(mh.ctx.Kind))),\n\t\t`// +kubebuilder:subresource:status`,\n\t\t`\n// +operator-sdk:csv:customresourcedefinitions:resources={{Deployment,v1,memcached-deployment}}`)\n\tpkg.CheckError(\"inserting CRD owned resources CSV marker\", err)\n}\n\nfunc (mh *Memcached) implementingMetrics() {\n\t// Create metrics file\n\tmetricsPath := filepath.Join(mh.ctx.Dir, \"monitoring/metrics.go\")\n\t_, err := os.Create(metricsPath)\n\tpkg.CheckError(\"creating metrics file\", err)\n\n\t// Add go files header\n\terr = kbutil.InsertCode(metricsPath,\n\t\t\"\",\n\t\tgoFilesHeader)\n\tpkg.CheckError(\"adding go files header\", err)\n\n\t// Add metrics implementation\n\terr = kbutil.InsertCode(metricsPath,\n\t\tgoFilesHeader,\n\t\tmetricsFragment)\n\tpkg.CheckError(\"adding metrics content\", err)\n\n\t// Add metricsdocs directory\n\terr = os.Mkdir(filepath.Join(mh.ctx.Dir, \"monitoring/metricsdocs\"), os.ModePerm)\n\tpkg.CheckError(\"creating metricsdocs directory\", err)\n\n\t// Create metricsdocs file\n\tmetricsdocsPath := filepath.Join(mh.ctx.Dir, \"monitoring/metricsdocs/metricsdocs.go\")\n\t_, err = os.Create(metricsdocsPath)\n\tpkg.CheckError(\"creating metricsdocs file\", err)\n\n\t// Add go files header\n\terr = kbutil.InsertCode(metricsdocsPath,\n\t\t\"\",\n\t\tgoFilesHeader)\n\tpkg.CheckError(\"adding go files header\", err)\n\n\t// Create metricsdocs generator tool\n\terr = kbutil.InsertCode(metricsdocsPath,\n\t\tgoFilesHeader,\n\t\tmetricsdocsFragment)\n\tpkg.CheckError(\"creating metricsdocs generator tool\", err)\n\n\t// Create docs directory\n\terr = os.Mkdir(filepath.Join(mh.ctx.Dir, \"docs\"), os.ModePerm)\n\tpkg.CheckError(\"creating docs directory\", err)\n\n\t// Create monitoring directory\n\terr = os.Mkdir(filepath.Join(mh.ctx.Dir, \"docs/monitoring\"), os.ModePerm)\n\tpkg.CheckError(\"creating monitoring directory\", err)\n}\n\nfunc (mh *Memcached) implementingAlerts() {\n\t// Create alerts file\n\talertsPath := filepath.Join(mh.ctx.Dir, \"monitoring/alerts.go\")\n\t_, err := os.Create(alertsPath)\n\tpkg.CheckError(\"creating alerts file\", err)\n\n\t// Add go files header\n\terr = kbutil.InsertCode(alertsPath,\n\t\t\"\",\n\t\tgoFilesHeader)\n\tpkg.CheckError(\"adding go files header\", err)\n\n\t// Add alerts implementation\n\terr = kbutil.InsertCode(alertsPath,\n\t\tgoFilesHeader,\n\t\talertsFragment)\n\tpkg.CheckError(\"adding alerts content\", err)\n}\n\nfunc (mh *Memcached) implementingPromRuleCi() {\n\t// Create prom-rule-ci directory\n\terr := os.Mkdir(filepath.Join(mh.ctx.Dir, \"monitoring/prom-rule-ci\"), os.ModePerm)\n\tpkg.CheckError(\"creating prom-rule-ci directory\", err)\n\n\t// Create prom-rules-tests file\n\tpromRuleTestsPath := filepath.Join(mh.ctx.Dir, \"monitoring/prom-rule-ci/prom-rules-tests.yaml\")\n\t_, err = os.Create(promRuleTestsPath)\n\tpkg.CheckError(\"creating prom-rules-tests file\", err)\n\n\t// Add prom-rules-tests implementation\n\terr = kbutil.InsertCode(promRuleTestsPath,\n\t\t\"\",\n\t\tpromRuleTestsFragment)\n\tpkg.CheckError(\"adding prom-rules-tests content\", err)\n\n\t// Create rule-spec-dumper file\n\truleSpecDumperPath := filepath.Join(mh.ctx.Dir, \"monitoring/prom-rule-ci/rule-spec-dumper.go\")\n\t_, err = os.Create(ruleSpecDumperPath)\n\tpkg.CheckError(\"creating rule-spec-dumper file\", err)\n\n\t// Add go files header to rule-spec-dumper\n\terr = kbutil.InsertCode(ruleSpecDumperPath,\n\t\t\"\",\n\t\tgoFilesHeader)\n\tpkg.CheckError(\"adding go files header\", err)\n\n\t// Add rule-spec-dumper implementation\n\terr = kbutil.InsertCode(ruleSpecDumperPath,\n\t\tgoFilesHeader,\n\t\truleSpecDumperFragment)\n\tpkg.CheckError(\"adding rule-spec-dumper content\", err)\n\n\t// Create verify-rules file\n\tverifyRulesPath := filepath.Join(mh.ctx.Dir, \"monitoring/prom-rule-ci/verify-rules.sh\")\n\t_, err = os.Create(verifyRulesPath)\n\tpkg.CheckError(\"creating verify-rules file\", err)\n\n\terr = os.Chmod(filepath.Join(mh.ctx.Dir, \"monitoring/prom-rule-ci/verify-rules.sh\"), 0777)\n\tpkg.CheckError(\"changing verify-rules file permissions \", err)\n\n\t// Add verify-rules implementation\n\terr = kbutil.InsertCode(verifyRulesPath,\n\t\t\"\",\n\t\tverifyRulesFragment)\n\tpkg.CheckError(\"adding verify-rules content\", err)\n}\n\nfunc (mh *Memcached) implementingRunbooks() {\n\trunbooksPath := \"docs/monitoring/runbooks/\"\n\n\t// Create runbooks directory\n\terr := os.Mkdir(filepath.Join(mh.ctx.Dir, runbooksPath), os.ModePerm)\n\tpkg.CheckError(\"creating runbooks directory\", err)\n\n\t// Create MemcachedDeploymentSizeUndesired runbook file\n\tmemcachedDeploymentSizeUndesiredRunbookPath := filepath.Join(mh.ctx.Dir, runbooksPath, \"memcachedDeploymentSizeUndesired.md\")\n\t_, err = os.Create(memcachedDeploymentSizeUndesiredRunbookPath)\n\tpkg.CheckError(\"creating MemcachedDeploymentSizeUndesired runbook file\", err)\n\n\t// Add MemcachedDeploymentSizeUndesired runbook content\n\terr = kbutil.InsertCode(memcachedDeploymentSizeUndesiredRunbookPath,\n\t\t\"\",\n\t\tmemcachedDeploymentSizeUndesiredRunbookFragment)\n\tpkg.CheckError(\"adding MemcachedDeploymentSizeUndesired runbook content\", err)\n\n\t// Create MemcachedOperatorDown runbook file\n\tmemcachedOperatorDownRunbookPath := filepath.Join(mh.ctx.Dir, runbooksPath, \"memcachedOperatorDown.md\")\n\t_, err = os.Create(memcachedOperatorDownRunbookPath)\n\tpkg.CheckError(\"creating MemcachedOperatorDown runbook file\", err)\n\n\t// Add MemcachedOperatorDown runbook content\n\terr = kbutil.InsertCode(memcachedOperatorDownRunbookPath,\n\t\t\"\",\n\t\tmemcachedOperatorDownRunbookFragment)\n\tpkg.CheckError(\"adding MemcachedDeploymentSizeUndesired runbook content\", err)\n}\n\nfunc (mh *Memcached) implementingPrometheusRBAC() {\n\t// Create prometheus role file\n\tprometheusRolePath := filepath.Join(mh.ctx.Dir, \"config/rbac/prometheus_role.yaml\")\n\t_, err := os.Create(prometheusRolePath)\n\tpkg.CheckError(\"creating prometheus role file\", err)\n\n\t// Add prometheus role content\n\terr = kbutil.InsertCode(prometheusRolePath,\n\t\t\"\",\n\t\tprometheusRoleFragment)\n\tpkg.CheckError(\"adding prometheus role content\", err)\n\n\t// Create prometheus role binding file\n\tprometheusRoleBindingPath := filepath.Join(mh.ctx.Dir, \"config/rbac/prometheus_role_binding.yaml\")\n\t_, err = os.Create(prometheusRoleBindingPath)\n\tpkg.CheckError(\"creating prometheus role binding file\", err)\n\n\t// Add prometheus role binding content\n\terr = kbutil.InsertCode(prometheusRoleBindingPath,\n\t\t\"\",\n\t\tprometheusRoleBindingFragment)\n\tpkg.CheckError(\"adding prometheus role binding content\", err)\n\n\t// Add prometheus rbac files to kustomization\n\tkustomizationPath := filepath.Join(mh.ctx.Dir, \"config/rbac/kustomization.yaml\")\n\terr = kbutil.InsertCode(kustomizationPath,\n\t\t`- leader_election_role.yaml\n- leader_election_role_binding.yaml`,\n\t\t`\n- prometheus_role.yaml\n- prometheus_role_binding.yaml`)\n\tpkg.CheckError(\"adding prometheus role binding content\", err)\n}\n\n// customizingController will customize the Controller to include monitoring\nfunc (mh *Memcached) customizingController() {\n\tcontrollerPath := filepath.Join(mh.ctx.Dir, \"internal\", \"controller\", fmt.Sprintf(\"%s_controller.go\",\n\t\tstrings.ToLower(mh.ctx.Kind)))\n\n\t// Add monitoring imports\n\terr := kbutil.InsertCode(controllerPath,\n\t\t`\"os\"`,\n\t\t`\n\t\"reflect\"`)\n\tpkg.CheckError(\"adding reflect import\", err)\n\n\terr = kbutil.InsertCode(controllerPath,\n\t\t`\"sigs.k8s.io/controller-runtime/pkg/log\"`,\n\t\tmonitoringv1ImportFragment)\n\tpkg.CheckError(\"adding monitoringv1 import\", err)\n\n\terr = kbutil.InsertCode(controllerPath,\n\t\t`cachev1alpha1 \"github.com/example/memcached-operator/api/v1alpha1\"`,\n\t\tmonitoringImportFragment)\n\tpkg.CheckError(\"adding monitoring import\", err)\n\n\t// Add monitoring parts\n\terr = kbutil.InsertCode(controllerPath,\n\t\t`const memcachedFinalizer = \"cache.example.com/finalizer\"`,\n\t\t`\n\t\tconst ruleName = \"memcached-operator-rules\"\n\t\tconst namespace = \"memcached-operator-system\"`)\n\tpkg.CheckError(\"adding monitoring constants\", err)\n\n\terr = kbutil.InsertCode(controllerPath,\n\t\t`// +kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;watch`,\n\t\t`\n\t\t// +kubebuilder:rbac:groups=monitoring.coreos.com,resources=prometheusrules,verbs=get;list;watch;create;update;delete`)\n\tpkg.CheckError(\"adding monitoring.coreos.com rbac\", err)\n\n\terr = kbutil.ReplaceInFile(controllerPath,\n\t\tcontrollerMemcachedInstanceFragment,\n\t\tcontrollerPrometheusRuleFragment)\n\tpkg.CheckError(\"adding prometheus rule reconciliation\", err)\n\n\terr = kbutil.InsertCode(controllerPath,\n\t\t`\tif *found.Spec.Replicas != size {`,\n\t\t`\n\t\t// Increment MemcachedDeploymentSizeUndesiredCountTotal metric by 1\n\t\tmonitoring.MemcachedDeploymentSizeUndesiredCountTotal.Inc()`)\n\tpkg.CheckError(\"adding metric incrementation\", err)\n}\n\n// customizingMain will add comments to main\nfunc (mh *Memcached) customizingMain() {\n\tmainPath := filepath.Join(mh.ctx.Dir, \"cmd\", \"main.go\")\n\n\terr := kbutil.InsertCode(mainPath,\n\t\t\"Scheme:   mgr.GetScheme(),\",\n\t\tmainRecorderFragment)\n\tpkg.CheckError(\"adding recorder fragment\", err)\n}\n\n// customizingMainMonitoring will customize main.go to register metrics\nfunc (mh *Memcached) customizingMainMonitoring() {\n\tmainPath := filepath.Join(mh.ctx.Dir, \"cmd\", \"main.go\")\n\tmarker := \"\\\"github.com/example/memcached-operator/internal/controller\\\"\"\n\n\terr := kbutil.InsertCode(mainPath,\n\t\tmarker,\n\t\tmonitoringImportFragment)\n\tpkg.CheckError(\"adding monitoringv1 import\", err)\n\n\t// Add monitoring imports\n\terr = kbutil.InsertCode(mainPath,\n\t\t`\"sigs.k8s.io/controller-runtime/pkg/log/zap\"`,\n\t\tmonitoringv1ImportFragment)\n\tpkg.CheckError(\"adding monitoringv1 import\", err)\n\n\t// Add monitoring parts\n\terr = kbutil.InsertCode(mainPath,\n\t\t\"utilruntime.Must(cachev1alpha1.AddToScheme(scheme))\",\n\t\tmainMonitoringFragment)\n\tpkg.CheckError(\"adding monitoring parts\", err)\n}\n\n// customizingDockerfile will customize the Dockerfile to include monitoring\nfunc (mh *Memcached) customizingDockerfile() {\n\tdockerfilePath := filepath.Join(mh.ctx.Dir, \"Dockerfile\")\n\n\t// Copy monitoring\n\terr := kbutil.InsertCode(dockerfilePath,\n\t\t`COPY internal/ internal/\n`,\n\t\t\"\\nCOPY monitoring/ monitoring/\")\n\tpkg.CheckError(\"adding COPY monitoring/\", err)\n}\n\nconst createdAt = `createdAt: \"2022-11-08T17:26:37Z\"`\n\n// customizingMakefile will customize the Makefile to include monitoring\nfunc (mh *Memcached) customizingMakefile() {\n\tmakefilePath := filepath.Join(mh.ctx.Dir, \"Makefile\")\n\n\t// TODO: update this to be different based on go plugin version\n\t// Add prom-rule-ci target to the makefile\n\terr := kbutil.InsertCode(makefilePath,\n\t\t`$(KUSTOMIZE) build config/default | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f -`,\n\t\tmakefileFragment)\n\tpkg.CheckError(\"adding prom-rule-ci target to the makefile\", err)\n\n\t// Add metrics documentation\n\terr = kbutil.InsertCode(makefilePath,\n\t\t`$(MAKE) docker-push IMG=$(CATALOG_IMG)`,\n\t\tmetricsdocsMakefileFragment)\n\tpkg.CheckError(\"adding metrics documentation\", err)\n}\n\nconst metricsFragment = `\n\npackage monitoring\n\nimport (\n\t\"github.com/prometheus/client_golang/prometheus\"\n\t\"sigs.k8s.io/controller-runtime/pkg/metrics\"\n)\n\n// MetricDescription is an exported struct that defines the metric description (Name, Help)\n// as a new type named MetricDescription.\ntype MetricDescription struct {\n\tName string\n\tHelp string\n\tType string\n}\n\n// metricsDescription is a map of string keys (metrics) to MetricDescription values (Name, Help).\nvar metricDescription = map[string]MetricDescription{\n\t\"MemcachedDeploymentSizeUndesiredCountTotal\": {\n\t\tName: \"memcached_deployment_size_undesired_count_total\",\n\t\tHelp: \"Total number of times the deployment size was not as desired.\",\n\t\tType: \"Counter\",\n\t},\n}\n\nvar (\n\t// MemcachedDeploymentSizeUndesiredCountTotal will count how many times was required\n\t// to perform the operation to ensure that the number of replicas on the cluster\n\t// is the same as the quantity desired and specified via the custom resource size spec.\n\tMemcachedDeploymentSizeUndesiredCountTotal = prometheus.NewCounter(\n\t\tprometheus.CounterOpts{\n\t\t\tName: metricDescription[\"MemcachedDeploymentSizeUndesiredCountTotal\"].Name,\n\t\t\tHelp: metricDescription[\"MemcachedDeploymentSizeUndesiredCountTotal\"].Help,\n\t\t},\n\t)\n)\n\n// RegisterMetrics will register metrics with the global prometheus registry\nfunc RegisterMetrics() {\n\tmetrics.Registry.MustRegister(MemcachedDeploymentSizeUndesiredCountTotal)\n}\n\n// ListMetrics will create a slice with the metrics available in metricDescription\nfunc ListMetrics() []MetricDescription {\n\tv := make([]MetricDescription, 0, len(metricDescription))\n\t// Insert value (Name, Help) for each metric\n\tfor _, value := range metricDescription {\n\t\tv = append(v, value)\n\t}\n\n\treturn v\n}\n`\n\nconst metricsdocsFragment = `\n\npackage main\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"sort\"\n\t\"text/template\"\n\n\t\"github.com/example/memcached-operator/monitoring\"\n)\n\nfunc main() {\n\tmetricDescriptions := monitoring.ListMetrics()\n\tsort.Slice(metricDescriptions, func(i, j int) bool {\n\t\treturn metricDescriptions[i].Name < metricDescriptions[j].Name\n\t})\n\n\ttmpl, err := template.New(\"Operator metrics\").Parse(\"# Operator Metrics\\n\" +\n\t\t\"This document aims to help users that are not familiar with metrics exposed by this operator.\\n\" +\n\t\t\"The metrics documentation is auto-generated by the utility tool \\\"monitoring/metricsdocs\\\" and reflects all of the metrics that are exposed by the operator.\\n\\n\" +\n\t\t\"## Operator Metrics List\" +\n\t\t\"{{range .}}\\n\" +\n\t\t\"### {{.Name}}\\n\" +\n\t\t\"{{.Help}} \" +\n\t\t\"Type: {{.Type}}.\\n\" +\n\t\t\"{{end}}\" +\n\t\t\"## Developing new metrics\\n\" +\n\t\t\"After developing new metrics or changing old ones, please run \\\"make generate-metricsdocs\\\" to regenerate this document.\\n\\n\" +\n\t\t\"If you feel that the new metric doesn't follow these rules, please change \\\"monitoring/metricsdocs\\\" according to your needs.\")\n\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// generate the template using the sorted list of metrics\n\tvar buf bytes.Buffer\n\tif err := tmpl.Execute(&buf, metricDescriptions); err != nil {\n\t\tpanic(err)\n\t}\n\n\t// print the generated metrics documentation\n\tfmt.Println(buf.String())\n}\n`\n\nconst alertsFragment = `\n\npackage monitoring\n\nimport (\n\tmonitoringv1 \"github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/util/intstr\"\n)\n\nconst (\n\truleName                     = \"memcached-operator-rules\"\n\talertRuleGroup               = \"memcached.rules\"\n\tdeploymentSizeUndesiredAlert = \"MemcachedDeploymentSizeUndesired\"\n\toperatorDownAlert            = \"MemcachedOperatorDown\"\n\toperatorUpTotalRecordingRule = \"memcached_operator_up_total\"\n\trunbookURLBasePath           = \"https://github.com/operator-framework/operator-sdk/tree/master/testdata/go/v4/monitoring/memcached-operator/docs/monitoring/runbooks/\"\n)\n\n// NewPrometheusRule creates new PrometheusRule(CR) for the operator to have alerts and recording rules\nfunc NewPrometheusRule(namespace string) *monitoringv1.PrometheusRule {\n\treturn &monitoringv1.PrometheusRule{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tAPIVersion: monitoringv1.SchemeGroupVersion.String(),\n\t\t\tKind:       \"PrometheusRule\",\n\t\t},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      ruleName,\n\t\t\tNamespace: namespace,\n\t\t},\n\t\tSpec: *NewPrometheusRuleSpec(),\n\t}\n}\n\n// NewPrometheusRuleSpec creates PrometheusRuleSpec for alerts and recording rules\nfunc NewPrometheusRuleSpec() *monitoringv1.PrometheusRuleSpec {\n\treturn &monitoringv1.PrometheusRuleSpec{\n\t\tGroups: []monitoringv1.RuleGroup{{\n\t\t\tName: alertRuleGroup,\n\t\t\tRules: []monitoringv1.Rule{\n\t\t\t\tcreateDeploymentSizeUndesiredAlertRule(),\n\t\t\t\tcreateOperatorDownAlertRule(),\n\t\t\t\tcreateOperatorUpTotalRecordingRule(),\n\t\t\t},\n\t\t}},\n\t}\n}\n\n// createDeploymentSizeUndesiredAlertRule creates MemcachedDeploymentSizeUndesired alert rule\nfunc createDeploymentSizeUndesiredAlertRule() monitoringv1.Rule {\n\treturn monitoringv1.Rule{\n\t\tAlert: deploymentSizeUndesiredAlert,\n\t\tExpr:  intstr.FromString(\"increase(memcached_deployment_size_undesired_count_total[5m]) >= 3\"),\n\t\tAnnotations: map[string]string{\n\t\t\t\"description\": \"Memcached-sample deployment size was not as desired more than 3 times in the last 5 minutes.\",\n\t\t},\n\t\tLabels: map[string]string{\n\t\t\t\"severity\":    \"warning\",\n\t\t\t\"runbook_url\": runbookURLBasePath + \"MemcachedDeploymentSizeUndesired.md\",\n\t\t},\n\t}\n}\n\n// createOperatorDownAlertRule creates MemcachedOperatorDown alert rule\nfunc createOperatorDownAlertRule() monitoringv1.Rule {\n\treturn monitoringv1.Rule{\n\t\tAlert: operatorDownAlert,\n\t\tExpr:  intstr.FromString(\"memcached_operator_up_total == 0\"),\n\t\tAnnotations: map[string]string{\n\t\t\t\"description\": \"No running memcached-operator pods were detected in the last 5 min.\",\n\t\t},\n\t\tFor: \"5m\",\n\t\tLabels: map[string]string{\n\t\t\t\"severity\":    \"critical\",\n\t\t\t\"runbook_url\": runbookURLBasePath + \"MemcachedOperatorDown.md\",\n\t\t},\n\t}\n}\n\n// createOperatorUpTotalRecordingRule creates memcached_operator_up_total recording rule\nfunc createOperatorUpTotalRecordingRule() monitoringv1.Rule {\n\treturn monitoringv1.Rule{\n\t\tRecord: operatorUpTotalRecordingRule,\n\t\tExpr:   intstr.FromString(\"sum(up{pod=~'memcached-operator-controller-manager-.*'} or vector(0))\"),\n\t}\n}\n`\n\nconst promRuleTestsFragment = `---\n# Prometheus official unit-testing documentation - https://prometheus.io/docs/prometheus/latest/configuration/unit_testing_rules/\n# rule_files contains the list of files to be tested\nrule_files:\n  - /tmp/rules.verify\n\n# group_eval_order contains the list of groups to be tested\ngroup_eval_order:\n  - memcached.rules\n\ntests:\n# for each time frame based on the interval, we define the metrics values\n  - interval: 1m\n    input_series:\n      - series: 'memcached_deployment_size_undesired_count_total'\n        # time:  0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15\n        values: \"0 0 0 1 2 3 3 3 3 3  3  3  3  4  5  6\"\n      - series: 'memcached_operator_up_total'\n        # time:  0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15\n        values: \"0 0 0 0 0 0 1 1 1 1  0  0  0  0  0  0\"\n\n# then, we evaluate the alerts behaviour in the eval_time we choose\n    alert_rule_test:\n      # it must not trigger before 5m\n      - eval_time: 4m\n        alertname: MemcachedDeploymentSizeUndesired\n        exp_alerts: []\n      - eval_time: 4m\n        alertname: MemcachedOperatorDown\n        exp_alerts: []\n      # it must trigger after 5m\n      - eval_time: 5m\n        alertname: MemcachedDeploymentSizeUndesired\n        exp_alerts:\n          - exp_annotations:\n              description: \"Memcached-sample deployment size was not as desired more than 3 times in the last 5 minutes.\"\n            exp_labels:\n              severity: \"warning\"\n              runbook_url: \"https://github.com/operator-framework/operator-sdk/tree/master/testdata/go/v4/monitoring/memcached-operator/docs/monitoring/runbooks/MemcachedDeploymentSizeUndesired.md\"\n      - eval_time: 5m\n        alertname: MemcachedOperatorDown\n        exp_alerts:\n          - exp_annotations:\n              description: \"No running memcached-operator pods were detected in the last 5 min.\"\n            exp_labels:\n              severity: \"critical\"\n              runbook_url: \"https://github.com/operator-framework/operator-sdk/tree/master/testdata/go/v4/monitoring/memcached-operator/docs/monitoring/runbooks/MemcachedOperatorDown.md\"\n      # it must not trigger before 15m\n      - eval_time: 14m\n        alertname: MemcachedDeploymentSizeUndesired\n        exp_alerts: [ ]\n      - eval_time: 14m\n        alertname: MemcachedOperatorDown\n        exp_alerts: [ ]\n      # it must trigger after 15m\n      - eval_time: 15m\n        alertname: MemcachedDeploymentSizeUndesired\n        exp_alerts:\n          - exp_annotations:\n              description: \"Memcached-sample deployment size was not as desired more than 3 times in the last 5 minutes.\"\n            exp_labels:\n              severity: \"warning\"\n              runbook_url: \"https://github.com/operator-framework/operator-sdk/tree/master/testdata/go/v4/monitoring/memcached-operator/docs/monitoring/runbooks/MemcachedDeploymentSizeUndesired.md\"\n      - eval_time: 15m\n        alertname: MemcachedOperatorDown\n        exp_alerts:\n          - exp_annotations:\n              description: \"No running memcached-operator pods were detected in the last 5 min.\"\n            exp_labels:\n              severity: \"critical\"\n              runbook_url: \"https://github.com/operator-framework/operator-sdk/tree/master/testdata/go/v4/monitoring/memcached-operator/docs/monitoring/runbooks/MemcachedOperatorDown.md\"\n`\n\nconst ruleSpecDumperFragment = `\n\npackage main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"os\"\n\n\t\"github.com/example/memcached-operator/monitoring\"\n)\n\nfunc verifyArgs(args []string) error {\n\tnumOfArgs := len(os.Args[1:])\n\tif numOfArgs != 1 {\n\t\treturn fmt.Errorf(\"expected exactly 1 argument, got: %d\", numOfArgs)\n\t}\n\treturn nil\n}\n\nfunc main() {\n\tif err := verifyArgs(os.Args); err != nil {\n\t\tfmt.Printf(\"ERROR: %v\\n\", err)\n\t\tos.Exit(1)\n\t}\n\n\ttargetFile := os.Args[1]\n\n\tpromRuleSpec := monitoring.NewPrometheusRuleSpec()\n\tb, err := json.Marshal(promRuleSpec)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\terr = ioutil.WriteFile(targetFile, b, 0644)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n}\n`\n\nconst verifyRulesFragment = `#!/bin/bash -e\n\nreadonly PROM_IMAGE=\"docker.io/prom/prometheus:v2.15.2\"\n\nfunction cleanup() {\n    local cleanup_files=(\"${@:?}\")\n    for file in \"${cleanup_files[@]}\"; do\n        rm -f \"$file\"\n    done\n}\n\nfunction lint() {\n    local target_file=\"${1:?}\"\n    docker run --rm --entrypoint=/bin/promtool \\\n        -v \"$target_file\":/tmp/rules.verify:ro \"$PROM_IMAGE\" \\\n        check rules /tmp/rules.verify\n}\n\nfunction unit_test() {\n    local target_file=\"${1:?}\"\n    local tests_file=\"${2:?}\"\n    docker run --rm --entrypoint=/bin/promtool \\\n        -v \"$tests_file\":/tmp/rules.test:ro \\\n        -v \"$target_file\":/tmp/rules.verify:ro \\\n        \"$PROM_IMAGE\" \\\n        test rules /tmp/rules.test\n}\n\nfunction main() {\n    local prom_spec_dumper=\"${1:?}\"\n    local tests_file=\"${2:?}\"\n    local target_file\n    target_file=\"$(mktemp --tmpdir -u tmp.prom_rules.XXXXX)\"\n    trap \"cleanup $target_file\" RETURN EXIT INT\n    \"$prom_spec_dumper\" \"$target_file\"\n    echo \"INFO: Rules file content:\"\n    cat \"$target_file\"\n    echo\n    lint \"$target_file\"\n    unit_test \"$target_file\" \"$tests_file\"\n}\n\nmain \"$@\"\n`\nconst memcachedDeploymentSizeUndesiredRunbookFragment = `# MemcachedDeploymentSizeUndesired\n\n## Meaning\nMemcachedDeploymentSizeUndesired is triggered when the number of available\n<code>memcached-sample</code> replicas doesn't match the requested configuration.\n\n## Impact\nUnavailability of distributed memory object caching system in the cluster.\n\n## Diagnosis\n- Check memcached-sample's pod namespace:\n\n  <code>export NAMESPACE=\"$(kubectl get deployment -A | grep memcached-sample | awk '{print $1}')\"</code>\n\n- Observe the status of the memcached-sample deployment:\n\n  <code>kubectl get deploy memcached-sample -n $NAMESPACE -o yaml</code>\n\n- Observe the logs of the memcached manager pod, to see why it cannot create the memcached-sample pods.\n\n   <code>kubectl get logs <memcached-operator-controller-manager-pod> -n memcached-operator-system</code>\n\n## Mitigation\nThere can be several reasons. Like:\n- Node resource exhaustion\n- Not enough memory on the cluster\n- Nodes are down\n\nTry to identify the root cause and fix it.`\n\nconst memcachedOperatorDownRunbookFragment = `# MemcachedOperatorDown\n\n## Meaning\nNo running memcached-operator-controller-manager pods were detected in the last 5 min.\n\n## Impact\nComplete failure in the <code>Memcached</code> CR lifecycle management.\ni.e. launching a new <code>Memcached</code> instance or shutting down an existing one.\n## Diagnosis\n- Observe the status of the memcached-operator-controller-manager deployment:\n\n  <code>kubectl get deploy memcached-operator-controller-manager -n mecmached-operator-system -o yaml</code>\n\n## Mitigation\nThere can be several reasons for the memcached-operator-controller-manager pod to be down, identify the root cause and fix it.\n\n- Check the status of the memcached-operator-controller-manager deployment to\nfind out more information. The following command will provide the associated events and show if there are any issues with pulling an image, crashing pod, etc.\n\n<code>kubectl describe deploy memcached-operator-controller-manager -n memcached-operator-system</code>\n\n- Check if there are issues with the nodes. For example, if they are in a NotReady state.\n\n  </code>kubectl get nodes</code>\n`\n\nconst prometheusRoleFragment = `---\napiVersion: rbac.authorization.k8s.io/v1\nkind: Role\nmetadata:\n  name: prometheus-role\n  namespace: system\nrules:\n  - apiGroups: [\"\"]\n    resources:\n      - services\n      - endpoints\n      - pods\n    verbs: [\"get\", \"list\"]\n`\nconst prometheusRoleBindingFragment = `---\napiVersion: rbac.authorization.k8s.io/v1\nkind: RoleBinding\nmetadata:\n  name: prometheus-role-binding\n  namespace: system\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: Role\n  name: prometheus-role\nsubjects:\n- kind: ServiceAccount\n  name: prometheus-k8s\n  namespace: monitoring\n`\n\nconst controllerMemcachedInstanceFragment = `\n\t// Fetch the Memcached instance\n\t// The purpose is check if the Custom Resource for the Kind Memcached\n\t// is applied on the cluster if not we return nil to stop the reconciliation\n\tmemcached := &cachev1alpha1.Memcached{}\n\terr := r.Get(ctx, req.NamespacedName, memcached)`\n\nconst controllerPrometheusRuleFragment = `\n\t// Check if prometheus rule already exists, if not create a new one\n\tfoundRule := &monitoringv1.PrometheusRule{}\n\terr := r.Get(ctx, types.NamespacedName{Name: ruleName, Namespace: namespace}, foundRule)\n\tif err != nil && apierrors.IsNotFound(err) {\n\t\t// Define a new prometheus rule\n\t\tprometheusRule := monitoring.NewPrometheusRule(namespace)\n\t\tif err := r.Create(ctx, prometheusRule); err != nil {\n\t\t\tlog.Error(err, \"Failed to create prometheus rule\")\n\t\t\treturn ctrl.Result{}, nil\n\t\t}\n\t}\n\n\tif err == nil {\n\t\t// Check if prometheus rule spec was changed, if so set as desired\n\t\tdesiredRuleSpec := monitoring.NewPrometheusRuleSpec()\n\t\tif !reflect.DeepEqual(foundRule.Spec.DeepCopy(), desiredRuleSpec) {\n\t\t\tdesiredRuleSpec.DeepCopyInto(&foundRule.Spec)\n\t\t\tif r.Update(ctx, foundRule); err != nil {\n\t\t\t\tlog.Error(err, \"Failed to update prometheus rule\")\n\t\t\t\treturn ctrl.Result{}, nil\n\t\t\t}\n\t\t}\n\t}\n\n\t// Fetch the Memcached instance\n\t// The purpose is check if the Custom Resource for the Kind Memcached\n\t// is applied on the cluster if not we return nil to stop the reconciliation\n\tmemcached := &cachev1alpha1.Memcached{}\n\terr = r.Get(ctx, req.NamespacedName, memcached)`\n\nconst mainRecorderFragment = `\n// Add a Recorder to the reconciler.\n// This allows the operator author to emit events during reconcilliation.`\n\nconst monitoringv1ImportFragment = `\n\n\tmonitoringv1 \"github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1\"\n`\n\nconst monitoringImportFragment = `\n\t\"github.com/example/memcached-operator/monitoring\"\n`\n\nconst mainMonitoringFragment = `\n\n\tutilruntime.Must(monitoringv1.AddToScheme(scheme))\n\n\tmonitoring.RegisterMetrics()`\n\nconst makefileFragment = `\nLDFLAGS            ?= -w -s\n\nbuild-prom-spec-dumper: ## Build binary from source\n\tgo build -ldflags=\"${LDFLAGS}\" -o _out/rule-spec-dumper ./monitoring/prom-rule-ci/rule-spec-dumper.go\n\ncurrent-dir := $(realpath .)\n\n# Unit testing for the operator alerts and recording rules\n# rule-spec-dumper dumps the prometheus rule spec to a temp _out/rule-spec-dumper file which prom-rules-tests runs against\nprom-rules-verify: build-prom-spec-dumper\n\t./monitoring/prom-rule-ci/verify-rules.sh \\\n\t\t\"${current-dir}/_out/rule-spec-dumper\" \\\n\t\t\"${current-dir}/monitoring/prom-rule-ci/prom-rules-tests.yaml\"\n\n`\n\nconst metricsdocsMakefileFragment = `\n\n##@ Generate the metrics documentation\n.PHONY: generate-metricsdocs\ngenerate-metricsdocs:\n\tmkdir -p $(shell pwd)/docs/monitoring\n\tgo run -ldflags=\"${LDFLAGS}\" ./monitoring/metricsdocs > docs/monitoring/metrics.md\n`\n\nconst userIDWarningFragment = `\n\t\t\t\t\t\t\t// WARNING: Ensure that the image used defines an UserID in the Dockerfile\n\t\t\t\t\t\t\t// otherwise the Pod will not run and will fail with \"container has runAsNonRoot and image has non-numeric user\"\".\n\t\t\t\t\t\t\t// If you want your workloads admitted in namespaces enforced with the restricted mode in OpenShift/OKD vendors\n\t\t\t\t\t\t\t// then, you MUST ensure that the Dockerfile defines a User ID OR you MUST leave the \"RunAsNonRoot\" and\n\t\t\t\t\t\t\t// \"RunAsUser\" fields empty.`\n\nconst runAsUserCommentFragment = `\n\t\t\t\t\t\t\t// The memcached image does not use a non-zero numeric user as the default user.\n\t\t\t\t\t\t\t// Due to RunAsNonRoot field being set to true, we need to force the user in the\n\t\t\t\t\t\t\t// container to a non-zero numeric user. We do this using the RunAsUser field.\n\t\t\t\t\t\t\t// However, if you are looking to provide solution for K8s vendors like OpenShift\n\t\t\t\t\t\t\t// be aware that you cannot run under its restricted-v2 SCC if you set this value.`\n"
  },
  {
    "path": "hack/generate/samples/internal/helm/generate.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage helm\n\nimport (\n\t\"path/filepath\"\n)\n\nfunc GenerateMemcachedSamples(binaryPath, rootPath string) {\n\tGenerateMemcachedSample(binaryPath, filepath.Join(rootPath, \"helm\"))\n}\n"
  },
  {
    "path": "hack/generate/samples/internal/helm/memcached.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage helm\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\n\tkbutil \"sigs.k8s.io/kubebuilder/v4/pkg/plugin/util\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\n\t\"github.com/operator-framework/operator-sdk/hack/generate/samples/internal/pkg\"\n)\n\n// Memcached defines the Memcached Sample in Helm\ntype Memcached struct {\n\tctx *pkg.SampleContext\n}\n\n// GenerateMemcachedSample will call all actions to create the directory and generate the sample\n// The Context to run the samples are not the same in the e2e test. In this way, note that it should NOT\n// be called in the e2e tests since it will call the Prepare() to set the sample context and generate the files\n// in the testdata directory. The e2e tests only ought to use the Run() method with the TestContext.\nfunc GenerateMemcachedSample(binaryPath, samplesPath string) {\n\tctx, err := pkg.NewSampleContext(binaryPath, filepath.Join(samplesPath, \"memcached-operator\"),\n\t\t\"GO111MODULE=on\")\n\tpkg.CheckError(\"generating Helm memcached context\", err)\n\n\tmemcached := Memcached{&ctx}\n\tmemcached.Prepare()\n\tmemcached.Run()\n}\n\n// Prepare the Context for the Memcached Helm Sample\n// Note that sample directory will be re-created and the context data for the sample\n// will be set such as the domain and GVK.\nfunc (mh *Memcached) Prepare() {\n\tlog.Infof(\"destroying directory for memcached helm samples\")\n\tmh.ctx.Destroy()\n\n\tlog.Infof(\"creating directory\")\n\terr := mh.ctx.Prepare()\n\tpkg.CheckError(\"creating directory\", err)\n\n\tlog.Infof(\"setting domain and GVK\")\n\tmh.ctx.Domain = \"example.com\"\n\tmh.ctx.Version = \"v1alpha1\"\n\tmh.ctx.Group = \"cache\"\n\tmh.ctx.Kind = \"Memcached\"\n}\n\n// Run runs the steps to generate the sample\nfunc (mh *Memcached) Run() {\n\t// When operator-sdk scaffolds Helm projects, it tries to use the discovery API of a Kubernetes\n\t// cluster to intelligently build the RBAC rules that the operator will require based on the\n\t// content of the helm chart.\n\t//\n\t// Here, we intentionally set KUBECONFIG to a broken value to ensure that operator-sdk will be\n\t// unable to reach a real cluster, and thus will generate a default RBAC rule set. This is\n\t// required to make Helm project generation idempotent because contributors and CI environments\n\t// can all have slightly different environments that can affect the content of the generated\n\t// role and cause sanity testing to fail.\n\tos.Setenv(\"KUBECONFIG\", \"broken_so_we_generate_static_default_rules\")\n\n\thelmChartPath := \"../../../hack/generate/samples/internal/helm/testdata/memcached-0.0.2.tgz\"\n\tlog.Infof(\"creating the project using the helm chart in: (%v)\", helmChartPath)\n\terr := mh.ctx.Init(\n\t\t\"--plugins\", \"helm\",\n\t\t\"--domain\", mh.ctx.Domain,\n\t\t\"--group\", mh.ctx.Group,\n\t\t\"--version\", mh.ctx.Version,\n\t\t\"--kind\", mh.ctx.Kind,\n\t\t\"--helm-chart\", helmChartPath)\n\tpkg.CheckError(\"creating the project\", err)\n\n\terr = mh.ctx.UncommentRestrictivePodStandards()\n\tpkg.CheckError(\"creating the bundle\", err)\n\n\tlog.Infof(\"customizing the sample\")\n\terr = kbutil.ReplaceInFile(\n\t\tfilepath.Join(mh.ctx.Dir, \"config\", \"samples\", \"cache_v1alpha1_memcached.yaml\"),\n\t\t\"securityContext:\\n    enabled: true\", \"securityContext:\\n    enabled: false\")\n\tpkg.CheckError(\"customizing the sample\", err)\n\n\tlog.Infof(\"enabling prometheus metrics\")\n\terr = kbutil.UncommentCode(\n\t\tfilepath.Join(mh.ctx.Dir, \"config\", \"default\", \"kustomization.yaml\"),\n\t\t\"#- ../prometheus\", \"#\")\n\tpkg.CheckError(\"enabling prometheus metrics\", err)\n\n\tlog.Infof(\"adding customized roles\")\n\terr = kbutil.ReplaceInFile(filepath.Join(mh.ctx.Dir, \"config\", \"rbac\", \"role.yaml\"),\n\t\t\"# +kubebuilder:scaffold:rules\", policyRolesFragment)\n\tpkg.CheckError(\"adding customized roles\", err)\n\n\tlog.Infof(\"creating the bundle\")\n\terr = mh.ctx.GenerateBundle()\n\tpkg.CheckError(\"creating the bundle\", err)\n\n\tlog.Infof(\"striping bundle annotations\")\n\terr = mh.ctx.StripBundleAnnotations()\n\tpkg.CheckError(\"striping bundle annotations\", err)\n\n\tlog.Infof(\"setting createdAt annotation\")\n\tcsv := filepath.Join(mh.ctx.Dir, \"bundle\", \"manifests\", mh.ctx.ProjectName+\".clusterserviceversion.yaml\")\n\terr = kbutil.ReplaceRegexInFile(csv, \"createdAt:.*\", createdAt)\n\tpkg.CheckError(\"setting createdAt annotation\", err)\n}\n\nconst createdAt = `createdAt: \"2022-11-08T17:26:37Z\"`\n\nconst policyRolesFragment = `\n##\n## Base operator rules\n##\n# We need to get namespaces so the operator can read namespaces to ensure they exist\n- apiGroups:\n  - \"\"\n  resources:\n  - namespaces\n  verbs:\n  - get\n# We need to manage Helm release secrets\n- apiGroups:\n  - \"\"\n  resources:\n  - secrets\n  verbs:\n  - \"*\"\n# We need to create events on CRs about things happening during reconciliation\n- apiGroups:\n  - \"\"\n  resources:\n  - events\n  verbs:\n  - create\n\n##\n## Rules for cache.example.com/v1alpha1, Kind: Memcached\n##\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds\n  - memcacheds/status\n  - memcacheds/finalizers\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n- apiGroups:\n  - \"\"\n  resources:\n  - pods\n  - services\n  - services/finalizers\n  - endpoints\n  - persistentvolumeclaims\n  - events\n  - configmaps\n  - secrets\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n- apiGroups:\n  - apps\n  resources:\n  - deployments\n  - daemonsets\n  - replicasets\n  - statefulsets\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n\n\n##\n## Rules customized for cache.example.com/v1alpha1, Kind: Memcached\n##\n- apiGroups:\n  - policy\n  resources:\n  - events\n  - poddisruptionbudgets\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n- apiGroups:\n  - \"\"\n  resources:\n  - serviceaccounts\n  - services\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n\n#+kubebuilder:scaffold:rules\n`\n"
  },
  {
    "path": "hack/generate/samples/internal/pkg/context.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage pkg\n\nimport (\n\t\"github.com/operator-framework/operator-sdk/internal/testutils\"\n)\n\n// SampleContext represents the Context used to generate the samples\ntype SampleContext struct {\n\ttestutils.TestContext\n}\n\n// NewSampleContext returns a SampleContext containing a new kubebuilder TestContext.\nfunc NewSampleContext(binary string, path string, env ...string) (s SampleContext, err error) {\n\ts.TestContext, err = testutils.NewPartialTestContext(binary, path, env...)\n\treturn s, err\n}\n"
  },
  {
    "path": "hack/generate/samples/internal/pkg/utils.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage pkg\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/annotations/metrics\"\n)\n\n// CheckError will exit with exit code 1 when err is not nil.\nfunc CheckError(msg string, err error) {\n\tif err != nil {\n\t\tlog.Errorf(\"error %s: %s\", msg, err)\n\t\tos.Exit(1)\n\t}\n}\n\n// StripBundleAnnotations removes all annotations applied to bundle manifests and metadata\n// by operator-sdk/internal/annotations/metrics annotators. Doing so decouples samples\n// from which operator-sdk version they were build with, as this information is already\n// available in git history.\nfunc (ctx SampleContext) StripBundleAnnotations() (err error) {\n\t// Remove metadata labels.\n\tmetadataAnnotations := metrics.MakeBundleMetadataLabels(\"\")\n\tmetadataFiles := []string{\n\t\tfilepath.Join(ctx.Dir, \"bundle\", \"metadata\", \"annotations.yaml\"),\n\t\tfilepath.Join(ctx.Dir, \"bundle.Dockerfile\"),\n\t}\n\tif err = removeAllAnnotationLines(metadataAnnotations, metadataFiles); err != nil {\n\t\treturn err\n\t}\n\n\t// Remove manifests annotations.\n\tmanifestsAnnotations := metrics.MakeBundleObjectAnnotations(\"\")\n\tmanifestsFiles := []string{\n\t\tfilepath.Join(ctx.Dir, \"bundle\", \"manifests\", ctx.ProjectName+\".clusterserviceversion.yaml\"),\n\t\tfilepath.Join(ctx.Dir, \"config\", \"manifests\", \"bases\", ctx.ProjectName+\".clusterserviceversion.yaml\"),\n\t}\n\n\treturn removeAllAnnotationLines(manifestsAnnotations, manifestsFiles)\n}\n\n// removeAllAnnotationLines removes each line containing a key in annotations from all files at filePaths.\nfunc removeAllAnnotationLines(annotations map[string]string, filePaths []string) error {\n\tvar annotationREs []*regexp.Regexp\n\tfor annotation := range annotations {\n\t\tre, err := regexp.Compile(\".+\" + regexp.QuoteMeta(annotation) + \".+\\n\")\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"compiling annotation regexp: %v\", err)\n\t\t}\n\t\tannotationREs = append(annotationREs, re)\n\t}\n\n\tfor _, file := range filePaths {\n\t\tb, err := os.ReadFile(file)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfor _, re := range annotationREs {\n\t\t\tb = re.ReplaceAll(b, []byte{})\n\t\t}\n\t\terr = os.WriteFile(file, b, 0644)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "hack/lib/common.sh",
    "content": "#!/usr/bin/env bash\n\n# Turn colors in this script off by setting the NO_COLOR variable in your\n# environment to any value:\nNO_COLOR=${NO_COLOR:-\"\"}\nif [ -z \"$NO_COLOR\" ]; then\n  header_color=$'\\e[1;33m'\n  error_color=$'\\e[0;31m'\n  reset_color=$'\\e[0m'\nelse\n  header_color=''\n  error_color=''\n  reset_color=''\nfi\n\nfunction log() { printf '%s\\n' \"$*\"; }\nfunction error() { error_text \"ERROR:\" $* >&2; }\nfunction fatal() { error \"$@\"; exit 1; }\n\nfunction header_text {\n  echo \"$header_color$*$reset_color\"\n}\n\nfunction error_text {\n  echo \"$error_color$*$reset_color\"\n}\n\n#===================================================================\n# FUNCTION trap_add ()\n#\n# Purpose:  prepends a command to a trap\n#\n# - 1st arg:  code to add\n# - remaining args:  names of traps to modify\n#\n# Example:  trap_add 'echo \"in trap DEBUG\"' DEBUG\n#\n# See: http://stackoverflow.com/questions/3338030/multiple-bash-traps-for-the-same-signal\n#===================================================================\nfunction trap_add() {\n    trap_add_cmd=$1; shift || fatal \"${FUNCNAME} usage error\"\n    new_cmd=\n    for trap_add_name in \"$@\"; do\n        # Grab the currently defined trap commands for this trap\n        existing_cmd=`trap -p \"${trap_add_name}\" |  awk -F\"'\" '{print $2}'`\n\n        # Define default command\n        [ -z \"${existing_cmd}\" ] && existing_cmd=\"echo exiting @ `date`\"\n\n        # Generate the new command\n        new_cmd=\"${trap_add_cmd};${existing_cmd}\"\n\n        # Assign the test\n         trap   \"${new_cmd}\" \"${trap_add_name}\" || \\\n                fatal \"unable to add to trap ${trap_add_name}\"\n    done\n}\n\nfunction listPkgDirs() {\n\tgo list -f '{{.Dir}}' ./cmd/... ./test/... ./internal/... | grep -v generated\n}\n\nfunction listFiles() {\n\t# pipeline is much faster than for loop\n\tlistPkgDirs | xargs -I {} find {} -name '*.go' | grep -v generated\n}\n"
  },
  {
    "path": "hack/tests/subcommand-olm-install.sh",
    "content": "#!/usr/bin/env bash\n\nset -ex\n\n\ntest_version() {\n    local version=\"$1\"\n    # If version is \"latest\", run without --version flag\n    local ver_flag=\"--version=${version}\"\n    if [[ \"$version\" == \"latest\" ]]; then\n      ver_flag=\"\"\n    fi\n\n    # Status should fail with OLM not installed\n    commandoutput=$(operator-sdk olm status 2>&1 || true)\n    echo $commandoutput | grep -F \"Failed to get OLM status\"\n\n    # Uninstall should fail with OLM not installed\n    commandoutput=$(operator-sdk olm uninstall 2>&1 || true)\n    echo $commandoutput | grep -F \"Failed to uninstall OLM\"\n\n    # Install should succeed with nothing installed\n    commandoutput=$(operator-sdk olm install $ver_flag 2>&1)\n    echo $commandoutput | grep -F \"Successfully installed OLM version \\\\\\\"${version}\\\\\\\"\"\n\n    # Install should fail with OLM Installed\n    commandoutput=$(operator-sdk olm install $ver_flag 2>&1 || true)\n    echo $commandoutput | grep -F \"Failed to install OLM version \\\\\\\"${version}\\\\\\\": detected existing OLM resources: OLM must be completely uninstalled before installation\"\n\n    # Status should succeed with OLM installed\n    commandoutput=$(operator-sdk olm status 2>&1)\n    echo $commandoutput | grep -F \"Successfully got OLM status\"\n\n    # Uninstall should succeed with OLM installed\n    commandoutput=$(operator-sdk olm uninstall 2>&1)\n    echo $commandoutput | grep -F \"Successfully uninstalled OLM\"\n}\n\ntest_version \"0.28.0\"\ntest_version \"0.17.0\" # Check installation of OLM for locally stored version of binaries\n"
  },
  {
    "path": "images/custom-scorecard-tests/Dockerfile",
    "content": "# Build the custom-scorecard-tests binary\nFROM --platform=$BUILDPLATFORM golang:1.25 AS builder\nARG TARGETARCH\n\nWORKDIR /workspace\n# Copy the Go Modules manifests\nCOPY go.mod go.mod\nCOPY go.sum go.sum\n# cache deps before building and copying source so that we don't need to re-download as much\n# and so that source changes don't invalidate our downloaded layer\nRUN go mod download\n\n# Copy the go source\nCOPY . .\n\n# Build\nRUN GOOS=linux GOARCH=$TARGETARCH make build/custom-scorecard-tests\n\n# Final image.\nFROM registry.access.redhat.com/ubi9/ubi-minimal:9.7\n\nENV HOME=/opt/custom-scorecard-tests \\\n    USER_NAME=custom-scorecard-tests \\\n    USER_UID=1001\n\nRUN echo \"${USER_NAME}:x:${USER_UID}:0:${USER_NAME} user:${HOME}:/sbin/nologin\" >> /etc/passwd\n\nWORKDIR ${HOME}\n\nCOPY --from=builder /workspace/build/custom-scorecard-tests /usr/local/bin/custom-scorecard-tests\n\nENTRYPOINT [\"/usr/local/bin/custom-scorecard-tests\"]\n\nUSER ${USER_UID}\n"
  },
  {
    "path": "images/custom-scorecard-tests/main.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\tscapiv1alpha3 \"github.com/operator-framework/api/pkg/apis/scorecard/v1alpha3\"\n\tapimanifests \"github.com/operator-framework/api/pkg/manifests\"\n)\n\n// This is the custom scorecard test example binary\n// As with the Redhat scorecard test image, the bundle that is under\n// test is expected to be mounted so that tests can inspect the\n// bundle contents as part of their test implementations.\n// The actual test is to be run is named and that name is passed\n// as an argument to this binary.  This argument mechanism allows\n// this binary to run various tests all from within a single\n// test image.\n\nconst PodBundleRoot = \"/bundle\"\n\nfunc main() {\n\tentrypoint := os.Args[1:]\n\tif len(entrypoint) == 0 {\n\t\tlog.Fatal(\"Test name argument is required\")\n\t}\n\n\t// Read the pod's untar'd bundle from a well-known path.\n\tcfg, err := apimanifests.GetBundleFromDir(PodBundleRoot)\n\tif err != nil {\n\t\tlog.Fatal(err.Error())\n\t}\n\n\tvar result scapiv1alpha3.TestStatus\n\n\t// Names of the custom tests which would be passed in the\n\t// `operator-sdk` command.\n\tswitch entrypoint[0] {\n\tcase CustomTest1Name:\n\t\tresult = CustomTest1(cfg)\n\tcase CustomTest2Name:\n\t\tresult = CustomTest2(cfg)\n\tdefault:\n\t\tresult = printValidTests()\n\t}\n\n\t// Convert scapiv1alpha3.TestResult to json.\n\tprettyJSON, err := json.MarshalIndent(result, \"\", \"    \")\n\tif err != nil {\n\t\tlog.Fatal(\"Failed to generate json\", err)\n\t}\n\tfmt.Printf(\"%s\\n\", string(prettyJSON))\n\n}\n\n// printValidTests will print out full list of test names to give a hint to the end user on what the valid tests are.\nfunc printValidTests() scapiv1alpha3.TestStatus {\n\tresult := scapiv1alpha3.TestResult{}\n\tresult.State = scapiv1alpha3.FailState\n\tresult.Errors = make([]string, 0)\n\tresult.Suggestions = make([]string, 0)\n\n\tstr := fmt.Sprintf(\"Valid tests for this image include: %s %s\",\n\t\tCustomTest1Name,\n\t\tCustomTest2Name)\n\tresult.Errors = append(result.Errors, str)\n\treturn scapiv1alpha3.TestStatus{\n\t\tResults: []scapiv1alpha3.TestResult{result},\n\t}\n}\n\nconst (\n\tCustomTest1Name = \"customtest1\"\n\tCustomTest2Name = \"customtest2\"\n)\n\n// Define any operator specific custom tests here.\n// CustomTest1 and CustomTest2 are example test functions. Relevant operator specific\n// test logic is to be implemented in similarly.\n\nfunc CustomTest1(bundle *apimanifests.Bundle) scapiv1alpha3.TestStatus {\n\tr := scapiv1alpha3.TestResult{}\n\tr.Name = CustomTest1Name\n\tr.State = scapiv1alpha3.PassState\n\tr.Errors = make([]string, 0)\n\tr.Suggestions = make([]string, 0)\n\talmExamples := bundle.CSV.GetAnnotations()[\"alm-examples\"]\n\tif almExamples == \"\" {\n\t\tfmt.Println(\"no alm-examples in the bundle CSV\")\n\t}\n\n\treturn wrapResult(r)\n}\n\nfunc CustomTest2(bundle *apimanifests.Bundle) scapiv1alpha3.TestStatus {\n\tr := scapiv1alpha3.TestResult{}\n\tr.Name = CustomTest2Name\n\tr.State = scapiv1alpha3.PassState\n\tr.Errors = make([]string, 0)\n\tr.Suggestions = make([]string, 0)\n\talmExamples := bundle.CSV.GetAnnotations()[\"alm-examples\"]\n\tif almExamples == \"\" {\n\t\tfmt.Println(\"no alm-examples in the bundle CSV\")\n\t}\n\treturn wrapResult(r)\n}\n\nfunc wrapResult(r scapiv1alpha3.TestResult) scapiv1alpha3.TestStatus {\n\treturn scapiv1alpha3.TestStatus{\n\t\tResults: []scapiv1alpha3.TestResult{r},\n\t}\n}\n"
  },
  {
    "path": "images/helm-operator/Dockerfile",
    "content": "# Build the manager binary\nFROM --platform=$BUILDPLATFORM golang:1.25 AS builder\nARG TARGETARCH\n\nWORKDIR /workspace\n# Copy the Go Modules manifests\nCOPY go.mod go.mod\nCOPY go.sum go.sum\n# cache deps before building and copying source so that we don't need to re-download as much\n# and so that source changes don't invalidate our downloaded layer\nRUN go mod download\n\n# Copy the go source\nCOPY . .\n\n# Build\nRUN GOOS=linux GOARCH=$TARGETARCH make build/helm-operator\n\n# Final image.\nFROM registry.access.redhat.com/ubi9/ubi-minimal:9.7\n\nENV HOME=/opt/helm \\\n    USER_NAME=helm \\\n    USER_UID=1001\n\nRUN echo \"${USER_NAME}:x:${USER_UID}:0:${USER_NAME} user:${HOME}:/sbin/nologin\" >> /etc/passwd\n\nWORKDIR ${HOME}\nUSER ${USER_UID}\n\nCOPY --from=builder /workspace/build/helm-operator /usr/local/bin/helm-operator\n\nENTRYPOINT [\"/usr/local/bin/helm-operator\", \"run\", \"--watches-file=./watches.yaml\"]\n"
  },
  {
    "path": "images/operator-sdk/Dockerfile",
    "content": "# Build the operator-sdk binary\nFROM --platform=$BUILDPLATFORM golang:1.25 AS builder\nARG TARGETARCH\n\nWORKDIR /workspace\n# Copy the Go Modules manifests\nCOPY go.mod go.mod\nCOPY go.sum go.sum\n# cache deps before building and copying source so that we don't need to re-download as much\n# and so that source changes don't invalidate our downloaded layer\nRUN go mod download\n\n# Copy the go source\nCOPY . .\n\n# Build\nRUN GOOS=linux GOARCH=$TARGETARCH make build/operator-sdk\n\n# Final image.\nFROM registry.access.redhat.com/ubi9/ubi-minimal:9.7\n\nARG TARGETARCH\nRUN microdnf install -y make gcc which tar gzip\n\n# Copy Go runtime from builder image\nCOPY --from=builder /usr/local/go /usr/local/go\nRUN ln -sf /usr/local/go/bin/* /usr/local/bin/ && go version\n\nCOPY --from=builder /workspace/build/operator-sdk /usr/local/bin/operator-sdk\n\nENTRYPOINT [\"/usr/local/bin/operator-sdk\"]\n"
  },
  {
    "path": "images/scorecard-storage/Dockerfile",
    "content": "FROM docker.io/busybox:1.36\n\n## Create a new non-root user to run as\nENV HOME=/opt/scorecard-untar \\\n    USER_NAME=scorecard-untar \\\n    USER_UID=1001\n\nRUN echo \"${USER_NAME}:x:${USER_UID}:0:${USER_NAME} user:${HOME}:/sbin/nologin\" >> /etc/passwd\n\nWORKDIR ${HOME}\n\nUSER ${USER_UID}\n"
  },
  {
    "path": "images/scorecard-test/Dockerfile",
    "content": "# Build the scorecard-test binary\nFROM --platform=$BUILDPLATFORM golang:1.25 AS builder\nARG TARGETARCH\n\nWORKDIR /workspace\n# Copy the Go Modules manifests\nCOPY go.mod go.mod\nCOPY go.sum go.sum\n# cache deps before building and copying source so that we don't need to re-download as much\n# and so that source changes don't invalidate our downloaded layer\nRUN go mod download\n\n# Copy the go source\nCOPY . .\n\n# Build\nRUN GOOS=linux GOARCH=$TARGETARCH make build/scorecard-test\n\n# Final image.\nFROM registry.access.redhat.com/ubi9/ubi-minimal:9.7\n\nENV HOME=/opt/scorecard-test \\\n    USER_NAME=scorecard-test \\\n    USER_UID=1001\n\nRUN echo \"${USER_NAME}:x:${USER_UID}:0:${USER_NAME} user:${HOME}:/sbin/nologin\" >> /etc/passwd\n\nWORKDIR ${HOME}\n\nCOPY --from=builder /workspace/build/scorecard-test /usr/local/bin/scorecard-test\n\nENTRYPOINT [\"/usr/local/bin/scorecard-test\"]\n\nUSER ${USER_UID}\n"
  },
  {
    "path": "images/scorecard-test/main.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\tscapiv1alpha3 \"github.com/operator-framework/api/pkg/apis/scorecard/v1alpha3\"\n\tapimanifests \"github.com/operator-framework/api/pkg/manifests\"\n\n\tregistryutil \"github.com/operator-framework/operator-sdk/internal/registry\"\n\t\"github.com/operator-framework/operator-sdk/internal/scorecard\"\n\t\"github.com/operator-framework/operator-sdk/internal/scorecard/tests\"\n)\n\n// this is the scorecard test binary that ultimately executes the\n// built-in scorecard tests (basic/olm).  The bundle that is under\n// test is expected to be mounted so that tests can inspect the\n// bundle contents as part of their test implementations.\n// The actual test is to be run is named and that name is passed\n// as an argument to this binary.  This argument mechanism allows\n// this binary to run various tests all from within a single\n// test image.\n\nfunc main() {\n\tentrypoint := os.Args[1:]\n\tif len(entrypoint) == 0 {\n\t\tlog.Fatal(\"test name argument is required\")\n\t}\n\n\t// Read the pod's untar'd bundle from a well-known path.\n\tbundle, err := apimanifests.GetBundleFromDir(scorecard.PodBundleRoot)\n\tif err != nil {\n\t\tlog.Fatal(err.Error())\n\t}\n\n\tmetadata, _, err := registryutil.FindBundleMetadata(scorecard.PodBundleRoot)\n\tif err != nil {\n\t\tlog.Fatal(err.Error())\n\t}\n\n\tvar result scapiv1alpha3.TestStatus\n\n\tswitch entrypoint[0] {\n\tcase tests.OLMBundleValidationTest:\n\t\tresult = tests.BundleValidationTest(scorecard.PodBundleRoot, metadata)\n\tcase tests.OLMCRDsHaveValidationTest:\n\t\tresult = tests.CRDsHaveValidationTest(bundle)\n\tcase tests.OLMCRDsHaveResourcesTest:\n\t\tresult = tests.CRDsHaveResourcesTest(bundle)\n\tcase tests.OLMSpecDescriptorsTest:\n\t\tresult = tests.SpecDescriptorsTest(bundle)\n\tcase tests.OLMStatusDescriptorsTest:\n\t\tresult = tests.StatusDescriptorsTest(bundle)\n\tcase tests.BasicCheckSpecTest:\n\t\tresult = tests.CheckSpecTest(bundle)\n\tdefault:\n\t\tresult = printValidTests()\n\t}\n\n\tprettyJSON, err := json.MarshalIndent(result, \"\", \"    \")\n\tif err != nil {\n\t\tlog.Fatal(\"failed to generate json\", err)\n\t}\n\tfmt.Printf(\"%s\\n\", string(prettyJSON))\n\n}\n\n// printValidTests will print out full list of test names to give a hint to the end user on what the valid tests are\nfunc printValidTests() scapiv1alpha3.TestStatus {\n\tresult := scapiv1alpha3.TestResult{}\n\tresult.State = scapiv1alpha3.FailState\n\tresult.Errors = make([]string, 0)\n\tresult.Suggestions = make([]string, 0)\n\n\tstr := fmt.Sprintf(\"Valid tests for this image include: %s, %s, %s, %s, %s, %s\",\n\t\ttests.OLMBundleValidationTest,\n\t\ttests.OLMCRDsHaveValidationTest,\n\t\ttests.OLMCRDsHaveResourcesTest,\n\t\ttests.OLMSpecDescriptorsTest,\n\t\ttests.OLMStatusDescriptorsTest,\n\t\ttests.BasicCheckSpecTest)\n\tresult.Errors = append(result.Errors, str)\n\treturn scapiv1alpha3.TestStatus{\n\t\tResults: []scapiv1alpha3.TestResult{result},\n\t}\n}\n"
  },
  {
    "path": "images/scorecard-test-kuttl/Dockerfile",
    "content": "# Build the scorecard-test-kuttl binary\nFROM --platform=$BUILDPLATFORM golang:1.25 AS builder\nARG TARGETARCH\nARG BUILDPLATFORM\n\nWORKDIR /workspace\n# Copy the Go Modules manifests\nCOPY go.mod go.mod\nCOPY go.sum go.sum\n# cache deps before building and copying source so that we don't need to re-download as much\n# and so that source changes don't invalidate our downloaded layer\nRUN go mod download\n\n# Copy the go source\nCOPY . .\n\n# Build\nRUN GOOS=linux GOARCH=$TARGETARCH make build/scorecard-test-kuttl\n\n# Final image.\n#FROM kudobuilder/kuttl@sha256:8d4dad161521450db95f88fe0e62487cc6587c5818df2a4e750fb9e54c082170\nFROM kudobuilder/kuttl:v0.15.0\n\nENV HOME=/opt/scorecard-test-kuttl \\\n    USER_NAME=scorecard-test-kuttl \\\n    USER_UID=1001 \\\n    KUBECONFIG=\n\nRUN echo \"${USER_NAME}:x:${USER_UID}:0:${USER_NAME} user:${HOME}:/sbin/nologin\" >> /etc/passwd\n\nWORKDIR ${HOME}\n# kuttl writes a kubeconfig file in the current working directory\nRUN chmod g+w \"${HOME}\"\n\nCOPY --from=builder /workspace/build/scorecard-test-kuttl /usr/local/bin/scorecard-test-kuttl\nCOPY --from=builder /workspace/images/scorecard-test-kuttl/entrypoint /usr/local/bin/entrypoint\n\nENTRYPOINT [\"/usr/local/bin/entrypoint\"]\n\nUSER ${USER_UID}\n"
  },
  {
    "path": "images/scorecard-test-kuttl/entrypoint",
    "content": "#!/bin/sh\n\nKUTTL_PATH=${KUTTL_PATH:-\"/bundle/tests/scorecard/kuttl\"}\nKUTTL_CONFIG=${KUTTL_CONFIG:-\"${KUTTL_PATH}/kuttl-test.yaml\"}\n\nif [ $# -eq 0 ]\n  then\n    # if the arg list is 0, then just call kuttl with no test flag\n    # NOTE: this was the original call\n    kubectl-kuttl test ${KUTTL_PATH} \\\n      --config=${KUTTL_CONFIG} \\\n      --namespace=${SCORECARD_NAMESPACE} \\\n      --report=JSON --artifacts-dir=/tmp > /tmp/kuttl.stdout 2> /tmp/kuttl.stderr\n  else\n    # if there is 1 or more then let's call kuttl multiple times\n    for i in $*; do\n      kubectl-kuttl test ${KUTTL_PATH} \\\n      --test $i  \\\n      --config=${KUTTL_CONFIG} \\\n      --namespace=${SCORECARD_NAMESPACE} \\\n      --report=JSON --artifacts-dir=/tmp > /tmp/kuttl.stdout 2> /tmp/kuttl.stderr\n    done\nfi\n\n# send the list of args to scorecard-test-kuttl\n# NOTE: I'm not sure it uses the args for anything at the moment\nexec scorecard-test-kuttl $@\n"
  },
  {
    "path": "images/scorecard-test-kuttl/main.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage main\n\nimport (\n\t\"encoding/json\"\n\t\"encoding/xml\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\n\t\"github.com/operator-framework/api/pkg/apis/scorecard/v1alpha3\"\n)\n\n// The scorecard test kuttl binary processes the\n// output from kuttl converting kuttl output into the\n// scorecard v1alpha3.TestStatus json format.\n//\n// The kuttl output is expected to be produced by kubectl-kuttl\n// at /tmp/kuttl-report.json.\nfunc main() {\n\n\tjsonFile, err := os.Open(\"/tmp/kuttl-report.json\")\n\tif err != nil {\n\t\tprintErrorStatus(fmt.Errorf(\"could not open kuttl report %v\", err))\n\t\treturn\n\t}\n\tdefer jsonFile.Close()\n\n\tvar byteValue []byte\n\tbyteValue, err = io.ReadAll(jsonFile)\n\tif err != nil {\n\t\tprintErrorStatus(fmt.Errorf(\"could not read kuttl report %v\", err))\n\t\treturn\n\t}\n\n\tvar jsonReport Testsuites\n\terr = json.Unmarshal(byteValue, &jsonReport)\n\tif err != nil {\n\t\tprintErrorStatus(fmt.Errorf(\"could not unmarshal kuttl report %v\", err))\n\t\treturn\n\t}\n\n\tvar suite *Testsuite\n\tif len(jsonReport.Testsuite) == 0 {\n\t\tprintErrorStatus(errors.New(\"no kuttl test suite was found. kuttl may not have run successfully\"))\n\t\treturn\n\t}\n\n\tsuite = jsonReport.Testsuite[0]\n\n\ts := getTestStatus(suite.Testcase)\n\n\tjsonOutput, err := json.MarshalIndent(s, \"\", \"    \")\n\tif err != nil {\n\t\tprintErrorStatus(fmt.Errorf(\"could not marshal scorecard output %v\", err))\n\t\treturn\n\t}\n\tfmt.Println(string(jsonOutput))\n}\n\nfunc getTestStatus(tc []*Testcase) (s v1alpha3.TestStatus) {\n\n\t// report the kuttl logs when kuttl tests can not be run\n\t// (e.g. RBAC is not sufficient)\n\tif len(tc) == 0 {\n\t\tr := v1alpha3.TestResult{}\n\t\tr.Log = getKuttlLogs()\n\t\ts.Results = append(s.Results, r)\n\t\treturn s\n\t}\n\n\tfor i := 0; i < len(tc); i++ {\n\t\tr := v1alpha3.TestResult{}\n\t\tr.Name = tc[i].Name\n\t\tr.State = v1alpha3.PassState\n\t\tif tc[i].Failure != nil {\n\t\t\tr.State = v1alpha3.FailState\n\t\t\tr.Errors = []string{tc[i].Failure.Text}\n\t\t}\n\t\ts.Results = append(s.Results, r)\n\t}\n\n\treturn s\n}\n\nfunc printErrorStatus(err error) {\n\ts := v1alpha3.TestStatus{}\n\tr := v1alpha3.TestResult{}\n\tr.State = v1alpha3.FailState\n\tr.Errors = []string{err.Error()}\n\tr.Log = getKuttlLogs()\n\ts.Results = append(s.Results, r)\n\tjsonOutput, err := json.MarshalIndent(s, \"\", \"    \")\n\tif err != nil {\n\t\tlog.Fatal(fmt.Errorf(\"could not marshal scorecard output %v\", err))\n\t}\n\tfmt.Println(string(jsonOutput))\n}\n\n// kuttl report format\n// the kuttl structs below are copied from the kuttl master currently,\n// in the future, these structs might be pulled into SDK as\n// normal golang deps if necessary\n\n// Property are name/value pairs which can be provided in the report for things such as kuttl.version\ntype Property struct {\n\tName  string `xml:\"name,attr\" json:\"name\"`\n\tValue string `xml:\"value,attr\" json:\"value\"`\n}\n\n// Properties defines the collection of properties\ntype Properties struct {\n\tProperty []Property `xml:\"property\" json:\"property,omitempty\"`\n}\n\n// Failure defines a test failure\ntype Failure struct {\n\t// Text provides detailed information regarding failure.  It supports multi-line output.\n\tText string `xml:\",chardata\" json:\"text,omitempty\"`\n\t// Message provides the summary of the failure\n\tMessage string `xml:\"message,attr\" json:\"message\"`\n\tType    string `xml:\"type,attr\" json:\"type,omitempty\"`\n}\n\n// Testcase is the finest grain level of reporting, it is the kuttl test (which contains steps)\ntype Testcase struct {\n\t// Classname is a junit thing, for kuttl it is the testsuite name\n\tClassname string `xml:\"classname,attr\" json:\"classname\"`\n\t// Name is the name of the test (folder of test if not redefined by the TestStep)\n\tName string `xml:\"name,attr\" json:\"name\"`\n\t// Time is the elapsed time of the test (and all of it's steps)\n\tTime string `xml:\"time,attr\" json:\"time\"`\n\t// Assertions is the number of asserts and errors defined in the test\n\tAssertions int `xml:\"assertions,attr\" json:\"assertions,omitempty\"`\n\t// Failure defines a failure in this testcase\n\tFailure *Failure `xml:\"failure\" json:\"failure,omitempty\"`\n}\n\n// TestSuite is a collection of Testcase and is a summary of those details\ntype Testsuite struct {\n\t// Tests is the number of Testcases in the collection\n\tTests int `xml:\"tests,attr\" json:\"tests\"`\n\t// Failures is the summary number of all failure in the collection testcases\n\tFailures int `xml:\"failures,attr\" json:\"failures\"`\n\t// Time is the duration of time for this Testsuite, this is tricky as tests run concurrently.\n\t// This is the elapse time between the start of the testsuite and the end of the latest testcase in the collection.\n\tTime string `xml:\"time,attr\" json:\"time\"`\n\t// Name is the kuttl test name\n\tName string `xml:\"name,attr\" json:\"name\"`\n\t// Properties which are specific to this suite\n\tProperties *Properties `xml:\"properties\" json:\"properties,omitempty\"`\n\t// Testcase is a collection of test cases\n\tTestcase []*Testcase `xml:\"testcase\" json:\"testcase,omitempty\"`\n}\n\n// Testsuites is a collection of Testsuite and defines the rollup summary of all stats.\ntype Testsuites struct {\n\t// XMLName is required to refine the name (or case of the name)\n\t//in the root xml element.  Otherwise it adds no value and is ignored for json output.\n\tXMLName xml.Name `json:\"-\"`\n\t// Name is the name of the full set of tests which is possible to set in kuttl but is rarely used :)\n\tName string `xml:\"name,attr\" json:\"name\"`\n\t// Tests is a summary value of the total number of tests for all testsuites\n\tTests int `xml:\"tests,attr\" json:\"tests\"`\n\t// Failures is a summary value of the total number of failures for all testsuites\n\tFailures int `xml:\"failures,attr\" json:\"failures\"`\n\t// Time is the elapsed time of the entire suite of tests\n\tTime string `xml:\"time,attr\" json:\"time\"`\n\t// Properties which are for the entire set of tests\n\tProperties *Properties `xml:\"properties\" json:\"properties,omitempty\"`\n\t// Testsuite is a collection of test suites\n\tTestsuite []*Testsuite `xml:\"testsuite\" json:\"testsuite,omitempty\"`\n}\n\nfunc getKuttlLogs() string {\n\tstderrFile, err := os.ReadFile(\"/tmp/kuttl.stderr\")\n\tif err != nil {\n\t\treturn fmt.Sprintf(\"could not open kuttl stderr file: %v\", err)\n\t}\n\n\tstdoutFile, err := os.ReadFile(\"/tmp/kuttl.stdout\")\n\tif err != nil {\n\t\treturn fmt.Sprintf(\"could not open kuttl stdout file: %v\", err)\n\t}\n\n\treturn string(stderrFile) + string(stdoutFile)\n}\n"
  },
  {
    "path": "images/scorecard-untar/Dockerfile",
    "content": "FROM registry.access.redhat.com/ubi9/ubi:9.7\n\n## Create a new non-root user to run as\nENV HOME=/opt/scorecard-untar \\\n    USER_NAME=scorecard-untar \\\n    USER_UID=1001\n\nRUN echo \"${USER_NAME}:x:${USER_UID}:0:${USER_NAME} user:${HOME}:/sbin/nologin\" >> /etc/passwd\n\nWORKDIR ${HOME}\n\nUSER ${USER_UID}\n"
  },
  {
    "path": "internal/annotations/metrics/metrics.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage metrics\n\nimport (\n\t\"regexp\"\n\t\"strings\"\n\n\tsdkversion \"github.com/operator-framework/operator-sdk/internal/version\"\n)\n\n// Static bundle annotation values.\nconst (\n\tmediaTypeV1 = \"metrics+v1\"\n)\n\n// Bundle annotation keys.\nconst (\n\tmediaTypeBundleAnnotation = \"operators.operatorframework.io.metrics.mediatype.v1\"\n\tbuilderBundleAnnotation   = \"operators.operatorframework.io.metrics.builder\"\n\tlayoutBundleAnnotation    = \"operators.operatorframework.io.metrics.project_layout\"\n)\n\n// Object annotation keys.\nconst (\n\tBuilderObjectAnnotation = \"operators.operatorframework.io/builder\"\n\tLayoutObjectAnnotation  = \"operators.operatorframework.io/project_layout\"\n)\n\n// MakeBundleMetadataLabels returns the SDK metric labels which will be added\n// to bundle resources like bundle.Dockerfile and annotations.yaml.\nfunc MakeBundleMetadataLabels(layout string) map[string]string {\n\treturn map[string]string{\n\t\tmediaTypeBundleAnnotation: mediaTypeV1,\n\t\tbuilderBundleAnnotation:   getSDKBuilder(sdkversion.Version),\n\t\tlayoutBundleAnnotation:    layout,\n\t}\n}\n\n// MakeBundleObjectAnnotations returns the SDK metric annotations which will be added\n// to CustomResourceDefinitions and ClusterServiceVersions.\nfunc MakeBundleObjectAnnotations(layout string) map[string]string {\n\treturn map[string]string{\n\t\tBuilderObjectAnnotation: getSDKBuilder(sdkversion.Version),\n\t\tLayoutObjectAnnotation:  layout,\n\t}\n}\n\nfunc getSDKBuilder(rawSDKVersion string) string {\n\treturn \"operator-sdk\" + \"-\" + parseVersion(rawSDKVersion)\n}\n\nfunc parseVersion(input string) string {\n\tre := regexp.MustCompile(`v[0-9]+\\.[0-9]+\\.[0-9]+`)\n\tversion := re.FindString(input)\n\tif version == \"\" {\n\t\treturn \"unknown\"\n\t}\n\n\tif isUnreleased(input) {\n\t\tversion = version + \"+git\"\n\t}\n\treturn version\n}\n\n// isUnreleased returns true if sdk was not built from released version.\nfunc isUnreleased(input string) bool {\n\tif strings.Contains(input, \"+git\") {\n\t\treturn true\n\t}\n\tre := regexp.MustCompile(`v[0-9]+\\.[0-9]+\\.[0-9]+-.+`)\n\treturn re.MatchString(input)\n}\n"
  },
  {
    "path": "internal/annotations/metrics/metrics_suite_test.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage metrics\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nfunc TestMetrics(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"Metrics Suite\")\n}\n"
  },
  {
    "path": "internal/annotations/metrics/metrics_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage metrics\n\nimport (\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nvar _ = Describe(\"SDK Label helper functions\", func() {\n\tDescribe(\"parseVersion\", func() {\n\t\tIt(\"should extract sdk version\", func() {\n\t\t\tversion := \"v0.17.0-159-ge87627f4-dirty\"\n\t\t\toutput := parseVersion(version)\n\t\t\tExpect(output).To(Equal(\"v0.17.0+git\"))\n\t\t})\n\t\tIt(\"should extract sdk version\", func() {\n\t\t\tversion := \"v0.18.0\"\n\t\t\toutput := parseVersion(version)\n\t\t\tExpect(output).To(Equal(\"v0.18.0\"))\n\t\t})\n\t\tIt(\"should extract sdk version\", func() {\n\t\t\tversion := \"v0.18.0-ge87627f4\"\n\t\t\toutput := parseVersion(version)\n\t\t\tExpect(output).To(Equal(\"v0.18.0+git\"))\n\t\t})\n\t\tIt(\"should return unknown\", func() {\n\t\t\tversion := \"noneSemanticVersion\"\n\t\t\toutput := parseVersion(version)\n\t\t\tExpect(output).To(Equal(\"unknown\"))\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "internal/annotations/scorecard/scorecard.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage scorecard\n\nimport (\n\t\"path/filepath\"\n)\n\n// Static bundle annotation values.\nconst (\n\tmediaTypeV1 = \"scorecard+v1\"\n)\n\n// Bundle annotation keys.\n// NB(estroz): version these keys based on their \"vX\" version (either with the version in their names,\n// or in subpackages). This may be a requirement if we create \"v2\" keys.\nconst (\n\tmediaTypeBundleKey = \"operators.operatorframework.io.test.mediatype.v1\"\n\tconfigBundleKey    = \"operators.operatorframework.io.test.config.v1\"\n)\n\nfunc MakeBundleMetadataLabels(configDir string) map[string]string {\n\treturn map[string]string{\n\t\tmediaTypeBundleKey: mediaTypeV1,\n\t\tconfigBundleKey:    configDir,\n\t}\n}\n\nfunc GetConfigDir(labels map[string]string) (value string, hasKey bool) {\n\tif configKey, hasMTKey := configKeyForMediaType(labels); hasMTKey {\n\t\tvalue, hasKey = labels[configKey]\n\t}\n\treturn filepath.Clean(filepath.FromSlash(value)), hasKey\n}\n\nfunc configKeyForMediaType(labels map[string]string) (string, bool) {\n\tswitch labels[mediaTypeBundleKey] {\n\tcase mediaTypeV1:\n\t\treturn configBundleKey, true\n\t}\n\treturn \"\", false\n}\n"
  },
  {
    "path": "internal/bindata/olm/manifests.go",
    "content": "// Code generated for package olm by go-bindata DO NOT EDIT. (@generated)\n// sources:\n// olm-manifests/0.26.0-crds.yaml\n// olm-manifests/0.26.0-olm.yaml\n// olm-manifests/0.27.0-crds.yaml\n// olm-manifests/0.27.0-olm.yaml\n// olm-manifests/0.28.0-crds.yaml\n// olm-manifests/0.28.0-olm.yaml\npackage olm\n\nimport (\n\t\"bytes\"\n\t\"compress/gzip\"\n\t\"fmt\"\n\t\"io\"\n\t\"io/ioutil\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"time\"\n)\n\nfunc bindataRead(data []byte, name string) ([]byte, error) {\n\tgz, err := gzip.NewReader(bytes.NewBuffer(data))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"Read %q: %v\", name, err)\n\t}\n\n\tvar buf bytes.Buffer\n\t_, err = io.Copy(&buf, gz)\n\tclErr := gz.Close()\n\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"Read %q: %v\", name, err)\n\t}\n\tif clErr != nil {\n\t\treturn nil, err\n\t}\n\n\treturn buf.Bytes(), nil\n}\n\ntype asset struct {\n\tbytes []byte\n\tinfo  os.FileInfo\n}\n\ntype bindataFileInfo struct {\n\tname    string\n\tsize    int64\n\tmode    os.FileMode\n\tmodTime time.Time\n}\n\n// Name return file name\nfunc (fi bindataFileInfo) Name() string {\n\treturn fi.name\n}\n\n// Size return file size\nfunc (fi bindataFileInfo) Size() int64 {\n\treturn fi.size\n}\n\n// Mode return file mode\nfunc (fi bindataFileInfo) Mode() os.FileMode {\n\treturn fi.mode\n}\n\n// Mode return file modify time\nfunc (fi bindataFileInfo) ModTime() time.Time {\n\treturn fi.modTime\n}\n\n// IsDir return file whether a directory\nfunc (fi bindataFileInfo) IsDir() bool {\n\treturn fi.mode&os.ModeDir != 0\n}\n\n// Sys return file is sys mode\nfunc (fi bindataFileInfo) Sys() any {\n\treturn nil\n}\n\nvar _olmManifests0260CrdsYaml = []byte(\"\\x1f\\x8b\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xec\\xbd\\x79\\x77\\x23\\xb7\\xb1\\x38\\xfa\\xbf\\x3f\\x05\\x8e\\xe2\\xfb\\x24\\x39\\x24\\x35\\x93\\xed\\x97\\xe8\\x26\\xf1\\xd1\\x95\\xc6\\x8e\\x9e\\x67\\xd1\\x19\\xc9\\xce\\xcb\\xcf\\xe3\\x1b\\x83\\xdd\\x45\\x12\\x51\\x37\\xd0\\x01\\xd0\\x94\\x98\\x38\\xdf\\xfd\\x1d\\x54\\x01\\xbd\\x70\\x13\\x97\\x9e\\x19\\x69\\x0c\\xe4\\x9c\\x78\\xc4\\xee\\xc6\\x52\\x28\\xd4\\x5e\\x85\\x7e\\xbf\\xff\\x19\\x2f\\xc4\\x77\\xa0\\x8d\\x50\\xf2\\x94\\xf1\\x42\\xc0\\xbd\\x05\\xe9\\xfe\\x32\\x83\\xdb\\xdf\\x9b\\x81\\x50\\x27\\xd3\\xe7\\x9f\\xdd\\x0a\\x99\\x9e\\xb2\\xf3\\xd2\\x58\\x95\\xbf\\x05\\xa3\\x4a\\x9d\\xc0\\x05\\x8c\\x84\\x14\\x56\\x28\\xf9\\x59\\x0e\\x96\\xa7\\xdc\\xf2\\xd3\\xcf\\x18\\xe3\\x52\\x2a\\xcb\\xdd\\xcf\\xc6\\xfd\\xc9\\x58\\xa2\\xa4\\xd5\\x2a\\xcb\\x40\\xf7\\xc7\\x20\\x07\\xb7\\xe5\\x10\\x86\\xa5\\xc8\\x52\\xd0\\xd8\\x79\\x18\\x7a\\xfa\\x6c\\xf0\\x87\\xc1\\xb3\\xcf\\x18\\x4b\\x34\\xe0\\xe7\\x37\\x22\\x07\\x63\\x79\\x5e\\x9c\\x32\\x59\\x66\\xd9\\x67\\x8c\\x49\\x9e\\xc3\\x29\\x4b\\xb8\\xe5\\x99\\x1a\\xd3\\x24\\xcc\\x40\\x15\\xa0\\xb9\\x55\\xda\\x0c\\x12\\xa5\\x41\\xb9\\xff\\xe4\\x9f\\x99\\x02\\x12\\x37\\xfa\\x58\\xab\\xb2\\x38\\x65\\x4b\\xdf\\xa1\\xfe\\xc2\\x24\\xb9\\x85\\xb1\\xd2\\x22\\xfc\\xcd\\x58\\x9f\\xa9\\x2c\\xc7\\x7f\\xfb\\xc5\\xd3\\xb0\\xd7\\x38\\x2c\\xfe\\x9e\\x09\\x63\\xbf\\x59\\x7c\\xf6\\x52\\x18\\x8b\\xcf\\x8b\\xac\\xd4\\x3c\\x9b\\x9f\\x30\\x3e\\x32\\x13\\xa5\\xed\\xeb\\x7a\\x78\\x37\\x5c\\xc2\\xad\\xd1\\x09\\x3d\\x16\\x72\\x5c\\x66\\x5c\\xcf\\x7d\\xfb\\x19\\x63\\x26\\x51\\x05\\x9c\\x32\\xfc\\xb4\\xe0\\x09\\xa4\\x9f\\x31\\xe6\\x41\\xe8\\xbb\\xea\\x33\\x9e\\xa6\\xb8\\x2d\\x3c\\xbb\\xd2\\x42\\x5a\\xd0\\xe7\\x2a\\x2b\\x73\\x59\\x0d\\xe5\\xde\\x49\\xc1\\x24\\x5a\\x14\\x16\\x41\\x7f\\x33\\x01\\x56\\x68\\xb0\\x76\\x86\\x20\\x61\\x6a\\xc4\\xec\\x04\\xc2\\xd8\\xd5\\x57\\x8c\\xfd\\xc3\\x28\\x79\\xc5\\xed\\xe4\\x94\\x0d\\x1c\\x84\\x07\\xa9\\x30\\x45\\xc6\\x67\\x6e\\x36\\x8d\\xb7\\x68\\x9b\\x2e\\xe8\\x59\\xe3\\x77\\x3b\\x73\\x53\\x37\\x56\\x0b\\x39\\x5e\\x37\\x15\\xf7\\xde\\xe6\\x73\\x20\\xd0\\xdc\\xcc\\x8a\\xc5\\x29\\xcc\\xfd\\xb8\\xe9\\xf8\\x45\\x39\\xcc\\x84\\x99\\x80\\xde\\x7c\\x12\\xd5\\x27\\x0b\\x73\\xb8\\x5a\\xf2\\x64\\xc5\\x44\\x1a\\x9d\\x86\\x03\\x35\\x58\\x38\\x0c\\x0b\\x03\\x9c\\x8d\\x17\\xd7\\x98\\x72\\x1b\\x7e\\xa4\\x97\\xa6\\xcf\\x79\\x56\\x4c\\xf8\\x73\\xff\\xa3\\x49\\x26\\x90\\xf3\\x1a\\x1f\\x54\\x01\\xf2\\xec\\xea\\xf2\\xbb\\x5f\\x5f\\xcf\\x3d\\x60\\x6d\\xe8\\xb4\\xf0\\x9c\\x09\\xc3\\x38\\xd3\\x50\\x28\\x23\\xac\\xd2\\x33\\x07\\xad\\xf3\\xeb\\xef\\x4c\\x8f\\x9d\\xbf\\xbd\\x30\\x3d\\xc6\\x65\\x5a\\x1d\\x3c\\x56\\xf0\\xe4\\x96\\x8f\\xc1\\x0c\\x16\\xe6\\xaa\\x86\\xff\\x80\\xc4\\x36\\x7e\\xd6\\xf0\\xcf\\x52\\x68\\x48\\x9b\\xb3\\x70\\xe0\\x09\\x30\\x99\\xfb\\xd9\\xc1\\xbf\\xf1\\x53\\xa1\\xdd\\x98\\xb6\\x71\\x90\\xa9\\x35\\xa8\\x5c\\xeb\\xf7\\xb9\\x15\\x1e\\x3a\\x30\\xd0\\x7b\\x2c\\x75\\x04\\x0e\\x0c\\xa2\\x80\\x3f\\x63\\x90\\x7a\\xd8\\x11\\x6a\\x08\\xe3\\xd6\\xaf\\xc1\\x80\\x24\\x92\\xe7\\x7e\\xe6\\xd2\\xaf\\x69\\xc0\\xae\\x41\\xbb\\x0f\\xdd\\x71\\x2f\\xb3\\xd4\\x51\\xc2\\x29\\x68\\xcb\\x34\\x24\\x6a\\x2c\\xc5\\xbf\\xaa\\xde\\x0c\\xb3\\x0a\\x87\\xc9\\xb8\\x05\\x63\\x19\\x9e\\x5a\\xc9\\x33\\x36\\xe5\\x59\\x09\\x04\\xca\\x9c\\xcf\\x98\\x06\\xd7\\x2f\\x2b\\x65\\xa3\\x07\\x7c\\xc5\\x0c\\xd8\\x2b\\xa5\\x81\\x09\\x39\\x52\\xa7\\x6c\\x62\\x6d\\x61\\x4e\\x4f\\x4e\\xc6\\xc2\\x06\\x1a\\x9e\\xa8\\x3c\\x2f\\xa5\\xb0\\xb3\\x13\\x24\\xc7\\x62\\x58\\x3a\\x72\\x78\\x92\\xc2\\x14\\xb2\\x13\\x23\\xc6\\x7d\\xae\\x93\\x89\\xb0\\x90\\xd8\\x52\\xc3\\x09\\x2f\\x44\\x1f\\x27\\x2b\\x91\\x8e\\x0f\\xf2\\xf4\\x17\\xda\\x53\\x7d\\x73\\x38\\x07\\xbe\\xa5\\xc8\\xcc\\x02\\xd9\\x5c\\x0b\\x6b\\x47\\x3c\\x09\\x8b\\xe8\\x73\\x5a\\x4b\\x0d\\x52\\xf7\\x93\\x83\\xca\\xdb\\x17\\xd7\\x37\\x2c\\x4c\\x80\\xc0\\x4e\\x10\\xae\\x5f\\x35\\x35\\xb0\\x1d\\xa0\\x84\\x1c\\x81\\xa6\\x37\\x47\\x5a\\xe5\\xd8\\x0b\\xc8\\xb4\\x50\\x42\\x5a\\x3a\\xd2\\x99\\x00\\x69\\x99\\x29\\x87\\xb9\\xb0\\x06\\x71\\x0e\\x8c\\x75\\xfb\\x30\\x60\\xe7\\xc8\\xc2\\xd8\\x10\\x58\\x59\\xb8\\x93\\x94\\x0e\\xd8\\xa5\\x64\\xe7\\x3c\\x87\\xec\\x9c\\x1b\\x78\\xef\\xa0\\x76\\x10\\x35\\x7d\\x07\\xbe\\xcd\\x81\\xdd\\xe4\\xc0\\x8b\\x1f\\x2c\\x9c\\x31\\xc6\\x02\\x87\\xdc\\xe8\\xe5\\x55\\x87\\x92\\xd1\\x09\\x5c\\x46\\x81\\xd9\\x9a\\xb3\\xe8\\x1a\\x4f\\x53\\x0d\\x66\\xc9\\x83\\x85\\x03\\x49\\x2f\\x12\\x9e\\x4c\\x94\\x71\\xfb\\xc7\\x2d\\x7b\\xf3\\xf2\\x15\\x4b\\xb8\\x64\\xa5\\x01\\x77\\x78\\x12\\x25\\xa5\\x43\\x08\\xab\\x18\\x77\\xbc\\xac\\x0f\\xf7\\xc2\\x20\\x02\\x69\\x18\\x0b\\x63\\xf5\\x6c\\xc0\\xbe\\x52\\x3a\\xe7\\xf6\\x94\\xfd\\x31\\xfc\\xd4\\xc7\\xee\\x94\\x66\\xa2\\xf8\\xf3\\xe9\\x1f\\x0b\\xa5\\xed\\x9f\\xd9\\x1b\\x99\\xcd\\x5c\\xa7\\x29\\xbb\\x9b\\x80\\x64\\xd7\\xd5\\xda\\xd8\\x9f\\x1a\\x7f\\x7c\\xad\\x8b\\x64\\xc0\\x2e\\xc7\\x52\\xe9\\xf0\\xa6\\xc3\\xaa\\xcb\\x9c\\x8f\\x81\\x8d\\x04\\x64\\x88\\xd7\\x06\\xec\\x60\\x7e\\x07\\xd7\\xee\\x22\\x23\\x71\\x69\\x24\\xc6\\xaf\\x78\\xf1\\x20\\x68\\xce\\xc3\\x9b\\x6e\\x2c\\x37\\x7c\\x93\\x79\\xd7\\x0f\\xad\\x42\\x54\\x76\\x4b\\x72\\xff\\xe4\\xc9\\x2d\\xe3\\x7e\\x94\\x9c\\x17\\x7d\\x83\\xc7\\xa6\\x01\\xa6\\xcd\\x20\\x70\\x1e\\x3a\\x70\\xf0\\xab\\x7f\\xbe\\xf4\\x94\\x6b\\xb0\\xed\\xb2\\x9b\\x2b\\xdb\\xfa\\xdb\\x5a\\x0c\\x79\\x10\\x68\\xaf\\x96\\x71\\x91\\x0d\\xc6\\x18\\xeb\\x22\\xb9\\x52\\x29\\x2d\\xfb\\xc1\\x51\\xbe\\x6e\\xbe\\xcd\\xe0\\xbe\\x50\\x06\\x0c\\x4b\\xc5\\x68\\x04\\xda\\xd1\\x1d\\x35\\x05\\xad\\x45\\x0a\\x86\\x8d\\x94\\xc6\\xfd\\x2a\\x54\\x8a\\x67\\xb2\\xda\\xbf\\x16\\xab\\xbd\\x52\\xe9\\xa6\\x1b\\xe3\\x86\\x46\\x86\\x41\\xc8\\xe8\\xd1\\x70\\xe5\\x72\\x97\\x9e\\x76\\xf6\\xc0\\xe1\\x75\\x8d\\x8f\\x50\\xfc\\x9f\\x2d\\x7f\\x3a\\x07\\x8f\\x33\\xff\\x72\\xc0\\x54\\x2f\\x51\\x79\\xd2\\x71\\x68\\xdc\\xf2\\x0f\\x4d\\xd5\\xe7\\xb2\\xe9\\x6e\\x30\\xe5\\x4d\\xa6\\xed\\x9a\\x54\\x29\\x9c\\x3d\\x30\\xfd\\x85\\x25\\x5c\\xe0\\x1f\\x43\\x30\\xf8\\x79\\x35\\x55\\xe4\\xe0\\x69\\x99\\x21\\xa9\\x29\\xb3\\xf6\\x8e\\xae\\x5a\\xc7\\x86\\x6b\\xd9\\x74\\x3d\\xf4\\x1e\\x8c\\x40\\x6b\\x48\\x2f\\x4a\\x87\\xbf\\xd7\\xd5\\xac\\x3c\\x91\\xa2\\x9f\\x5f\\xdc\\x43\\x52\\xae\\x3a\\x63\\x2b\\x97\\xee\\x84\\x62\\xbf\\x4c\\xd0\\xec\\x4e\\x64\\x99\\x1f\\xce\\x11\\x94\\xf0\\xc0\\xad\\x17\\xe5\\x18\\x07\\x1e\\x43\\x44\\xda\\x70\\x2b\\xcc\\x68\\x86\\xe0\\xa8\\x00\\x06\\xf7\\x8e\\x67\\xa3\\xc6\\x82\\x18\\x2f\\x46\\x02\\x52\\x36\\x9c\\x79\\x76\\xed\\x88\\x67\\x8f\\x0d\\x4b\\xcb\\x84\\x45\\x5e\\x9e\\x4c\\x94\\x32\\xc0\\x38\\xc1\\x1d\\xfb\\x9d\\x0a\\x85\\x92\\x12\\x53\\x12\\x1c\\xfd\\xc9\\x1d\\x43\\xf6\\x07\\xa7\\xd1\\xfd\\x00\\x67\\x5e\\x7f\\x26\\x0c\\xcb\\x1d\\xc5\\xaf\\x60\\x15\\xd0\\xd1\\x75\\x73\\x27\\xec\\x04\\xff\\x18\\x3b\\x91\\xdb\\x49\\x61\\xa6\\xcc\\x5d\\xa7\\x77\\x20\\xc6\\x13\\x6b\\x7a\\x4c\\x0c\\x60\\x80\\xbb\\x0b\\x3c\\x99\\x34\\xba\\xcd\\x01\\xac\\x61\\x3c\\xcb\\xc2\\x14\\x9a\\x28\\x41\\x7c\\x33\\x77\\x22\\x0a\\x3b\\xaa\\x64\\x18\\x2f\\x6f\\xf4\\x2a\\xbe\\x3a\\xbf\\x6b\\x4b\\xc1\\xd5\\x63\\x60\\x93\\xc1\\x71\\x8f\\x25\\x2a\\x2f\\x4a\\xeb\\x60\\xe2\\xe6\\x38\\x9c\\x31\\x61\\x9d\\x9c\\x4d\\xf2\\x92\\x56\\xe5\\x98\\x56\\x02\\x99\\x1f\\x38\\x08\\xab\\xc4\\x99\\x1c\\x71\\x70\\x3a\\xa2\\x1c\\xb3\\x03\\x5a\\xdc\\x41\\x90\\x3f\\x5d\\x77\\x82\\x16\\x81\\xeb\\xcb\\xb9\\x4d\\x26\\x5e\\x04\\x4e\\x94\\xd6\\x60\\x0a\\x25\\xf1\\x4b\\x7c\\xf2\\xa2\\x9e\\xdb\\x7f\\x57\\x1f\\x1d\\x99\\xe3\\x1a\\x98\\x13\\x31\\x9e\\x04\\x58\\x72\\x0d\\xf8\\x5b\\x7b\\x0f\\xd6\\x9d\\x91\\xfa\\x9c\\x70\\xad\\x5b\\xba\\xe4\\xb2\\x26\\x2c\\xe4\\x0f\\x9c\\x92\\x05\\xd4\\x3e\\x93\\x0c\\xf2\\xc2\\xce\\x1a\\x38\\xd1\\xd8\\x3d\\x0b\\x3a\\xaf\\x60\\x80\\x1b\\x8c\\xc7\\xd5\\xd0\\xfa\\x44\\x5e\\x64\\x22\\x11\\xd6\\x63\\x08\\x7b\\xc6\\x8e\\x10\\x45\\x84\\x75\\xa4\\x8c\\x49\\xd5\\x57\\xc5\\xf1\\x80\\x9d\\xa1\\xf9\\x62\\x83\\x01\\xa4\\xaa\\xfa\\xf7\\x1d\\xb9\\x41\\x8d\\xaa\\xfb\\x7a\\x70\\x6d\\x1b\\x12\\x15\\x6a\\xab\\x65\\xba\\xc5\\xd6\\xf7\\xf3\\x07\\x99\\xcc\\x4b\\x79\\xcb\\x5f\\x27\\x98\\x3c\\xf8\\xea\\xa6\\xe4\\x2d\\xbc\\x1d\\xe6\\xb0\\xc9\\xdb\\xf3\\x5b\\x4d\\x28\\x6d\\x20\\x83\\xc4\\xa9\\xa4\\x0e\\xf6\\x3d\\xc6\\x8d\\x51\\x89\\x70\\x52\\x7e\\x8d\\xb4\\x6d\\x4c\\xa7\\x95\\x3c\\x0c\\x7b\\xb6\\x2d\\xfc\\xd9\\xd6\\xeb\\x77\\x6d\\xfe\\xe0\\x6d\\xfa\\xdd\\x02\\x34\\x32\\xe1\\x84\\xdf\\xd1\\x1c\\x54\\x5a\\x04\\x6b\\x38\\xc3\\xa7\\x87\\x86\\x65\\x7c\\x08\\x99\\xd9\\x0c\\x08\\x6c\\xab\\x53\\x5b\\xb7\\x0d\\xcf\\xef\\xca\\x05\\xad\\x5c\\x88\\xd7\\x31\\xab\\x8d\\x77\\x44\\xdb\\xe9\\x66\\x5c\\x48\\xe3\\xf5\\xe7\\x1e\\xe3\\xec\\x16\\x66\\xa4\\x6a\\x3b\\x0d\\x3e\\x18\\x2e\\xf0\\x65\\x0d\\xc4\\x6e\\x1c\\x72\\xdc\\xc2\\x0c\\x5f\\xf2\\x7a\\xf7\\x16\\xd3\\xdd\\x1a\\x39\\xa8\\x6d\\x73\\x4c\\xeb\\xd6\\x77\\x13\\xdd\\xf2\\x8b\\xb0\\xe8\\x2d\\x3e\\xdb\\x1e\\x7f\\xa9\\xdd\\xc2\\x5a\\xc9\\x6b\\x59\\x5b\\x10\\x49\\x10\\x27\\x71\\x3f\\x70\\x93\\x90\\x7f\\x85\\x3d\\xe6\\x45\\x91\\x09\\x40\\x7d\\x7e\\xcb\\x61\\xd6\\x6a\\x01\\xeb\\x5a\\x80\\xde\\x5e\\xeb\\x7a\\x5b\\x19\\x34\\x08\\x21\\x0f\\x0d\\x21\\x9f\\x3b\\xe9\\x13\\x51\\x90\\x7e\\x6b\\x00\\x0f\\x6e\\xb0\\xfc\\x7c\\xc7\\x33\\x51\\x9b\\xda\\x0c\\xf2\\xd9\\x4b\\xd9\\x63\\xaf\\x95\\x75\\xff\\x79\\xe1\\x34\\x61\\xd3\\x63\\x17\\x0a\\xcc\\x6b\\x65\\xf1\\xcf\\x01\\xfb\\xda\\x12\\xae\\xbf\\xdc\\x90\\xb2\\x75\\x00\\x20\\x9a\\xef\\x5e\\xe0\\x39\\x93\\x44\\x53\\xdc\\xf2\\x9b\\x36\\x23\\x33\\x60\\x97\\x24\\xb6\\x54\\x07\\x57\\x18\\x76\\x29\\x9d\\x70\\xe8\\xc1\\x80\\x56\\x3c\\x7c\\xd7\\x77\\x91\\x97\\x06\\x8d\\x3c\\x52\\xc9\\x3e\\xca\\x00\\x4b\\xfb\\x20\\xe8\\xb9\\x7e\\x9a\\xf0\\x5b\\xd3\\xdd\\xea\\xae\\xbe\\x46\\x5b\\xc3\\xcb\\x95\\x1f\\x4f\\xf8\\x14\\x45\\x3a\\x21\\xc7\\x59\\x25\\xbc\\xf5\\xd8\\xdd\\x44\\x24\\x13\\x92\\xba\\x87\\x40\\xa6\\xc1\\x42\\x83\\x63\\x58\\xdc\\x38\\x52\\xe5\\x7e\\x19\\x83\\x76\\xc2\\xae\\x08\\xfd\\x91\\x61\\x32\\xe3\\x09\\xa4\\x2c\\x45\\xd1\\x92\\x8c\\x6c\\xdc\\xc2\\x58\\x24\\x2c\\x07\\x3d\\x06\\x56\\x38\\x4e\\xb2\\xdb\\xee\\x6f\\x47\\xd8\\xa9\\x6d\\x4d\\xde\\x9b\\x03\\x6e\\x85\\x6e\\xc8\\x22\\xbf\\x72\\xb2\\xee\\x07\\xe2\\x8e\\x28\\x57\\x47\\xee\\x18\\xb9\\xe3\\x5c\\x8b\\xdc\\xb1\\x6a\\x91\\x3b\\x3e\\xd0\\x22\\x77\\x8c\\xdc\\xf1\\xbd\\x73\\x47\\xd2\\x65\\x77\\x50\\x9e\\xff\\x4a\\x26\\x8e\\x79\\x6d\\x19\\x39\\x6d\\x70\\xd3\\xb5\\xd5\\x66\\xc7\\x6f\\xae\\x3d\\xc1\\xb9\\x41\\x55\\x5b\\x90\\x93\\x44\\x73\\x39\\x06\\xf6\\xbc\\xff\\xfc\\xd9\\xb3\\x6d\\x94\\x6a\\xbf\\x91\\x1b\\x7d\\x31\\xf2\\x9e\\x1e\\x21\\xed\\xaf\\x7f\\xb5\\xf6\\x8b\\x55\\xf6\\xb7\\x0e\\xac\\xa6\\x1e\\xc7\\x2b\\x43\\x5e\\x4b\\x76\\x58\\x61\\xf8\\x44\\xea\\x24\\x95\\x65\\x39\\x58\\xc6\\x6d\\xcb\\x54\\x24\\x72\\xe8\\x55\\xae\\x02\\x44\\x78\\xef\\xa5\\x0c\\x16\\xd8\\x94\\x29\\xe9\\xed\\x78\\x0e\\xf8\\x83\\xdd\\x66\\x90\\x00\\x27\\x97\\xda\\x10\\xaa\\x59\\xa8\\xdc\\x8d\\x2a\\xa4\\x0d\\xc7\\xc5\\x4d\\x01\\x02\\x54\\xd8\\x11\\x0c\\xc6\\x03\\x96\\x96\\xf8\\x19\\x97\\xde\\x6d\\x7a\\x4c\\xb3\\x35\\x33\\x63\\x21\\x47\\x4b\\xae\\xd2\\xf8\\x1f\\x37\\x6d\\xab\\x67\\xee\\x65\\x98\\x82\\xb4\\x25\\xcf\\xb2\\x19\\x83\\xa9\\x48\\x6c\\xb5\\x3e\\xf4\\xda\\x0a\\x4b\\xc6\\xf6\\xcd\\x4c\\x84\\x1b\\x89\\x0e\\x9b\\x8b\\x0b\\xfd\\x05\\x0c\\x36\\x0f\\x7c\\xb3\\x0d\\xb7\\x5f\\xe8\\x7b\\x93\\x33\\x39\\xc7\\x0b\\x69\\x25\\x83\\x95\\xc2\\xaa\\x75\\xfd\\x92\\x0d\\x1c\\xff\\x89\\xc8\\xf5\\xe6\\xed\\xc3\\x26\\x57\\xb6\\x35\\x25\\xdb\\x82\\x7a\\xcd\\x8b\\xa5\\x65\\x96\\x39\\xc4\\x20\\x2b\\xec\\xe2\\x02\\x96\\x58\\x47\\x69\\x49\\x2d\\x64\\x26\\xc3\\x3b\\x99\\x98\\xcf\\x5e\\x5f\\x38\\xa8\\xb8\\x77\\x6e\\x54\\xa1\\x32\\x35\\x9e\\x35\\x21\\x4d\\xe1\\x45\\x22\\x2f\\x82\\x71\\x9c\\x33\\x53\\x0e\\xbd\\xd0\\xe0\\xd0\\xef\\xf5\\xdc\\xd6\\x44\\xcb\\x5f\\xb4\\xfc\\x45\\xdd\\x66\\xa1\\x45\\xdd\\xa6\\x6a\\x51\\xb7\\x79\\xa0\\x45\\xdd\\x26\\xea\\x36\\xd1\\xf2\\xc7\\x22\\x77\\x5c\\x03\\x93\\xc8\\x1d\\x59\\xe4\\x8e\\x2b\\xd7\\x15\\xb9\\xe3\\x5a\\xf0\\x44\\xee\\x18\\xb9\\xe3\\xb2\\x56\\xa8\\x74\\x8f\\x40\\xc7\\x42\\xa5\\x6b\\xe2\\x1c\\xc9\\xea\\x93\\xa8\\x7e\\xa6\\x12\\x6e\\x7d\\x5c\\xbe\\xfb\\xc4\\xdb\\xf9\\x0c\\xcf\\xc9\\x10\\xd5\\x63\\xff\\x52\\x12\\x28\\x78\\xcd\\xed\\x0d\\x9a\\x93\\x94\\x9d\\x80\\x76\\xaf\\x1f\\x99\\xe3\\xb5\\x81\\x4d\\x31\\x4e\\x32\\xc6\\x49\\x3e\\xfa\\x38\\xc9\\x09\\x37\\xb4\\xaf\\x44\\x94\\x56\\x87\\x4d\\x36\\x0e\\xe4\\x0d\\xe8\\xfc\\x89\\x46\\x4d\\x3a\\x74\\xf1\\xdb\\x8d\\x19\\x4f\\xf5\\x96\\xd2\\xca\\x53\\xef\\x2f\\x80\\xf4\\xaa\\xbd\\x5e\\x2f\\x2f\\xe3\\xa2\\x78\\x9a\\x42\\xca\\x0a\\xd0\\x7d\\x42\\x11\\xc5\\x46\\x42\\xa6\\x4b\\xd6\\x1a\\xe0\\xf3\\x51\\xa3\\x1f\\xdb\\xeb\\xf8\\x88\\x21\\x90\\xed\\x89\\xec\\x60\\x73\\x6d\\x1a\\x8e\\x5b\\x14\\xfe\\x51\\x04\\x44\\x6e\\x2b\\xd5\\xf7\\x99\\xf5\\x46\\xde\\x6f\\x36\\x94\\xeb\\xb7\\x17\\xcd\\x51\\xa0\\x0e\\x26\\xe1\\xdd\\xf5\\x4a\\x14\\xcb\\xff\\x59\\x82\\x9e\\x61\\xfe\\x47\\x2d\\xb0\\x56\\xb9\\x75\\xde\\x47\\x26\\x0c\\x4b\\xb8\\x21\\x4e\\xb1\\xad\\x6a\\xb9\\xa5\\x1a\\xb5\\x9b\\x9e\\xb2\\xbb\\x25\\x9a\\xcd\\xc3\\x65\\xbe\\x2b\\xd2\\x49\\x83\\x0e\\x4e\\x30\\x5b\\xaa\\x84\\x2f\\xf1\\x02\\xd4\\xd6\\xff\\xad\\xe6\\xb3\\xab\\xe8\\xb6\\x93\\xe0\\xb6\\x14\\x29\\x1e\\xb1\\x72\\xce\\x76\\x57\\xd0\\xd9\\xce\\x4a\\x3a\\xdb\\x49\\x51\\x67\\xbb\\x2a\\xeb\\x6c\\x0f\\x85\\x9d\\xed\\xa6\\xb4\\xb3\\x79\\x54\\x70\\x3b\\xe4\\xa5\\xac\\xf7\\xa3\\xbf\\xb3\\x7d\\x54\\x54\\xb6\\x87\\x1e\\xcf\\xe6\\x97\\x5a\\xa1\\xa9\\x7e\\x5f\\x4a\\x3d\\xe2\\x7a\\x4b\\xaf\\xff\\xd0\\xc0\\xda\\x4d\\xa7\\x67\\xf3\\xa0\\xf2\\xca\\xb0\\x40\\x85\\xf6\\x89\\x68\\xf8\\x1f\\x44\\xdd\\x66\\x7b\\xa9\\xdc\\x6c\\x77\\xb5\\x9b\\xed\\x8e\\x19\\xc8\\xea\\x5e\\xa2\\x3b\\x75\\x5f\\x86\\x49\\xbd\\x10\\x8b\\xc0\\x1c\\xdc\\x11\\xfb\\xb7\\xe3\\x04\\xb8\\x2f\\xff\\x61\\x05\\x17\\xda\\x38\\xf9\\xce\\xdb\\x4c\\x9a\\xcf\\xbc\\x76\\xde\\xec\\x26\\xa7\\x14\\x62\\x47\\xaa\\xa7\\x3c\\x73\\xbc\\x87\\xe2\\x38\\xbc\\x5e\\xe4\\x7a\\x9f\\x67\\xd3\\x3d\\x76\\x37\\x71\\xda\\xa6\\xa3\\x52\\x55\\xbe\\xf3\\xc1\\x2d\\xcc\\x0e\\x7a\\x0b\\x88\\x74\\x70\\x29\\x0f\\x88\\x47\\x2d\\xa0\\x4e\\xc5\\xd0\\x94\\xcc\\x66\\xec\\x00\\x9f\\x1d\\x74\\xcd\\xd9\\x77\\x60\\x5c\\xcd\\x12\\x2a\\xbb\\xf2\\x85\\x1d\\xb0\\x44\\x86\\xb2\\x2e\\xdd\\x0b\\x9b\\xc4\\x45\\xc8\\xb1\\x11\\x46\\x31\\x35\\x83\\xc1\\x50\\x8b\\x06\\x73\\xa9\\xa2\\x46\\x10\\xc7\\xf0\\xf7\\x34\\x28\\xbf\\xa5\\xf4\\x95\\x2e\\x42\\xce\\xb9\\xef\\x8c\\x98\\xd4\\x62\\x48\\x93\\xdf\\x78\\x25\\xc1\\xa0\\x60\\x07\\x95\\x89\\xa8\\xf1\\x31\\xbe\\x3b\\xa0\\x70\\x90\\x9a\\xdb\\xc9\\x74\\x3e\\x40\\xa4\\xfe\\x02\\x65\\xc4\\x1c\\xb8\\x34\\xec\\x20\\xd8\\x9e\\x0e\\x4d\\xfd\\xc6\\xc1\\xa0\\xce\\xee\\xab\\x7a\\x3c\\xfa\\xf7\\x7f\\x8e\\x5b\\x19\\x7d\\x75\\x87\\x51\\xd2\\x8e\\x92\\x76\\x94\\xb4\\xb7\\xf8\\x2a\\x4a\\xda\\xab\\x5b\\x94\\xb4\\xb7\\x68\\x51\\xd2\\x8e\\x92\\xf6\\xba\\x81\\xa3\\xa4\\x1d\\x25\\xed\\x87\\x07\\xdf\\x4d\\xd2\\xde\\x35\\x4e\\xa8\\x29\\xf7\\x7a\\xe7\\x1c\\x15\\x32\\xe3\\x56\\x24\\x75\\x0c\\x51\\x78\\x8b\\xfe\\xd5\\xad\\xbc\\xdd\\x94\\xa5\\x97\\x4b\\xdb\\x4d\\x89\\x7c\\x41\\xb7\\x18\\x3c\\x20\\x5a\\x57\\xc2\\xf7\\xc2\\x97\\xeb\\xa5\\xee\\xc7\\x15\\x0b\\xb5\\x03\\x6e\\x34\\x1c\\x0a\\x3b\\x22\\xc7\\x4d\\x70\\x85\\xfb\\xc2\\x7f\\x43\\xa8\\xfd\\xe4\\x29\\x3b\\x0a\\x1e\\x97\\x63\\x07\\x7c\\xa9\\x6c\\xfb\\xa1\\xb4\\xa2\\x5f\\xbf\\x51\\xf9\\x60\\xd0\\xbd\\xd8\\xca\\xb7\\x69\\xb9\\x25\\x2a\\xaf\\x7b\\xe5\\x29\\xae\\xf7\\xd3\\x91\\x10\\xd0\\xad\\x39\\x08\\xe3\\xcb\\x1b\\x62\\xb4\\x84\\x2e\\xa5\\x74\\xbd\\x2a\\x19\\xdc\\xc7\\x44\\x73\\xa8\\x1e\\x9f\\xc7\\x3c\\x12\\x96\\x70\\x3e\\x28\\x31\\xd5\\x50\\x6a\\xf8\\x3b\\xb9\\xa5\\x12\\x88\\x3e\\x94\\x5f\\x49\\xef\\x11\\x75\\xbf\\x04\\xaf\\x6f\\x40\\x4a\\x5c\\x91\\xa8\\x46\\x1f\\xb0\\x17\\x88\\x87\\xcd\\x8e\\x85\\x41\\xf8\\xf0\\x2c\\x53\\x77\\xdb\\x90\\xa4\\x0f\\x95\\x16\\x75\\xb7\\x75\\x5a\\xd4\\x9c\\xff\\x2e\\x66\\x45\\xfd\\x4c\\xb2\\xa2\\xf0\\x21\\x1d\\xa1\\xce\\xd3\\xa3\\xd8\\x5f\\x7d\\x01\\x42\\x0d\\x08\\xaa\\xbc\\xcc\\xac\\x28\\xea\\x58\\x29\\x43\\x43\\x65\\x24\\x65\\x8e\\x7c\\xe4\\x49\\x1b\\x2f\\xdd\\x68\\x3c\\x99\\xcc\\xe3\\x27\\xf6\\x87\\xb1\\x55\\x06\\x0f\\xad\\x8f\\xee\\xe0\\x59\\xe6\\x73\\x8a\\x82\\x48\\x4a\\x21\\x2c\\xe2\\x63\\x47\\x26\\x5c\\xf8\\x9a\\xad\\x95\\x36\\x83\\x44\\xe6\\xc8\\xd1\\xc2\\xcc\\x6d\\xa8\\xa3\\x6a\\x6b\\x88\\x28\\x29\\x45\\x53\\x08\\xac\\x77\\x2c\\xa6\\x20\\x6b\\x4a\\x7a\\x64\\x8e\\x8f\\x03\\x0f\\xef\\x94\\xc2\\xbf\\x17\\x0a\\xfd\\xc7\\x06\\x25\\xfd\\xf3\\x26\\x34\\x1a\\x17\\x54\\x51\\xe9\\x1a\\x7c\\x35\\x8d\\xfe\\x98\\x21\\x18\\xdb\\xf8\\xf9\\xb7\\xb3\\x31\\xec\\xe0\\xdf\\xff\\x80\\xbe\\xfd\\xa7\\x93\\x59\\xf6\\x91\\x2d\\x8c\\x1f\\x23\\xb6\\xfe\\xd1\\x5b\\x15\\x63\\x70\\x7d\\xdd\\xf6\\x0d\\xae\\x7f\\xef\\x96\\xc3\\x8f\\x1b\\x63\\xff\\x04\\xac\\x85\\x1f\\x33\\xc6\\x3e\\x5a\\x08\\xd7\\x6e\\xca\\x63\\x0b\\x7d\\x6f\\xb7\\x9d\\x2c\\x82\\xd1\\x1a\\xb8\\x33\\x17\\xde\\x92\\xe1\\xec\\x6b\\x05\\xdc\\x12\\x23\\x76\\xf4\\xb3\\x47\\x1f\\xfb\\x87\\xf1\\xb1\\x47\\x89\\x77\\xc3\\x16\\x25\\xde\\x95\\x40\\x89\\x12\\x2f\\x8b\\x12\\xef\\x43\\xcb\\x8b\\x12\\xef\\x5a\\xf0\\x44\\x89\\x77\\xed\\xa6\\x44\\x89\\x37\\x4a\\xbc\\xec\\xa9\\x49\\xbc\\xbb\\x54\\xe9\\x8a\\xbe\\xee\\xbd\\x7c\\xdd\\xdb\\x52\\x8b\\xad\\x68\\xc4\\x96\\x78\\xb0\\xb5\\x6f\\x3b\\xfa\\xb5\\x1f\\x8b\\x5f\\x7b\\xe3\\x84\\x7f\\x69\\xc5\\xbe\\x49\\xff\\xcd\\xbd\\x5a\\x95\\xf9\\xcf\\xa7\\x4a\\xa4\\xac\\x28\\xad\\xcf\\xa7\\x8e\\xd9\\xff\\x5d\\x64\\xff\\xb7\\x20\\x1f\\x4b\\x00\\x6c\\x54\\x02\\x60\\x15\\xcc\\x62\\x1d\\x80\\x58\\x07\\xa0\\x63\\x27\\x74\\xac\\x03\\x10\\xeb\\x00\\xc4\\x3a\\x00\\xa1\\xc5\\xec\\x24\\x16\\xb3\\x93\\x36\\x6a\\x31\\x3b\\x69\\x75\\x8b\\xd9\\x49\\x8f\\xd6\\xfa\\xca\\x62\\x76\\xd2\\xe3\\xb6\\xc4\\xb2\\x98\\x9d\\x14\\xad\\xb3\\x1b\\x6e\\xd4\\x13\\xcc\\x4e\\x8a\\x75\\x00\\x1e\\x6b\\x8c\\x02\\x8b\\x92\\x76\\x94\\xb4\\xa3\\xa4\\x1d\\x25\\xed\\xf5\\x2d\\x4a\\xda\\x5b\\xb4\\x28\\x69\\x47\\x49\\x7b\\xdd\\xc0\\x51\\xd2\\x8e\\x92\\xf6\\xc3\\x83\\xc7\\x3a\\x00\\x4f\\x28\\x36\\x82\\xc5\\x3a\\x00\\x31\\x5e\\x22\\xd6\\x01\\xf8\\xf9\\xd6\\x01\\x68\\xf9\\xee\\x3f\\x5e\\x31\\x80\\xed\\xa7\\x11\\x2b\\x02\\xc4\\x8a\\x00\\xb1\\x22\\x40\\xac\\x08\\x10\\x5a\\xac\\x08\\x40\\xed\\x31\\xd9\\x1a\\x63\\x7e\\xd4\\x4a\\xa0\\xc4\\xfc\\x28\\x16\\xf3\\xa3\\x1e\\x5a\\xde\\x13\\xb0\\x1b\\xc6\\xfc\\xa8\\x47\\x68\\x2b\\x8c\\xf9\\x51\\xd1\\x2e\\x38\\xbf\\x39\\x4f\\x24\\x3f\\x2a\\x56\\x04\\x78\\x8c\\xde\\xf6\\x28\\xf1\\x6e\\xd8\\xa2\\xc4\\xbb\\x12\\x28\\x51\\xe2\\x65\\x51\\xe2\\x7d\\x68\\x79\\x51\\xe2\\x5d\\x0b\\x9e\\x28\\xf1\\xae\\xdd\\x94\\x28\\xf1\\x46\\x89\\x97\\x3d\\x35\\x89\\x37\\x56\\x04\\x88\\x15\\x01\\x62\\x45\\x80\\xa7\\xe8\\xe1\\x7e\\x70\\xa7\\xe1\\xde\\x6a\\x9e\\xd8\\x73\\x25\\x2d\\xc8\\x95\\x7e\\xed\\xd6\\x86\\xbe\\x68\\x7d\\xe2\\x88\\xe4\\x48\\x8c\\x4b\\xed\\x65\\xf0\\xf1\\xdb\\xab\\x73\\x96\\x70\\xcb\\x33\\x35\\x66\\x57\\x0a\\x0f\\xa9\\x1f\\xa4\\xfa\\x39\\x07\\xcb\\x53\\x6e\\x39\\xb9\\x24\\x71\\x43\\xb5\\x9a\\x8a\\x14\\x0f\\x6b\\x0a\\xf7\\x4c\\xe4\\x7c\\x0c\\x78\\xc0\\x4a\\x4c\\x56\\xbf\\x83\\x2c\\xeb\\xdf\\x4a\\x75\\x27\\xd9\\x14\\xb4\\x69\\x1c\\xf7\\x1f\\x55\\x91\\xff\\xc8\\x0c\\xe8\\x29\\x65\\xd1\\xc3\\x7d\\xe1\\x36\\x4b\\x58\\xa2\\x18\\x61\\xc4\\x66\\xb7\\xb5\\x2f\\xee\\x9c\\x9e\\x5e\\x53\\x1a\\xb9\\x30\\xf5\\x5a\\x70\\xda\\x6e\\xec\\x2f\\x9c\\xa8\\xf0\\x85\\x43\\xda\\xd2\\x04\\x5c\\x1b\\x89\\x0c\\xfa\\x43\\x6e\\x20\\x0d\\xfd\\x1b\\x87\\x71\\x4a\\xa7\\x34\\x87\\xd2\\x8a\\x4c\\xfc\\x0b\\x3c\\xd5\\x01\\x6e\\x4b\\x0d\\xab\\xb6\\x6b\\x03\\x3e\\xf0\\xb0\\x92\\xd1\\x67\\x09\\x4f\\x26\\x70\\x21\\x56\\xab\\x07\\xfd\\x30\\xd5\\xd5\\x2f\\x6d\\xa2\\x2f\\x84\\x71\\x36\\xae\\x1a\\x71\\xee\\x3f\\x08\\x1a\\x41\\x2a\\x34\\x1e\\xd1\\x19\\x33\\x56\\xe9\\x00\\xd1\\x42\\x43\\x3f\\xe1\\x59\\x52\\x66\\x78\\x20\\xcf\\xae\\x2e\\x69\\xa4\\x87\\xeb\\x3e\\x3c\\x40\\xc4\\xea\\x45\\x6f\\x31\\xe3\\xf0\\xc9\\xfa\\x39\\x2f\\x62\\x01\\xca\\x0b\\xa8\\xa8\\xef\\x33\\xed\\x1c\\x72\\xa5\\x67\\x37\\x5c\\x8f\\x61\\xb3\\xf3\\x78\\xf0\\xaa\\xf1\\xc5\\xfc\\x71\\xfc\\xfc\\xeb\\x37\\xaf\\x5e\\xbc\\x7a\\x79\\xf9\\xea\\xf2\\xc6\\x53\\xb0\\x91\\xd2\\x4b\\x0f\\xaa\\x17\\x83\\x49\\x1f\\x57\\x23\\xeb\\x27\\xc2\\x32\\x91\\x0b\\x5b\\x7d\\x45\\x27\\xad\\xe7\\x29\\x19\\x86\\xa3\\x94\\xd2\\x8a\\x1c\\x28\\x98\\x82\\x5b\\xeb\\x98\\xa5\\x3b\\x05\\x39\\x80\\xc5\\xca\\x13\\x39\\xbf\\x05\\x47\\xba\\xd8\\xb8\\xe4\\x9a\\x4b\\x0b\\x81\\x38\\x0a\\x4b\\x1f\\xa5\\x8a\\x19\\xe5\\x05\\x7a\\xe1\\xb5\\x7e\\x37\\x0f\\x03\\x5e\\x76\\xbf\\x0a\\xb1\\x1a\\x13\\x3e\\xa5\\x12\\x07\\x23\\xe5\\xa8\\xa0\\xdb\\x8a\\x5c\\xa5\\x62\\x24\\x12\\x52\\xbb\\x58\\xce\\xd3\\xca\\x0f\\xef\\xa5\\x37\\xd0\\x15\\x49\\xaf\\x17\\x70\\xca\\xfa\\x0b\\xe0\\x01\\x39\\x15\\x5a\\x49\\x94\\x29\\xa7\\x5c\\x0b\\x3e\\xcc\\xfc\\xaa\\x86\\x64\\xa2\\xc3\\x7e\\xeb\\x09\\x4a\\x36\\x9c\\x59\\x30\\xbe\\x27\\x0f\\x2d\\x5f\\x8b\\x62\\xcd\\x77\\xef\\x24\\x01\\x9a\\xc4\\x91\\x9a\\x29\\xba\\x37\\xc5\\x88\\x09\\x7b\\xe8\\xd8\\x91\\x11\\x9e\\x08\\x69\\x48\\xcb\\x24\\x2c\\x5a\\xd9\\x42\\x0b\\x12\\x79\\x79\\xb5\\x77\\x9e\\xf8\\x71\\xc3\\xf2\\xd2\\x71\\x17\\xc7\\x6d\\x8d\\x11\\xc3\\x0c\\x7a\\x8e\\xa7\\x8a\\xe6\\xbb\\x43\\x70\\x70\\xc0\\x2f\\x90\\xef\\x4d\\xc1\\xed\\xb0\\xc3\\x1c\\x12\\x67\\x00\\x1c\\x63\\x55\\x58\\x48\\x82\\x13\\x13\\x4d\\x61\\xc4\\xcb\\x8c\\xf8\\x0e\\x81\\x19\\xb7\\x6a\\xa6\\x4a\\xdd\\x22\\xab\\x13\\xee\\x30\\x07\\x4f\\x45\\x08\\x50\\xc1\\x33\\xdc\\x63\\x29\\x38\\xc1\\x4d\\x48\\x47\\xc9\\xc7\\x4a\\xa5\\x4e\\x7e\\xd3\\xea\\x5e\\xe4\\xd8\\x9b\\x47\\xad\\x0a\\x3e\\xc3\\x19\\x4b\\x55\\x39\\xcc\\xaa\\x0d\\x73\\xa4\\xd4\\x53\\xfb\\x82\\x27\\xb7\\x6e\\x2c\\xec\\x98\\x71\\xcb\\x4e\\x6c\\x5e\\x9c\\xe0\\x5f\\xfe\\xff\\xfd\\x1b\\x66\\xf0\\x0f\\xa3\\x64\\x90\\x03\\x1a\\xd3\\x1c\\xcc\\xc1\\x5f\\x18\\x36\\x04\\x63\\xfb\\x30\\x1a\\x29\\x6d\\xff\\xdb\\x41\\xab\\x94\\x88\\x78\\x52\\x55\\x4b\\x0f\\x9b\\x59\\xba\\xc3\\x8e\\x70\\x52\\x88\\x93\\xad\\x13\\xa2\\xf4\\x92\\xc3\\xd6\\x40\\x83\\xc1\\xc1\\x2a\\xba\\xeb\\x0e\\x8d\\x96\\xa7\\xec\\x7f\\x8f\\xde\\xfd\\xf2\\xa7\\xfe\\xf1\\x97\\x47\\x47\\xdf\\x3f\\xeb\\xff\\xe1\\x87\\x5f\\x1e\\xbd\\x1b\\xe0\\x3f\\xbe\\x38\\xfe\\xf2\\xf8\\xa7\\xf0\\xc7\\x2f\\x8f\\x8f\\x8f\\x8e\\xbe\\xff\\xe6\\xd5\\xd7\\x37\\x57\\x2f\\x7e\\x10\\xc7\\x3f\\x7d\\x2f\\xcb\\xfc\\x96\\xfe\\xfa\\xe9\\xe8\\x7b\\x78\\xf1\\xc3\\x86\\x9d\\x1c\\x1f\\x7f\\xf9\\xf9\\x8a\\x09\\x71\\x39\\x7b\\x33\\x5a\\xc7\\x6d\\x36\\x0b\\x28\\xeb\\x6f\\x42\\xa2\\xef\\xfb\\xb7\\xe5\\x10\\xb4\\x04\\x0b\\xa6\\x2f\\xa4\\xed\\x2b\\xdd\\xa7\\x0f\\x4e\\x99\\xd5\\x25\\x2c\\xfd\\xcc\\x89\\x53\\x0f\\x59\\xe1\\x5b\\x24\\xf2\\x75\\xe3\\x83\\x39\\x8b\\xa3\\x2f\\xc3\\xe2\\x0d\\x02\\x6e\\xc8\\x8a\\xd6\\x15\\x24\\xbd\\x8c\\xdc\\xe6\\x06\\x61\\x70\\xc0\\xae\\x97\\x7c\\x89\\x32\\x9f\\x7f\\xe3\\xd0\\x90\\x74\\x68\\xe6\\xfb\\x99\\x0b\\x32\\x23\\x1a\\x88\\x7d\\xee\\x2e\\x1b\\x6c\\xa7\\x11\\x3e\\xb8\\x1f\\x85\\x16\\x4a\\x0b\\x3b\\x3b\\xcf\\xb8\\x31\\xaf\\x79\\x0e\\x1b\\x41\\xf7\\x72\\x54\\x4b\\xda\\x3d\\x77\\xd8\\x1c\\x39\\xf6\\xfc\\x87\\xb4\\x9f\\xd0\\x2f\\x52\\x0e\\x27\\xc4\\x36\\xde\\x0f\\x10\\x0a\\xef\\x54\\x67\\x26\\x9c\\x3e\\xa5\\xd9\\xbf\\x40\\x2b\\x5f\\x45\\x47\\x03\\x09\\xc2\\xe1\\xf1\\x7a\\xe0\\xad\\x59\\xab\\x81\\xa4\\xc4\\xb5\\x3a\\xa6\\x7d\\xef\\xc4\\xd9\\x91\\x18\\x6f\\xc6\\x70\\xaf\\x97\\x7d\\xca\\x12\\x2e\\xdd\\xb4\\xb1\\x8a\\xd2\\x88\\xfd\\x98\\xc1\\x98\\x27\\xb3\\x1f\\xdd\\xf4\\x7f\\xd4\\xe0\\x26\\xe2\\x04\\xfd\\x1f\\x49\\x2e\\x6d\\x49\\x9e\\x87\\xbe\\x2c\\x96\\x61\\x20\\xb0\\xea\\x95\\x90\\xff\\x20\\xad\\xa0\\x52\\x78\\x34\\x06\\x8f\\x16\\x2a\\x1d\\x38\\xc8\\x0d\\xe6\\xe6\\x8e\\x34\\xa9\\x7a\\x58\\xf1\\xbd\\xef\\xbf\\xf8\\x61\\xe1\\x4d\\x6f\\xdf\\xb0\\x8a\\xf4\\x88\\x26\\x7e\\xea\\x12\\x09\\xa6\\x23\\x6c\\x61\\x81\\xec\\x2c\\xcd\\x05\\x9a\\x54\\xd8\\xd1\\xd5\\xf5\\xd9\\x71\\x6b\\x25\\x8e\\xf5\\x12\\x8b\\x49\\x15\\x18\\x79\\x68\\x89\\xd9\\x4d\\xc0\\xd4\\x66\\x14\\x64\\x1b\\x18\\xc5\\x44\\xa7\\x05\\xc3\\x98\\xc2\\x98\\x0e\\x60\\x68\\x59\\x19\\x42\\x35\\xf8\\xf5\\x19\\xfb\\xd1\\x09\\x55\\x99\\x90\\x40\\xb0\\x2b\\xb4\\x98\\x8a\\x0c\\xc6\\x6e\\xc4\\x86\\x53\\x88\\x9d\\x97\\x5a\\x83\\xb4\\xd9\\x2c\\x94\\x57\\x5a\\xbe\\x2b\\xc2\\x38\\x82\\xde\\x46\\xb7\\x80\\x59\\x95\\x4a\\x57\\x6d\\x96\\x7b\\xdb\\x40\\x3a\\x60\\xd7\\xf8\\xc5\\x8c\\xec\\x7f\\xfe\\x3d\\xdc\\x1b\\xe4\\x8b\\xab\\x36\\x97\\x69\\x30\\xae\\x63\\x21\\xe9\\x2b\\x91\\x12\\x8b\\x03\\xad\\x95\\xf6\\x21\\x97\\xa4\\x47\\xa8\\xcc\\x29\\x0b\\x95\\x7a\\xe2\\x58\\x93\\x09\\x52\\x55\\x82\\x22\\x81\\x8f\\x4b\\xf5\\x80\\x59\\x02\\xf8\\xd5\\x6b\\x6e\\x0b\\x15\\x56\\x55\\xf3\\x45\\xee\\x77\\xe9\\x26\\x37\\x2a\\x9d\\x56\\x52\\x69\\x53\\x78\\xe6\\x9a\\xa0\\x99\\x93\\x5f\\x9a\\xc3\\xf7\\x6a\\x3d\\x8e\\x0b\\x8f\\x6a\\x26\\x8c\\xa9\\x61\\x58\\x8a\\x0c\\x4d\\x2c\\x42\\xd7\\xea\\x11\\x22\\x32\\x6f\\x2a\\x6f\\xaa\\xc8\\x7d\\x6d\\xb3\\xb2\\x28\\x94\\xb6\\xb5\\xe2\\x9d\\xb4\\xb4\\x32\\x52\\x8c\\x97\\x00\\xc0\\x4d\\xab\\xd0\\x50\\x70\\x5d\\x51\\x6c\\x03\\x2c\\x99\\x70\\xe9\\xd8\\xbf\\x5b\\xe8\\x2b\\x85\\x71\\xa8\\x14\\xcc\\xec\\x86\\xe5\\x43\\x55\\x5a\\xc4\\x31\\x7f\\x56\\x47\\xaa\\x94\\x29\\x73\\x44\\xe5\\x94\\x4d\\xac\\x2d\\xcc\\xe9\\xc9\\x49\\xcd\\x8f\\x06\\x42\\x9d\\xa4\\x2a\\x31\\x27\\x89\\x92\\x09\\x14\\xd6\\x9c\\x84\\xd3\\x74\\x52\\xa8\\xb4\\x1f\\xfe\\xe8\\xf3\\x70\\x48\\x4e\\x0e\\x57\\xf1\\xf8\\x0d\\x38\\xa1\\x87\\xfc\\x29\\xa3\\xbd\\x5a\\xf1\\x16\\xc8\\x72\\x4d\\x25\\xa7\\xfe\\xfa\\x8f\\xdd\\x0b\\x35\\x18\\x97\\xbe\\x64\\x55\\x86\\x75\\xcf\\xd6\\xb8\\x37\\xdb\\xd6\\x9d\\xfa\\xfd\\xaa\\xfe\\x58\\x25\\x98\\x36\\xa8\\xdb\\xa1\\x69\\x76\\xbd\\x9e\\x68\\xaf\\xb3\\x7a\\x3d\\x60\\xe7\\x5a\\xa8\\x3d\\x86\\xb4\\xcd\\x89\\x7b\\xf5\\x44\\x51\\x00\\xb0\\x96\\x63\\xf5\\x31\\x27\\x9b\\xd3\\x13\\x47\\xae\\xe4\\x8c\\x39\\x7c\\xb6\\xbe\\x14\\x5d\\xa3\\x36\\x9b\\xd5\\x18\\x1c\\xfd\\xc7\\xca\\x54\\xdd\\x83\\xd1\\x08\\x12\\xfb\\xe7\\x86\\x5d\\xa0\\x32\\x48\\x55\\xe6\\xe5\\x3f\\x86\\x7f\\xfd\\x79\\xb5\\x4a\\xb8\\x91\\x25\\x78\\x33\\x5f\\x1e\\x4d\\x69\\xbd\\x8d\\xae\\x6d\\xca\\xc1\\x0f\\xe6\\x58\\x36\\x41\\x80\\xfa\\x42\\x45\\x0e\\xbd\\x1d\\xde\\x20\\x45\\x96\\x4d\\x2f\\xef\\x38\\x9a\\xd1\\x78\\xd9\\x78\\x0a\\xd7\\xa0\\xb6\\xde\\x58\\x55\\x9b\\xd5\\x81\\xbd\\x56\\x3e\\x4b\\x00\\x7a\\xec\\x0a\\x0b\\xb7\\xd5\\xbf\\x20\\x23\\x7b\\xad\\x28\\x5f\\x60\\xad\\xf6\\xbf\\xb1\\x11\\xf3\\x41\\x6f\\x66\\x0b\\x20\\xdf\\xd4\\xbe\\x4b\\x5a\\x59\\xcb\\x77\\x59\\x63\\x70\\xcb\\x34\\xbd\\x0e\\x32\\xb7\\x30\\xab\\xfd\\x5d\\xde\\x33\\x8a\\xe6\\xe4\\x5e\\x8d\\x25\\x41\\xf8\\x24\\xf7\\xd5\\x7f\\xfb\\x80\\x5f\\x95\\x0f\\x85\\xa4\\xc1\\xa8\\xeb\\xb0\\x15\\xd8\\x7b\\x00\\xa8\\x4c\\xf1\\x4f\\x1c\\xa6\\x0b\\x70\\x6d\\xe6\\x22\\x6d\\xc1\\xec\\xcd\\x16\\x0e\\xd1\\xca\\xc5\\xb2\\xdc\\x15\\xda\\xf0\\x7f\\xbe\\xf8\\x67\\xc9\\xb3\\x01\\xbb\\x20\\xaa\\x88\\xab\\xf7\\x3f\\xf9\\x97\\x16\\x5c\\x42\\x77\\x22\\x4b\\x13\\xae\\x53\\xe4\\x06\\x74\\x46\\x99\\x51\\xb4\\x7b\\xbc\\x12\\x38\\xc2\\x69\\xaf\\xf7\\x88\\x0a\\x13\\xb2\\x82\\x6b\\x2b\\x92\\x32\\xe3\\xc8\\xb6\\x60\\xac\\xf4\\xac\\x13\\x88\\xd6\\x48\\x73\\x0d\\x89\\x92\\xe9\\x03\\x56\\xfa\\x15\\xd4\\xd5\\x7f\\xdb\\x84\\x31\\x8a\\x51\\xa0\\x85\\x8f\\xbf\\x17\\x39\\xcc\\x23\\xe9\\x51\\x5b\\xb9\\x51\\xa3\\x70\\xaa\\xab\\x23\\xd6\\x23\\xa9\\xe6\\x4e\\x18\\x68\\x3a\\x49\\x84\\x61\\x82\\x12\\x78\\x8e\\x1b\\xe4\\xb1\\x3a\\x15\\x03\\xf6\\x3f\\xb3\\xc0\\xaf\\x7a\\x4c\\xd8\\x60\\x9a\\x46\\xbd\\xd9\\x8f\\xe9\\x51\\xd6\\x03\\xbb\\x3e\\x50\\x23\\xa5\\x61\\x0a\\x9a\\x1d\\xa5\\x0a\\xbf\\xc1\\x1c\\x95\\xe3\\x01\\xfb\\xbf\\x4e\\xc4\\x27\\x1b\\xc4\\x98\\xd2\\x29\\x3c\\x8a\\x07\\x49\\xc4\\x62\\x25\\x51\\x34\\xd1\\x3f\\x63\\x47\\x94\\xda\\x22\\xf2\\x1c\\x52\\xc1\\x2d\\x64\\xb3\\x63\\x8a\\x6e\\x0a\\xc9\\x31\\x9b\\x6c\\xdd\\x26\\x19\\x51\\x8d\\x4c\\xa8\\xdf\\xfd\\x66\\xcd\\x9b\\x38\\xd9\\x2d\\x76\\xf6\\xbb\\x60\\xe4\\xaa\\x21\\x43\\x52\\xe6\\xdc\\x16\\x56\\x3c\\x48\\xad\\xf1\\x78\\x37\\x3c\\xdc\\x0d\\xd9\\x2f\\x90\\x99\\x6a\\x83\\xff\\xe1\\xf0\\x80\\x33\\x0d\\x63\\xc4\\x72\\xc2\\xdc\\x3d\\x70\\x5c\\x24\\xcb\\x33\\xba\\x1e\\xe0\\x68\\xeb\\xed\\xd9\\x7d\\xe6\\xc4\\xff\\xdf\\xfd\\x26\\xe5\\x96\\xaf\\x78\\x81\\xf6\\x7c\\x56\\x2c\\x33\\x0e\\x3c\\xc4\\x28\\xeb\\xce\\x57\\x6d\\xd6\\x06\\x06\\x5a\\x3f\\xfc\\x4e\\x3d\\xa0\\xa8\\xbf\\xec\\xcb\\xb6\\x4a\\x8d\\x26\\x35\\x0a\\xa2\\x08\\xfb\\xdd\\xd7\\x30\\x16\\xc6\\xea\\x59\\xc3\\xb2\\xe9\\x3d\\x1a\\x8a\\x09\\x69\\x2c\\x97\\x56\\x20\\x65\\x63\\xe1\\xcd\\xbe\\xb7\\x0d\\x3a\\xf1\\x7b\\xc0\\xde\\x38\\x5d\\x0b\\x6d\\x58\\x77\\x8e\\x4d\\x93\\x80\\x7d\\x33\\x2b\\x80\\xfd\\xa9\\xf1\\xc7\\xd7\\xba\\x48\\x10\\xd7\\x3c\\xa1\\x21\\xe4\\xe2\\x69\\xaa\\xc1\\x2c\\xd2\\x87\\x65\\xe8\\xb3\\x76\\xfd\\x41\\xcd\\x7f\\x10\\x04\\x87\\x57\\xc1\\x20\\xe0\\x1d\\xb7\\xc6\\x88\\xb1\\x93\\x32\\x43\\x2a\\x65\\x30\\xf3\\xb6\\xa4\\x4d\\xd2\\x0a\\xf0\\x43\\x72\\xc1\\x40\\x5e\\x31\\x01\\x61\\x83\\xdc\\x9f\\x28\\x69\\xca\\x3c\\x44\\x44\\x3a\\xad\\xa7\\x00\\x99\\x82\\x4c\\x66\\x98\\x7b\\x93\\x4d\\x41\\x0f\\xd8\\xb7\\xc6\\xed\\x14\\xfb\\x8b\\x18\\x3b\\xbd\\xcf\\x0f\\xda\\x14\\x95\\x82\\x1b\\x69\\x6e\\x06\\xc2\\x34\\x0a\\xd2\\x62\\x8c\\xa7\\x93\\x81\\x42\\x0f\\x0d\\x77\\x81\\x4f\\xf2\\x09\\x71\\x26\\xf3\\x93\\x28\\xc9\\xd6\\x7a\\x53\\xa5\\x7c\\x06\\x23\\x68\\x80\\x0b\\x1d\\x78\\xb7\\xa4\\xb1\\x22\\x57\\x5a\\xa1\\x8c\\x08\\xa9\\x68\\x15\\x1d\\x6d\\xa5\\x8d\\xaa\\x11\\x25\\x75\\x52\\xbf\\x6d\\x45\\x18\\x03\\x96\\xe6\\x16\\x83\\x8a\\x5b\\x29\\x09\\xf8\\xd0\\xb4\\xd2\\x04\\x32\\xf3\\xac\\xed\\x69\\x6b\\x7e\\x67\\x43\\x95\\xef\\xf6\\x94\\x6b\\x9a\\xae\\xb9\\xbc\\x85\\x94\\x65\\x70\\x2f\\x12\\x35\\xd6\\xbc\\x98\\x88\\x04\\x33\\x17\\xc9\\xaf\\xe2\\x64\\x75\\x4b\\xbe\\xf3\\xc1\\xe1\\x4a\\x44\\x5b\\x45\\xc6\\x8b\\x72\\x98\\x09\\x33\\x81\\xa5\\xb2\\xcc\\x5a\\x1c\\x35\\x90\\x68\\xb0\\x4b\\x29\\x48\\x0b\\x45\\xaf\\xe9\\xbd\\x9a\\x29\\x87\\x70\\x2f\\xdf\\x81\\x0f\\x67\\x24\\x9c\\xc3\\x83\\xe7\\x40\\x9c\\x24\\xee\\x20\\x05\\x0f\\x45\\x5d\\x4d\\xba\\x82\\xe1\\x80\\x5d\\xda\\x60\\x98\\x76\\x5f\\xdc\\x02\\x14\\x84\\x69\\x18\\x77\\x60\\x72\\xb4\\xa9\\x18\\x21\\x13\\xa0\\xfc\\x4b\\xca\\x63\\x05\\x08\\x66\\x46\\xab\\x05\\x90\\x18\\x04\\x68\\xe0\\x0f\\x7b\\x03\\xd2\\x2e\\x17\\x6a\\xd6\\xeb\\x5d\\x6b\\x74\\xae\\xf5\\x60\\xac\\x68\\xca\\xc3\\x90\\xac\\x69\\x51\\xe0\\x89\\xee\\xdf\\x0e\\x94\\xf8\\x64\\xdb\\x1d\\xa4\\x74\\xd9\\x6b\\x8a\\xdb\\x7a\\x98\\xd6\\x7c\\xdb\\x7a\\xdd\\x47\\x03\\x18\\x36\\x51\\x77\\xbe\\xa7\\xf9\\x43\\xeb\\x2d\\x36\\x61\\x6f\\x53\\x61\\x12\\x77\\xd2\\x21\\x65\\xe7\\x4a\\x9a\\x90\\x33\\xcb\\x25\\xa5\\xc1\\x4e\\x79\\x46\\xa8\\x10\\x3a\\x2e\\x54\\x86\\xfe\\x8d\\xb4\\x0c\\xea\\x04\\x85\\xb6\\x42\\x3e\\x04\\xac\\x75\\x6d\\xc2\\x54\\x56\\xb0\\xb9\\x07\\x58\\xec\\x43\\x5c\\x30\\xf0\\x87\\x2b\\x95\\x65\\xeb\\xb9\\xd8\\x5a\\xbd\\x74\\x13\\xad\\x34\\x00\\x60\\x63\\xff\\xeb\\x65\\x80\\x98\\xb7\\xc5\\x39\\x9c\\xae\\x3d\\x48\\x88\\x1a\\x4e\\xd4\\xad\\x00\\x3b\\x04\\x7b\\x07\\x20\\x59\\x32\\x81\\xe4\\xd6\\xd4\\x01\\x1a\\x58\\x75\\x7e\\x6e\\xd7\\xbc\\xfd\\xa9\\x4d\\xb1\\x2a\\x79\\xca\\xed\\x0a\\x2a\\x1a\\x06\\x80\\xdc\\x66\\x12\\xee\\xe6\\x03\\x0e\\x16\\x89\\x3d\\x9f\\x72\\x91\\xf1\\x61\\x46\\xb9\\xe2\\xd5\\x5f\\xbd\\xe6\\x3c\\x44\\xe0\\xe7\\x45\\x99\\x65\\xde\\x89\\x84\\x0e\\x58\\xab\\xf9\\x68\\x24\\x12\\x8c\\x41\\x41\\x37\\x73\\x1d\\xd6\\xb4\\x74\\x09\\x3b\\xb9\\x96\\x8d\\xe5\\xb6\\x5c\\xd8\\xa3\\x35\\x1b\\xbc\\x6e\\x63\\x9d\\x1e\\x22\\x56\\x1a\\x88\\xe6\\xea\\x87\\xb7\\x94\\x15\\x37\\x0d\\x20\\x65\\xab\\x65\\xff\\x1e\\xb0\\xd7\\xca\\xfa\\xb8\\x8c\\x57\\x60\\x4c\\x88\\xfd\\x78\\x0b\\xdc\\x28\\xd9\\xa0\\xae\\x28\\xfd\\x6a\\x31\\x16\\x92\\x67\\x7e\\x51\\x4d\\xfb\\x5e\\xa5\\x7b\\x70\\x34\\x29\\xe7\\x62\\xac\\xb9\\xad\\x88\\x62\\x3d\\x6f\\xcf\\x5d\\x3c\\x5f\\x24\\x4b\\xe8\\x80\\x9d\\xc9\\x19\\xee\\xb7\\x0f\\xd8\\x70\\x3d\\x5b\\xad\\xd2\\x32\\x01\\xef\\x7c\\x2e\\x4d\\xb3\\x93\\x4e\\xc9\\x68\\xdb\\xbd\\x70\\x1e\\x06\\xa9\\x03\\x10\\x53\\xb0\\x5c\\x78\\x97\\x92\\x92\\xc0\\xb8\\x29\\x9c\\x1e\\x17\\x70\\x92\\x4c\\xe1\\x35\\x80\\x91\\x59\\x9c\\x5d\\x5d\\xb2\\xb7\\x3e\\x93\\x78\\xc0\\xfa\\xfd\\x3e\\xf9\\x3d\\x8d\\xd5\\x65\\x82\\xfc\\xc5\\x1d\\x21\\x99\\x7a\\x4e\\x41\\xd8\\x47\\xf1\\x36\\x8d\\xd8\\x5d\\x6f\\xf9\\x20\\x11\\xac\\xe0\\x76\\xc2\\x06\\x04\\xf8\\x41\\x03\\x14\\x8c\\x7d\\xe5\\x78\\xcd\\x3d\\xcf\\x0b\\x87\\xf7\\xef\\x24\\x51\\xef\\xaf\\x94\\xba\\xa6\\x4d\\xa2\\x31\\xff\\xcd\\x4e\\x4e\\xe6\\x71\\x42\\x0d\\x9d\\x88\\xea\\x0d\\x88\\x88\\x1a\\x23\\xa5\\x0e\\x4d\\x7b\\x49\\x03\\xf7\\xe1\\x37\\x18\\xfe\\xb3\\x64\\x74\\x1c\\x8b\\x6b\\x38\\x65\\xef\\x0e\\xce\\xc2\\xe9\\x7b\\x77\\xd0\\x63\\xef\\x0e\\xae\\xb4\\x1a\\x63\\x4c\\xa8\\x1c\\xbf\\xf3\\x41\\x9e\\xef\\x0e\\x2e\\x60\\xac\\x79\\x0a\\xe9\\xbb\\x03\\xd7\\xed\\x2f\\x31\\x98\\xf7\\x15\\xe8\\x31\\x7c\\x03\\xb3\\x3f\\x61\\x67\\xd5\\xcf\\x81\\x23\\xfc\\x89\\xe2\\x7e\\xdd\\xef\\x8e\\x05\\x3b\\x3e\\xf5\\xa7\\x9c\\x17\\xd5\\x0f\\xaf\\x78\\x51\\x7d\\x7c\\x5e\\xe3\\xd9\\xf7\\x3f\\xe4\\x60\\xf9\\xf4\\xf9\\xa0\\xde\\xd1\\x1f\\xff\\x61\\x94\\x3c\\x7d\\x77\\x50\\xcf\\xbf\\xa7\\x72\\x81\\x41\\x13\\xb3\\x77\\x07\\xac\\x35\\xea\\xe9\\xbb\\x03\\x1c\\x37\\xfc\\x1e\\x26\\x79\\xfa\\xee\\xc0\\x8d\\xe4\\x7e\\xd6\\xca\\xaa\\x61\\x39\\x3a\\x7d\\x77\\x80\\xb1\\x08\\xbd\\xe7\\x3d\\x0d\\x45\\xcf\\x09\\x4c\\x7f\\xaa\\x47\\x78\\x77\\xf0\\xa3\\xdb\\x93\\x93\\x13\\xef\\xc2\\xf0\\x37\\x2b\\xfc\\x67\\xb9\\xb1\\xfa\\x41\\xba\\xff\\x50\\x3c\\x52\\x9f\\x65\\xdc\\xd8\\x1b\\xcd\\xa5\\xc1\\xf1\\x6f\\x44\\xbe\\xdc\\x8d\\x4b\\xba\\x1c\\x9e\\xf7\\x95\\xcf\\x35\\xd2\\x80\\x95\\x8f\\x09\\x1b\\x56\\x3e\\x5e\\xc1\\x3d\\x37\\xe1\\x5c\\x8b\\x6b\\xd8\\xd0\\xea\\xbc\\xf8\\x61\\x9d\\x0d\\xe1\\xe4\\xb9\\x60\\xa7\\xa9\\xf6\\xc7\\xf1\\x00\\xff\\x36\\xf8\\x2a\\x1d\\xee\\x88\\x7b\\xfa\\x86\\xb1\\xce\\xb8\\x6f\\x3e\\x40\\xa7\\x56\\xf0\\xef\\x7c\\x05\\x0f\\x56\\xca\\x14\\x74\\x86\\xce\\xaa\\xba\\x57\\xf2\\x84\\xa4\\x03\\x46\\x76\\x03\\x5e\\x59\\x69\\x30\\x8e\\x0e\\xb9\\x93\\x6c\\x18\\xaf\\x29\\x86\\x27\\xf4\\xe8\\x68\\x87\\x2f\\x62\\x42\\xdd\\x20\\xa3\\x4b\\x12\\x28\\x2c\\x72\\xba\\xdd\\x5d\\xcc\\xac\\x61\\x54\\x71\\x92\\x55\\xdf\\xae\\x46\\x0f\\x8f\\x1c\\x1b\\x02\\xde\\xbf\\x4d\\xfe\\xfd\\x49\\x99\\x73\\xc7\\x3a\\x78\\x8a\\x61\\x3c\\xd5\\x33\\x52\\xdf\\x48\\xdd\\x22\\x92\\x4a\\x4e\\x21\\xb2\\xf1\\x87\\x7d\\xf0\\xa0\\xf6\\x8c\\x84\\x57\\xd9\\x6a\\x0f\\x58\\x4c\\x36\\x5a\\x7c\\xce\\xef\\x5f\\x82\\x1c\\xdb\\xc9\\x29\\xfb\\xf5\\xaf\\xfe\\xcf\\xef\\x7e\\xbf\\xe2\\x45\\x22\\x8c\\x90\\x7e\\x0d\\xd2\\xdb\\x82\\x36\\x04\\xc3\\xe2\\x87\\xf3\\x46\\xc3\\x41\\x88\\xbf\\x1c\\x8c\\xeb\\x77\\x2a\\x23\\x77\\x8d\\x41\\x77\\x1c\\x63\\xb0\\x3c\\xbb\\x2c\\x0b\\x07\\x97\\xaf\\x30\\xba\\xd6\\x58\\x2e\\x13\\xe8\\x39\\x21\\x69\\x69\\x67\\xa2\\x22\\xe0\\xd9\\x8c\\x3d\\xff\\x15\\xdd\\x40\\x84\\x43\\x2f\\x90\\xef\\xef\\xef\\x7f\\x18\\x2c\\x99\\xb2\\x30\\xec\\x0f\\xbd\\xb9\\xf9\\x08\\xc3\\xdc\\x56\\xa9\\x11\\x22\\x0e\\xa9\\x98\\x1a\\x88\\x13\\x06\\x63\\xc0\\x22\\x27\\x84\\x6a\\xbe\\x0f\\x6d\\xdc\\x43\\xf6\\xc0\\xcd\\x6c\\x81\\xb9\\x90\\x22\\x2f\\xf3\\x53\\xf6\\x6c\\x65\\x3c\\xa7\\x23\\x69\\x1b\\xee\\x26\\xbd\\x5c\\x0b\\x02\\xdc\\x91\\xae\\xb1\\xe6\\x79\\x8e\\x71\\xf4\\x22\\x05\\x69\\xc5\\x48\\x60\\xd0\\x40\\x85\\xda\\xa8\\xee\\xd3\\x87\\x21\\x06\\xa5\\x82\\x22\\x86\\xa7\\x38\\x3a\\xd4\\x40\\xf6\\x2b\\x92\\x73\\x34\\x72\\x60\\xef\\xbd\\x49\\x9a\\x04\\x6a\\x56\\x00\\x9d\\x06\\x52\\x60\\x18\\xdc\\x17\\x24\\xaa\\x36\\xdc\\x10\\x39\\x70\\x29\\xe4\\xd8\\xd4\\xf1\\x5c\\xfe\\xf6\\x29\\xf7\\xf0\\x6e\\x02\\xde\\x7b\\x0e\\x4d\\x5f\\x50\\xe2\\x94\\xa5\\x14\\xf5\\x26\\x5e\\x87\\x07\\x62\\x00\\x28\\xc9\\xe8\\xf3\\x36\\x4d\\x27\\x39\\xe6\\x90\\x9d\\x73\\x03\\xe1\\x34\\x36\\xa3\\xb9\\x42\\x29\\xa4\\x2a\\xb5\\xa7\\xb3\\xa3\\xfa\\xfc\\xd9\\xaf\\xd6\\x6e\\x79\\xf5\\xde\\x6a\\x17\\x5e\\x15\\xe6\\xf5\\xfd\\x59\\xff\\xff\\xf2\\xfe\\xbf\\x7e\\x38\\xf2\\xff\\x78\\xd6\\xff\\xc3\\xdf\\x7b\\xa7\\x3f\\x7c\\xd1\\xf8\\xf3\\x87\\xd5\\xd1\\x59\\xcb\\x85\\xf9\\x15\\xe8\\xe3\\x99\\x48\\x90\\x13\\xc3\\x8e\\xf6\\x42\\x94\\xca\\x8d\\x2e\\xa1\\xc7\\xbe\\xe2\\x99\\x81\\x1e\\xfb\\x56\\x22\\x6b\\xd8\\x13\\x68\\xeb\\x3d\\xd4\\x8e\\x2b\\x1f\\xb8\\x51\\x57\\x79\\xca\\xfd\\x2b\\x38\\xa5\\xf5\\xef\\xf8\\xe9\\xae\\x53\\x5f\\x37\\x03\\x52\\x30\\x35\\x34\\x28\\x8d\\x6c\\xe0\\x19\\xe5\\x13\\x8c\\x94\\x1a\\x78\\x09\\x77\\x90\\xa8\\xfc\\xa4\\x7a\\x4e\\xa2\\xf5\\x2b\\x2e\\x67\\xac\\x26\\x6b\\x24\\x94\\xce\\x63\\xba\\xc1\\x80\\x79\\x9e\\x68\\x65\\x4c\\x5d\\xe4\\x87\\x65\\xe2\\x16\\xd8\\x59\\xad\\x37\\x3a\\x62\\x39\\x84\\x84\\xa3\\x2c\\xae\\x87\\xc2\\x6a\\x4e\\x46\\xdf\\x20\\x57\\xd6\\x16\\xa5\\x51\\x99\\xb1\\x23\\xa7\\xae\\x0e\\x30\\x90\\x6c\\x81\\xba\\xfa\\x82\\x61\\x7c\\x28\\x32\\xbc\\xb7\\xc9\\xa9\\xd2\\x89\\x92\\xa3\\x4c\\x78\\x15\\x20\\x2f\\x94\\xb6\\x5c\\xda\\x90\\xd5\\x34\\x86\\x7b\\xba\\x2a\\x8e\\xdc\\x0e\\xc2\\xb0\\xa3\\x54\\x9a\\xe7\\xcf\\x7f\\xf5\\xeb\\xeb\\x72\\x98\\xaa\\x9c\\x0b\\xf9\\x55\\x6e\\x4f\\x8e\\xbf\\x3c\\xfa\\x67\\xc9\\x33\\xf4\\xf2\\xbe\\xe6\\x39\\x7c\\x95\\xdb\\xd5\\x97\\x6e\\x6d\\xcd\\x16\\x9f\\xff\\x6e\\x83\\x53\\x74\\xf4\\x3d\\x9d\\x95\\x1f\\x8e\\xbe\\xef\\xfb\\x7f\\x7d\\x11\\x7e\\x3a\\xfe\\xf2\\xe8\\xdd\\x60\\xed\\xf3\\xe3\\x2f\\x4e\\x30\\x46\\xb2\\x3a\\x72\\x3f\\x7c\\xdf\\xaf\\x8f\\xdf\\xe0\\x87\\x2f\\x8e\\xbf\\x6c\\x3c\\x3b\\x5e\\x76\\x18\\x5b\\xa1\\x8b\\x4e\\x0b\\xe8\\xe7\\xbc\\xe8\\xdf\\xc2\\x6c\\xc5\\xe1\\x5c\\x29\\x8e\\x2e\\x76\\x44\\x10\\xcb\\x79\\xb1\\x4c\\xfb\\x1e\\x89\\xf1\\x2b\\x5e\\xbc\\x85\\x11\\x68\\x90\\xc9\\x52\\x24\\xdf\\xd3\\x03\\xe3\\xf4\\x87\\x35\\x8f\\x30\\x02\\x6b\\x07\\xab\\x93\\xe3\\x3b\\x64\\x69\\x5b\\x27\\x4e\\x6f\\x80\\x2d\\x9b\\xc9\\x8f\\x72\\x4d\\xfc\\xe2\\x83\\x83\\x54\\xeb\\xdc\\xb9\\x87\\x70\\xbe\\xbf\\x23\\xfb\\xd1\\xce\\xfd\\x94\\x62\\xa5\\xa6\\xd5\\xb6\\x61\\x5e\\x5e\\x90\\xe8\\x8b\\xa4\\x07\\xc5\\xb9\\x89\\x72\\x7a\\x5e\\x29\\xc5\\x3f\\x4b\\x60\\x97\\x17\\x55\\x3e\\xbd\\x90\\x49\\x56\\x62\\x05\\xbf\\x6f\\xbf\\xbd\\xbc\\x70\\xfa\\xfb\\xff\\x78\\x72\\x73\\x07\\x2c\\x55\\xf2\\xd0\\xb2\\x37\\xaf\\x5f\\xfe\\x0d\\x8d\\x01\\xf8\\x46\\x8f\\x18\\xba\\x4f\\xea\\xcd\\x04\\x27\\x33\\x99\\x67\\xc0\\xec\\x7f\\x80\\xe2\\xe4\\x70\\xe4\\x84\\x17\\x95\\xfd\\x04\\xc9\\x1d\\x46\\x58\\x65\\x85\\xc1\\x44\\x00\\x66\\x4a\\xed\\x67\\xe7\\x3a\\x26\\x8f\\x2f\\xa6\\xfe\\x79\\x7f\\x70\\xc8\\x61\\xc0\\x4c\\x90\\x9d\\x82\\x3b\\x13\\x25\\x25\\x24\\xe8\\x34\\x77\\x52\\xe0\\x7b\\x38\\x1f\\x0e\\x91\\xdf\\x78\\x99\\x15\\xc7\\xd8\\xe1\\x30\\x78\\x87\\xda\\xce\\x68\\xe1\\xe6\\x70\\x4e\\x2b\\x7d\\xef\\x27\\x69\\x61\\xbd\\x3b\\x8d\\x48\\xf6\\x4c\\xf4\\x6c\\xbe\\x7d\\xc0\\xfe\\xbc\\x10\\xc6\\xd5\\x56\\x9d\\xe7\\xf2\\xb6\\xd0\\xb6\\x5a\\x39\\x47\\x27\\xdc\\xb0\\x21\\x80\\x44\\x73\\x2e\\x59\\xff\\x40\\x7a\\xac\\x83\\xda\\x10\\x5b\\x16\\x7d\\xab\\xfa\\xe9\\xf2\\xcd\\x7b\\x00\\x72\\x0f\\x43\\x6d\\x8d\\xe6\\x3a\\x57\\x1a\\x63\\x5b\\x45\\xf5\\x6e\\x32\\x5b\\x06\\x03\\x53\\x57\\x0a\\xac\\x64\\x90\\x6d\\x17\\xb6\\x5a\\x31\\x99\\xb3\\xea\\xa2\\x66\\xe1\\x8d\\x1a\\x5e\\xcf\\x58\\x9c\\x92\\xd3\\x1e\\x5b\\x96\\x0d\\xab\\xd0\\x9b\\xd7\\xb6\\xec\\x6d\\x3f\\x47\\xda\\xe6\\x6b\\xd0\\x53\\xb1\\x13\\xf3\\x7b\\xe8\\x60\\x26\\x14\\x67\\x72\\xf6\\xfe\\x8f\\x95\\x13\\xbd\\x76\\x1e\\x04\\x4d\\x7f\\x89\\x7a\\xc0\\x7d\\xb3\\x36\\xfe\\x1d\\x21\\xb8\\x2e\\xca\\x7f\\x9b\\x3e\\xb6\\x65\\x96\\x44\\x4d\\x5a\\x49\\x1e\\xc6\\x2a\\x8d\\x2e\\xf7\\xe6\\x6f\\xe5\\xb0\\x12\\x94\\xeb\\xde\\xbd\\x0e\\xc4\\xfe\\xfd\\x9f\\xcf\\x3e\\xeb\\xf7\\xfb\\x9f\\xf1\\x42\\x04\\x36\\xcb\\x78\\x21\\xe0\\xde\\x82\\xa4\\x4b\\x8b\\x6f\\x7f\\x8f\\x61\\xbc\\xd3\\xe7\\x9f\\xdd\\x0a\\x99\\x9e\\xb2\\xf3\\xd2\\x58\\x95\\x07\\xb3\\x38\\x56\\x7e\\x45\\xfc\\xfc\\x2c\\x98\\x31\\xdc\\x20\\x5c\\x4a\\x65\\x9b\\x41\\xb0\\x4e\\xfd\\xd6\\x8e\\x9c\\xe8\\xfe\\x18\\xe4\\xc0\\x89\\x6b\\x18\\xe6\\x0c\\x1a\\x3b\\x0f\\x43\\x4f\\x9f\\x0d\\xfe\\x30\\x70\\x6a\\x3f\\xe2\\x90\\xb7\\xfe\\x19\\xcb\\xf3\\xe2\\x14\\x33\\xc5\\x3f\\xf3\\x42\\x09\\x4b\\xb2\\xd2\\x60\\x79\\x5c\\x04\\x9f\\xff\\xde\\x0c\\xaa\\x60\\xb8\\x41\\xa2\\x34\\x28\\xf7\\x9f\\xfc\\x33\\xa7\\x8f\\xbb\\x59\\x8c\\xb5\\x2a\\x8b\\xba\\xfc\\x48\\xeb\\x1d\\x2f\\xaf\\xf8\\xc9\\x52\\xf4\\x5a\\x03\\xc1\\xfb\\x4c\\x65\\x74\\x11\\xad\\x07\\x02\\x0d\\xef\\xcf\\x90\\x87\\x1c\\x3e\\x77\\xd2\\xe7\\x37\\xab\\xdf\\x79\\x29\\x0c\\x1d\\xa9\\x22\\x2b\\x35\\xcf\\x56\\x2d\\x04\\x5f\\x31\\x13\\xa5\\xed\\xeb\\x7a\\x5a\\x98\\x83\\x6a\\xa6\\xcd\\x7f\\xfb\\x17\\x85\\xc4\\x80\\xa4\\x15\\xbd\\x7d\\xc6\\x98\\x49\\x94\\xc3\\x9f\\x0a\\xcd\\xd2\\xcf\\x58\\x70\\xcb\\xf9\\xce\\xfb\\xad\\x4c\\x18\\xf4\\x0d\\x9e\\xab\\xac\\xcc\\x9b\\x4e\\xaa\\xfe\\x22\\x5b\\x71\\x50\\x0b\\xca\\xf1\\xf9\\xf5\\x77\\x0d\\xec\\xfd\\x87\\x51\\xf2\\x8a\\x3b\\x6d\\x84\\x92\\x2a\\x52\\x61\\x8a\\x8c\\xcf\\x5e\\xb7\\x25\\x63\\xda\\xcd\\x0b\\x7a\\xf6\\xd9\\x03\\x07\\x67\\xc9\\xf8\\x73\\xbe\\xc5\\xf5\\x53\\x98\\x36\\xf6\\xa9\\x39\\xfc\\x77\\x0b\\xbf\\x6f\\x3a\\x7c\\x58\\x3e\\x77\\x23\\x37\\x02\\x5a\\x94\\x84\\x50\\x05\\xc5\\xac\\x99\\xd0\\x92\\x57\\x68\\x46\\x6f\\x17\\x1f\\xac\\x98\\x52\\xb3\\x4b\\xd2\\x5d\\x8b\\x09\\x37\\x8b\\x20\\xbe\\x9a\\xfb\\x75\\x49\\x77\\xf4\\xe2\\xf4\\x39\\xcf\\x8a\\x09\\x0f\\x66\\x18\\x93\\x4c\\x20\\x6f\\x84\\x7a\\xa9\\x02\\xe4\\xd9\\xd5\\xe5\\x77\\xbf\\xbe\\x9e\\x7b\\x30\\x9f\\x04\\xbc\\x0c\\xfb\\x49\\xbc\\x26\\x0a\\x52\\x79\\xd6\\x70\\xef\\x9c\\xdc\\xfb\\xe3\\xd2\\x6f\\xae\\x0b\\x48\\x7e\\x1c\\x2c\\xcc\\x7c\\x81\\x3b\\x2d\\x17\\x39\\xfb\\x55\\xaa\\xfc\\xdc\\xcf\\x0e\\xfe\\x8d\\x9f\\x56\\xf1\\xb4\\x06\\x5d\\x9c\\xa3\\xcc\\xed\\x50\\x2b\\x07\\x12\\xbf\\xc6\\x10\\xa2\\x60\\x6b\\xf4\\x84\\xd4\\xc3\\xb1\\x72\\x2d\\x56\\x06\\x65\\x32\\xd6\\x52\\xa8\\x03\\xad\\x69\\xc0\\xae\\x31\\xe6\\xac\\x72\\x54\\x24\\x4a\\x4e\\x41\\x5b\\xa6\\x21\\x51\\x63\\x29\\xfe\\x55\\xf5\\x66\\xe6\\x1c\\xdd\\x78\\x6a\\x25\\xcf\\x42\\xec\\x2e\\x1a\\x15\\xf9\\x8c\\x69\\xf8\\x07\\x7a\\x26\\x65\\xa3\\x87\\x50\\x48\\xa8\\x4a\\xf1\\xa8\\xf3\\x37\\xc6\\xc2\\x06\\xaa\\x9f\\xa8\\x3c\\x2f\\xa5\\xb0\\xb3\\x13\\x24\\xe0\\x62\\x58\\x3a\\xc2\\x79\\x92\\xc2\\x14\\xb2\\x13\\x23\\xc6\\x7d\\xae\\x93\\x89\\xb0\\x90\\x38\\x85\\xe5\\x84\\x17\\xa2\\x8f\\x93\\x95\\xe4\\x57\\xcc\\xd3\\x5f\\x54\\xac\\x67\\x3e\\xfa\\x68\\x25\\x67\\x44\\x02\\xbb\\x16\\xd6\\x8e\\xbc\\xfa\\x1c\\xc4\\x46\\x51\\xa4\\x1a\\xa4\\xc1\\x80\\xfb\\xf6\\xc5\\xf5\\x4d\\xa5\\x44\\xfa\\x73\\x89\\x10\\x6e\\x98\\xf3\\x6b\\x60\\x3b\\x40\\x09\\x39\\x82\\x60\\x7a\\x0d\\x85\\x15\\x40\\xa6\\x54\\x6e\\x1e\\xed\\x7f\\x99\\x40\\xc9\\xab\\x1c\\xe6\\x02\\xc3\\x96\\x30\\x57\\x99\\x82\\x4b\\xcf\\x91\\xe9\\xa1\\x59\\x89\\x22\\x5e\\x06\\xec\\xb2\\x61\\x05\\x7b\\xef\\xa0\\x46\\x1b\\x73\\xdf\\x81\\x6f\\x73\\x60\\x37\\x79\\xf6\\xe2\\x07\\x4b\\x24\\xc0\\xc0\\x4b\\x57\\xee\\xce\\xca\\x33\\xcc\\x52\\x48\\x32\\x1e\\x32\\x5d\\x2c\\x64\\x19\\x7b\\xf3\\xf2\\x15\\x46\\x08\\x85\\xe8\\xcb\\x2c\\x5b\\xac\\x4e\\x97\\x70\\xc9\\x72\\x2e\\x31\\xa2\\xa1\\x28\\xc8\\x36\\xce\\x7d\\x85\\xf8\\x10\\x8c\\xb2\\xe9\\xe4\\xd7\\xe9\\xa5\\x7d\\xb6\\x9c\\x41\\x85\\xa7\\x7e\\x82\\x73\\x4f\\xd6\\x89\\xc2\\x0b\\x32\\xd0\\x1a\\xa8\\x9d\\xd5\\xef\\x7a\\x1b\\x41\\x29\\xc9\\xe5\\x8f\\xa5\\x34\\x6e\\x21\\xc4\\x2a\\xe6\\xbc\\x40\\x29\\x2f\\xa4\\x36\\xf2\\x26\\x82\\x63\\xc6\\xcd\\x2c\\x24\\x9d\\x0d\\x67\\xcc\\x89\\x71\\x48\\x10\\xac\\x52\\x3e\\x30\\xc7\\x7d\\x8b\\x84\\x41\\x83\\xd5\\x02\\xa6\\x4d\\x03\\x69\\xe5\\x88\\xda\\x5e\\x27\\xd8\\x3c\\x8d\\x76\\xad\\x48\\xcc\\x0b\\xe1\\x65\\x97\\xb4\\x12\\x2c\\x37\\x80\\xde\\xd5\\xa5\\xc7\\xb7\\x5a\\x1c\\x35\\x1e\\xdf\\x7c\\x31\\x4c\\x2f\\x1f\\x54\\x72\\x2d\\x8e\\xe4\\x11\\x2b\\x65\\x75\\x45\\x45\\x0c\\x68\\x6d\\x22\\x21\\xe5\\xfb\\x6b\\x2e\\xdd\\x83\\xa5\\xc8\\xbd\\x03\\xb4\\x1e\\xd2\\xa0\\xd4\\x9d\\x5c\\x1d\\x1d\\xd0\\x6d\\x8a\\x57\\x13\\x76\\xd5\\xcf\\xa1\\x9a\\x4c\\x1d\\x36\\x63\\x15\\x9e\\x56\\xd2\\xa0\\x11\\x76\\x55\\xc1\\x99\\xa9\\xe0\\x8c\\x8f\\xc7\\x1a\\xa3\\x65\\x57\\x46\\x1a\\x6c\\x98\\xa6\\xb5\\x49\\x3d\\xc8\\x3e\\x49\\xf2\\x6b\\xdf\\x70\\x64\\x70\\xed\\x0b\\x2b\\x2d\\xb4\\xe1\\x85\\x45\\x61\\xb1\\xdd\\x36\\x4b\\x28\\xe3\\x68\\x46\\x0b\\xa0\\x55\\xfa\\x81\\xdc\\x95\\x4d\\x8b\\x56\\x6d\\x54\\xac\\xaa\\xbd\\xcf\\x73\\x13\\xf1\\x4f\\x87\\x58\\x53\\xac\\x22\\xcd\\x8e\\x1c\\x24\\xb5\\x37\\xdb\\xbb\\x49\\x0a\\xd0\\x4e\\x1f\\xa7\\x78\\x62\\xce\\x12\\x92\\xdf\\x2a\\xc2\\x13\\xbc\\xc3\\x0f\\x4c\\x67\\x8b\\x82\\x6d\\x9b\\x57\\x05\\xed\\x63\\x48\\xd5\\x03\\xaf\\x6d\\x53\\xc7\\xb3\\x09\\xb4\\x07\\x5f\\xde\\xb2\\x10\\x58\\x83\\xc3\\x74\\xde\\xb7\\x03\\x43\\xe7\\x9d\\x6e\\x90\\x93\\x43\\xad\\x6d\\xde\\xe2\\x77\\xaf\\x9a\\x91\\x24\\x9a\\xdf\\x31\\x90\\x89\\x72\\xc4\\xe2\\xff\\xbd\\x7e\\xf3\\x3a\\xe4\\xaf\\x5d\\x5a\\x26\\xf2\\xc2\\x5f\\x96\\xc3\\x5e\\x71\\x6d\\x26\\x3c\\x03\\xaa\\x8d\\xfc\\xad\\xcc\\x5b\\x7f\\xcf\\x85\\x80\\xa7\\x90\\xf1\\x19\\x75\\x96\\x42\\xa2\\xd0\\x12\\xaf\\x34\\x2b\\x9c\\x80\\x9b\\x17\\x25\\xa6\\x70\\xe0\\x53\\x1c\\xf7\\xc1\\x24\\x9d\\x1d\\x40\\x53\\x9b\\xa8\\x86\\xb3\\xa5\\x16\\xd0\\x76\\xbb\\xef\\xa7\\x9b\\xd2\\x80\\xe6\\x64\\x36\\x2d\\x5f\\xb7\\x45\\xf1\\xba\\x0d\\x57\\x59\\x65\\xc8\\x5c\\xad\\xb1\\xb1\\x35\\x7b\\xdc\\x32\\x17\\x6c\\xed\\xad\\x58\\x29\\x14\\x99\\x9a\\x39\\xbc\\x78\\xf8\\xac\\x6c\\xb8\\x9e\\x8d\\xcf\\xf5\\xa6\\xfd\\x6d\\x7a\\x96\\x37\\xec\\x8f\\x8c\\x53\\x5d\\xf4\\xb4\\x4c\\x81\\xda\\xa9\\xa3\\x75\\xee\\xbf\\xad\\x3a\\x5a\\x62\\x7f\\x5c\\xdd\\xdb\\x7b\\x61\\x7e\\x57\\x97\\xc1\\xda\\x50\\x79\\x7d\\x3d\\x6d\\xaa\\xfe\\xc4\\xdc\\x9d\\x6f\\x2a\\x37\\x72\\x43\\xae\\xae\\xbc\\x81\\x64\\xad\\xc7\\xbc\\x24\\x1d\\x6a\\xd4\\x3d\\x58\\x24\\xfb\\x3d\\xb1\\xbd\\x07\\x04\\x9c\\xf0\\xda\\x03\\x62\\x4e\\x78\\xed\\x21\\x61\\x87\\xda\\x36\\x7c\\xf4\\x61\\x2c\\xa4\\xd6\\x4e\\x1e\\x77\\x9a\\xbd\\x17\\xd5\\xab\\x9d\\x49\\xdb\\x5b\\xd1\\x39\\x25\\x7f\\x18\\xcd\\x97\\xcc\\xf4\\x0a\\xcd\\xb7\\x2d\\xf3\\xe7\\xaa\\x09\\xb3\\xa3\\x55\\x26\\xf3\\x81\\xd3\\x8b\\x07\\x68\\x94\\xfd\\xfe\\x87\\x01\\x75\\x79\\x1c\\xb2\\xe1\\xbd\\x6d\\x43\\x3c\\xd0\\x79\\xa8\\x69\\x39\\x2f\\x95\\x75\\x0e\\xa6\\xe9\\x7a\\x2f\\xfc\\x4a\\x48\\x9d\\x5d\\x5d\\x06\\x03\\xeb\\x07\\xdc\\x5a\\x53\\x40\\xf2\\x08\\xa4\\xee\\xeb\\xd6\\x34\\x5a\\x32\\xb7\\xcf\\x03\\x75\\x02\\xb5\\x9b\\x2c\\x1b\\x66\\x2a\\xb9\\xf5\\xb6\\xe4\\xb7\\x17\\x55\\xca\\xa5\\xd3\\xba\\x9c\\xf0\\xe3\\x13\\x2e\\x99\\x78\\x88\\x88\\x44\\x31\\x3b\\x8a\\xd9\\x51\\xcc\\x7e\\x2a\\x62\\x36\\xf9\\x6c\\x1e\\x03\\xa5\\x9a\\x9b\\xc8\\x4a\\x5a\\x45\\xf1\\xb0\\x91\\x5a\\xad\\x69\\x91\\x5a\\x61\\x8b\\xd4\\xea\\x81\\xf6\\xe4\\xa8\\xd5\\x46\\x32\\xe0\\x06\\x71\\x9d\\xeb\\x0f\\x72\\x34\\x70\\x47\\x03\\x77\\x34\\x70\\xfb\\x16\\x79\\x99\\x6f\\x91\\x97\\x45\\x5e\\x16\\x0d\\xdc\\xeb\\xba\\x8c\\x06\\xee\\x2d\\x3b\\x8a\\x06\\xee\\x68\\xe0\\x6e\\xb5\\x68\\xe0\\x8e\\x06\\xee\\x68\\xe0\\x8e\\x06\\xee\\x15\\x2d\\x8a\\xd9\\x3b\\x76\\x1a\\xc5\\xec\\x35\\xed\\xd3\\x16\\xb3\\xa3\\x81\\x3b\\x52\\xab\\x48\\xad\\x22\\xb5\\x7a\\x1a\\xd4\\x6a\\x7f\\x03\\x77\\x92\\x01\\x97\\xcb\\x15\\xdd\\xb9\\x3c\\x09\\x7c\\xaf\\x71\\xb5\\x2f\\xe5\\x97\\xd0\\xaf\\x43\\x98\\xf0\\xa9\\x50\\xa5\\xae\\x0b\\x8a\\x9d\\x5f\\x7f\\xc7\\xc6\\x60\\x8d\\xc3\\x02\\x58\\x7e\\xf9\\xc8\\x9e\\x49\\xf9\\x20\\xf9\\x30\\x5b\\xda\\xf1\\x43\\xa4\\xc4\\x7f\\xb9\\xde\\xa0\\x3f\\x54\\xca\\xad\\x6e\\x11\\x62\\x28\\xd7\\x07\\x39\\x79\\x9b\\xb8\\xff\\x83\\x55\\x7a\\xc7\\xf2\\xe0\\xff\\xf3\\xb7\\x17\\x5d\\x85\\xfc\\xe3\\x2d\\x40\\x55\\xaf\\xbe\\x60\\x35\\x56\\xd8\\xf4\\x35\\x31\\xdf\\xdc\\x49\\x48\\x31\\x19\\x34\\x94\\xf7\\x77\\x87\\x5e\\x24\\xc2\\x66\\xb3\\x6a\\xe0\\xa5\\x17\\xda\\x3d\\x9d\\xd4\\x81\\xf3\\xb7\\x17\\x9b\\xbb\\x54\\xc2\\x06\\x7c\\x08\\xef\\x49\\xf4\\x8d\\x44\\xdf\\x48\\xd5\\xa2\\x18\\xb4\\x63\\xa7\\x51\\x0c\\x5a\\xd3\\x3e\\x6d\\x31\\xe8\\xb1\\xfb\\x12\\xa2\\x07\\x80\\x45\\x0f\\x40\\x78\\x2d\\x7a\\x00\\xa2\\x07\\xa0\\x1b\\x30\\x45\\x0f\\x40\\xf4\\x00\\xac\\x7f\\x29\\x0a\\x93\\x3b\\x76\\x1a\\x85\\xc9\\x35\\xed\\xd3\\x16\\x26\\xa3\\x07\\x20\\x52\\xab\\x48\\xad\\x22\\xb5\\x7a\\x1a\\xd4\\xea\\x29\\x86\\xb8\\x47\\x43\\x6c\\x34\\xc4\\x46\\x43\\x6c\\xe4\\x46\\x91\\x1b\\x3d\\xd0\\x9e\\x1c\\x37\\x8a\\x86\\xd8\\x6d\\x3b\\x8a\\x86\\xd8\\x68\\x88\\x5d\\xd5\\xa2\\x21\\x36\\x1a\\x62\\xa3\\x21\\x36\\x1a\\x62\\xd7\\xb7\\x28\\x4c\\x62\\x8b\\xc2\\xe4\\x03\\xed\\xc9\\x09\\x93\\xd1\\x10\\x1b\\xa9\\x55\\xa4\\x56\\x91\\x5a\\x3d\\x0d\\x6a\\xb5\\xbf\\x21\\xf6\\x81\\x93\\xd4\\x42\\x99\\xa6\\xfd\\xd4\\x4b\\x8e\\x21\\x1e\\x18\\x2b\\xfb\\xfb\\x1b\\xdf\\xe8\\x0a\\xac\\x70\\xc1\\x7d\\x8f\\x65\\x22\\x17\\xa1\\x6e\\xbb\\xd2\\x0e\\x3b\\xfa\\x09\\x37\\x60\\x16\\xfa\\x58\\x32\\xfe\\xfa\\xb9\\xaf\\x3f\\xa9\\x6b\\xef\\x61\\xa9\\x02\\x99\\x85\\x0c\\xfd\\x78\\x5c\\xd9\\x7a\\x1a\\x22\\xd9\\x00\\x76\\x6e\\x7c\\xf7\\x62\\x7d\\x6f\\xed\\xc3\\xcb\\xde\\xe1\\x8a\\xff\\x07\\xc9\\xf7\\xc3\\xd7\\xaa\\x0f\\xb9\\x81\\xdf\\xfd\\x66\\xe1\\x36\\x90\\xe6\\x2b\\x39\\xa4\\x82\\xdb\\xdd\\x6f\\x3d\\xaf\\x87\\x58\\x8d\\xb9\\x1b\\x9c\\x80\\x6a\\x1a\\x3b\\xf6\\xe2\\xaf\\x2b\\x78\\x70\\xef\\x1c\\x82\\xa5\\x97\\xf4\\x72\\xb8\\x35\\x7f\\xfe\\xb6\\xeb\\x9a\\xff\\xca\\x15\\xd7\\xba\\x54\\x9a\\xd5\\xdd\\x04\\xc2\\x35\\x71\\xfe\\x42\\x07\\x13\\x3a\\x15\\xa6\\xca\\x75\\x58\\x7a\\x2b\\xe1\\x9e\\xc9\\x0b\\x61\\x9c\\x25\\x8f\\x1f\\xda\\xb4\\x65\\x77\\x5a\\x2c\\x05\\x56\\x00\\xd0\\x05\\xf9\\x55\\x2e\\xaa\\x22\\x0e\\xf3\\x10\\x2b\\xb8\\x76\\x7c\\x22\\xf8\\x5f\\x50\\x74\\x69\\xbc\\x3d\\x07\\xef\\xf5\\x77\\x34\\xae\\x95\\x57\\x1e\\x96\\x53\\xfa\\x8d\\x5a\\x13\\xab\\x7c\\x3e\\x9b\\x88\\x27\\xfe\\x66\\xa9\\x2b\\xd0\\xb9\\x30\\x66\\x55\\x7a\\x46\\x7b\\xea\\x0f\\x31\\x8f\\x0d\\x98\\xc6\\x0a\\xf8\\x87\\x15\\x35\\xa6\\x53\\x09\\x91\\xa4\\xf6\\x0f\\x79\\xc2\\x74\\x99\\xf9\\xab\\xb5\\xfd\\xa5\\x12\\x8c\\x27\\x89\\x2a\\xa5\\x65\\x12\\x20\\xa5\\xc4\\x8f\\x65\\xb8\\xba\\x01\\xcb\\xd9\\x40\\x8a\\xdc\\x54\\x86\\xec\\xd3\\x3c\\x1f\\x7c\\xcb\\xaf\\xe1\\x8c\\x96\\xb0\\xf4\\x9a\\x92\\x66\\xdb\\x5c\\xe6\\xc4\\xe1\\x1f\\xe6\\xdd\\xdb\\x08\\x04\\x1b\\x8b\\x03\\x6d\\x43\\x97\\xca\\x44\\x32\\x7b\\x5b\\x66\\xe0\\x2f\\x5e\\x15\\x92\\xf8\\x56\\xe5\\x0a\\x6b\\x2a\\x0a\\x05\\xbe\\x8d\\xb3\\xa7\\x1b\\x9f\\x53\\x05\\x64\\xa0\\xf2\\xa5\\x5d\\x5a\\x9f\\x87\\xbb\\x1f\\xe9\\xc2\\x24\\xf7\\x11\\xe3\\x45\\x91\\x61\\xe2\\x95\\x72\\xbc\\xfb\\x6e\\x22\\x92\\x49\\x7d\\x6b\\xed\\xb2\\xd7\\x36\\x97\\xe1\\x36\\x52\\x32\\xd8\\x56\\x8a\\x06\\x0b\\xc6\\xd3\\xe1\\x43\\xa8\\xc2\\xb6\\xd4\\x38\\x18\\x5d\\xbc\\xf2\\xb5\\x56\\x65\\xb1\\xe1\\xeb\\x8b\\x76\\x37\\xfa\\x3a\\xdc\\x69\\xd9\\x14\\x47\\xc2\\x43\\xef\\xcc\\x0c\\xf7\\xf0\\x93\\x71\\xce\\x1b\\xeb\\x07\\x8c\\x5d\\x8e\\x58\\x5e\\x66\\x56\\x14\\x19\\x7e\\x42\\xf5\\x62\\xe8\\xea\\xef\\x8a\\x6f\\xf4\\x18\\x97\\xb3\\xe0\\x1b\\xf5\\x97\\x2f\\x41\\xca\\xf8\\xd8\\xf5\\x68\\xc3\\x95\\xec\\x74\\x6b\\x53\\x99\\x3b\\x19\\xa4\\x61\\xf6\\xc3\\x0b\\x3e\\xdd\\xf7\\x55\\xef\\xec\\x4e\\x64\\x19\\x5e\\x8a\\x9f\\x65\\xea\\x0e\\xd2\\x01\\x3b\\x38\\x98\\x27\\xe5\\x89\\xd2\\x8d\\xf9\\x20\\x31\\x39\\xf8\\xa2\\xf5\\x96\\xa3\\x1c\\xf5\\x84\\x37\\xc1\\x11\\xb6\\xb5\\x78\\xcd\\xb6\\x13\\xb1\\xd9\\xf6\\xca\\x04\\x63\\x52\\xc9\\x60\\x36\\xfe\\xf6\\xed\\xcb\\xdd\\x10\\xe1\\x75\\xbb\\x0f\\x7f\\x4b\\x17\\x58\\xb7\\x2d\\x05\\xd7\\x56\\xf0\\x8c\\x95\\x3a\\x33\\x84\\x0b\\xdc\\x09\\xcc\\x3a\\x5c\\x73\\x36\\xe1\\xe8\\xf7\\x4e\\xc0\\xd0\\x7d\\x5a\\xec\\x0b\\xda\\x7d\\xbf\\x39\\x74\\xc6\\x95\\xcc\\x66\\x8c\\xd3\\xd6\\x8c\\xca\\x2c\\xeb\\xb1\\x91\\x90\\xdc\\x91\\x6e\\x28\\x42\\xee\\x9d\\xd3\\x44\\xd9\\xb5\\x90\\x09\\xb8\\x35\\xf5\\x2b\\xe1\\x04\\x67\\xe4\\x7a\\x74\\x34\\xa2\\x3a\\xe8\\xa9\\xbf\\x9a\\xd9\\xdb\\x1d\\x8c\\x1f\\xc2\\x1d\\xfa\\x04\\x2f\\x94\\x75\\x52\\xad\\x17\\x7b\\xde\\xaa\\x0c\\xbd\\x35\\x95\\x49\\x19\\x6f\\x09\\xe3\\xcd\\xc7\\xff\\x23\\x24\\xaa\\x7b\\xec\\x2d\\x32\\x1f\\xa7\\x36\\x82\\xb0\\x13\\xa7\\x45\\x16\\x45\\x86\\x17\\xc8\\x3b\\x64\\xa9\\x91\\xf2\\xc8\\x94\\xc9\\xc4\\x2d\\xe9\\xa0\\x50\\xa9\\x39\\x70\\xa4\\xe8\\xc0\\x40\\xa2\\xc1\\x9a\\x83\\x63\\xf7\\xd7\\xfc\\x1a\\x70\\x7d\\xcd\\xef\\x4e\\x78\\x21\\x0e\\x8e\\x7b\\x0c\\x01\\x84\\x57\\x90\\x29\\x3b\\x79\\xba\\x78\\x18\\xd6\\xda\\xba\\xf9\\xf2\\xa1\\x36\\x77\\xbf\\x6e\\xa3\\x07\\x7f\\x9f\\x96\\x2a\\xe8\\x7a\\x2a\\x47\\xe7\\x2d\\x60\\x66\\xa6\\x43\\x4a\\xba\\x39\\xbb\\xf6\\xb8\\xcd\\x11\\x7c\\xc6\\xce\\x24\\x03\\xf2\\x91\\x80\\x65\\x39\\x70\\xe9\\xdf\\x86\\x29\\xe8\\x99\\x9d\\xa0\\xdb\\xc4\\x54\\x04\\xe4\\xc9\\x03\\x7d\\x3f\\x80\\xfb\\x03\\x1f\\x80\\x5b\\x23\\x39\\xdd\\x79\\x38\\x0f\\xdc\\xc3\\x2f\\x0e\\xe7\\x09\\x69\\xcd\\x11\\x9e\\x2c\\x28\\x91\\x45\\xef\\x04\\xc6\\xef\\xdc\\x97\\x6d\\x10\\xd2\\x4f\\x44\\x2d\\x2b\\xfa\\xf1\\xf2\\x25\\xdd\\x6f\\xe8\\x61\\xf5\\x8d\\x90\\xa9\\xa9\\xea\\xd9\\xa5\\xd5\\x3d\\xd6\\x0e\\xde\\x4b\\x81\\x8c\\x33\\x7c\\x8a\\x00\\x5e\\x14\\x81\\x37\\x15\\x5b\\x1f\\xe8\\xbe\\xa1\\x23\\x3d\\x06\\xb5\\x06\\xef\\x4b\\x6c\\x49\\x4a\\x8e\\x4e\\xf5\\xc8\\x79\\xe7\\x44\\x90\\x8c\\x0f\\x21\\x33\\xde\\xe0\\x02\\x8d\\xe9\\xb3\\xb3\\x97\\xaf\\xaa\\x7b\\x43\\xf1\\x1e\\xee\\x0f\\xad\\xcc\\x6c\\x10\\x05\\xb0\\x70\\xfb\\xea\\x62\\xdb\\x5c\\x7e\\x45\\x50\\x6c\\x67\\x56\\x67\\xd7\\x60\\xe9\\x98\\xe5\\xbc\\x70\\xa7\\x8c\\xfa\\x58\\x6a\\x15\\x7e\\x89\\x90\\x7e\\xf8\\xb0\\x6c\\x25\\xf7\\x6f\\x7e\\x5b\\xe2\\xb2\\x41\\x36\\x3a\\x2a\\x9b\\x45\\x1a\\x6c\\x73\\xf6\\xd6\\x58\\x49\\xea\\x36\\x67\\x54\\x6d\\x21\\xb4\\xd7\\x0d\\xbc\\x34\\x9f\\xf0\\xa6\\xb1\\x35\\x05\\x43\\xa5\\x18\\xa8\\xf0\\x85\\x0e\\xbf\\xd7\\x5d\\x74\\xbc\\x05\\xdb\\x28\\x5e\\x4e\\xf7\\xce\\x20\\xb1\\x6a\\x7d\\xf1\\xcf\\xf0\\xb2\\x85\\xbc\\xc8\\x1e\\x3a\\x79\\x6c\\x6b\\x25\\x2d\\x17\\xf2\\x2d\\xf0\\x74\\x76\\x0d\\x89\\x92\\xe9\\x86\\x04\\xb6\\xb5\\x1f\\xaf\\x84\\x14\\x79\\x99\\x33\\x59\\xe6\\x43\\x40\\x10\\x1b\\xea\\x0b\\x09\\x09\\x29\\xc0\\x9c\\x49\\xb8\\xcb\\x66\\xe1\\x12\\x7f\\x56\\xa8\\x34\\xd0\\x93\\xa1\\x53\\xd8\\x78\\x3a\\xc3\\x9b\\x47\\xb1\\x4c\\xb6\\x9c\\xb9\\x4e\\x84\\xad\\xb9\\x8f\\x66\\x89\\xe6\\xc6\\x89\\x45\\x3d\\xec\\x54\\x58\\xc7\\xb1\\x86\\x80\\x5e\\x3a\\x91\\x82\\xdb\\x63\\x3e\\xe5\\x22\\x73\\xa2\\xf5\\x80\\x5d\\xc0\\x88\\x97\\x19\\x5e\\xa0\\xcb\\x9e\\xb1\\x23\\x37\\x58\\xd0\\xc9\\x96\\x7d\\xe0\\xc4\\x5d\\xa3\\x9c\\x36\\x6f\\x7c\\x55\\x0d\\x9c\\xd0\\xf1\\x16\\x7e\\x87\\x4d\\xaa\\xb8\\x86\\xb6\\x69\\x35\\xd7\\xd0\\x0a\\x5e\\x9a\\x4d\\x55\\xf9\\xd6\\xc6\\x5c\\xca\\xd4\\x9d\\x87\\xa6\\x24\\xda\\x20\\xe9\\xc2\\xf8\\x9e\\x37\\x63\\xd9\\xeb\\xab\\xad\\x2c\\x99\\xb5\\x56\\x63\\x0d\\xc6\\x5c\\x00\\x4f\\x33\\x21\\x61\\x77\\xfc\\xba\\x99\\x00\\xcb\\xf9\\x3d\\xe2\\x98\\x15\\x39\\x38\\x49\\xa4\\x89\\x61\\xbc\\xb9\\x2a\\xab\\x58\\xce\\x6f\\xa1\\x1a\\x9e\\x0d\\x61\\x84\\x17\\x24\\xe3\\x82\\x1b\\xbb\\x4f\\xf8\\x33\\xe2\\x22\\x73\\x1a\\xfa\\x4d\\x1b\\x36\\x78\\x57\\xb2\\xca\\x32\\xd0\\x84\\x38\\xee\\x6f\\x21\\x4b\\x0c\\xb1\\x2b\\xb4\\x42\\x65\\x92\\x3e\\x6d\\xf2\\x78\\xe4\\xa1\\xdc\\xbd\\x4c\\x74\\x38\\xdc\\xa5\\x7b\\x35\\x07\\x8a\\x17\\xf7\\x09\\x19\\x0a\\x35\\x70\\x83\\xaf\\x11\\x6e\\x9a\\x52\\x8f\\x9c\\xea\\x18\\x34\\xce\\xc6\\x84\\xfc\\x25\\xec\\xec\\xb5\\xb2\\x3e\\x92\\xaf\\x5a\\x20\\x7e\\xed\\xaf\\x88\\x06\\x63\\x45\\x8e\\x07\\x2c\\x2d\\x75\\xb8\\xb0\\x1a\\x61\\xc6\\x97\\x6f\\x7d\\xeb\\xa8\\xfc\\xee\\xd9\\xb3\\x0d\\xe5\\xb7\\xf7\\x8f\\xf4\\x1a\\x50\\x53\\xde\\x05\\x5f\\x5e\\x57\\x74\\x28\\x90\\x7f\\xa7\\x02\\xbb\\x3d\\x16\\x5e\\x0c\\xc6\\x9b\\xb7\\x41\\xa3\\xc7\\x55\\x18\\x2b\\xe4\\xb8\\x14\\x66\\xc2\\x86\\x60\\xef\\x00\\x24\\x83\\x7b\\xaa\\xa9\\xc3\\xfe\\x05\\x5a\\xe1\\xa6\\x3a\\xf0\\xd6\\x6e\\x86\\x16\\xd0\\x9e\\x3f\\x1e\\x88\\x4d\\x85\\x11\\x4a\\xfe\\x45\\x18\\xab\\xf4\\xec\\xa5\\xc8\\xc5\\x03\\x05\\xa8\\x43\\x5b\\x74\\xfb\\x55\\x10\\x54\\x59\\xca\\xde\\xd2\\x56\\x5c\\x03\\x2d\\x58\\x03\\x5a\\x41\\xad\\x22\\xf5\\x94\\xb9\\x73\\x32\\xe4\\xc9\\xed\\x7b\\x03\\xf0\\xb3\\xc7\\x02\\xe1\\xc0\\xae\\x77\\x80\\x2a\\xca\\x7b\\x55\\x07\\x48\\xb6\\x08\\x29\\x5f\\xdc\\x13\\x7c\\x5a\\x50\\xbe\\x9b\\x28\\x03\\xf8\\x02\\x19\\x2a\\xf1\\xb3\\xe0\\x58\\x10\\xa6\\x22\\x18\\xe8\\x96\\x95\\x60\\x18\\x1f\\x8d\\xda\\x6f\\xd4\\x87\\x1d\\x25\\xcf\\xbc\\x34\\x96\\xe5\\xdc\\x26\\x13\\x32\\x65\\xa9\\xb4\\x12\\x27\\x0e\\x8d\\x17\\xfb\\xb7\\x81\\xf2\\xc6\\x86\\xe8\\xed\\x4d\\xc6\\x8c\\xe6\\xf9\\xe2\\xde\\xe9\\x96\\x0f\\x7a\\x84\\xda\\xad\\x05\\xf2\\xf9\\x6e\\xda\\x1a\\x70\\xd6\\xde\\x10\\x2f\\xb7\\xe5\\x74\\x79\\xff\\x0d\\x1a\\x91\\xeb\\x5f\\x70\\x17\\xce\\x5e\\x5f\\x6c\\x6e\\x8a\\xd9\\x45\\xc1\\xdd\\x5a\\xc5\\x9d\\x37\\x97\\xaf\\x59\\x54\\x30\\x99\\xfa\\x27\\x6d\\x9b\\x39\\x6a\\x28\\xa6\\xc7\\x38\\xbb\\x85\\x59\\x8f\\xb8\\xd8\\xfc\\x85\\xf9\\x1a\\x32\\x2f\\x49\\x00\\xde\\x1b\\xef\\x5e\\xa2\\xef\\x36\\x07\\xc9\\x0e\\xd8\\x43\\x6d\\x3b\\x77\\x46\\x68\\x7d\\x37\\xd1\\x2d\\xbf\\x08\\x8b\\xde\\xe2\\xb3\\xed\\x11\\x9c\\xda\\x2d\\xcc\\xb6\\xfb\\x60\\x6e\\xbb\\xdd\\x2e\\x78\\xdd\\x87\\xf6\\xdd\\xfd\\x50\\x09\\x7a\\xd5\\x56\\x6f\\xe7\\x67\\x6a\\xb6\\xad\\x4d\\x54\\xa1\\x05\\x20\\xee\\xb5\\xbc\\x0a\\xfd\\x9a\\x56\\x26\\xb7\\xc6\\x43\\x43\\xc8\\xe8\\xce\\xf4\\x44\\x14\\x94\\xf5\\xe0\\x9d\\x01\\x1e\\x23\\xd9\\x77\\x3c\\x13\\x69\\xd5\\x05\\x9d\\xdf\\x4b\\xd9\\x73\\xe2\\x93\\xfb\\x0f\\x12\\x5d\\x12\\xd7\\x2e\\x14\\x98\\xd7\\xca\\xe2\\x2f\\x1f\\x0c\\x40\\x34\\xcd\\xbd\\xc0\\x43\\x5d\\x78\\x2b\\x34\\x52\\x19\\x54\\xbc\\x28\\xe2\\x3e\\x80\\xe1\\x72\\x3e\\x72\\xc7\\xb0\\x4b\\xc9\\x94\\x0e\\x70\\x70\\x0f\\x7d\\x47\\xd4\\x05\\xf2\\x89\\x21\\x39\\x38\\xd0\\x3e\\xbd\\xb4\\x0f\\x0f\\x3e\\xa5\\x5b\\xd0\\x5b\\xd3\\x9d\\xef\\x0a\\xe5\\x03\\x7a\\x82\\x3a\\x56\\x91\\xa1\\xb4\\xeb\\x45\\x55\\x1e\\x1c\\xe5\\x22\\x61\\x39\\xe8\\x31\\x7a\\x5c\\x92\\x8d\\x3d\\x0e\\xed\\x4d\\xd9\\x8e\\xee\\x52\\xdb\\x9a\\xfa\\x36\\x07\\xdc\\x0a\\x0b\\x90\\x35\\x91\\x09\\x68\\x1f\\xe6\\x46\\x3d\\xb4\\x4c\\x4e\\xff\\x76\\x14\\x1c\\xf7\\xe0\\x3f\\xac\\xe0\\x42\\x9b\\x01\\x3b\\x63\\x46\\xc8\\x71\\x06\\xad\\x67\\x5e\\xc3\\x68\\x76\\xe3\\x7a\\x10\\x86\\x39\\x52\\x3b\\xe5\\x99\\xd7\\xa5\\xb8\\x64\\x40\\x36\\x2b\\xd7\\xfb\\x3c\\x4b\\xed\\x79\\x49\\xc5\\x51\\x9e\\xca\\xd1\\x75\\x70\\x0b\\xb3\\x83\\xde\\x02\\xd2\\x1c\\x5c\\xca\\x03\\xe2\\x2d\\x0b\\x68\\x52\\x31\\x22\\xf4\\x91\\x1d\\xe0\\xb3\\x83\\x2e\\xb9\\xf0\\x96\\x0c\\x67\\x57\\x3b\\x5a\\x7b\\xd0\\x8d\\x31\\x22\\xc4\\x87\\xec\\x28\\xac\\xb7\\xb4\\x44\\x1f\\x15\\x65\\x15\\x2b\\x0d\\x90\\xb4\\x8e\\xa7\\x8c\\x41\\x90\\x33\\x51\\xaa\\x44\\xc5\\x54\\xc2\\x1d\\x4a\\x8f\\x8f\\x46\\xf0\\x73\\x9a\\x84\\x90\\xe3\\x6f\\x8b\\x94\\xdb\\x8d\\xc2\\x73\\xa9\\xb5\\x20\\x72\\xf8\\x96\\x3a\\x61\\x25\\xf6\\xe2\\x70\\x6b\\x24\\xc6\\xac\\xe0\\x9a\\xe7\\x66\\xc0\\xae\\x7c\\x3d\\x55\\xc4\\x34\\x31\\x6a\\xda\\x12\\x3d\\xec\\x6e\\x66\\x05\\xb0\\x3f\\xb1\\xb7\\xcd\\xb9\\x0c\\x58\\xbf\\xdf\\x67\\x37\\x6f\\x2e\\xde\\x9c\\x32\\xfa\\x85\\xa4\\x6c\\xab\\xd8\\x48\\xa1\\x12\\xa4\\x4a\\xed\\x86\\x9a\\x82\\x44\\xc5\\xdf\\xc9\\xf7\\x4a\\xc2\\x9b\\x91\\x3b\\x21\\xdc\\xc2\\x14\\x34\\xbb\\x73\\x5b\\x95\\x88\\x14\\x2a\\xeb\\xd5\\xe0\\xf0\\xfd\\xe2\\xf1\\x6e\\x92\\x49\\xce\\xef\\xaf\\x4b\\x3d\\xde\\x62\\x03\\xd8\\xc2\\x26\\x34\\x4d\\x36\\xb5\\x32\\x89\\xa8\\xd7\\xcc\\x3d\\x37\\xc9\\x04\\xd2\\x32\\x83\\x94\\xf1\\xa1\\x9a\\x42\\xcb\\x64\\xdb\\xfe\\x0c\\x59\\x7a\\x09\\xe1\\x43\\xc7\\xf3\\x86\\x46\\x65\\xa5\\xad\\x94\\xd5\\x23\\xb8\\x3f\\x65\\xbf\\x45\\xd7\\x36\\x67\\x05\\xe8\\x04\\xa4\\xe5\\x63\\x98\\x37\\x03\\xd0\\x7b\\xcf\\x9f\\xfd\\xd7\\xb1\\xe7\\x47\\xae\\x47\\x6f\\x3d\\x79\\xe6\\x30\\xe2\\x15\\xbf\\xff\\x56\\xd6\\xa6\\x41\\x61\\xd8\\xb3\\x01\\x3b\\x9b\\x1b\\x0c\\xbf\\xcb\\x92\\x32\\x43\\x5b\\x0b\\xba\\xeb\\x1b\\x43\\x0e\\x67\\x4c\\xab\\x12\\x1d\\xf6\\xac\\x2c\\xda\\xda\\xec\\xaf\\x7e\\xfb\\x5f\\x4e\\xe9\\xe3\\x79\\x91\\xc1\\x69\\x28\\xc3\\x4c\\x6a\\xb3\\x93\\x61\\xac\\x62\\xbf\\x7e\\xf6\\x5f\\x44\\x3d\\xdd\\xf9\\xac\\xb5\\xc2\\x1a\\x66\\xdc\\x01\\xac\\x2c\\x98\\xc8\\x29\\x9c\\x13\\xb2\\x59\\x5d\\xcf\\x59\\xb7\\xd1\\xdf\\x58\\xae\\xad\\xe9\\x31\\xf4\\xea\\x57\\xc2\\xa1\\x55\\x96\\x67\\x73\\x5a\\x3e\\x6a\\xe1\\x70\\x47\\x40\\x4a\\x15\\xc2\\x04\\xd0\\x50\\xc5\\x9e\\xff\\xfa\\xd9\\x7f\\x2d\\x9a\\x53\\xde\\xc8\\x04\\xf0\\x4b\\xfc\\x02\\xc3\\x2c\\x86\\x4e\\xb9\\xbf\\x15\\x59\\x06\\x69\\xef\\xc1\\xe9\\x8f\\x4a\\x6d\\x27\\xa0\\x7b\\x0c\\xa4\\x09\\xc6\\x2a\\x37\\xbf\\xb9\\xb9\\x61\\xef\\xba\\x94\\x12\\x65\\x04\\xb2\\x0e\\xa3\\x45\\xab\\x61\\xe1\\xf2\\x8b\\x75\\x8c\\xd0\\xb2\\x5c\\x19\\xbb\\x7c\\xca\\x9b\\x1f\\x37\\xd7\\xb8\\x9c\\xbd\\x19\\x6d\\x2b\\x0e\\xf4\\x77\\x30\\x43\\x2c\\x7e\\xbd\\x83\\x48\\x79\\xdf\\xbf\\xad\\x12\\x7f\\xfb\\x42\\xda\\xbe\\xd2\\x7d\\xea\\xe6\\x94\\x59\\x5d\\x3e\\xec\\x35\\xa8\\x5b\\xde\\x3a\\x01\\x1f\\x80\\x0c\\x94\\x8d\\xf3\\xb6\\xb0\\xab\\xef\\xe5\\xe4\\xef\\x7e\\x9e\\x53\\x75\\x27\\x57\\x53\\x0e\\x24\\x9c\\x9e\\x66\\xec\\x78\\xea\\xdb\\x16\\xb7\\xb9\\x63\\xe3\\x46\\x77\\x6f\\xff\\x9f\\x45\\xec\\xde\\x82\\x1c\\xf8\\xb3\\x5b\\x9d\\x76\\x27\\x57\\xa1\\xc7\\xa3\\xb7\\xc1\\xe8\\xd5\\xb1\\x25\\xce\\x47\\x36\\x27\\xf7\\x02\\x0d\\xb3\\x84\\x72\\x2d\\x9c\\xf0\\x25\\x14\\x88\\xe6\\x51\\x3b\\x64\\x2c\\x46\\x14\\xb8\\x73\\x6e\\x56\\x1e\\xf4\\x0c\\xb8\\xb1\\xcb\\x40\\x11\\x0f\\xfa\\xc3\\x6d\\x7d\\x12\\xc0\\x7c\\x6b\\x0b\\x9d\\x4e\\x42\\x42\\x90\\xd7\\x36\\xc6\\x73\\x42\\x94\\x83\\xb7\\x40\\x1e\\x3e\\x0a\\x38\\x6b\\x09\\x51\\x07\\xd5\\x91\\x70\\xfb\\xd7\\x96\\xaf\\xde\\x57\\xd8\\x4c\\x30\\x72\\xee\\x22\\x5a\\xfb\\x4f\\x1b\\xc1\\xc1\\xde\\x74\\xea\\x89\\x57\\xe5\\x51\\x24\\x97\\x26\\xe9\\x2b\\x14\\xe5\\xe7\\x0f\\x46\\x18\\x7d\\x60\\x0a\\x48\\x06\\x1a\\xf0\\xf4\\x51\\x34\\x32\\x29\\x40\\xa8\\x17\\x9d\\x65\\x77\\x7c\\x66\\x0e\\x1e\\x8d\\x14\\x9e\\x83\\xe5\\xeb\\x13\\x4d\\xe6\\x5b\\x9b\\xe8\\x5f\\x5b\\x2e\\x53\\xae\\x53\\x3f\\xcb\\xc3\\x43\\x53\\x75\\x39\\x60\\xaf\\xd0\\x17\\x27\\x47\\xea\\x94\\x4d\\xac\\x2d\\xcc\\xe9\\xc9\\xc9\\x58\\xd8\\xc1\\xed\\xef\\xcd\\x40\\xa8\\x93\\x44\\xe5\\x79\\x29\\x85\\x9d\\x9d\\xa0\\x03\\x4e\\x0c\\x4b\\xab\\xb4\\x39\\x49\\x61\\x0a\\xd9\\x89\\x11\\xe3\\x3e\\xd7\\xc9\\x44\\x58\\x48\\x6c\\xa9\\xe1\\x84\\x17\\xa2\\x5f\\xcb\\xdc\\x66\\x90\\xa7\\xbf\\x08\\x03\\xbd\\x67\\xc1\\xba\\x75\\x06\\xd1\\x3a\\xa5\\xa7\\xd0\\x2f\\xe5\\xad\\x54\\x77\\xb2\\x8f\\x9a\\xb0\\xd9\\xea\\x34\\x6e\\x16\\x05\\x11\\xda\\x1c\\xbc\\xb7\\x09\\x7c\\x28\\x54\\xfa\\xde\\x37\\xc1\\x2d\\xa6\\xcf\\x65\\xda\\x27\\xa7\\xe5\\x7b\\xde\\x8b\\x5d\\x6c\\xc3\\xfd\\x3a\\xb0\\x60\\x93\\xa8\\x77\\x6a\\xbb\\x69\\x53\\x3c\\xb1\\x62\\x0a\\x3b\\x39\\xc1\\x43\\x6b\\x6d\\xf7\\x9b\\x10\\x70\\x9a\\x96\\x9a\\x76\\xbc\\xe1\\x0d\\x0f\\xbe\\x9d\\x9c\\xcf\\x50\\x56\\xc2\\xb1\\x99\\x22\\x51\\x40\\xaa\\x14\\xbc\\xe5\\x74\\x8a\\xa6\\x81\\x6b\\x47\\x8e\\x6e\\x9c\\x28\\xed\\x7d\\xe4\\x68\\x37\\x9e\\x19\\x0b\\x39\\x11\\x37\\xfa\\x3e\\x9b\\x31\\xab\\x67\\xe4\\x58\\xd7\\xb7\\x4e\\x79\\xf5\\x9e\\x6f\\xa7\\x31\\xdc\\xe2\\x7b\\xc6\\xa8\\x44\\xa0\\xe8\\x54\\xc3\\x35\\xc8\\x6d\\xc1\\x06\\xc8\\x59\\xa1\\x8c\\xc0\\xb1\\x3d\\xcf\\xdc\\xce\\xb2\\xb7\\x3b\\xbb\\x6d\\xb8\\xf9\\x7e\\xf7\\x9b\\x6d\\xb6\\x6e\\x84\\x55\\x4e\\xb6\\xb4\\xd2\\xb7\\x23\\x30\\x46\\xcd\\x2c\\x03\\xbf\\x3d\\x87\\x26\\x28\\xbe\\x4e\\xac\\x49\\x94\\x34\\x56\\x73\\xb1\\x3a\\x8f\\x6a\\x79\\xdb\\xd1\\x95\\xb2\\xbb\\xbf\\x82\\x21\\x06\\x9d\\xed\\x04\\x14\\xb6\\x3c\\x31\\x76\\x88\\x99\\x35\\x29\\x54\\xa0\\x6e\\x02\\x86\\xd2\\xac\\x42\\x2c\\xa2\\x23\\x5c\\x3b\\x9a\\x66\\x77\\x80\\x11\\xdb\\x0b\\x4e\\xf4\\x35\\x55\\x59\\x4a\\x2f\\x50\\x7a\\xbd\\xae\\xd6\\x75\\x39\\x96\\xaa\\xfa\\xf9\\xc5\\x3d\\x24\\xe5\\xa6\\x39\\xf9\\x8b\\x6d\\xc1\\x16\\x18\\x0c\\x2a\\x3e\\x6c\\x85\\x26\\xe1\\x8e\\x6e\\x78\\xe0\\xe5\\x17\\x85\\x60\\xf7\\x82\\x8c\\xe1\\x56\\x98\\x11\\xe5\\xac\\x55\\x1b\\x01\\x0d\\xc7\\x69\\x85\\xc2\\x95\\x7b\\x19\\x59\\x1c\\xa5\\x4e\\x08\\x8b\\xe4\\x26\\x99\\x28\\x65\\xdc\\x29\\xc7\\xfd\\xc4\\x7e\\xa7\\x42\\x91\\xcf\\x10\\x13\\x68\\x34\\xcb\\x1d\\x8d\\x09\\x89\\x34\\x75\\xf7\\x24\\x38\\xd5\\x9f\\x09\\x43\\x2a\\x7c\\x05\\xc1\\xe0\\xe5\\x72\\xdd\\xa0\\xe1\\xd2\\xfd\\x31\\x46\\xa9\\xcb\\x58\\x66\\xca\\xdc\\x75\\x7a\\x07\\x62\\x3c\\xb1\\xa6\\xc7\\xc4\\x00\\x06\\x88\\x35\\xc0\\x93\\x49\\xa3\\xdb\\x1c\\xc0\\xb6\\xee\\x6d\\x6a\\xa2\\x5a\\xd3\\xca\\x7c\\x54\\x65\\x45\\xf8\\x54\\xa0\\x5e\\xc5\\x63\\xe6\\xf7\\x72\\x29\\xb8\\x7a\\x0c\\x6c\\x32\\x38\\xee\\xb1\\x3a\\x65\\xdf\\xcd\\x71\\x38\\x63\\xc2\\x82\\xa3\\xd9\\xa8\\xcb\\x68\\x55\\x8e\\x69\\x25\\x10\\x62\\x42\\x71\\x5e\\x55\\xca\\x08\\x7a\\x61\\x53\\xd4\\x39\\x0f\\x68\\x71\\x07\\x6e\\xdf\\x70\\xe6\\x65\\x1e\\x8a\\x2a\\xe1\\xfa\\xd0\\x2c\\x0f\\x55\\x62\\x91\\x06\\x53\\x28\\xd2\\x56\\xe7\\x0d\\xf6\\xff\\x5d\\x7d\\x74\\x64\\x8e\\x6b\\x60\\x4e\\xc4\\x78\\x12\\x60\\xc9\\x3d\\x23\\x68\\xef\\xc1\\xf6\\x67\\x8f\\xed\\xe5\\x8b\\xa1\\xb6\\xa3\\x47\\x86\\x5a\\xdb\\x37\\x1e\\xf2\\x2d\\x6a\\xac\\x6a\\xec\\xbf\\x05\\x9d\\x57\\x50\\x44\\x14\\x41\\x92\\xe1\\xed\\xe4\\xe1\\x8a\\x2d\\x8f\\x63\\xec\\x19\\x3b\\x42\\x24\\x13\\xf6\\xd0\\x20\\xc2\\xf7\\x55\\x71\\x3c\\x60\\x67\\x4c\\x96\\xd5\\x99\\x5b\\x37\\x80\\x54\\x55\\xff\\xbe\\x23\\x37\\xa8\\x51\\x75\\x5f\\x3b\\xae\\x78\\x2f\\x72\\x47\\x6d\\x37\\x4f\\x7b\\xb3\\xf5\\x3d\\x04\\xe0\\xe1\\xa2\\xa1\\xeb\\x3a\\x21\\x58\\xef\\xd8\\xc1\\x7e\\xa4\\x3b\\xf4\\x11\\x56\\xb1\\x7b\\x1f\\x0b\\x01\\x1a\\x78\\x5c\\xeb\\x28\\x0c\\xd0\\x79\\xaf\\x29\\x3d\\x55\\x07\\xb2\\x7d\\x8a\\x09\\x16\\xbb\\x62\\x05\\xeb\\x06\\x33\\x58\\x47\\x70\\x65\\x7b\\x45\\xf8\\x2c\\x6f\\xf3\\x61\\x30\\x21\\x0b\\xab\\x05\\xed\\x16\\x91\\x1f\\xce\\xf0\\xe9\\x96\\xc1\\x4f\\xab\\xdb\\xbe\\x94\\xae\\x6e\\x7b\\xd1\\xbc\\xba\\xad\\x45\\xbc\\xc7\\x17\\x18\\xb4\\xbc\\x75\\x84\\xb6\\xd4\\xf6\\x27\\x6d\\x75\\xdb\\x3e\\xb4\\x68\\x55\\x3f\\x3b\\x04\\x1c\\x2d\\x6f\\x5d\\x9d\\x4d\\x6a\\x3b\\x04\\x27\\x2d\\x6f\\x0b\\x22\\xea\\xfb\\x89\\x55\\x5a\\xde\\x76\\x36\\xb2\\x2e\\x6f\\xbb\\xc6\\x35\\x2d\\x6f\\x73\\xa9\\x8e\\xef\\x29\\xc8\\xa9\\xd7\\x8e\\x70\\x62\\x5f\\x5b\\x3a\\xc7\\x2f\\xf7\\xe2\\x27\\x75\\xeb\\x18\\xc4\\xbb\\x45\\x46\\x2d\\x6f\\xf3\\x02\\xe0\\x13\\x89\\x92\\x5a\\xd2\\xd5\\xd7\\xd6\\x75\\xf3\\x72\\xe5\\xc7\\x94\\xe3\\x1e\\xe2\\x7c\\xbc\\x42\\xd1\\xf3\\xa9\\x37\\xc1\\x4e\\x8d\\x11\\xd9\\x85\\x06\\x2c\\x6d\\x80\\x61\\x63\\xc1\\x0e\\xf3\\x61\\x02\\xb3\\x96\\xb7\\xee\\x18\\x27\\xb5\\x8e\\xd8\\x27\\xb5\\xce\\x90\\x1b\\x05\\x9e\\xaf\\xc8\\x2e\\xfc\\x11\\x65\\x1d\\xb2\\x4c\\x47\\x59\\x27\\xca\\x3a\\x5b\\xb4\\x28\\xeb\\x6c\\xda\\xa2\\xac\\xb3\\xaa\\x45\\x59\\x67\\x49\\x8b\\xb2\\x4e\\x94\\x75\\xf6\\x6a\\x8f\\x4f\\xd6\\x21\\x4b\\x55\\x67\\x06\\xb3\\xbf\\x92\\xc1\\x75\\xde\\x42\\x86\\xd2\\x54\\x08\\x09\\x6a\\x9b\\xca\\x1c\\xef\\xbf\\xf6\\x24\\xf6\\x06\\xcd\\x6b\\x3e\\xd2\\x5d\\x73\\x39\\x06\\xf6\\xbc\\xff\\xfc\\xd9\\x86\\xe9\\x84\\xcb\\xdb\\x3e\\x41\\x3f\\xcd\\xb6\\x6d\\xea\\xe1\\x7c\\x5b\\xe5\\x91\\x78\\x6f\\xde\\x25\\x7f\\x52\\x2b\\x87\\x47\\x4b\\xc2\\x5c\\xe1\\x20\\xaa\\xaa\\x62\\xe5\\x60\\x19\\xb7\\x2d\\x83\\xb8\\xc8\\xa1\\x72\\x88\\xb6\\x52\\x98\\xeb\\x98\\x60\\x25\\xbd\\xbf\\xc3\\x6d\\xea\\x60\\xb7\\x19\\x24\\xc0\\x29\\x0e\\x7e\\x08\\xd5\\x2c\\x54\\x0e\\x94\\xa0\\x1a\\x0e\\xbd\\x9b\\x02\\x04\\x58\\xb1\\x23\\x18\\x8c\\x07\\x2c\\xa5\\x64\\x6f\\x2e\\x7d\\xcc\\xd9\\x71\\xaf\\xe9\\x1e\\xcf\\x1d\\x71\\xd5\\xf8\\x1f\\x37\\x6d\\xef\\x1f\\x87\\x29\\x48\\x5b\\xf2\\x2c\\x9b\\x31\\x98\\x8a\\xc4\\x56\\xeb\\xc3\\x80\\x42\\x61\\xc9\\xd9\\xb9\\x8f\\x2b\\x65\\x0f\\xf1\\x70\\x5f\\x91\\xb0\\xbf\\x70\\xb6\\xb6\\xf3\\x57\\x87\\xb6\\xbf\\xec\\xb6\\x30\\x8f\\xdd\\xe9\\xcd\\x9c\\x5c\\x42\\x10\\x1a\\xac\\x54\\xab\\xac\\x1b\\x8d\\xfc\\x95\\xf8\\x4f\\x44\\xf0\\x37\\x6f\\x77\\x75\\x8f\\xb1\\x8e\\x78\\xc2\\xde\\x7c\\x60\\x5e\\x81\\x2a\\xb3\\xcc\\xa1\\x37\\x79\\xcc\\x16\\x41\\xb0\\xc4\\x93\\xb5\\x24\\x5b\\x87\\xdc\\xac\\x79\\x23\\x6b\\x07\\xdf\\xb9\\x51\\x85\\xca\\xd4\\x78\\xd6\\xdc\\x41\\x7f\\x0f\\x4c\\x5d\\x1e\\x87\\x33\\x53\\x0e\\xbd\\x08\\xe8\\x0e\\xd1\\xeb\\xb9\\x2d\\x8f\\xbe\\x90\\x95\\x2d\\xfa\\x42\\x16\\x5a\\xb4\\x0f\\xcc\\xb7\\x68\\x1f\\xd8\\xa2\\x45\\xfb\\xc0\\x92\\x16\\xed\\x03\\x8b\\x2d\\xda\\x07\\xa2\\x7d\\x60\\x9f\\xf6\\xe9\\xdb\\x07\\x58\\xf4\\x85\\xac\\x6a\\x51\\xd6\\xa9\\x5b\\x94\\x75\\x36\\x6f\\x51\\xd6\\x59\\x6c\\x51\\xd6\\x89\\xb2\\x4e\\x94\\x75\\xa2\\xac\\xb3\\x6b\\xdb\\x03\\xb9\\x0b\\x95\\x76\\x9e\\x22\\x53\\xa8\\x74\\x4d\\x86\\x0c\\xd9\\xab\\x13\\xd5\\xcf\\x54\\x52\\x55\\x26\\x71\\x9f\\x78\\xcf\\x87\\xe1\\x39\\x99\\xd0\\x7b\\xec\\x5f\\x4a\\x02\\xa5\\x27\\x50\\xc9\\xdb\\x1c\\x98\\xc2\\x4b\\x24\\x0a\\x95\\x1e\\x99\\xe3\\x1d\\x02\\xcf\\x63\\x86\\x4d\\xcc\\xb0\\xf9\\x19\\x64\\xd8\\x4c\\xb8\\xf1\\x85\\x93\\x90\\xb4\\xae\\x4e\\xb8\\x69\\x1c\\xff\\x1b\\xd0\\xf9\\xcf\\x36\\xdf\\xc6\\x21\\x9c\\x47\\x18\\xbc\\xa7\\xae\\x46\\x0a\\x82\\x5d\\xea\\x7d\\xbb\\x90\\x5e\\xb5\\x21\\xe6\\xf5\\x32\\xba\\xa2\\x27\\x4d\\x21\\x65\\x05\\xe8\\x3e\\x21\\x99\\x62\\x23\\xe1\\xeb\\x87\\xcd\\xe1\\xaf\\x87\\xf0\\x13\\xcf\\x9b\\x69\\x43\\xe2\\x49\\x27\\xcf\\xb4\\x97\\xd2\\x99\\x6f\\xaa\\xe9\\xa2\\x6b\\x71\\xc5\\x27\\x97\\x4a\\xd3\\x8d\\x56\\xda\\x67\\xd6\\xbb\\xd3\\xbe\\xd9\\x4b\\x2f\\xed\\x4a\\x89\\x44\\x25\\xef\\x7a\\xab\\x32\\xc9\\xab\\xdb\\xd2\\xe2\\xb6\\xff\\x2c\\x41\\xcf\\x98\\x9a\\x82\\xae\\x15\\xa3\\xea\\x76\\x9f\\x5e\\x75\\x49\\x4d\\xc2\\x7d\\x01\\xe5\\x6e\\x0c\\x3c\\x9d\\x98\\x22\\xba\\xd4\\xd4\\xbb\\xf6\\x1a\\xb2\\x47\\x56\\x3d\\x79\\x75\\xeb\\x56\\x71\\xe8\\x50\\x6d\\x78\\x6a\\xb5\\x98\\x57\\xb7\\x4e\\xcd\\x6f\\xac\\x63\\x13\\x1c\\xeb\\xd0\\x0c\\xc7\\xba\\x35\\xc5\\xb1\\xce\\xcd\\x71\\xac\\x4b\\x93\\x1c\\xfb\\xe0\\x15\\xa4\\x57\\xb7\\x8e\\xcd\\x47\\xac\\x73\\x2b\\x1d\\x7b\\x82\\xf5\\xa8\\x57\\xb7\\xf7\\x00\\xee\\x2e\\x2d\\x76\\x2c\\x56\\xb7\\xde\\xbb\\x75\\x6d\\x50\\x63\\x5d\\x1b\\xd5\\x58\\xd7\\x78\\xb8\\x53\\x15\\xed\\xd5\\x2d\\xd6\\xd7\\x7e\\x0f\\x72\\x5a\\x67\\x42\\xc4\\xbe\\x35\\xb9\\x1f\\x9a\\x68\\x07\\x38\\x59\\xdd\\xfd\\xfb\\xa1\\x14\\x20\\xe2\\xd2\\xf5\\x85\\xb3\\x6e\\xec\\xc6\\x5d\\x5f\\x18\\xaa\\xd9\\xbc\\x18\\x35\\xc4\\xad\\x22\\x46\\xe3\\xef\\x69\\x30\\x78\\x95\\xb2\\x51\\x3c\\xae\\xd1\\xd9\\xc2\\xd5\\x33\\xb5\\xe9\\xac\\xba\\x7c\\xc6\\x29\\x05\\xf5\\xa5\\x55\\x8d\\x8f\\xf1\\xdd\\x01\\x85\\x93\\xd6\\xd2\\x84\\x4c\\xe7\\x03\\x4c\\xeb\\x2f\\x50\\xbf\\xa0\\xeb\\x70\\x0f\\x82\\x1d\\xfb\\xd0\\xd4\\x6f\\x1c\\x0c\\x9a\\x37\\xe7\\xfa\\x1e\\x8f\\xfe\\xfd\\x9f\\xe3\\x56\\xf5\\x96\\xba\\xc3\\xa8\\xfd\\x6d\\xdc\\xa2\\xf6\\xb7\\x57\\x8b\\xda\\xdf\\xca\\x16\\xb5\\xbf\\x3d\\x5a\\xd4\\xfe\\x36\\x6b\\x51\\xfb\\x5b\\xdd\\xa2\\xf6\\x17\\xb5\\xbf\\x1d\\x5a\\xd4\\xfe\\xa2\\xf6\\xb7\\x6b\\xfb\\x19\\x6b\\x7f\\xdd\\x46\\x35\\x37\\x75\\x31\\x1f\\x24\\x82\\xf2\\xa3\\xe5\\x56\\x24\\x75\\xc4\\x73\\x78\\x8b\\xfe\\xd5\\xad\\x0e\\xd8\\xd4\\xef\\x96\\x6b\\x80\\x4d\\x2d\\x71\\x41\\x0b\\x1e\\x3c\\xa0\\xee\\x55\\x0a\\xe1\\xc2\\x97\\xeb\\x35\\xc1\\x4f\\x2d\\x72\\xbb\\x33\\x4c\\x6c\\xb8\\x84\\x3b\\x45\\xc5\\x9b\\x10\\x58\\x56\\x5f\\xdc\\x5e\\x45\\x9d\\xa5\\xec\\x28\\xf8\\xe2\\xf1\\x22\\x16\\xa9\\x6c\\xfb\\xa1\\xb4\\xa2\\x5f\\xbf\\x51\\x79\\xe7\\x31\\xa8\\xa6\\x95\\xcf\\xdf\\x72\\x21\\x57\\x31\\x6c\\x55\\x7c\\x54\\x8d\\x3d\\x8e\\x3c\\x82\\x6e\\xcd\\x01\\x2f\\xbe\\x1d\\x09\\x49\\x91\\x8e\\xe1\\xd2\\x20\\x25\\x43\\xd0\\x14\\xd1\\x53\\xba\\x7a\\xc1\\xe3\\x39\\x89\\xbe\\x38\\x1f\\x94\\x7f\\x6b\\xd8\\x35\\xa2\\x7c\\x38\\x1e\\x32\\x2e\\x7d\\x32\\xac\\x92\\xe1\\x56\\x7b\\xba\\xa9\\xbe\\x96\\x97\\xab\\xbb\\x58\\xaa\\xd1\\x07\\xec\\x05\\x62\\x7d\\xb3\\x63\\x61\\x10\\x3e\\xfe\\x9a\\x88\\x6e\\x10\\xf9\\x71\\x15\\x6e\\xb8\\xdb\\xba\\x70\\xc3\\x5c\\xc4\\x48\\xac\\xdb\\x10\\xeb\\x36\\xec\\x55\\xb7\\x01\\x1f\\xd2\\xe1\\xee\\xbc\\x80\\x03\\xfb\\xab\\xbf\\x5e\\x49\\x03\\x82\\x2a\\x2f\\x33\\x2b\\x8a\\x3a\\x02\\xdb\\xd0\\x50\\x19\\x69\\x12\\x23\\x1f\\x09\\xda\\xc6\\x77\\x37\\x1a\\x4f\\x26\\xf3\\x78\\x8f\\xfd\\x61\\xc4\\xb6\\x41\\x72\\xe2\\xa3\\x2d\\xf1\\x32\\x24\\xac\\x38\\x10\\xd4\\x0e\\x0a\\x29\\x15\\x4f\\x3f\\x52\\xf0\\x02\\x09\\xb6\\xa9\\xb5\\x66\\xba\\xab\\xcb\\xd1\\xf9\\xcc\\xa1\\x84\\xa3\\xd8\\x6b\\x18\\x44\\xf3\\x42\\x0b\\x8c\\x5a\\x15\\x53\\x90\\x35\\x97\\x38\\x32\\xc7\\xc7\\x41\\x1a\\xea\\x94\\x7b\\xbd\\x17\\xee\\xf3\\xc7\\x06\\x97\\xf8\\xf3\\x26\\xfc\\x07\\x17\\x54\\x71\\xa0\\x1a\\x7c\\x35\\xff\\x79\\xda\\x21\\x91\\xfb\\x47\\xb7\\x75\\x61\\x91\\xeb\\x2c\\xaa\\xed\\xa3\\x47\\xb4\\xfd\\x9c\\x6a\\x5f\\x3c\\x4a\\x1f\\xc6\\xa3\\xd3\\x3a\\x3e\\x0d\\xbf\\x45\\x4c\\x18\\xdd\\xbc\\x3d\\x85\\x84\\xd1\\x8f\\xe4\\x9b\\x78\\x3a\\x79\\xa3\\x4f\\xd6\\x1f\\xf1\\x54\\xf2\\x46\\xa3\\x0f\\x62\\xab\\xf6\\xa9\\xa6\\x73\\xb6\\x5b\\x87\\x3e\\x87\\xe8\\x6f\\xe8\\x58\\xa6\\xea\\x84\\xf9\\xbf\\x1f\\x3f\\x43\\x27\\xf8\\xd7\\x69\\x74\\x59\\x8c\\x2c\\xfb\\x98\\x91\\x65\\x51\\x0b\\x8b\\x5a\\x58\\xbb\\x45\\x2d\\x6c\\xa1\\x45\\x2d\\x6c\\x8b\\x16\\xb5\\xb0\\xd5\\x2d\\x6a\\x61\\x8b\\x2d\\x6a\\x61\\x51\\x0b\\xdb\\xa0\\x45\\x2d\\x2c\\x6a\\x61\\x9b\\xb6\\x9f\\x99\\x16\\xd6\\x5d\\xbd\\xf5\\x18\\xe1\\xf5\\x1e\\x22\\xbc\\xba\\xa1\\x84\\x1d\\xd0\\xbf\\x4e\\xb0\\xae\\xa3\\x88\\xae\\x18\\xcd\\xf5\\xb8\\xa3\\xb9\\xf6\\x2c\\x3b\\x27\\xad\\x78\\x3f\\xa5\\xe7\\x9a\\xbb\\xbd\\xaa\\xfe\\x1c\\x9f\\x2a\\x91\\xb2\\xa2\\xb4\\xbe\\xfa\\x56\\xac\\x41\\xf7\\x98\\x6b\\xd0\\xb5\\x76\\x34\\x16\\xa2\\xdb\\xa8\\x10\\xdd\\x2a\\x98\\xc5\\x6a\\x74\\x2b\\xda\\xe3\\x89\\x31\\x8b\\xd5\\xe8\\xb6\\x6d\\xb1\\x1a\\xdd\\xf2\\x16\\xab\\xd1\\xad\\x69\\xb1\\x1a\\x5d\\xac\\x46\\x17\\xeb\\x11\\xec\\xd1\\x62\\x3d\\x82\\x25\\x2d\\xd6\\x23\\xd8\\xbd\\xc5\\x7a\\x04\\x1b\\xb5\\x58\\x8f\\x20\\xd6\\x23\\x68\\xb7\\xe8\\x85\\xda\\xaf\\xc5\\x7a\\x04\\x7b\\xb6\\xe8\\x99\\x8a\\xf5\\x08\\xf6\\xea\\x30\\x56\\xa3\\xfb\\xa4\\x62\\x06\\x59\\xd4\\xfe\\xa2\\xf6\\xb7\\x71\\x8b\\xda\\xdf\\xca\\x16\\xb5\\xbf\\x3d\\x5a\\xd4\\xfe\\x36\\x6b\\x51\\xfb\\x5b\\xdd\\xa2\\xf6\\x17\\xb5\\xbf\\x1d\\x5a\\xd4\\xfe\\xa2\\xf6\\xb7\\x6b\\xfb\\x19\\x6b\\x7f\\xb1\\x1a\\xdd\\xa3\\x8f\\x55\\x64\\x8f\\x31\\x23\\x29\\x56\\xa3\\x8b\\xf1\\x8b\\x3b\\x6d\\x77\\xac\\x46\\xf7\\x70\\xfb\\xd9\\x57\\xa3\\x6b\\xc5\\xd2\\x7d\\xbc\\x92\\x74\\xdb\\x4f\\x23\\xd6\\xa5\\x8b\\x75\\xe9\\x62\\x5d\\xba\\x58\\x97\\x2e\\xd6\\xa5\\x8b\\x75\\xe9\\x36\\x6f\\x8f\\xdf\\x9b\\xf1\\xe8\\xf4\\x8f\\x4f\\xc3\\x83\\x11\\x2b\\x22\\x6c\\xde\\x62\\x45\\x84\\x95\\x2d\\x56\\x44\\x88\\x15\\x11\\xa2\\x37\\x62\\x97\\x16\\x2b\\x22\\x6c\\xd9\\xa2\\xe7\\x21\\x56\\x44\\xd8\\xaa\\xc5\\xba\\x74\\x9f\\x4c\\x8c\\x59\\xd4\\xc2\\xa2\\x16\\xd6\\x6e\\x51\\x0b\\x5b\\x68\\x51\\x0b\\xdb\\xa2\\x45\\x2d\\x6c\\x75\\x8b\\x5a\\xd8\\x62\\x8b\\x5a\\x58\\xd4\\xc2\\x36\\x68\\x51\\x0b\\x8b\\x5a\\xd8\\xa6\\xed\\x67\\xa6\\x85\\xc5\\xba\\x74\\x8f\\x3a\\xd6\\x2b\\xd6\\xa5\\x5b\\xd2\\x62\\x5c\\xd7\\xe3\\x8e\\xeb\\xda\\x11\\x57\\x78\\x69\\x55\\xae\\x4a\\x69\\xaf\\x41\\x4f\\x45\\x02\\x67\\x49\\xe2\\xfe\\xba\\x51\\xb7\\xb0\\x65\\x2c\\x51\\x5b\\x0d\\x5d\\xd3\\x2d\\x13\\x32\\x15\\x09\\x2a\\x92\\x77\\x13\\xc0\\xb2\\x72\\x4e\\xbe\\xc5\\xf7\\x18\\xa7\\x17\\x99\\xc5\\x37\\x6b\\xf4\\xc2\\x79\\x3a\\xa2\\x86\\x01\\x36\\xd8\\xf5\\xb6\\xf0\\x22\\x08\\x0d\\x95\\xca\\x80\\xcb\\x2d\\xbe\\xf4\\xdc\\x10\\xf4\\x96\\xa7\\xb9\\x05\\x90\\x97\\x9e\\x14\\xd7\\x9d\\xb1\\x21\\x64\\x4a\\x8e\\x7d\\x3c\\x8f\\x3f\\x01\\x03\\x76\\x5e\\xbf\\x90\\x70\\x89\\x87\\xa7\\xd4\\x1a\\xa4\\xcd\\x66\\x08\\x07\\x2c\\x70\\x85\\x5a\\x43\\xae\\xa6\\x90\\x22\\xc9\\xc6\\x30\\x22\\x92\\x23\\xb9\\x65\\x19\\x70\\x37\\x96\\x84\\x7a\\x30\\x77\\x78\\x38\\xbb\\xc2\\xfe\\xa9\\xd3\\x21\\xf8\\xd0\\xa6\\x9d\\x80\\xb8\\x3d\\x6d\\xdc\\x89\\x1a\\xce\\x59\\x36\\xbc\\xd8\\x84\\x7c\\x29\\x41\\xfd\\xa8\\xb1\\x42\\x3c\\x9a\\x33\\x55\\xb2\\x3b\\x4e\\x92\\x92\\x2e\\x25\\x1e\\x66\\x5c\\xba\\x03\\xed\\x96\\x83\\xef\\x21\\x93\\xec\\x6e\\x7e\\xe8\\x23\\x55\\xdb\\xf2\\xb3\\x7d\\xcc\\x01\\x5c\\x8f\\x77\\x62\\x52\\xad\\xad\\x39\\x3c\\xd3\\xe3\\x92\\x44\\x42\\x8f\\xca\\x20\\xad\\x9e\\x61\\xbc\\x1d\\xc9\\x14\\x0d\\x4c\\xcc\\xf9\\x18\\x0e\\x0f\\x0d\\x3b\\x7f\\x75\\xe1\\xc8\\x5f\\x69\\x1c\\xb5\\xf6\\x55\\xf6\\x3c\\x39\\x2c\\xb4\\x9a\\x8a\\xd4\\x21\\xf7\\x77\\x5c\\x0b\\x3e\\xcc\\x9c\\xdc\\x39\\x02\\x0d\\xd2\\x89\\x05\\x9f\\x1f\\x7d\\x77\\xf6\\xf6\\xef\\xaf\\xcf\\x5e\\xbd\\x38\\x46\\x09\\x14\\xee\\x0b\\x2e\\xdd\\xa9\\x28\\x4d\\x1d\\x28\\xea\\x87\\x73\\x03\\x81\\x9c\\x0a\\xad\\xa4\\x9b\\x1f\\xea\\x6a\\x9c\\x4d\\x43\\xaf\\x49\\x75\\x18\\x34\\x18\\x95\\x4d\\x21\\x25\\x39\\xb9\\x1a\\x2d\\x70\\x1d\\x21\\x8b\\xd2\\x06\\xdd\\x11\\xc3\\x17\\xdd\\x01\\x92\\xc9\\x84\\xcb\\xb1\\x9b\\xe7\\x85\\x2a\\x5d\\x7f\\x9f\\x7f\\x8e\\x33\\xd2\\x90\\x96\\x09\\x49\\x4e\\x3c\\x60\\xed\\xe7\\xbd\\xc0\\x29\\x1c\\xad\\x37\\x54\\x12\\xd1\\x24\\xbc\\x08\\x73\\x6e\\x2e\\xcb\\xcc\\xa4\\xe5\\xf7\\xa7\\x14\\xbf\\x77\\xf0\\x79\\xe3\\xd1\\x41\\x28\\x27\\xa9\\xdc\\x10\\xc4\\x6f\\x68\\x56\\x19\\x56\\x32\\xcc\\xd8\\x41\\xf3\\xed\\x01\\x7b\\xe1\\xc6\\x80\\xb4\\x09\\x40\\x0a\\xbf\\x84\\x29\\x68\\xd4\\x3c\\x3d\\xf8\\x7a\\x4c\\xc3\\x98\\xeb\\x34\\x03\\x83\\x81\\x87\\x81\\x36\\x93\\x76\\xe0\\x01\\x06\\x95\\x5e\\x2b\\x95\\x5d\\x46\\x4c\\xd8\\x2b\\x85\\x41\\x88\\x23\\x75\\xca\\x26\\xd6\\x16\\xe6\\xf4\\xe4\\xe4\\xb6\\x1c\\x82\\x96\\x60\\xc1\\x0c\\x84\\x3a\\x49\\x55\\x62\\x4e\\x2c\\x37\\xb7\\xe6\\x44\\x48\\x77\\xb8\\xfa\\x29\\xb7\\xbc\\xdf\\x38\\xd5\\x27\\xc4\\xb9\\xfb\\x89\\xca\\x73\\x2e\\xd3\\x3e\\xf7\\xd8\\xd5\\xaf\\xb6\\xf5\\xe4\\x17\\x9e\\xa7\\xf6\\x79\\xf5\\x96\\x90\\x7d\\xde\\x37\\x13\\xc8\\xb2\\xc3\\x1d\\xf0\\x79\\x3f\\x99\\x6f\\x0f\\x59\\x6f\\x2f\\x19\\xcf\\xaf\\x7d\\xff\\x03\\xfc\\xa2\\x3a\\xaf\\x04\\x83\\x01\\x7b\\xad\\xac\\x8f\\x8f\\xf5\\xa1\\xd8\\x48\\x47\\x11\\xbe\\x2b\\x8f\\xf4\\x8b\\xd7\\x37\\x6f\\xff\\x76\\xf5\\xe6\\xf2\\xf5\\x4d\\x3c\\xd9\\xf1\\x64\\xc7\\x93\\xbd\\xc7\\xc9\\x06\\x39\\xdd\\xfb\\x54\\x07\\x99\\xb3\\x71\\x4c\\xaa\\xfd\\x46\\x4e\\x6d\\xc0\\x86\\x63\\x50\\x6d\\xc0\\xde\\x12\\x22\\xb5\\x8f\\x06\\xf5\\x16\\x04\\x5e\\xc8\\xe9\\x77\\xbc\\x6d\\x61\\x97\\x4b\\xc1\\xc1\\xfc\\x0b\\x24\\x28\\x57\\x32\\xf8\\x3e\\xf1\\xf1\\x7b\\x58\\xb3\\xf6\\x75\\x5f\\xed\\x24\\x45\\x52\\xdb\\xdf\\xb5\\xe4\\x86\\xde\\xdd\\xd0\\xd0\\xda\\xbe\\xd7\\x3c\\xaf\\x2b\\x54\\x2f\\xd9\\xb5\\x01\\x7b\\x15\\xd4\\x1e\\x76\\xfe\\xf7\\xcb\\x8b\\x17\\xaf\\x6f\\x2e\\xbf\\xba\\x7c\\xf1\\x76\\x77\\x3d\\xba\\x03\\x8b\\x0b\\xda\\x14\\x3a\\x02\\xc0\\xe1\\x8e\\x5c\\xb2\\xd0\\x30\\x15\\xaa\\x34\\xd9\\xac\\xb2\\x82\\x2c\\x27\\x02\\xf3\\xa7\\xdf\\xfb\\x7d\\x67\\x95\\x3e\\xbe\\xf4\\xb3\\xc8\\x6c\\xbb\\x65\\xb6\\x17\\x30\\xe2\\x65\\x46\\xda\\xd3\\xc1\\xc1\\x60\\x17\\x2e\\x47\\xad\\x2b\\xf4\\xfd\\x4a\\xab\\x3d\\x2a\\x30\\xb7\\x50\\xf8\\x9a\\x6a\\xb7\\x8f\\x94\\x5e\\x79\\x8c\\x0f\\x7d\\xf4\\x41\\x8b\\xf5\\x78\\xe1\\x91\\x2c\\x74\\x5e\\x7a\\x24\\x27\\xd9\\x9e\\xd0\\xd9\\xd3\\xcb\\xd0\\x8d\\xef\\x3d\\x51\\x72\\x24\\xc6\\xaf\\x78\\xf1\\x0d\\xcc\\xde\\xc2\\x68\\x3f\\x33\\x71\\x1b\\xde\\x68\\x7d\\xf4\\xae\\x64\\xb4\\x55\\x3a\\x76\\x46\\x83\\xed\\xe7\\xa6\\xe9\\xcc\\x49\\xd3\\x55\\x74\\xc6\\xfe\\x91\\x19\\xdd\\x05\\x52\\x74\\x12\\x44\\xb1\\x50\\x0f\\x9f\\xec\\xd0\\xde\\xa2\\xdc\\x55\\x8c\\x4d\\x27\\x9e\\xfb\\xfd\\xb8\\x7c\\x68\\x6d\\x66\\xd7\\x64\\xf7\\x9e\\xce\\xda\\x4d\\xd5\\x8e\\x44\\xc9\\x04\\x0a\\x6b\\x4e\\xd4\\xd4\\x71\\x2e\\xb8\\x3b\\xb9\\x53\\xfa\\xd6\\xe9\\x11\\x4e\\x77\\xed\\x13\\xd6\\x9a\\x13\\xf4\\x19\\x9c\\xfc\\x82\\xdc\\x60\\x37\\x6f\\x2e\\xde\\x9c\\xb2\\xb3\\x34\\xf5\\x97\\x9b\\x94\\x06\\x46\\x65\\xe6\\xaf\\x13\\x18\\x30\\x5e\\x88\\xef\\x40\\x1b\\xa1\\x64\\x8f\\xdd\\x0a\\x99\\xf6\\x58\\x29\\xd2\\x2f\\x77\\x27\\xce\\xa1\\x75\\xb8\\x0b\\xaa\\x20\\x57\\x67\\xc7\\x3b\\x71\\x8d\\x3e\\x96\\x59\\x8b\\x77\\x55\\x44\\xc4\\x71\\x2d\\x61\\x0d\\xe2\\x66\\xb0\\x3a\\x7b\\x21\\xa3\\x23\\xd0\\x6c\\x6f\\xa2\\x9f\\x6f\\xb8\\x85\\xdd\\xd2\\xd5\\xc3\\x9a\\xb0\\x92\\x8b\\xd3\\x23\\x6a\\xa1\\xd2\\x53\\x66\\xca\\xa2\\x50\\xda\\x1a\\x96\\x83\\xe5\\x4e\\xe9\\x1d\\x38\\x0c\\xeb\\xb5\\xff\\x44\\x5f\\x55\\x8f\\xfd\\x58\\xfd\\x88\\x0e\\x27\\xf3\\xfd\\xe1\\xe1\\x1f\\xbf\\x79\\xf1\\xb7\\x3f\\x1f\\x1e\\xfe\\xf0\\x63\\xf3\\x29\\xb2\\x42\\x8a\\x02\\x6a\\xbf\\x62\\x0a\\x48\\x06\\x52\\xa5\\xf0\\x1a\\xc7\\xc0\\x3f\\x4d\\xcb\\xcd\\xe2\\x1f\\x58\\x6e\\x4b\\x33\\x98\\x28\\x63\\x2f\\xaf\\xaa\\x3f\\x0b\\x95\\xce\\xff\\x65\\xf6\\x90\\x38\\xd8\\xe3\\x64\\x0c\\xb8\\x45\\x57\\xdc\\x4e\\x1e\\x09\\x7b\\xa8\\x69\\x49\\xc7\\x47\\xd5\\xf7\\xda\\xbc\\x44\\x27\\xe7\\xf8\\xcf\\xaf\\x02\\x08\\x9c\\xf4\\x74\\xa7\\x85\\xb5\\xe8\\x7a\\xf3\\xa9\\xe0\\x6a\\xd4\\x73\\xa7\\xb6\\x16\\x3b\\xa7\\xcf\\xf7\\xae\\x8f\\xd2\\x29\\x69\\xab\\x76\\xb0\\x63\\x80\\x21\\x44\\x3c\\xb4\\xe8\\x20\\x57\\x0c\\x76\\xd1\\xc5\\x7c\\x76\\x75\\xc9\\xa6\\x04\\xe1\\x47\\x03\\x9c\\x90\\xde\\xfb\\xd5\\x7b\\xa5\\x71\\xd5\\xa5\\x4b\\x1e\\x54\\x95\\x86\\x78\\x4a\\x41\\x41\\x55\\x92\\x31\\xcb\\x44\\x2e\\x7c\\xac\\xa1\\xbf\\xa0\\xc9\\xb0\\x23\\xfa\\x71\\x90\\x14\\x65\\xcf\\xbf\\x30\\xc8\\x21\\x57\\x7a\\x56\\xfd\\x09\\xc5\\x04\\x72\\xa7\\x69\\xf5\\x8d\\x55\\x9a\\x8f\\xa1\\x57\\x7d\\x4e\\x9f\\x55\\x7f\\xd1\\x87\\xad\\x01\\x16\\xbf\\x26\\x55\\xb8\\x76\\x95\\x7a\\x8a\\x0c\\xe9\\xa7\\x47\\xdb\\x02\\xe8\\x1f\\x09\\x69\\xab\\x30\\xe3\\xf5\\x7b\\x10\\x09\\x2b\\x4b\\x1c\\x09\\x9c\\x15\\x14\\x51\\x9f\\x9c\\xaa\\xac\\xcc\\xc1\\xf4\\x2a\\x31\\x88\\xac\\x01\\x72\\xea\\x34\\x4b\\xf3\\xa8\\x04\\xb5\\x54\\x4c\\x85\\xe9\\x22\\x8c\\x78\\x89\\x9c\\x26\\x7c\\x44\\xbe\\x2a\\x6d\\x51\\x5a\\x5f\\x6f\\xa6\\x71\\xb1\\x9b\\x32\\x68\\xb7\\xa8\\x8a\\x02\\xb4\\xc8\\xfe\\xf3\\x83\\xfd\\xa3\\xd1\\xb9\\xb5\\xa0\\xe5\\x29\\xfb\\xdf\\xa3\\x77\\xbf\\xfc\\xa9\\x7f\\xfc\\xe5\\xd1\\xd1\\xf7\\xcf\\xfa\\x7f\\xf8\\xe1\\x97\\x47\\xef\\x06\\xf8\\x8f\\x2f\\x8e\\xbf\\x3c\\xfe\\x29\\xfc\\xf1\\xcb\\xe3\\xe3\\xa3\\xa3\\xef\\xbf\\x79\\xf5\\xf5\\xcd\\xd5\\x8b\\x1f\\xc4\\xf1\\x4f\\xdf\\xcb\\x32\\xbf\\xa5\\xbf\\x7e\\x3a\\xfa\\x1e\\x5e\\xfc\\xb0\\x61\\x27\\xc7\\xc7\\x5f\\x7e\\xbe\\xf7\\xd4\\xb9\\x9c\\xbd\\xd9\\x93\\x80\\x52\\xeb\\x77\\x56\\x2e\\x68\\xbe\\xc7\\x8e\\xe2\\xac\\xef\\xfb\\xb5\\xd2\\xd4\\x17\\xd2\\xf6\\x95\\xee\\x53\\xd7\\xa7\\xcc\\xea\\x72\\x3f\\x62\\x52\\x33\\xa5\\xae\\xcf\\x7f\\xb8\\xbd\\xeb\\xb4\\x66\\x48\\x15\\xbb\\x7e\\x34\\x07\\xdc\\x40\\xa2\\xc1\\x7e\\x08\\x4b\\x0e\\x8d\\x14\\xe4\\x94\\xb9\\x98\\xc7\\x4f\\x8d\\xcf\\xfd\\x1c\\x8c\\x3b\\x55\\xc8\\x20\\xee\\x6b\\x2d\\x89\\x8e\\xb4\\xca\\x07\\xac\\xe1\\xde\\x98\\x62\\xc2\\x87\\x7f\\xef\\x16\\xf6\\xb0\\x82\\x86\\x16\\x8d\\x41\\xd1\\x18\\xb4\\xa2\\x3d\\x68\\x0c\\xba\\x26\\x3c\\x7c\\xb4\\x96\\x20\\x90\\xd3\\x5d\\x5d\\x18\\x4b\\x3d\\xe8\\x41\\xd7\\xb1\\x8a\\x15\\xaa\\x28\\x33\\x6e\\x57\\x78\\xc6\\x96\\xb8\\xd3\\xfd\\x51\\xaf\\xe3\\x91\\xeb\\x60\\x1a\\x62\\x68\\xf9\\x72\\x1f\\x26\\x3b\\xcb\\x32\\x26\\x24\\x1d\\x7c\\xec\\x20\\x38\\xcc\\x34\\x90\\x6a\\xc3\\x38\\xf9\\xb3\\xa7\\x6e\\x0a\\x77\\xbe\\xac\\x5c\\x33\\x2e\\xc7\\x30\\x63\\xb9\\xb6\\x18\\x7b\\x8c\\x65\\xe7\\x88\\x95\\x78\\xef\\x93\\x90\\x75\\xf1\\xb9\\x4a\\x38\\xac\\x72\\x41\\x96\\xde\\x8c\\x99\\x71\\x63\\xc3\\xb4\\x71\\x36\\x96\\xdf\\xa2\\xb7\\x31\\x81\\x14\\x64\\x02\\x98\\x98\\x56\\x42\\xbd\\xd6\\xa1\\xd3\\xdb\\xd8\\x0b\\x39\\xa5\\x3e\\x38\\x4b\\x4b\\x0a\\x06\\x21\\xf2\\xb7\\xbc\\x8f\\x4f\\x2b\\x00\\xc1\\x21\\xe2\\x75\\xb8\\xc0\\xb8\\x8a\\x43\\x40\\xaa\\x5f\\x69\\xd8\\x55\\x7e\\x5f\\x65\\x65\\x35\\x1f\\x27\\xf2\\x60\\x7f\\x9e\\x59\\x79\\xb6\\xf6\\x12\\x86\\x16\\x98\\x65\\x6d\\x7e\\x6e\\x33\\xc9\\x4f\\xc1\\x19\\xb8\\x3f\\xfb\\xfc\\xd9\\xb1\\xce\\x8e\\xd8\\x66\\x37\\x2c\\x73\\x0b\\xdf\\x49\\x97\\x6c\\xb2\\x0b\\x67\\x49\\xa1\\x61\\x24\\xee\\x3b\\x3a\\xa7\\x67\\xb2\\xb6\\xc4\\x88\\x14\\xa4\\x15\\x23\\x41\\x77\\xde\\x17\\x1a\\x0a\\x90\\x69\\x55\\xb8\\x14\\x93\\xc3\\x65\\x1b\\x36\\x8f\\x32\\x98\\x87\\x04\\xee\\x6e\\x49\\xd9\\xf5\\x32\\x61\\x3f\\xd2\\x31\\x16\\xe9\\xd8\\xce\\xed\\x03\\xd1\\x31\\x8f\\xb9\\x8f\\x87\\x88\\x61\\xe4\\xf9\\xfe\\xd1\\xef\\xe7\\xed\\x50\\x76\\x44\\xe4\\xad\\x11\\xad\\xce\\xec\\x3a\\xc1\\x5e\\x0c\\x65\\x49\\x56\\x69\\xd8\\x15\\x69\\xb4\\x8a\\x82\\xd7\\xd8\\x44\\x8c\\x1d\\x64\\x33\\x98\\x42\\xe6\\xe5\\x26\\x96\\x73\\xc9\\xc7\\x94\\xdf\\x6d\\x55\\x30\\xd5\\x3a\\x45\\xcb\\xe1\\xb1\\x16\\xe9\\x42\\xdc\\x3d\\xca\\xf1\\x0e\\xb7\\x33\\xc5\\x53\\x7c\\xa8\\x55\\x96\\x81\\x36\\x2c\\x13\\xb7\\xc0\\x2e\\xa0\\xc8\\xd4\\xcc\\xa7\\x6b\\xcb\\x94\\x5d\\x5b\\x6e\\x1d\\x56\\x5f\\x83\\xdd\\xcd\\xed\\xbb\\x17\\xc6\\xe2\\x8c\\xaf\\xca\\x2c\\xbb\\x52\\x99\\x48\\x76\\x32\\xaa\\xb4\\x77\\xee\\x12\\xf7\\xab\\x28\\xb3\\x8c\\x15\\xd8\\xe5\\x80\\xbd\\x91\\x48\\x34\\xce\\xb2\\x3b\\x3e\\x33\\x3d\\xf6\\x1a\\xa6\\xa0\\x7b\\xec\\x72\\xf4\\x5a\\xd9\\x2b\\x92\\xbe\\xdb\\x01\\x77\\xf4\\x22\\x13\\x23\\x76\\x8a\\xd5\\x6d\\x2c\\xb3\\x7c\\x8c\\xba\\x53\\x70\\x03\\xf6\\x1c\\xfc\\x9b\\x1d\\x10\\x7d\\xb8\\x13\\x66\\xa9\\xb2\\xb2\\x37\\xe2\\xfc\\x02\\x7b\\x72\\xb4\\x8a\\xfe\\xfe\\xe0\\xdb\\x94\\x89\\x11\\x24\\xb3\\x24\\xdb\\xff\\x68\\x9d\\x25\\x18\\xc0\\x50\\x67\\x9c\\x37\\xf0\\xdb\\x57\\x53\\xf7\\x39\\x9e\\xa8\\x05\\x0a\\xc9\\xa8\\xcc\\x39\\xd5\\x6f\\xaf\\x51\\xbd\\x9a\\x11\\x69\\xbb\\xa6\\x53\\x25\\x71\\x67\\xe6\\xb9\\x2f\\xdb\\x2c\\x94\\xb1\\xd7\\x4e\\x43\\xef\\xa4\\x18\\xfa\\xe1\\x55\\xe8\\x8e\\x61\\xc9\\xe7\\x2c\\x83\\x94\\x89\\x3c\\x87\\xd4\\x69\\xf1\\xd9\\x8c\\xf1\\x91\\xc5\\x5c\\xdb\\x96\\x85\\x20\\xd1\\x40\\x58\\xeb\\xab\\x98\\x4c\\xb8\\x4c\\x33\\xd0\\x6c\\xc4\\x45\\xe6\\xed\\x01\\xad\\xf7\\x2d\\xe8\\x5c\\x48\\x34\\x0b\\x90\\x47\\x16\\x4d\\x0c\\xee\\xaf\\x24\\x51\\x3a\\x94\\xa7\\x17\\xd6\\x84\\x47\\xf5\\xc1\\x44\\x3e\\xd2\\x40\\x80\\x79\\xd7\\x32\\x1b\\x66\\x2a\\xb9\\x35\\xac\\x94\\x56\\x64\\x34\\x19\\xa5\\x6e\\x59\\xa2\\xf2\\x22\\xc3\\xa3\\xb3\\xc7\\xc9\\xaa\\xfe\\xd9\\xaf\\x50\\xa9\\xef\\x7a\\x37\\x27\\xbf\\xa8\\x1f\\xe1\\x0f\\xbb\\x32\\xf4\\x0e\\x04\\xb1\\x2e\\xc4\\x30\\xb8\\x87\\xa4\\xb3\\x3c\\xff\\x17\\xf7\\x90\\x34\\x0a\\x4b\\xe0\\x7d\\x0c\\x78\\xa2\\x31\\xcf\\x93\\xdf\\xc2\\x27\\x54\\xc9\\x6e\\x8f\\x5c\\xba\\x66\\x6b\\xc1\\xef\\x9c\\xfa\\x0c\\x85\\xb0\\xfc\\x10\\x2c\\x13\\x12\\xe9\\x9b\\xcf\\xaf\\x63\\x42\\x1a\\xc7\\xd9\\x5b\\x87\\x81\\x8e\\x9e\\x17\\x5a\\x59\\x2a\\x34\\x56\\x41\\x98\\x55\\x81\\xd4\\xa1\\x2f\\x2c\\x30\\xa0\\x94\\x65\\x47\\x87\\x27\\x87\\xc7\\x0b\\xf6\\xc7\\x43\\x27\\x81\\x64\\x40\\xb4\\x36\\x24\\xee\\x55\\x93\\x32\\x22\\x2f\\xb2\\x19\\xce\\xe3\\x30\\xed\\x31\\x61\\x43\\xa4\\xb5\\x2e\\x65\\x98\\x95\\x4f\\xfa\\xeb\\x31\\xa3\\x98\\xd5\\x3c\\x54\\x57\\xa1\\x5f\\xdd\\x4b\\x56\\x97\\x9e\\xca\\x1f\\x1d\\xfe\\x74\\xd8\\x63\\x60\\x93\\x63\\x76\\xa7\\xe4\\xa1\\xc5\\xe9\\x0f\\xd8\\x8d\\x72\\xa2\\x74\\xdd\\xd1\\x4c\\x95\\x4c\\x02\\x05\\xf6\\xc3\\x7d\\x91\\x89\\x44\\xd8\\x6c\\x86\\x14\\x8b\\xa9\\xd2\\x52\\x0e\\x31\\xb7\\x21\\xd9\\xf0\\xc5\\xbd\\xb0\\x3e\\x5e\\xcd\\x91\\x8c\\x67\\x08\\x4d\\xa2\\x5a\\x8c\\x3b\\x31\\x67\\x0a\\x27\\x13\\xe0\\x99\\x9d\\x50\\x90\\x88\\x54\\xb2\\xff\\x2f\\xd0\\x0a\\x73\\x10\\xa5\\x7f\\xf2\\xc9\\x55\\xfd\\xeb\\x44\\x73\\x70\\x44\\xf4\\x6b\\xe8\\xee\\x12\\x9f\\xbf\\xdc\\xdc\\x5c\\x7d\\x0d\\x76\\x8e\\x64\\xb8\\x51\\x42\\xe8\\x0e\\x5a\\x03\\x40\\x8f\\x94\\xce\\x1f\\x01\\xed\\xe8\\xc6\\x59\\xd9\\x67\\x85\\xd2\\x8f\\x81\\x84\\x4d\\x94\\xd9\\x6b\\x2f\\xd9\\xc2\\x7e\\x2a\\x63\\x51\\x1b\\xf2\\xd2\\x98\\x84\\xc4\\xed\\x60\\x3b\\x86\\x24\\xdc\\x73\\x73\\x79\\x35\\x60\\x7f\\x53\\xa5\\x5b\\xcd\\x90\\x0f\\xb3\\x59\\x55\\x89\\xc1\\x80\\x65\\x07\\xae\\xab\\x03\\x47\\x9e\\x1c\\x36\\xfc\\x05\\x78\\xea\\x54\\x14\\x47\\x3d\\x80\\x3f\\x8e\\xfb\\xac\\x98\\x3f\\x0f\\x7e\\x6e\\xdd\\xf2\\x81\\xd2\\x58\\x95\\xb3\\x89\\x5f\\x76\\x3b\\xf5\\xd2\\x9f\\x8c\\x01\\x9e\\x9e\\x90\\xd7\\xa4\\xa1\\x20\\x0a\\xe7\\xbf\\xf9\\xe4\\xe8\\xd7\\x02\\xdd\\x20\\xb8\\xfb\\xdf\\x87\\x58\\xc6\\x2a\\x69\\x82\\xcd\\x5f\\xe8\\x44\\x89\\x41\\x92\\x80\\xe5\\x50\\x0d\\x76\\x73\\x95\\x34\\xdb\\x23\\xae\\x3d\\xba\\x73\\x22\\xe7\\x7c\\x47\\xe8\\xd4\\xdb\\x3f\\xd6\\xab\\xd3\\xca\\xa3\\xdd\\xc4\\x0d\\xb0\\x65\\x46\\x56\\x8f\\x33\\x64\\x7d\\x21\\x7b\\x0e\\x9a\\x63\\x82\\x0f\\x35\\xe1\\x52\\x49\\x91\\xf0\\x4c\\xfc\\x0b\\x52\\x56\\x16\\x4a\\xfa\\xf8\\x39\\x94\\x73\\x12\\x6e\\xa0\\x8f\\x4e\\x5d\\x69\\x7d\\xcd\\xb4\\x3a\\x5b\\xd1\\x1d\\x47\\xab\\x14\\x0a\\x1f\\xe8\\xc6\\x73\\xf4\\x91\\xc6\\x7b\\xbc\\x05\\x36\\x3f\\x04\\x98\\xbb\\x41\\x31\\xd6\\x25\\x04\\x8a\\x0e\\x02\\xc8\\x17\\xc3\\xc7\\xad\\x72\\xda\\x2e\\x26\\x78\\x12\\x09\\x47\\x62\\x64\\x40\\x4f\\xf7\\x47\\x81\\xee\\x96\\xae\\x76\\xb7\\x2b\\x84\\xb6\\x24\\x1b\\x5b\\x33\\x59\\xe6\\x43\\xd0\\x75\\xfe\\x8b\\xb6\\x8b\\x00\\x69\\xc4\\x3f\\xbc\\xa6\\xd7\\x83\\xd1\\xb8\\x7d\\x49\\xa3\\xfb\\xf2\\x77\\xbf\\xfd\\xed\\xaf\\x7f\\x3b\\xa0\\xee\\xab\\x58\\x08\\xc9\\x2e\\xcf\\x5e\\x9f\\xfd\\xfd\\xfa\\xbb\\x73\\x4c\\xc1\\xdd\\x17\\xaa\\x1d\\x05\\x7a\\x76\\x1d\\xe6\\xd9\\x69\\x90\\xe7\\x7b\\x0d\\xf1\\xc4\\xc4\\x92\\xbd\\xa9\\x48\\xdb\\xc3\\x80\\x5d\\x3a\\x0c\\x70\\xda\\xa1\\xd3\\x6b\\xbd\\x84\\xd9\\x28\\x89\\xe6\\x24\\xda\\xb6\\xb9\\xd6\\x1d\\xb5\\x47\\x71\\xc6\\x6c\\x52\\x5c\\xab\\xe4\\xb6\\x43\\xed\\xe9\\x02\\x0a\\x0d\\x09\\x59\\xe3\\x6e\\xce\\xaf\\xa8\\x77\\xa7\\xc5\\xbe\\x7e\\x73\\x53\\x27\\x34\\x60\\xd4\\x0f\\x7b\\x19\\xac\\x58\\x7f\\xf1\\xf6\\x3a\\xa7\\xf9\\xde\\x42\\x61\\x2b\\x03\\xc1\\x90\\x27\\xb7\\x77\\x5c\\xa7\\x68\\x3f\\xe3\\x56\\x0c\\x45\\x26\\xa8\\xc4\\x70\\xb8\\x7a\\x52\\x2a\\x0a\\x2b\\xa4\\x52\\x6a\\x6a\\x34\\x5f\\xc0\\xb3\\x36\\xba\\xa2\\x61\\x8c\\x58\\xe0\\x88\\x8b\\x0c\\xed\\xb4\\xa5\\xb4\\x22\\x07\\x1f\\x77\\x94\\x14\\x95\\xe1\\xb0\\x69\\x39\\x8f\\x2a\\x5e\\x68\\x8f\\x56\\xc5\\x3b\\x7c\\x13\\x7c\\x87\\x5b\\x6b\\x7b\\xfb\\x46\\x3f\\x3e\\x62\\x56\\xe7\\x59\\x1c\\xa5\\x9d\\x44\\x56\\xf7\\xb3\\x60\\x75\\x85\\x86\\x6b\\xab\\x8a\\x8e\\x7c\\x31\\xd4\\xd9\\x0a\\x4f\\xcc\\x10\\x46\\xca\\x11\\xe1\\x95\\xae\\x95\\x70\\x13\\xb1\\xc4\\x14\\xc4\\x60\\x3b\\x53\\x2d\\xf7\\x09\\xc5\\x7d\\x9a\\x32\\x99\\x04\\x33\\xa8\\x04\\x63\\x4e\\xd0\\xe9\\x52\\x16\\xa4\\x1b\\x23\\xb9\\x2e\\x35\\xf4\\xdc\\xea\\x20\\xc7\\xd9\\xf5\\xea\\x5c\\x0a\\x37\\x3c\\x48\\xfa\\x11\\x6c\\x42\\xf6\\xe1\\x06\\x21\\xc7\\xf2\\xa3\\x7e\\xfa\\xf3\\xce\\x9a\\x44\\x73\\x33\\x01\\x2c\\x62\\x02\\xf7\\x22\\xdc\\xb9\\x72\\xa5\\xd2\\xc3\\xc3\\x7a\\x29\\x8e\\xb1\\x8c\\x35\\x4f\\x80\\x15\\xa0\\x85\\x72\\xcc\\xa8\\x94\\x36\\x55\\x77\\x92\\x0d\\x61\\x2c\\xa4\\x09\\xa0\\x70\\x7d\\x07\\x98\\xa1\\xd7\\x47\\x98\\xaa\\xfc\\xdc\\x80\\xbd\\x6d\\x95\\x54\\xf1\\xc9\\x4e\\x89\\xaa\\x8f\\xa6\\x9f\\xf3\\xbc\\xbf\\x0a\\x39\\x56\\xe3\\x62\\xe6\\x0a\\xc2\\x21\\x08\\xd7\\x6e\\x30\\xe5\\xa3\\x52\\xe2\\xc8\\x29\\x64\\x7c\\x46\\x31\\xad\\x23\\x21\\x51\\x73\\xd4\\xe6\\xb8\\x03\\xbf\\x96\\x03\\x61\\xfd\\x6c\\xe5\\x3c\\xf0\\x42\\x00\\x9e\\x4c\\xf6\\x73\\x31\\x47\\x47\\xd8\\x86\\x2d\\x3a\\xc2\\xf6\\xe9\\x24\\x3a\\xc2\\xa2\\x23\\xec\\x81\\x16\\x1d\\x61\\xd1\\x11\\x36\\xd7\\x1e\\xad\\x96\\x14\\x1d\\x61\\x3b\\xb7\\xe8\\x08\\x5b\\xdf\\xa2\\x23\\x6c\\x83\\x16\\x1d\\x61\\x1b\\xb6\\xe8\\x08\\x5b\\xdd\\xa2\\x23\\x6c\\xbf\\xc9\\x44\\x47\\x58\\x74\\x84\\xf9\\xf6\\xf3\\xb3\\x0e\\x86\\x16\\x1d\\x61\\x0b\\x9d\\x44\\x47\\x58\\x74\\x84\\x6d\\xdc\\x1e\\xad\\x8a\\x17\\x1d\\x61\\xd4\\xa2\\x23\\xac\\xdd\\x7e\\x5e\\xac\\x2e\\xb8\\x91\\xae\\x9c\\x42\\xb9\\x7f\\x7e\\xde\\x15\\xba\\x2e\\x44\\xe2\\xbd\\x51\\xcd\\x0b\\xf0\\xaa\\xa1\\x1a\\x77\\xde\\x35\\x4a\\x9c\\x84\\xb4\\x22\\xef\\x77\\xaa\\xbd\\x59\\x4b\\x73\\xbf\\xb6\\x75\\x88\\x84\\x84\\x49\\x73\\x52\\x28\\xfa\\xbf\\xda\\x1d\\xd2\\xf0\\x83\\x90\\x5a\\xbd\\x7b\\xfe\\xdd\\x47\\xcb\\x2c\\xdb\\xc7\\xf9\\xf1\\x61\\x1c\\x1f\\x8f\\xc4\\x4b\\xd4\\x81\\xb3\\x23\\x3a\\x3a\\x3e\\x39\\x47\\xc7\\xa7\\x73\\x03\\xb0\\xf7\\xff\\xdf\\x4c\\x34\\x98\\x89\\xca\\x76\\x46\\xf4\\x16\\x92\\xbf\\x12\\x52\\xe4\\x65\\xee\\x70\\xce\\x38\\x7c\\x16\\xd3\\x2a\\xd0\\xc0\\x54\\xe8\\x4a\\x14\\x9b\\x6c\\x95\\xee\\x45\\x91\\x02\\x16\\x6e\\xe5\\x22\\x73\\xdb\\x88\\xb9\\xa8\\x13\\x3e\\x75\\xb8\\x6e\\xca\\x24\\x01\\xc0\\x6b\\xe1\\x9a\\x1a\\xce\\xaf\\x07\\xd5\\x48\\xd5\\x35\\x20\\xcf\\xf7\\xa3\\x37\\xfb\\x31\\x71\\x2a\\xad\\x8a\\xbd\\xfc\\xfa\\x57\\x3b\\xf5\\x31\\xd6\\x45\\x37\\x74\\xf9\\xeb\\xb7\\x57\\xe7\\xcd\\x2b\\xbf\\x65\\x20\\xcb\\x42\\x4e\\x55\\x86\\x50\\xe5\\xf4\\x92\\x13\\xd6\\x3e\\x22\\x91\\xde\\x5f\\xed\\xd8\\x4b\\xe5\\xe8\\x82\\x47\\xec\\x2b\\x55\\xb7\\xed\\x66\\x4e\\x76\\x6e\\x5b\\x8e\\xc6\\xb8\\x97\\x54\\xc1\\x7f\\x63\\xd9\\x79\\x6f\\xea\\xb6\\xbf\\x3c\\xbb\\xff\\x71\\x60\\x58\\x62\\x07\\x17\\xde\\x19\\x80\\x0f\\xfc\\x95\\xd3\\x81\\x05\\x37\\x15\\x97\\x70\\xab\\x95\\x55\\xac\\xc8\\x78\\x7d\\x2f\\x15\\xee\\xc0\\x5f\\x90\\x6f\\x9c\\x4f\\x20\\xb9\\x7d\\xeb\\x7d\\xb4\\x47\\x06\\xa0\\x92\\x27\\xc7\\xc2\\x4e\\xca\\xe1\\x20\\x51\\xf9\\x89\\x3b\\xc6\\xf4\\x7f\\xc3\\x4c\\x0d\\x4f\\x72\\x6e\\x2c\\x68\\x27\\x62\\x7a\\xb6\\xd4\\x4f\\x5c\\x2f\\x42\\x8e\\x07\\x79\\x7a\\x3c\\x60\\xef\\x24\\x65\\xd7\\xd7\\xf7\\x60\\x36\\x6a\\x4b\\xb8\\xf1\\x43\\x9d\\x8f\\x21\\x38\\x8a\\xa8\\x74\\xf3\\xfa\\xf2\\xe1\\x0c\\xa7\\x37\\xd8\\xa7\\x50\\xf3\\xde\\x6c\\x64\\x4f\\xff\\xf8\\x87\\xf7\\x8d\\x47\\xca\\xc5\\x3a\\x30\\x92\\x3c\\x35\\x1f\\x78\\x67\\xb1\\x20\\x1d\\xf8\\xbe\\x1f\\x91\\xdf\\xfb\\xd1\\x88\\xb3\\x8f\\xc5\\xd7\\xfd\\x08\\xab\\x5d\\x77\\xe0\\xdf\\xee\\xc2\\xb7\\xdd\\x9d\\x5f\\xfb\\x3d\\x14\\x85\\x7e\\xca\\xfe\\xec\\x0e\\x8d\\x7e\\x1d\\xf9\\xb1\\x3f\\x84\\x0f\\xbb\\x93\\x55\\xef\\xeb\\xbb\\xfe\\x70\\x7e\\xeb\\x6e\\x96\\xdb\\xa5\\xba\\xf1\\x54\\x7d\\xd5\\x1d\\x18\\xef\\xbb\\x34\\xdc\\x77\\x66\\xb4\\x7f\\x6f\\xbe\\xe9\\xfd\\xfd\\xd2\\x8f\\xc0\\x27\\xbd\\x37\\x90\\x85\\x14\\x56\\xf0\\xec\\x02\\x32\\x3e\\xbb\\x86\\x44\\xc9\\x74\\x67\\x3e\\x36\\x57\\x8b\\xb4\\x3a\\x3f\\x86\\xba\\xf5\\x16\\xac\\x76\\xa2\\xc7\\x84\\xfb\\x92\\xeb\\x4e\\x6f\\xa3\\xc4\\x96\\xe0\\xe5\\xf0\\x62\\x0b\\xfa\\x9b\\x69\\x96\\x8f\\xd2\\x6f\\xc1\\x1e\\x8d\\xa9\\x8c\\xb2\\x5e\\xba\\xdc\\xc4\\xbf\\xa8\\x3b\\xa6\\x46\\x16\\x24\\x3b\\x12\\x32\\xec\\xe3\\x71\\x43\\xd9\\xac\\xed\\x96\\x15\\x5a\\xbb\\xa7\\xcf\\x9f\\x85\\x97\\x3f\\x3d\\x83\\x24\\x9a\\x5e\\x8d\\x79\\xff\\xf6\\x61\\x3f\\xd0\\xc3\\x06\\x62\\xff\\xe2\\xa8\\xcc\\xda\\x46\\x62\\x32\\x1c\\xb7\\xe9\\xcd\\xf3\\xba\\x68\\xf4\\x73\\xec\\xb7\\x3a\\x6d\\x5c\\xa6\\xcc\\x67\\xc2\\x7d\\x7a\\x9b\\xb6\\x77\\xc4\\x4d\\x5b\\xf4\\xab\\x22\\x6c\\x1e\\xb2\\x27\\xdf\\x9c\\x5f\\x45\\x73\\xf2\\xe3\\x32\\xca\\x7c\\xa4\\xa8\\x95\\x47\\x28\\xe8\\x3e\\xd1\\x48\\x95\\x28\\xe8\\x6e\\xd1\\x1a\\xb9\\xb1\\x5f\\x6b\\x9e\\xc0\\x55\\xe7\\x32\\x42\\x38\\x4e\\x2c\\x2d\\x35\\xf7\\x04\\xb0\\x12\\xf9\\xc2\\xe1\\x91\\x00\\x29\\x9d\\xa6\\x2a\\x9f\\x18\\x33\\x75\\x47\\x65\\x96\\xcd\\xc8\\xe6\\xd0\\xca\\xbe\\x26\\x2f\\xfc\\x7c\\x32\\x2f\\x1a\\xfe\\x97\\x8c\\x52\\x0b\\x96\\x85\\x56\\x9e\\x67\\xea\\x52\\x4a\\x47\\x83\\xeb\\x9b\\xdf\\x50\\x90\\xc4\\x62\\xd4\\xbc\\x95\\x32\\x6c\\xc4\\xd8\\x4d\\xdf\\xf1\\x3f\\xcc\\x26\\xae\\x43\\x13\\x5b\\x1d\\xba\\xaf\\x47\\x4a\\x27\\x62\\x98\\xcd\\xd8\\x84\\x67\\xd5\\x35\\x3f\\x9c\\xdd\\x8a\\x2c\\xf3\\xdd\\x0c\\xd8\\x35\\x58\\x72\\x5c\\x10\\xef\\xcc\\x94\\x1c\\xe3\\xe4\\xb8\\x0c\\xd7\\x4b\\x42\\xe2\\xbe\\x4d\\x32\\xe0\\xb2\\x2c\\x68\\x3c\\xc7\\x89\\x67\\xaa\\xd4\\x61\\xbc\\x41\\xe5\\xfe\\xa8\\x38\\xb0\\x14\\x59\\xaf\\x71\\x89\\xdd\\xda\\x8d\\xad\\x4d\\x34\\xc6\\x09\\x00\\x6f\\x42\\xf1\\xed\\x5e\\xb3\\xcf\\x50\\x1f\\xdd\\x34\\xae\\x30\\x2a\\xb4\\x9a\\x8a\\x94\\x7c\\x28\\x01\\x6c\\x78\\x5d\\x36\\x5d\\x53\\x54\\x9d\\x67\\xa9\\x64\\x5f\\xc2\\x98\\xa3\\xa0\\xe2\\x4f\\x11\\xed\\x19\\xf5\\x43\\xb1\\x05\\x32\\xc5\\x8b\\x8b\\x9c\\x84\\xaf\\x8a\\x56\\x3a\\xff\\x54\\xd0\\x95\\xcb\\x0d\\xc8\\xb1\\x23\\xa9\\x98\\xc2\\x48\\xd5\\x52\\x0a\\x4b\\xd7\\xf8\\x4f\\x4a\\xcb\\x52\\x75\\x27\\x8f\\xbd\\xcd\\x4a\\x18\\xc6\\xd9\\x10\\x2c\\x6f\\xc4\\x9a\\x7a\\x06\\x67\\x18\\x48\\x3e\\xcc\\xdc\\x9e\\x63\\x28\\xd6\\xcd\\x52\\x00\\xb1\\x11\\x70\\x5b\\x6a\\x60\\x63\\x6e\\x61\\xa9\\x9c\\x43\\xeb\\x5d\\x0f\\x5e\\x61\\xbc\\x81\\x75\\xc4\\x4a\\x69\\x60\\x4f\\xf6\\xde\\x99\\x70\\xf4\\xbb\\xdf\\xec\\x46\\x23\\x44\\x0e\\xaa\\xb4\\x1f\\x44\\xfb\\xbb\\x9b\\x88\\x64\\xd2\\x14\\x66\\x45\\x0e\\x86\\xa9\\x72\\x4e\\x2d\\x7e\\xee\\x3f\\x5b\\xbe\\x43\\x51\\x05\\x5c\\xd6\\x76\\x35\\x1f\\x2f\\xb1\\x7e\\xcd\\x97\\x63\\xa8\\xef\\xf7\\xc6\\x08\\xf2\\x8b\\xd7\\xd7\\x7f\\x7f\\x79\\xf6\\x3f\\x2f\\x5e\\x0e\\xd8\\x0b\\x9e\\x4c\\x9a\\x35\\x39\\x24\\xe3\\x48\\x34\\x90\\x50\\x4c\\xf8\\x14\\x18\\x67\\xa5\\x14\\xff\\x2c\\xbd\\x5b\\xf9\\xa8\\xfa\\xf6\\xb8\\xd3\\x8a\\xf4\\x3b\\x72\\x5f\\x47\\x6d\\x76\\xc2\\xf8\\xa5\\x97\\xde\\x61\\x6f\\x3e\\x62\\x4b\\x19\\xc0\\x6b\\x6a\\x16\\xc4\\xa7\\xca\\x97\\x3d\\x23\\x15\\x01\\x05\\x2e\\x0c\\xac\\xbf\\x78\\xf3\\xe2\\x1a\\x03\\xf6\\x0b\\x4d\\x95\\x4a\\x30\\xc2\\x0b\\x9f\\x63\\x4f\\x43\\x70\\x5f\\xf8\\xfb\\x89\\x07\\xec\\x4c\\xce\\xe8\\x21\\x9d\\x29\\x61\\x58\\x26\\x8c\\x05\\xe4\\x7a\\x5e\\x6c\\x0b\\x5e\\xf2\\x83\\x67\\x03\\xfc\\xdf\\x01\\xe3\\x69\\xaa\\x9d\\x5c\\x57\\x05\\xae\\x25\\x0b\\x91\\xa4\\x24\\xf9\\x89\\x61\\xd6\\x58\\x80\\x04\\x4b\\x71\\x6a\\xaf\\x54\\xea\\x67\\x8e\\x9c\\x04\\x3d\\x64\\xc4\\x06\\x8d\\xd5\\xdc\\xc2\\x58\\x24\\x2c\\x07\\x3d\\x06\\x56\\x70\\x9b\\x4c\\x58\\xce\\x67\\x2c\\x51\\x5a\\x97\\x05\\xdd\\x66\\x90\\x72\\xcb\\x07\\xec\\x2b\\xa5\\x59\\x1e\\x0e\\xb1\\xc3\\x79\\xc7\\x87\\xaf\\x97\\x47\\x0e\\xd4\\x27\\xbb\\xf9\\x4f\\x61\\x4c\\x09\\xe6\\xe4\\xf9\\xb3\\xdf\\xff\\xea\\xb7\\xbf\\xfd\\xa4\\x2e\\xc0\\xab\\x42\\x7b\\x31\\xee\\xa5\\x71\\x01\\x1e\\x0f\\xbb\\x40\\xbb\\x4e\\x17\\x22\\x0a\\x39\\xce\\x9a\\xf8\\xb5\\x1b\\x03\\xd8\\x57\\xcb\\xdc\\x57\\xc7\\xec\\xd7\\x2b\\xb8\\xda\\x55\\xd5\\xec\\xe4\\x22\\xbe\\x7a\\x0e\\x1d\\x5d\\x5f\\x55\\xf3\\xc1\\xa0\\x58\\x79\\xda\\xa0\\x9a\\x37\\x12\\x5f\\x5e\\x85\\x83\\xe9\\xe5\\x9c\\x7c\\xee\\x1a\\xdb\\xa2\\x8e\\x81\\xea\\xb1\\x67\\xec\\x8f\\xec\\x9e\\xfd\\x11\\x15\\xad\\xdf\\xed\\x7b\\xd9\\xd7\\xbe\\x2a\\x50\\x17\\x21\\x4d\\x4e\\xbf\\xbf\\xbc\\xea\\x08\\xe2\\x7f\\x75\\x44\\xd3\\xf5\\xe8\\xa0\\x6a\\x15\\x1b\\x0a\\x2f\\xd8\\xc3\\xbd\\x05\\xed\\x04\\x4d\\xbf\\x13\\x1f\\xf5\\x9a\\x34\\x37\\xc1\\x0f\\x88\\x66\\xe4\\x78\\xb8\\x1c\\xb5\\xc3\\xa8\\xb6\\x43\\x34\\xf7\\xf9\\x5f\\x94\\xb1\\xaf\\x3d\\x15\\x6a\\x5f\\xf8\\x53\\xf7\\x96\\x23\\xe1\\x6f\\x91\\x31\\xc7\\x37\\x8c\\xad\\x0f\\x98\\x61\\xa9\\xc2\\xa8\\x2e\\x0a\\x71\\x9e\\x88\\x3d\\x82\\x35\\x1e\\x0f\\x1a\\xef\\xe7\\xbf\\x6f\\xed\\xe7\\xba\\x9d\\x9a\\x33\\xa5\\xa0\\x0e\\xe4\\x45\\xac\\x46\\x8d\\xae\\x42\\xa5\\x5e\\x3a\\x73\\xd3\\x4a\\x1b\\x3c\\x63\\x8d\\x78\\xe6\\xad\\x36\\x95\\xbd\\x19\\x71\\xc9\\x9d\\xa7\\x84\\x4b\\x4a\\x32\\x19\\x81\\xd6\\x14\\x95\\x3e\\x9c\\x85\\xe0\\xc0\\xbd\\x37\\x6f\\xaf\\x93\\x54\\x68\\x65\\x55\\xa2\\xf6\\xb8\\xc9\\xad\\xed\\xed\\xf6\\xdd\\x21\\x10\\x0a\\xc2\\x5d\\x0f\\xf9\\x6f\\x2f\\xae\\x7a\\xec\\xe6\\xfc\\x0a\\x6f\\xb7\\xba\\x3e\\xbf\\xb9\\x6a\\xeb\\x2c\\x07\\x37\\xe7\\x57\\x07\\x1f\\x15\\x14\\x2c\\x08\\x7c\\x68\\xa2\\xde\\xa1\\x93\\x96\\x09\\xca\\x49\\x93\\xfd\\x9c\\x17\\xfd\\x5b\\x98\\xed\\xc8\\x53\\xbb\\xe0\\xeb\\xfd\\x6a\\x87\\x3b\\x59\\x10\\x81\\x39\\xe7\\xc5\\xd6\\xbd\\x69\\xe0\\xa9\\xf8\\x40\\x99\\x5e\\x21\\xec\\xb6\\x1a\\x73\\x79\\xca\\x57\\xae\\xa6\\x90\\x92\\x94\\x1e\\xbe\\x00\\x99\\x16\\x4a\\x38\\x79\\x31\\xe6\\x81\\x6d\\xff\\x75\\xcc\\x03\\xdb\\xb8\\xc5\\x3c\\xb0\\x98\\x07\\xb6\\xd8\\x1e\\x4d\\xe0\\x6c\\xcc\\x03\\xfb\\xb4\\x3c\\xf8\\x31\\x0f\\x6c\\xfb\\xf6\\xd1\\x1d\\xf7\\x31\\x0f\\x6c\\x79\\x8b\\x79\\x60\\x31\\x0f\\x6c\\xb3\\x16\\xf3\\xc0\\xb6\\x6f\\x8f\\x2e\\xe4\\x28\\xe6\\x81\\x6d\\xd5\\x62\\x1e\\xd8\\x62\\x8b\\x79\\x60\\x2b\\x5a\\xcc\\x03\\x5b\\xd1\\x62\\x1e\\xd8\\x62\\x8b\\x79\\x60\\xdb\\xb5\\x98\\x07\\x16\\xf3\\xc0\\x3e\\xe9\\xf0\\x58\\x16\\xf3\\xc0\\x7c\\x8b\\x79\\x60\\x9f\\x44\\x10\\x20\\x8b\\x79\\x60\\x1b\\xb5\\x98\\x07\\x16\\xf3\\xc0\\x76\\x69\\x31\\x0f\\xec\\x53\\x31\\xca\\xc4\\x3c\\xb0\\x98\\x07\\xf6\\xf3\\x11\\x74\\x63\\x1e\\x58\\xcc\\x03\\x8b\\x79\\x60\\x31\\x0f\\x6c\\xed\\x2c\\x62\\x1e\\xd8\\xa7\\xa0\\x02\\x6a\\x30\\xe2\\x5f\\x70\\xa5\\x32\\x91\\xcc\\xf6\\x8e\\x52\\x7c\\xeb\\x2f\\x3e\\x36\\xbe\\x5b\\x56\\x60\\xbf\\x8d\\xd0\\xaa\\x3d\\x32\\x4f\\x1e\\x59\\xc2\\xcd\\xdb\\x06\\xe0\\x9a\\x89\\x37\\xd5\\xe5\\xcf\\xef\\x01\\x04\\x8f\\x22\\xf9\\x26\\x2c\\xf0\\xf5\\xee\\x9e\\x94\\x7e\\xb8\\x80\\x80\\xc0\\xb7\\x9b\\xdd\\x62\\x6f\\x15\\xa1\\xb9\\x90\\x8e\\xe2\\xc1\\x0f\\x9b\\x19\\x91\\x15\\x26\\x58\\x55\\x51\\x30\\xb1\\x12\\x41\\x78\\x51\\x64\\x02\\xcc\\x80\\x5d\\x57\\x17\\xf0\\x20\\xf5\\x32\\xa7\\x2c\\x29\\xca\\x1e\\xcb\\x21\\x57\\x7a\\xb6\\x87\\x36\\xd1\\x81\\xc0\\xd9\\xda\\xb5\\x8e\\x40\\xf6\\x96\\xfa\\x0c\\x60\\x70\\x4a\\x44\\x51\\x64\\x33\\x12\\xa6\\xea\\x54\\xd2\\x0a\\x6a\\x22\\x10\\x97\\x14\\xc5\\x9d\\xb9\\x28\\x0f\\x61\\x5b\\x6a\\xd8\\x6b\\x65\\xdf\\x7a\\x84\\xff\\x68\\xb1\\xf6\\xab\\xa2\\xca\\xb9\\x55\\xb9\\x48\\x76\\x21\\xd8\\x44\\x63\\xf7\\x8f\\x29\\x3f\\x57\\x79\\x51\\x5a\\x68\\x91\\x6d\\x02\\x16\\x49\\x72\\xc2\\x34\\x55\\xb8\\xfd\\xa3\\xc1\\x13\\x25\\x47\\x62\\xec\\x45\\xf1\\x13\\xba\\xd1\\xbd\\x5f\\xad\\xa7\\xdf\\xb8\\x45\\xfd\\x09\\x86\\x82\\x27\\x19\\x17\\xbb\\xfb\\xed\\xdb\\xa1\\x55\\xe7\\xd8\\x17\\x66\\xe8\\xd6\\xc1\\x55\\x18\\xa3\\x5b\\x41\\xab\\x57\\x05\\x2e\\x09\\x3a\\x26\\x83\\xf0\\x88\\x3e\\xee\\x51\\xa4\\xaf\\xd3\\x3f\\x50\\xe8\\x5c\\xb2\\xa1\\xef\\x64\\x2d\\x1e\\x4b\\xc6\\xb3\\x62\\xb2\\x5e\\x40\\x76\\x13\\xb9\\x98\\x49\\x9e\\x8b\\x24\\x60\\xcc\\x59\\x96\\xa9\\x84\\x14\\xa2\\xb6\\x88\\x1c\\xfa\\xa6\\xfe\\xdc\\x20\\x79\\x5e\\x5a\\x3e\\xcc\\x60\\xc0\\x2e\\x29\\x43\\x48\\xc9\\x6c\\xe6\\xb0\\xc9\\x80\\x0d\\x8e\\x0f\\xbf\\xfd\\x3b\\xc7\\x60\\xed\\x1f\\x80\\xb1\\x67\\xf0\\xc5\\x52\\x69\\x08\\x37\\x84\\xb2\\xa1\\x40\\xba\\x53\\xa6\\x24\\x30\\x90\\x56\\xcf\\xdc\\xde\\x5d\\xa9\\xf4\\xda\\x6d\\x5f\\xeb\\xed\\xbd\\x93\\xa4\\xf6\\x8c\\xb9\\xe8\\x22\\xde\\x62\\xcf\\x58\\x8b\\x6e\\x22\\x24\\xf6\\x8f\\x8e\\x58\\x74\\xf3\\x36\\xf2\\x16\\x9b\\x81\\x8f\\xad\\x5d\\x2d\\x54\\x3a\\x58\\x72\\x2a\\x83\\x68\\x70\\xa5\\x52\\xc7\\xe0\\x34\\x34\\xaf\\xc2\\xf3\\xfa\\x21\\x1e\\x90\\x9c\\xdf\\xa2\\x8a\\xcd\\x6d\\xcd\\xf9\\xf8\\x94\\x8b\\xcc\\x1d\\xa1\\x25\\xf9\\xf8\\xfb\\x05\\x4e\\x74\\x20\\x1a\\x74\\x9d\\x0c\\xc6\\xf6\\xc5\\xa0\\x2e\\x93\\xb9\\x18\\xde\\xdc\\x95\\x8b\\xdd\\xaa\\x3f\\xb0\\x05\\xc6\\xfb\\x12\\xfb\\x6a\\x84\\x63\\x39\\x9c\\xc8\\xf9\\x3d\\xea\\xac\\x3c\\x57\\xa5\\xb4\\x94\\xe1\\x45\\xfc\\xb9\\x22\\xfa\\x14\\xb4\\xf6\\xe8\\x38\\x2f\\xeb\\x86\\xec\\xf0\\x34\\xa4\\xc0\\x5c\\x75\\x11\\x4d\\xce\\xad\\x05\\x2d\\x4f\\xd9\\xff\\x1e\\xbd\\xfb\\xe5\\x4f\\xfd\\xe3\\x2f\\x8f\\x8e\\xbe\\x7f\\xd6\\xff\\xc3\\x0f\\xbf\\x3c\\x7a\\x37\\xc0\\x7f\\x7c\\x71\\xfc\\xe5\\xf1\\x4f\\xe1\\x8f\\x5f\\x1e\\x1f\\x1f\\x1d\\x7d\\xff\\xcd\\xab\\xaf\\x6f\\xae\\x5e\\xfc\\x20\\x8e\\x7f\\xfa\\x5e\\x96\\xf9\\x2d\\xfd\\xf5\\xd3\\xd1\\xf7\\xf0\\xe2\\x87\\x0d\\x3b\\x39\\x3e\\xfe\\xf2\\xf3\\x9d\\xa7\\xbc\\xb7\\x8d\\xba\\x3b\\x0b\\x75\\x47\\xf6\\xe9\\xf7\\x62\\x9d\\xf6\\x71\\x9c\\x1d\\x9d\\x45\\x1f\\x83\\xbe\\x70\\x1a\\xbd\\x05\\x69\\xdd\\x69\\x0c\\x5c\\x12\\x15\\x91\\xaa\\x1f\\x61\\x98\\xca\\x85\\x75\\x0a\\x9c\\x13\\x6b\\x78\\x33\\xf3\\x6c\\x4e\\x3d\\xf1\\x74\\x00\\x73\\x2f\\x39\\xa6\\x88\\x35\\xb2\\xb6\\x1a\\x5a\\x8d\\x0a\\xa6\\x58\\x54\\x8f\\x24\\x13\\x79\\x91\\x41\\x0e\\xd2\\xe2\\x79\\xee\\x07\\x49\\x10\\xf5\\xc5\\x41\\x3d\\x93\\x84\\x24\\x76\\xb8\\x4f\\x00\\x52\\x3f\\x58\\x24\\x1d\\x0f\\xb7\\x48\\x3a\\x3e\\x45\\xd2\\x61\\x20\\x29\\xb5\\xb0\\xb3\\x73\\x25\\x2d\\xdc\\xef\\xe4\\x11\\x6d\\x53\\x8e\\xeb\\x76\\x87\\x5e\\x21\\xf3\\x31\\xad\\xfe\\x19\\x53\\x05\\x65\\x70\\xce\\x95\\xc8\\x9a\\xa8\\x32\\x4b\\x31\\x2d\\xbb\\x94\\xe8\\x10\\xa2\\x7a\\x1b\\x60\\xc9\\x5b\\x83\\x02\\x21\\x4a\\x8b\\xf3\\x83\\x04\\xff\\x0b\\xb9\\x85\\xfe\\x59\\x8a\\x29\\xcf\\x40\\xda\\xc6\\x17\\x57\\xe8\\x71\\x68\\x7e\\xb4\\xe9\\x99\\xb7\\xdc\\xdc\\xd6\\x07\\x1e\\xfa\\x85\\x4a\\xeb\\xf3\\x7d\\x12\\x96\\x84\\x3f\\xc1\\xbd\\x7d\\x8a\\x4a\\x3a\\xca\\x4f\\x57\\x5a\\x4c\\x45\\x06\\x63\\x78\\x61\\x12\\x9e\\x21\\x5d\\xeb\\x86\\x95\\x9c\\xad\\xe8\\x1d\\x37\\x5e\\xab\\xcc\\x38\\x99\\xdf\\x91\\x72\\xc6\\x83\\xcb\\x0e\\x35\\xe1\\x31\\x17\\x92\\x2a\\x5c\\x15\\xe1\\x63\\x43\\xbe\\x3f\\xc7\\x1d\\x0a\\xae\\xdd\\x06\\x57\\x3e\\x3e\\xd4\\xab\\x87\\x4a\\x65\\x3e\\x77\\x39\\x9b\\xd5\\xfd\\xfb\\x2c\\x7e\\xa9\\xfe\\x2e\\xe1\\xee\\xef\\xae\\x37\\xc3\\x46\\x19\\x1f\\x57\\xae\\x3d\\xa7\\x6c\\xcf\\x7b\\xe7\\xeb\\xae\\x57\\x2e\\x00\\x13\\x83\\x4b\\x60\\x3c\\xbb\\xe3\\x33\\x53\\x3b\\x3a\\x1b\\xb5\\xdc\\xcc\\x29\\x7b\\x7e\\x8c\\xe8\\xcc\\x0d\\xab\\xfa\\x48\\xd9\\xaf\\x8e\\x31\\x5c\\xef\\xfc\\xec\\xea\\xef\\xd7\\x7f\\xbb\\xfe\\xfb\\xd9\\xc5\\xab\\xcb\\xd7\\xec\\xb5\\xb2\\x40\\x3c\\xaf\\xa1\\xff\\x24\\x95\\x81\\xc9\\xcd\\xb2\\xb2\\xff\\x0d\\x94\\x19\\xa0\\x8e\\x85\\xd1\\xe7\\x32\\x55\\x77\\x66\\x67\\x2b\\x28\\xa1\\x9f\\x03\\x1e\\x70\\xb9\\x9b\\x99\\x87\\x17\\x1c\\x6f\\x38\\xdf\\x83\\xc3\\x2c\\x44\\x84\\x37\\x3b\\x45\\x16\\x9f\\xa6\\x27\\xa9\\x56\\x05\\x01\\x21\\x38\\xa5\\x1b\\x06\\x92\\x96\\xdb\\xab\\x99\\xd9\\x86\\xfb\\x3b\\x6a\\x77\\x38\\xd6\\x5c\\xda\\xda\\x3b\\x5b\\xef\\x99\\xbf\\x5a\\x7d\\xb0\\xf7\\x76\\x7c\\x3c\\xc6\\xdf\\x85\\x95\\x80\\xa7\\xdd\\xd5\\x25\\x38\\x4b\\x53\\x48\\x5b\\xe0\\xff\\xe4\\xf2\\x89\\xce\\xc3\\xe2\\x1a\\x6e\\x2f\\x76\\xf5\\xe6\\xfa\\xf2\\xff\\x9b\\xc3\\xe3\\x59\\xb1\\x5f\\x62\\x43\\x37\\x35\\x6e\\xb4\\x2a\\x3a\\xdb\\xdd\\xb7\\xbe\\x86\\x4a\\xdc\\xdf\\x47\\xb1\\xbf\\x15\\xb7\\xec\\x26\\x9c\\xf6\\x6d\\x29\\xdb\\xc5\\x49\\xeb\\xfe\\x59\\xae\\x52\\x18\\xb0\\xab\\x2a\\xae\\xa7\\xfd\\xb4\\x51\\xaa\\x8c\\x6b\\x60\\xee\\x15\\x69\\x05\\xcf\\xb2\\x59\\x53\\x44\\xb3\\x8a\\xea\\x89\\xb4\\xaa\\xac\\x35\\x09\\xf9\\x88\\x67\\xe6\\x63\\x53\\xe3\\x7d\\x78\\xa3\\x93\\x23\\x5e\\x39\\x75\\xb9\\x93\\xed\\xa8\\x7a\\x63\\x29\\x48\\x65\\xbd\\x60\\xed\\x66\\x89\\x95\\xeb\\xb4\\x4a\\x18\\xe9\\xe6\\x8d\\xe4\\x89\\x16\\x7f\\x33\\x14\\x5b\\x14\\x58\\xa3\\x30\\x01\\xd8\\x57\\x55\\xcf\\xe4\\x96\\x2d\\x0d\\xcc\\x0b\\xe8\\x9e\\x35\\xd6\\xda\\xba\\xeb\\x5d\\x03\\x4f\\xd1\\x6b\\x51\\x70\\x3b\\xa1\\xd8\\xe7\\x9c\\x9b\\x5b\\x48\\xe9\\x07\\x2f\\x9a\\x55\\x8e\\x13\\x34\\xf4\\x86\\xa1\\x6e\\xdc\\xbc\\x83\\x8f\\x04\\x45\\x32\\x8a\\xc8\\x46\\xef\\x0a\\xa4\\x1f\\x79\\xd7\\xf7\\x38\\x84\\x0e\\x28\\x6f\\x64\\x36\\x7b\\xab\\x94\\xfd\\xaa\\x2a\\x88\\xd3\\x09\\x06\\xfc\\xd5\\x4b\\xcb\\x6d\\xc7\\x15\\x8a\\x93\\x1c\\xc7\\xed\\xe3\\x6e\\xe0\\xa1\\x6a\\xd6\\xe2\\xb9\\xa8\\x77\\xfc\\xa9\\x1f\\x29\\x5d\\xca\\x33\\xf3\\xb5\\x56\\xe5\\xce\\x4c\\x6c\\x41\\xd8\\xfc\\xfa\\xf2\\x02\\x49\\x51\\xe9\\x43\\x0b\\xa5\\xd5\\x33\\x2c\\x02\\xb6\\x58\\xc9\\xb9\\x52\\x0c\\xbe\\xf5\\xc1\\x91\\xcd\\x33\\x51\\xc7\\xb1\\xb1\\x57\\x7c\\xc6\\x78\\x66\\x54\\x80\\xa5\\x77\\x6b\\xcd\\x6b\\xa1\\x5e\\xc5\\x75\\x8f\\x87\\xca\\x4e\\x16\\x74\\x5b\\x77\\xa0\\x16\\xbf\\xeb\\x35\\x22\\x0d\\xeb\\x78\\x00\\x21\\x17\\x3e\\xb7\\xe8\\x33\\x29\\x34\\x24\\x90\\x82\\x4c\\x3e\\xf6\\xb6\\x7f\\xec\\x00\\x3d\\x44\\x9d\\xd7\\x4a\\xba\\x83\\xd9\\x09\\xf2\\x5c\\x56\\x91\\x99\\x1e\\xa4\\x4d\\x54\\x41\\xa7\\x98\\xd7\\xfe\\x38\\x46\\x7a\\xe2\\xb1\\x2c\\x0d\\x68\\x0a\\x4b\\xd5\\x25\\xd0\\x4e\\x7e\\x53\\x0e\\x21\\x73\\x90\\x77\\x2a\\x29\\xd6\\x11\\xe5\\x96\\xcc\\x19\\x22\\xe7\\x63\\x60\\xdc\\x56\\x98\\x66\\x15\\x03\\x69\\x4a\\xed\\x37\\x51\\x58\\x96\\x2a\\xa8\\xeb\\x68\\x71\\xc3\\xbe\\xbd\\xbc\\x60\\xcf\\xd8\\x91\\x1b\\xeb\\x18\\xf1\\x67\\xc4\\x45\\x86\\x41\\xa0\\x18\\x54\\x32\\xa7\\xa3\\x8e\\x42\\x17\\x38\\x25\\x44\\x5e\\xa6\\x34\\x11\\x89\\x1e\\x93\\x8a\\x99\\x32\\x99\\x84\\x39\\x39\\xbd\\x37\\xa8\\xcd\\x3e\\x71\\x09\\x3d\\x2f\\x8f\\x13\\xd7\\x3f\\x2e\\x85\\xfa\\xd6\\x80\\xee\\x8c\\x40\\x7d\\xbb\\x03\\x81\\x6a\\x8a\\x51\\x0e\\xe7\\xda\\xd0\\x23\\xc4\\xca\\xc1\\xf2\\x94\\x5b\\xee\\x09\\x57\\x78\\xe1\\xd1\\x6e\\xe9\\xcf\\x9b\\x7c\\x19\\x78\\x29\\x64\\x79\\x4f\\x89\\x02\\xdd\\x99\\x5a\\xae\\x5f\\x60\\xb7\\x2c\\x09\\x50\\xc7\\x5d\\xa7\\xe0\\xbb\\x34\\x58\\x53\\x1a\\x41\\x32\\x97\\x2d\\x5c\\xe9\\xad\\x10\\x13\\x91\\x4e\\x70\\x0a\\x86\\x01\\x27\\x9c\\x70\\x99\\xaa\\x7c\\x61\\x30\\x27\\x44\\x42\\xeb\\x0e\\x84\\x01\\x8b\\xd8\\xd7\\x6e\\x8f\\xc4\\x28\\x94\\xc1\\x14\\xf6\\xa8\\x12\\x3c\\x7f\\xe7\\x83\\xeb\\xcd\\x01\\x27\\x60\\x04\\x76\\xcf\\x32\\x3e\\x84\\xcc\\x07\\x6a\\x51\\xf8\\xe7\\x22\\x06\\x7e\\xec\\xec\\x31\\xad\\xb2\\xee\\xd2\\xdd\\xdf\\xaa\\x0c\\x28\\x1d\\x23\\x00\\xc2\\x75\\xff\\x24\\xe0\\x80\\x9d\\x74\\x05\\x07\\xd4\\x06\\x5b\\x70\\x40\\xbd\\xf6\\x29\\xc0\\xa1\\xdc\\x83\\xd5\\xb3\\x79\\x38\\x38\\xb9\\xa1\\x0d\\x07\\x64\\xde\\x8f\\x1d\\x0e\\x06\\x92\\x44\\xe5\\xc5\\x95\\x56\\x4e\\xed\\xec\\x8c\\x37\\xf9\\x6e\\x6b\\x9f\\x21\\x19\\x36\\x96\\x84\\x6e\\x22\\x2f\\x68\\xbf\\xcc\\x75\\x23\\x11\\x8b\\x5b\\x62\\x12\\x21\\x1b\\xeb\\xff\\x69\\xf0\\x2c\\x24\\x3d\\xf3\\x8c\\x2c\\xf4\\xd2\\x72\\x2f\\xba\\x2f\\xfd\\x83\\xa7\\xcc\\x0e\\xba\\xc8\\x65\\xde\\xc3\\xd8\\xd9\\x09\\x37\\x52\\x09\\xcf\\xf0\\x16\\x88\\xfd\\x50\\x8e\\xcd\\xa3\\xdd\\x7c\\xc7\\x8d\\xf4\\x3b\\xf4\\x51\\xe2\\x6f\\x8d\\x48\\x63\\x8e\\x86\\x96\\x60\\xc2\\x94\\x2a\\x85\\x86\\x2f\\x9b\\xa2\\x17\\x6f\\x28\\x4d\\x0b\\xdf\\x0b\\x99\\x7f\\x4e\\xae\\x08\\x6e\\xe5\\xb4\\xf5\\xb5\\x55\\xbe\\x96\\xf1\\xab\\xea\\x6e\\x09\\x37\\x41\\x90\\xa9\\x90\\x63\\xb4\\xab\\xf5\\x98\\x86\\x8c\\x72\\x06\\x3d\\x11\\xb8\\x25\\x0d\\xf2\\x10\\x8f\\x44\\xe8\\x34\\x9c\\x87\\x30\\x74\\x08\\x4c\\xf6\\x3d\\x37\\xa3\\x8d\\xc5\\x88\\xc8\\xad\\x30\\xec\\xe0\\x65\\x00\\xc0\\x1e\\xc5\\xf8\\x1f\\x23\\x87\\x39\\xa0\\x15\\x56\\xbb\\x49\\x96\\xce\\x5b\\x21\\x53\\x9f\\x5e\\xd7\\x02\\x56\\x75\\x9b\\x13\\xc9\\xc1\\x98\\xb8\\x29\\xd2\\x26\\x6d\\x39\\x65\\xef\\x24\\xab\\x80\\xc5\\xfa\\x3b\\xa3\\xc7\\x5b\\x12\\x99\\x83\\x8d\\xae\\xbf\\xde\\xf0\\x5a\\x0d\\x32\\xdf\\xcd\\xb7\\x12\\xf7\\xde\\x8d\\xdb\\x77\\x9a\\xfb\\xe2\\x7b\\x61\\x2d\\x1f\\xb5\\xa0\\xa7\\xa7\\x7e\\x5d\\x6b\\x31\\x7f\\xa5\\x6e\\x83\\x48\\x9f\\x38\\xb4\\xb6\\x42\\x8e\\x4d\\x53\\x93\\xe1\\x59\\xd6\\x32\\x86\\x2f\\x53\\x65\\xc2\\x0e\\x57\\x77\\x77\\x2d\\xaa\\x10\\x73\\x69\\xc1\\x4f\\x45\\x0d\\xc9\\x9c\\x38\\xf1\\xc4\\x95\\x90\\x71\\x6e\\xf8\\xb9\\x76\\x90\\xb0\\x82\\x67\\xd7\\xc5\\xee\\x97\\x0d\\xb0\\x85\\xc2\\xd6\\xaf\\xae\\xcf\\xda\\x5d\\x23\\xb3\\xf6\\x31\\xe9\\x80\\xcf\\x19\\x4f\\x73\\x61\\x0c\\x1a\\xc2\\x60\\x38\\x51\\xea\\x96\\x1d\\xad\\xbd\\x73\\xad\\x6f\\xc4\\xd8\\x9c\\x78\\x9c\\xef\\xbb\\xd9\\x1f\\x33\\x21\\xb3\\x2a\\x2a\\x0a\\xf5\\x60\\x69\\xab\\x30\\x78\\x1c\\x24\\xa9\\x66\\x81\\x7b\\xe8\\x6f\\xa0\\xf1\\xc1\\x0a\\x8b\\xd3\\xa4\\x3b\\x67\\x1c\\x16\\x7c\\x74\\x82\\xbd\\xb8\\x3d\\xfb\\xa5\\x12\\x3e\\xb8\\x45\\xaf\\x3d\\x6e\\xcf\\xd7\\x5b\\x5e\\x0a\\x47\\x92\\x1e\\x3f\\x3a\\x90\\xbc\\x70\\x91\\x80\\xe9\\xae\\xcc\\xeb\\x5f\\xea\\x3e\\x59\\x0a\\x94\\x75\\x0f\\x18\\xfd\\xc4\\x57\\x06\\xd9\\xa1\\x5d\\xfa\\x10\\x8b\\xb7\\xf8\\x4f\\x0f\\x9b\\x12\\x75\\x3b\\x5b\\x09\\x93\\xa1\\xfa\\xa4\\xa4\\x3b\\x8a\\x86\\x24\\x30\\x88\\x10\\x13\\x25\\x95\\xcf\\x91\\x73\\x4c\\x54\\x49\\x44\\x69\\x24\\x51\\xe4\\xcd\\xc3\\x3d\\xf1\\x24\\xba\\x31\\xd5\\xf3\\xda\\x4b\\xdc\\x74\\x04\\x62\\xf1\\x07\\x5b\\x5d\\x92\\x48\\x73\\xb8\\x13\\x76\\x82\\x37\\x36\\x4c\\xe6\\xbc\\x86\\x38\\x13\\x0d\\x06\\x1d\\x30\\x92\\x81\\xd6\\x4a\\xfb\\x80\\xac\\x60\\xb7\\xf6\\xa9\\x5a\\x57\\x2a\\xc5\\x88\\x2e\\x87\\x24\\xdc\\xfd\\x75\\x68\\x9a\\x8e\\xea\\xfa\\x52\\xa7\\xaa\\x06\\x27\\x8c\\x46\\x90\\xa0\\xa0\\xd5\\x04\\x30\\x51\\xed\\xa3\\xfa\\x0a\\x0b\\x9f\\x84\\xe0\\x10\\xcc\\x5f\\x0a\\x95\\x8b\\x7b\\x37\\x4a\\xf3\\xab\\xa6\\x4b\\xdc\\x5f\\x1d\\xb1\\xfc\\xf1\\xf1\\x80\\xb1\\x4b\\x59\\x45\\xf0\\xf6\\xdc\\x2e\\x36\\xdf\\x0c\\xa1\\x67\\xd6\\x2d\\xb1\\x79\\xa3\\x18\\x2e\\xa0\\x69\\x38\\x73\\xd2\\xa1\\x2e\\x3b\\xc0\\xf8\\x7d\\xcc\\xe1\\xac\\x69\\x12\\xef\\x94\\x1c\\xa0\\x69\\xdc\\x77\\xea\\xb6\\x3e\\xc8\\x00\\xfb\\x98\\xca\\xdd\\x2b\\xef\\xcb\\x5c\\xfe\\x34\\x1c\\x20\\x6c\\x5f\\x3a\\xe7\\xab\\x9f\\x75\\x74\\xcd\\xd3\\x75\\xa3\\xb7\\x86\\xf4\\x5e\\x39\\xdc\\xae\\x54\\x4a\\xd5\\x0f\\xab\\xea\\x6d\\xd9\\x2c\\x54\\x63\\xac\\x72\\xa2\\x1b\\x32\\x9e\\x54\\x94\\x3c\\xd0\\x2c\\x8b\\xe8\\x2f\\xc7\\x49\\x99\\x13\\xb5\\xb3\\x60\\x5b\\xc8\\x8b\\x0c\\xb0\\xea\\x4a\\xa3\\xe7\\xba\\xa0\\x4c\\xe3\\x5e\\xa8\\x5e\\x9d\\xc1\\x56\\x5d\\x2d\\xe5\\x8b\\x31\\xf6\\xd8\\x3f\\xf0\\x50\\x56\\x81\\xa8\\xa1\\x4e\\xdc\\x55\\xf5\\x39\\x69\\x88\\xc2\\x84\\x4b\\xe2\\x30\\x39\\xd5\\xaa\\x60\\xba\\x60\\xa9\\x18\\x61\\x9e\\xa4\\xf5\\x43\\x16\\x5c\\xf3\\xdc\\x91\\x78\\xc3\\x3c\\x08\\x86\\x30\\x16\\x14\\x10\\x59\\x11\\xb6\\x43\\x27\\xee\\xf9\\xda\\x1c\\x3d\\x22\\x86\\xc2\\xb2\\x5c\\x8c\\x27\\x84\\x28\\x8c\\x63\\x45\\x1d\\x16\\x9c\\x8a\\x99\\xe2\\x29\\x5e\\x2e\\xcb\\x94\\x66\\x77\\x5c\\xe7\\x8e\\x6f\\xf0\\x64\\x82\\x1e\\x4a\\x2e\\x59\\x5a\\x6a\\xbc\\x2f\\xc5\\x02\\x4f\\x67\\x7d\\x63\\xb9\\x75\\x92\\x32\\x68\\xaf\\x50\\x86\\xf9\\xc7\\xcb\\xb1\\xd6\\xb6\\x78\\x39\\xd6\\x86\\x2d\\x5e\\x8e\\x15\\x2f\\xc7\\x5a\\x6c\\x8f\\x26\\x3a\\x34\\x5e\\x8e\\xf5\\x69\\x95\\x35\\x8d\\x97\\x63\\x6d\\xdf\\x3e\\x7a\\x35\\xd3\\x78\\x39\\xd6\\xf2\\x16\\x2f\\xc7\\x8a\\x97\\x63\\x6d\\xd6\\xe2\\xe5\\x58\\xdb\\xb7\\x47\\x57\\x87\\x39\\x5e\\x8e\\xb5\\x55\\x8b\\x97\\x63\\x2d\\xb6\\x78\\x39\\xd6\\x8a\\x16\\x2f\\xc7\\x5a\\xd1\\xe2\\xe5\\x58\\x8b\\x2d\\x5e\\x8e\\xb5\\x5d\\x8b\\x97\\x63\\xc5\\xcb\\xb1\\x3e\\xe9\\x3b\\x03\\x58\\xbc\\x1c\\xcb\\xb7\\x78\\x39\\xd6\\x27\\x51\\x19\\x9d\\xc5\\xcb\\xb1\\x36\\x6a\\xf1\\x72\\xac\\x78\\x39\\xd6\\x2e\\x2d\\x5e\\x8e\\xf5\\xa9\\x18\\x65\\xe2\\xe5\\x58\\xf1\\x72\\xac\\x9f\\x8f\\xa0\\x1b\\x2f\\xc7\\x8a\\x97\\x63\\xc5\\xcb\\xb1\\xe2\\xe5\\x58\\x6b\\x67\\x11\\x2f\\xc7\\xfa\\x14\\x54\\x40\\x63\\x53\\xb1\\x53\\x6d\\xd0\\x4d\\xca\\x18\\xf9\\xf0\\xf4\\x46\\xd5\\x80\\x61\\x39\\x1a\\x81\\x46\\xca\\x85\\x23\\x2f\\x84\\x55\\xd5\\x15\\x1b\\xe7\\x5d\\xb9\\x60\\x7b\\x58\\x11\\xc9\\x67\\xf2\\xac\\xf8\\xdc\\x97\\x29\\xc0\\x1a\\x9e\\x75\\x0c\\xf9\\x8b\\x37\\x5f\\x2d\\xa9\\x99\\xb4\\x73\\xbc\\xe1\\xae\\xd1\\xd3\\x38\\xe7\\x37\\x72\\x37\\x2f\\xfc\\x0a\\x80\\x2f\\xcb\\x2c\\xf3\\x70\\x4f\\x32\\x65\\x7c\\xec\\x3b\\x02\\x2b\\x99\\x70\\x29\\x21\\xe8\\x7b\\xc2\\xa2\\x1d\\x65\\x08\\x20\\x99\\x2a\\xc0\\xfb\\xc0\\x39\\x33\\x42\\x8e\\x33\\x60\\xdc\\x5a\\x9e\\x4c\\x06\\x6e\\x24\\x19\\x80\\x5d\\xc7\\xa9\\xfb\\x5f\\x8c\\xd5\\xc0\\xf3\\x10\\xb1\\x9f\\x73\\x41\\x5d\\x31\\x9e\\x68\\x65\\x0c\\xcb\\xcb\\xcc\\x8a\\xa2\\xea\\x8c\\x19\\xc0\\x54\\x1b\\x62\\x54\\x15\\x30\\x30\\x5e\\xae\\x0e\\x6e\\xef\\xd5\\xa3\\xf9\\x69\\xa9\\x66\\xd1\\x3a\\xd4\\x36\\x7b\\x58\\x48\\x3c\\x2f\\xec\\xac\\x8a\\xf0\\x05\\x36\\x12\\xda\\x58\\x96\\x64\\x02\\xb9\\x35\\x8e\\x48\\x59\\xd5\\xd8\\x5f\\x2f\\xf0\\x6a\\xe9\\x67\\x6a\\xfc\\x54\\x65\\x8a\\x62\\x6b\\x61\\x0d\\xc5\\xcb\\xd6\\x1d\\xfa\\xae\\x52\\x61\\xbc\\x98\\x6f\\x7a\\x8c\\x87\\x8a\\x6a\\x04\\xe8\\x30\\x53\\x04\\x75\\xe0\\x2c\\xd4\\xbb\\xff\\xa9\\xd1\\x5d\\xa3\\x92\\x6c\\x1d\\x50\\x5c\\x23\\x3a\\x26\\x3f\\x04\\xe4\\xec\\xb5\\xf2\\x3c\\x6a\\x81\\xc2\\xdf\\x97\\x31\\x77\\x0c\\x70\\x03\\x24\\x4c\\x1d\\x0e\\x40\\x02\\x8e\\xbf\\xf2\\x15\\x58\\xff\\xc1\\x91\\xbe\\xc1\\x14\\x5f\\x81\\x31\\x7c\\x0c\\x57\\x3b\\x3a\\x1a\\x56\\x69\\x64\\xe8\\x6b\\xa8\\x37\\x06\\x51\\x21\\x6b\\xdd\\x49\\xd6\\x8c\\xdb\\x6c\\x8b\\x41\\x2c\\xa7\\x39\\x55\\xc2\\xcf\\x9d\\x16\\xd6\\x02\\x6e\\x2a\\xd6\\xde\\x43\\x8f\\xe8\\x7c\\x6a\\xfe\\xe1\\x5c\\xf4\\xe7\\xab\\xd0\\x49\\xfd\\xb1\\x23\\xea\\x32\\xa5\\x58\\xcc\\x21\\xb0\\xa1\\x16\\x30\\x62\\x23\\x81\\x01\\x9e\\x18\\x72\\xd9\\xa3\\x52\\x4c\\x9c\\xac\\x00\\xc6\\x38\\x7d\\x57\\xc9\\x20\\xcb\\x86\\x79\\x0d\\xd8\\x5f\\xfd\\xc4\\xac\\x2e\\x65\\xc2\\x1b\\x55\\x6e\\x31\\xf7\\x54\\x8c\\xd8\\x18\\x43\\x36\\xbd\\xb4\\xf8\\x9b\\x67\\x7f\\xf8\\x1d\\x1b\\xce\\x1c\\x4b\\x43\\xc9\\xca\\x2a\\xcb\\xb3\\x6a\\x91\\x19\\xc8\\xb1\\x83\\x15\\x1d\\xcf\\x76\\xf6\\x64\\x05\\x01\\xbc\\x06\\x84\\x26\\xfe\\xfc\\x57\\xb7\\xc3\\x36\\x8f\\x3d\\x49\\x61\\x7a\\xd2\\x80\\x5f\\x3f\\x53\\xe3\\x65\\x17\\x67\\xed\\x1e\\xcc\\xbd\\xa3\\x4a\\xb4\\x04\\xcd\\xba\\xb9\\xf1\\x31\\xd4\\x04\\x63\\x13\\x75\\x47\\xb2\\xfe\\x12\\xec\\xa9\\x13\\xb1\\x0a\\x55\\x94\\x19\\x19\\x9d\\xbf\\xaa\\xf2\\x8e\\x4b\\x03\\x8b\\xd9\\x81\\x4b\\xcf\\x05\\x9a\\x49\\x7d\\x17\\xf3\\x15\\xd5\\x29\\x52\\x37\\x0c\\xa9\\x7c\\xd6\\x89\\x37\\xe4\\x55\\xa5\\xc1\\x50\\x11\\xfa\\x8a\\x67\\xd9\\x90\\x27\\xb7\\x37\\xea\\xa5\\x1a\\x9b\\x37\\xf2\\x85\\xd6\\x4a\\xb7\\xe7\\x92\\x71\\x47\\x2d\\x27\\xa5\\xbc\\xa5\\xab\\x1f\\xaa\\xe2\\x09\\x6a\\xec\\x5d\\xb9\\x21\\xc5\\x61\\xd9\\x82\\x29\\x93\\x3e\\x10\\xe1\\xa0\\x06\\xd5\\xbd\\xc0\\xbd\\xa8\\x75\\x1d\\x9f\\xc4\\x45\\x18\\xd9\\xec\\xdf\\x34\\x91\\xed\\x57\\xcf\\x7e\\xf3\\x7b\\x42\\x5d\\xa6\\x34\\xfb\\xfd\\x33\\x8c\\xe6\\x36\\x3d\\x3a\\xc4\\x48\\xdb\\x1c\\xa3\\xc8\\x79\\x96\\x39\\xb5\\xa1\\x89\\x94\\x0e\\xd0\\xcb\\x90\\xf0\\x83\\xe3\\xa0\\xdd\\x1f\\xdd\\x36\\x16\\xa5\\x6e\\x6e\\xfe\\x86\\x72\\x94\\xb0\\x06\\xb2\\x51\\x8f\\xf2\\x95\\x2a\\xb5\\xe6\\x10\\x19\\xc3\\xa1\\xa7\\x3e\\x98\\x34\\xf6\\x08\\x04\\xa0\\xa9\\xca\\xca\\x1c\\x2e\\x60\\x2a\\xba\\xb8\\xdd\\xaf\\xd5\\x5b\\x50\\xf5\\x33\\x61\\x30\\x35\\x6c\\x98\\xa9\\xe4\\x96\\xa5\\xfe\\x61\\x23\\xbe\\x65\\xbe\\x46\\xf8\\xd3\\xbd\\xa8\\xb5\\xb9\\xfe\\x56\\x6c\\x4f\\xce\\x8b\\xa2\\xca\\x1e\\xd2\\xfc\\xae\\x05\\x0c\\x3c\\x93\\x58\\xc8\\xe0\\xe9\\x5f\\xd4\\x4a\\x2b\\x72\\x74\\x73\\xe7\\x2e\\x76\\x0e\\x08\\xda\\xdf\\x46\\x5d\\xcf\\xbe\\xa3\\xeb\\xf8\\xea\\x0e\\xc3\\x69\\x28\\xf0\\xdf\\x94\\x6f\\xb2\\x90\\x2f\\x59\\xa5\\xdc\\x55\\x88\\x41\\x02\\x80\\x43\\x1f\\x24\\xc9\\x1f\\xed\\x42\\x51\\xb6\\x77\\x60\\x53\\x0b\\x2e\\x72\\xcd\\x9d\\x76\\x9c\\x15\\xa0\\x8d\\x30\\x8e\\x2f\\x7f\\x87\\x07\\x8a\\x2e\\x33\\xac\\x4d\\x80\\x1f\\x07\\x08\\x74\\xb8\\xb1\\xb0\\xf2\\xfe\\x94\\xf2\\x4a\\xa5\\xbe\\x43\\x24\\x85\\x54\\x54\\x7a\\x89\\x58\\xdb\\x96\\x6a\\x3b\\x64\\xa8\\x1f\\x9b\\x54\\x7e\\x57\\x43\\xb3\\x4d\\x29\\xdd\\x2f\\x15\\xa9\\xa4\\xb7\\x3e\\x25\\x02\\x89\\xeb\\x7b\\xaa\\xf4\\xb1\\x9a\\x7c\\x47\\x64\\x00\\x09\\xa3\\xdf\\xdc\\x36\\x25\\x6c\\x29\\x8f\\x74\\x50\\x1a\\x22\\xbd\\xd7\\x03\\x07\\x8c\\xbc\\xe0\\xee\\x4c\\xf8\\x4f\\xd9\\xe1\\xe9\\xe1\\x47\\x25\\x92\\x04\\x22\\xad\\x0a\\x3e\\xde\\xeb\\x96\\x9f\\x39\\x48\\xcd\\x77\\xdb\\x2c\\x41\\xe1\\xd4\\x20\\x7c\\x5e\\x15\\x64\\xc3\\xb7\\x20\\xad\\x2b\\xec\\x60\\xfd\\x24\\xf2\\x8e\\x06\\x00\\x7b\\x05\\x81\\x32\\xb5\\xef\\xf8\\x8c\\x71\\xad\\x4a\\x99\\x7a\\xfb\\x52\\x65\\xe0\\x7b\\x35\\x37\\xf0\\x6b\\x25\\xa1\\xbe\\x35\\xb4\\x5d\\xc1\\x02\\x2d\\xfa\\x42\\xb2\\xe7\\x83\\xe7\\xcf\\x3e\\x15\\x4e\\x85\\x2b\\x9c\\xe3\\x54\\xaf\\x2b\\x4e\\x45\\xf4\\xe9\\xa3\\xae\\x35\\xd4\\xc2\\xef\\x68\\xbd\\xaf\\xbc\\x89\\xa5\\x2e\\x75\\x2f\\x42\\x21\\x6d\\xfc\\xe9\\x4e\\x0b\\x0b\\x8d\\xcb\\x01\\x8f\\x50\\x71\\x71\\xfa\\x61\\xa3\\x5e\\xc3\\xf1\\xb2\\x3b\\x26\\xf6\\x04\\xd2\\x7e\\x05\\x32\\x4c\\x39\\x7c\\x8f\\x74\\xcb\\x13\\x28\\x3c\\x6e\\xcb\\x2c\\x5c\\x66\\x0d\\x09\\x6b\\x02\\xea\\xe0\\x80\\x1d\\xd1\\x9b\\x87\\x94\\xea\\x7c\\xfc\\x51\\x51\\xcb\\x03\\xed\\xc5\\x7d\\xb1\\x47\\xf5\\xcd\\xb9\\xac\\xfa\\x82\\xa3\\x0d\\xae\\xe8\\x10\\x82\\xff\\x03\\x13\\x3e\\x05\\x4c\\xf1\\x16\\x19\\xd7\\x19\\xfa\\x1c\\xaf\\x69\\xee\\x6c\\x58\\x5a\\x06\\x72\\x2a\\xb4\\x92\\x39\\x48\\xcb\\x30\\x06\\x7e\\x98\\x41\\xf3\\x6e\\xec\\xcf\\x8f\\xbe\\x3b\\x7b\\x8b\\x01\\x0d\\xc7\\xbe\\x58\\x85\\x9f\\x65\\x69\\x42\\x61\\x9b\\xe6\\x4c\\x1a\\xdd\\x3d\\xb8\\x7d\\x61\\x1e\\x0e\\x86\\x48\\x73\\xc3\\xbc\\xdc\\x38\\x79\\x69\\x4b\\xba\\xb0\\xe5\\x3e\\xc9\\x4a\\x23\\xa6\\x1f\\x8b\\x92\\xf8\\xdc\\xfb\\x0b\\xb1\\xd3\\x3e\\xcf\\xd5\\x01\\xa8\\x01\\xb5\\x90\\xd2\\x8f\\xa6\\xf5\\x25\\x69\\x80\\x0b\\x0e\\x93\\x43\\x53\\xa5\\x06\\x36\\x7d\\xe0\\xde\\xf4\\xe4\\xab\\x6c\\x50\\xf8\\x5c\\xa8\\xc5\\xb8\\x20\\x42\\x60\\x45\\x99\\x8f\\x6b\\x84\\x4a\\xa5\\x39\\xc7\\x19\\x6e\\x07\\xd6\\x76\\x40\\x72\\x2b\\x5b\\xf0\\xe2\\xf5\\x75\\xb3\\x3c\\x09\\xa9\\x4b\\x2a\\x1d\\xb0\\xab\\xfa\\xc7\\xba\\x86\\x0d\\x56\\x56\\xab\\x94\\x48\\xd0\\xe3\\xba\\xdc\\xf8\\x18\\x24\\x68\\x14\\x12\\x5c\\x97\\xad\\x0b\\x57\\xd9\\x90\\x1b\\x72\\xf2\\x5c\\xbc\\xbe\\x26\\x9b\\xed\\x76\\x30\\xdb\\x59\\xcc\\xde\\x5d\\x42\\xc5\\x94\\x16\\x4c\\x63\\xd8\\x41\\xb8\\x6d\\xdf\\xa6\\x56\\x19\\xac\\x1c\\x60\\x50\\x29\\xa5\\x8e\\xd9\\xe5\\x15\\xe3\\x69\\xaa\\xd1\\xed\\x33\\x97\\x7c\\xe3\\xf4\\xf3\\xe0\\x5b\\xc0\\x7a\\x31\\xdc\\x40\\x73\\x4e\\x0d\\x70\\x23\\x89\\xab\\x01\\xcb\\x2e\\xca\\x22\\x13\\xe4\\x46\\x68\\x7e\\x50\\xd7\\xb9\\xc1\\xeb\\xbf\\xb6\\x47\\xda\\x7d\\xd4\\xbc\\x9d\\x95\\xbc\\x3d\\xa8\\x90\\xda\\xb5\\x5c\\xe5\\x9a\\xdd\\xd3\\x60\\x54\\x36\\xad\\x4b\\x0d\\xcf\\xed\\x9a\\x3f\\x11\\x68\\x12\\xaf\\x76\\x2d\\x54\\xa7\\xdc\\x68\\xc7\\x40\\x5a\\x2d\\x60\\x71\\xb7\\xd8\\x5b\\x37\\x72\\x89\\xa7\\xa9\\xea\\x50\\x4c\\x01\\xfd\\xe3\\xbe\\x30\\xa7\\x2f\\xf0\\x56\\x17\\x3f\\x26\\xdf\\x30\\xd5\\x9f\\x06\\xae\\x03\\x45\\xc3\\x59\\xed\\x78\\x12\\xd9\\xc7\\x42\\x84\\x79\\x63\\xc7\\xc5\\xeb\\x6b\\xa2\\x84\\xb4\\xf8\\xea\\xde\\xda\\x65\\xbb\\x54\\x53\\xb5\\x9d\\x31\\xf0\\xa3\\xd5\\x1f\\xda\\x47\\xf3\\x98\\xbb\\xf6\\xcf\\xdf\\xf3\\xbd\\x57\\x20\\xcb\\x1e\\xe2\\xdf\\x5e\\xc9\\x76\\x7b\\x8c\\x6e\\x80\\xeb\\x64\\xb2\\x0b\\xfc\\xd7\\x10\\x02\\xea\\x94\\xa5\\x8a\\x22\\x01\\x46\\x4a\\xa3\\x4a\\xdc\\x47\\xf2\\x9e\\x29\\x75\\x5b\\x16\\x9b\\x50\\x74\\xdf\\x0d\\x5d\\xc5\\xb6\\x11\\x81\\x68\\x7d\\xf1\\xb3\\xa2\\xe9\\xa9\\x34\\xbb\\xf8\\x7b\\xdb\\xb2\\x0f\\x58\\x92\\x78\\xb0\\xa3\\x3a\\x81\\x42\\xcd\\xeb\\x4d\\xe7\\x59\\x69\\x2c\\xe8\\xaf\\x84\\x36\\xf6\\x20\\x54\\x92\\x46\\x0c\\x26\\x9b\\xc8\\x61\\xf3\\x85\\xbf\\x0a\\x3b\\xf1\\x45\\x1d\\x0f\\x7b\\xed\\x47\\xee\\x6f\\xdf\\xf1\\xa1\\xd3\\x69\\x0f\\x5f\\x2b\\x09\\x87\\x83\\x79\\xb1\\xab\\x22\\xe5\\x15\\x59\\x5b\\xc9\\x53\\xfc\\xd4\\x0d\\x64\\x14\\x2f\\x8a\\x0f\\x1a\\xb8\\x72\\xe3\\x0b\\x5a\\xba\\x11\\x02\\xfd\\x33\\x60\\x19\\xc7\\xe2\\x71\\xf8\\xf6\\xa4\\x2e\\x40\\x49\\x15\\xa5\\xa8\\x82\\xa6\\xf2\\x82\\xde\\xac\\x09\\xa2\\x46\\x91\\x29\\xab\\x56\\x2f\\x7b\\x17\\x79\\x6e\\x6b\\x0c\\xa0\\xc2\\xa4\\xbe\\x2a\\xc9\\x4b\\x21\\x6f\\xb7\\x44\\xbf\\x76\\x74\\xc9\\x8b\\x85\\xde\\x5a\\x95\\xc6\\xc9\\x47\\x2b\\x24\\x05\\xdf\\x39\\x16\\xc3\\x87\\xaa\\xb4\\xa1\\xf2\\x89\\x69\\x28\\x8e\\x42\\xfe\\x83\\xf6\\x02\\xed\\xed\\x05\\xd5\\xf2\\x5b\\xa6\\x23\\x9a\\x1e\\x19\\x7d\\x82\\x12\\x68\\x66\\xd2\\x72\\xac\\x3a\\x7a\\xa1\\x92\\x5b\\xd0\\x2c\\x73\\xd3\\x18\\xb0\\x3a\\xf0\\xa5\\x55\\xe7\\x52\\x97\\xb0\\x65\\xd4\\xc5\\xae\\x96\\x0e\\x28\\x26\\x90\\x83\\xe6\\x59\\x5d\\xee\\x75\\x0f\\x50\\xbf\\xf4\\x84\\xb3\\xea\\xb5\\x19\\x93\\x42\\xe5\\xd2\\x7c\\x81\\x46\\x77\\x0e\\x5f\\x2c\\x7b\\x2b\\xe7\\xb3\\x50\\x03\\x57\\x48\\x0c\\x37\\xb8\\x17\\x06\\xcd\\xfa\\x85\\x4a\\x9b\\x89\\x67\\xa5\\x01\\xdd\\xaf\\xd2\\x02\\x7d\\xee\\x8d\\xa9\\x02\\x71\\x52\\x18\\x96\\xe3\\xb1\\x90\\x63\\x4f\\x9d\\x91\\xa6\\x37\\x0a\\x71\\x57\\x9a\\x0e\\x46\\x7a\\x27\\x1a\\xa8\\x14\\x2d\\x4a\\x0f\\x14\\x5f\\x26\\x9a\\xef\\xe7\\x2a\\xa5\\xd7\\x87\\x33\\xd2\\x06\\xc3\\xce\\xd6\\x01\\xd2\\x97\\x92\\x29\\xed\\x0b\\x30\\xf0\\x34\\xc5\\xb9\\x2f\\xae\\x10\\x9f\\xb6\\x57\\xd5\\xab\\xe2\\x38\\x28\\xb2\\xbb\\xfa\\xaa\\x01\\x16\\x53\\x0e\\x9d\\xb0\\x53\\xea\\x6d\\x6b\\x87\\xee\\x4a\\xf8\\x77\\x22\\xfa\\xed\\xaa\\x42\\x67\\xb2\\xde\\xe2\\xf3\\x66\\xc0\\x1c\\x67\\x16\\xf2\\x42\\x69\\xae\\x67\\xf3\\x2e\\x4c\\x47\\xa4\\x1c\\x0a\\x38\\x00\\xce\\x41\\xea\\x4a\\xa5\\x48\\xc7\\x97\\x6c\\xfc\\x94\\xee\\xf8\\x5d\\xb2\\xf7\\x4b\\x71\\x0c\\xa9\\xa0\\x54\\x2c\\x40\\xd4\\xd1\\x6b\\x93\\x4c\\x20\\x2d\\x31\\x7a\\x7c\\x5c\\x72\\xbc\\x83\\xdc\\x9d\\x62\\x6f\\xec\\x9e\\xf9\\xb0\\x3c\\x42\\x86\\x2a\\xe0\\xaf\\x4a\\x13\\x98\\x61\\x90\\x0c\\xd6\\xe7\\x74\\xbf\\x60\\x9d\\x4f\\x0a\\x0d\\xa4\\x2b\\x98\\xf1\\x3a\\xd6\\x2a\\x4a\\xf0\\xa6\\xbe\\x15\\x02\\x17\\x0b\\x53\\x91\\xd8\\xf0\\xd1\\x68\\x15\\xe2\\x24\\xbc\\xba\\xf9\\xf5\\x4a\\xf9\\xba\\x80\\x09\\x38\\x62\\x64\\x4d\\xbd\\x14\\x1f\\x55\\x82\\x95\\x3f\\xdf\\x49\\xc7\\x24\\x56\\xe3\\x62\\x8d\\x78\\x0f\\xa0\\x1c\\xca\\xd5\\xed\\xad\\x58\\x73\\x7c\\x2b\\x28\\x2d\\x59\\xfb\\xb6\\x25\\x99\\xf6\\x10\\xca\\x77\\xf7\\xb8\\xed\\xe4\\x29\\xdb\\x47\\xfe\\xe7\\x7a\\xbc\\xbf\\xae\\x74\\x78\\xa6\\xc7\\x65\\x4e\\xd5\\xbd\\xd5\\x5c\\x81\\x65\\xc2\\x39\\xb4\\x6b\\x39\\x96\\x75\\xfe\\xea\\xa2\\x99\\xc2\\xd0\\x8c\\xcd\\x0e\\x09\\x20\\x4e\\x14\\xda\\xd3\\xde\\x39\\x6f\\xf0\\xbc\\x74\\xca\\x59\\x65\\x45\\xad\\x69\\xab\\xd7\\xe2\\xbc\\x45\\xaf\\x1a\\x2d\\x68\\xb1\\x42\\x16\\x8e\\x1b\\xa3\\x0c\\xd1\\x28\\x3d\\x92\\x4c\\xb8\\x1c\\xa3\\x19\\x5c\\x95\\xae\\xbf\\xcf\\x3f\\xc7\\x19\\x69\\x48\\xcb\\xc4\\xdf\\x28\\x11\\xe2\\x9f\\x3f\\x0f\\xd6\\x3f\\x5f\\x28\\x08\\x2f\\xb6\\x33\\x09\\x2f\\xc2\\x9c\\x9b\\xcb\\x22\\x56\\x7d\\xca\\xc4\\x00\\x06\\xec\\xe0\\xf3\\xc6\\xa3\\x03\\x1a\\xbd\\xd0\\xca\\x0d\\xe1\\x43\\xa7\\x71\\x56\\x99\\xb0\\x78\\x10\\x0e\\x9a\\x6f\\x0f\\xd8\\x0b\\x37\\x06\\x7a\\x44\\x2a\\x00\\x36\\xa2\\x7b\\x87\\x35\\xf8\\x7a\\x4c\\xc3\\x98\\xeb\\x34\\xc3\\x8c\\xbb\\x51\\x25\\x94\\x50\\x5e\\x8e\\x07\\x18\\x9e\\x3e\\x8c\\xa7\\x93\\xca\\x2e\\xb3\\x4e\\x6e\\x98\\x16\\x61\\xb9\\xb9\\x35\\x27\\x24\\xca\\xf4\\x53\\x6e\\x79\\x1f\\x6f\\xe1\\x20\\xa2\\x71\\x42\\xea\\x75\\xdf\\xd7\\x3f\\xed\\x73\\x8f\\x53\\xfd\\x6a\\x5b\\x4f\\x7e\\xe1\\x33\\xab\\xfa\\xbc\\x7a\\x4b\\xc8\\x3e\\xef\\x63\\x25\\xd2\\xff\\x9f\\xbd\\xff\\x71\\x6e\\xdb\\xc6\\xfa\\x85\\xf1\\x7f\\x05\\xe3\\xdd\\xb9\\xb6\\xb6\\x92\\x9c\\xb4\\xbb\\x3b\\xdd\\xdc\\x7e\\xb7\\xe3\\xb5\\x9d\\xd6\\xd3\\xc4\\xd1\\xb5\\x9d\\xf6\\xf6\\x9b\\xf4\\xe9\\x03\\x91\\x90\\x84\\xc7\\x24\\xc0\\x25\\x40\\xd9\\xda\\x37\\xef\\xff\\xfe\\x0e\\xce\\x01\\x40\\x90\\x92\\x1d\\x9b\\x64\\x6c\\xd9\\x25\\x77\\x66\\x1b\\x4b\\x14\\x08\\x1e\\x00\\xe7\\xf7\\xf9\\x9c\\xe6\\xb9\\xa2\\x8f\\x90\\x56\\xd0\\xca\\xd2\\x6d\\x01\\x83\\x5b\\x57\\x4f\\x3d\\x0c\\x3a\\xd0\\x00\\x9a\\x88\\x94\\xb0\\xd7\\x3e\\x83\\xc1\\x22\\xbd\\x56\\x0e\\xf2\\xf1\\xe9\\xc5\\xd9\\xaf\\x93\\x77\\x27\\xa7\\x17\\xfd\\x79\\xee\\xcf\\x73\\x7f\\x9e\\x5b\\x9c\\x67\\x26\\x96\\xad\\xcf\\xb2\\xb7\\x7f\\x36\\x99\\x84\\x35\\x08\\xbb\\xa0\\xa2\\xfa\\x19\\x25\\x67\\x1d\\x8b\\xe5\\xcf\\xd4\\x28\\x7c\\x59\\xce\\x14\\xe8\\x22\\x46\\x6f\\xdc\\x14\\x45\\xb5\\x37\\x60\\x1f\\xae\\xc3\\x27\\x9f\\x9d\\xf5\\x88\\xb9\\x55\\x1d\\xe6\\xac\\x9c\\x06\\x40\\x00\\x9b\\x56\\x2d\\x6c\\x7c\\x77\\xf8\\xfb\\xc9\\xd1\\xf1\\xe9\\xc5\\xc9\\xeb\\x93\\xe3\\xb3\\x47\\x4d\\x36\\x68\\x09\\xee\\x56\\x95\\xc6\\x0d\\xa5\\x64\\x96\\xb3\\x25\\x97\\x85\\x4a\\x56\\x1e\\x85\\x76\\x33\\x13\\x58\\xcf\\x57\\x13\\xc6\\x3c\\x5b\\x79\\xa0\\xdd\\x8d\\x3f\\xeb\\x85\\x6d\\xb7\\xc2\\xb6\\x9a\\x7b\\xd1\\x02\\xd7\\xa3\\xab\\xed\\xfb\\x3a\\x97\\x69\\x47\\x5b\\xf8\\x1c\\x4d\\x76\\xe7\\xf2\\xde\\xb4\\x9f\\x76\\x2d\\x04\\x40\\x45\\xf4\\x58\\xe5\\xb1\\xc4\\x1b\\x30\\x5a\\x68\\x9a\\xe9\\x16\\x6d\\x01\\x3a\\x01\\x0d\\xed\\x06\\x5f\\x13\\xf3\\x14\\xde\\xd2\\xec\\x27\\xb6\\x3a\\x63\\x2d\\xe1\\x43\\x6a\\xa1\\x86\\x84\\x45\\x46\\xd0\\x91\\x4b\\xb6\\xc2\\x08\\xe4\\xa1\\x7b\\x58\\x3b\\x10\\xcc\\x2d\\xc4\\x5c\\xbd\\x64\\x6d\\xf0\\x70\\xbb\\x04\\x4b\\xbd\\x64\\x2d\\x12\\x17\\xdd\\xb5\\x06\\xe8\\x69\\x96\\x10\\xf4\\x34\\xb3\\xa6\\x5b\\x05\\x61\\xfa\\x05\\xc0\\x61\\x77\\x43\\x71\\x6f\\xf9\\xac\\xbe\\x37\\xba\\x82\\x5c\\x1a\\xc9\\xc5\\xae\\xf6\\x6d\\xd2\\xd6\\xc8\\x58\\xac\\x23\\xdc\\xb5\\x6a\\x1f\\x32\\x53\\xf6\\xff\\x84\\xc0\\xb1\\x17\\xef\\x8e\\xde\\xbd\\x22\\x07\\x71\\x6c\\x93\\x87\\x0b\\xc5\\x66\\x45\\x82\\x69\\xc0\\x6a\\x4c\\x68\\xc6\\x7f\\x66\\xb9\\x82\\xbe\\x6a\\x97\\x5c\\xc4\\x43\\x52\\xf0\\xf8\\xfb\\x36\\xa0\\x4b\\x78\\x75\\xb8\\x0a\\xd2\\x05\\x6c\\xba\\x5d\\x89\\x73\\x1b\\x8f\\x0b\\x65\\x97\\x67\\x22\\x04\\x2b\\x03\\x61\\x6f\\x3a\\xfc\\x15\\xab\\x64\\x74\\x44\\x9a\\xb6\\x2d\\xe4\\x08\\x2e\\x61\\xb7\\x7c\\x75\\xb7\\x64\\xac\\x98\\x27\\xee\\x01\\xaa\\xe2\\x57\\x44\\x15\\x00\\x14\\xa3\\x7c\\xdf\\x37\\xe8\\xa4\\x3a\\xac\\xfe\\xa9\\x32\\x1a\\xb1\\x21\\xf9\\x6f\\xff\\x21\\x74\\x6a\\x57\\x1f\\x76\\x77\\xbf\\xfb\\xe9\\xf8\\xd7\\x7f\\xee\\xee\\xfe\\xf6\\xdf\\xe1\\xb7\\x20\\x0a\\xc1\\x6a\\xae\\xdd\\x02\\xf1\\x1d\\x21\\x63\\x76\\x0a\\xcf\\x80\\x3f\\xad\\xba\\x76\\x10\\x45\\xb2\\x10\\xda\\x7e\\x01\\x55\\xbd\\xe3\\x85\\x54\\xfa\\x64\\xe2\\xff\\xcc\\x64\\x5c\\xff\\x4b\\xb5\\x42\\x12\\xdb\\x4a\\xc1\\x00\\x4b\\xd4\\xa2\\x3a\\x05\\xaf\\xee\\xc4\\x43\\xc9\\x4b\\x3a\\x3e\\xaa\\x76\\x54\\xdf\\x1f\\x23\\x5a\\xb0\\x14\\xb1\\x8c\\x5e\\x3b\\x12\\x40\\x6f\\x5a\\x07\\x1f\\x20\\xa0\\xe6\\xda\\x68\\xa6\\x55\\x58\\xb9\\x9d\\xe5\\xcb\\x56\\x4d\\xbc\\xf1\\xea\\x90\\xb5\\xf9\\x15\\xec\\x98\\x60\\x40\\x11\\x4b\\x2d\\x3c\\xc8\\x5e\\xc0\\x3a\\x2b\\xa5\\x8c\\xc6\\x1e\\x4c\\x4e\\xc8\\x12\\x29\\xbc\\x35\\xc4\\x71\\x51\\xb0\\xd7\\x5f\\x94\\xc7\\x85\\xb1\\xb6\\x8a\\x85\\xf8\\x0a\\x5b\\xb9\\xba\\xef\\x6d\\x9d\\xbd\\xf2\\xd0\\x57\\xcc\\x18\\x36\\x7b\\xf8\\xe1\\x38\\xca\\x8a\\xa1\\xbd\\x61\\x9c\\xb2\\x54\\xe6\\x2b\\xff\\xa7\\x8f\\xf1\\x8d\\x94\\x96\\x39\\x9d\\x43\\x5d\\x06\\xfe\\x1c\\x7f\\xe6\\xff\\xc2\\x1f\\x56\\x1e\\xb0\\xfe\\x6b\\x34\\x85\\xa3\\x22\\x37\\x4a\\x43\\xb2\\x72\\x1c\\xb9\\x21\\x5e\\x44\\x79\\x6d\\x21\\x6f\\x73\\xa4\\xdf\\x12\\xd6\\xe6\\x77\\x46\\xdb\\x86\\xad\\x78\\x55\\x37\\x64\\x19\\xa8\\x07\\x85\\xd3\\x53\\x11\\xec\\x49\\x5b\\x77\\x3a\\xf4\\x6a\\x10\\x7a\\x03\\xc4\\xd2\\x58\\x96\\x8d\\x91\\xb3\\xca\\xab\\x43\\x6e\\x16\\xf3\\x25\\x57\\xb2\\x45\\xf5\\x89\\x1f\\xe8\\xe6\\x94\\x7a\\x0b\\x7d\\x81\\x89\\x43\\xde\\x6d\\x76\\x9d\\x01\\x58\\x90\\x3f\\xaf\\x35\\xb6\\xff\\xb2\\x4d\\x57\\x22\\xbc\\x32\\xaa\\x35\\xcb\\xc5\\x2b\\xf2\\x5f\\x7b\\x1f\\xbf\\xfa\\x34\\x1a\\x7c\\xbf\\xb7\\xf7\\xe1\\xc5\\xe8\\x1f\\xbf\\x7d\\xb5\\xf7\\x71\\x0c\\xff\\xf8\\xcb\\xe0\\xfb\\xc1\\x27\\xf7\\xc7\\x57\\x83\\xc1\\xde\\xde\\x87\\x9f\\xde\\xfe\\x70\\x31\\x39\\xfe\\x8d\\x0f\\x3e\\x7d\\x10\\x45\\x7a\\x89\\x7f\\x7d\\xda\\xfb\\xc0\\x8e\\x7f\\xbb\\xe3\\x20\\x83\\xc1\\xf7\\x7f\\x6e\\x3d\\xf5\\x0e\\xb0\\x3b\\xf1\\xea\\x12\\xc1\\xb3\\x3a\\x62\\x27\\xdb\\xef\\x0b\\xc2\\xd6\\xe3\\xe5\\xb6\\x57\\xd7\\xe7\\xdf\\x65\\x0f\\xbf\\x2a\\x05\\x92\\x17\\xd7\\x5b\\x73\\xc0\\x15\\x8b\\x72\\xa6\\x1f\\xc2\\x93\\x83\\x4f\\x0a\\x10\\x04\\x76\\x15\\xf1\\xa6\\xc5\\x73\\x93\\x73\\x7f\\x04\\xe7\\x8e\\x6f\\x6b\\x07\\xeb\\x5a\\x6a\\xa2\\xb3\\x5c\\xa6\\xae\\x2a\\x1c\\xc2\\x1b\\xd0\\x9f\\xde\\xdd\\x77\\xc9\\x5a\\x35\\x47\\xc5\\xab\\x77\\x06\\xf5\\xce\\xa0\\x1b\\xae\\xcf\\x3a\\x83\\xce\\x71\\x1f\\x6e\\xad\\x27\\x88\\x89\\x65\\xd3\\x10\\xc6\\xc6\\x08\\xba\\xb3\\x75\\x42\\x08\\xb5\\xbb\\x05\\xd4\\xc6\\xee\\xa8\\x97\\xfd\\x20\\xcb\\x14\\x1a\\x14\\x68\\xe9\\xe6\\x18\\x26\\x39\\x80\\x5e\\xcd\\x78\\xf0\\x61\\x80\\xb2\\xec\\x02\\x4d\\x1b\\x8b\\xf0\\xc7\\x96\\x66\\x0a\\x1e\\x22\\xba\\x02\\x06\\x09\\x89\\x8e\\x90\\x7a\\xfa\\x0b\\x66\\x82\\x5e\\x62\\x72\\xa8\\x31\\xd2\\xb8\\x28\\x61\\x34\\xbd\\x72\\x58\\x62\\x2f\\x53\\xa5\\x64\\x84\\x49\\xad\\xbe\\x08\\x00\\x90\\xdd\\xec\\xb4\\x61\\x36\\xd0\\x20\\x3e\\xcb\\x59\\xc4\\x62\\x26\\x22\\x66\\x71\\x99\\x2b\\xbd\\x2f\\xa9\\x20\\xc7\\x62\\xe9\\xb0\\xa9\\x63\\x57\\x52\\x02\\x33\\xd9\\x3c\\xc6\\xf3\\x4a\\x40\\x30\\x1b\\xd1\\x06\\xc1\\x82\\x3c\\x04\\xe0\\xfa\\x65\\x36\\x2b\\xa4\\x62\\xc8\\x59\\xe9\\x65\\x6d\\xd6\\x1e\\xaf\\xb5\\x14\\x6f\\x2f\\x33\\x7d\\x64\\xab\\x95\\x32\\xb4\\x26\\x2c\\x4b\\xf7\\x73\\x55\\x48\\x3e\\x87\\x60\\x60\\x7b\\xf1\\xf9\\x87\\x13\\x9d\\x1d\\x89\\xcd\\x6e\\x44\\xe6\\x3d\\x62\\x27\\x5d\\x8a\\xc9\\x2e\\x82\\x25\\x59\\xce\\x66\\xfc\\xba\\xa3\\x73\\x7a\\x20\\x4a\\x4f\\x0c\\x8f\\x99\\xd0\\x7c\\xc6\\xb1\\xc4\\x24\\xcb\\x59\\xc6\\x04\\x56\\x09\\xd0\\x68\\x01\\xbc\\xdf\\x4a\\xca\\x32\\x38\\xbd\\x8d\\xc9\\x3c\\xa8\\x70\\x77\\xcb\\xca\\xce\\x37\\x29\\xfb\\x3d\\x1f\\x23\\x3d\\x1f\\x6b\\x7c\\x3d\\x10\\x1f\\xb3\\x3b\\x77\\x7b\\x98\\x18\\x64\\x9e\\xb7\\xcf\\x79\\x3f\\xac\\x62\\xad\\xd8\\xae\\xb4\\xf7\\xdc\\x68\\x65\\xd9\\xd1\\x3e\\x8c\\xd2\\xc8\\x01\\xdd\\x6a\\x3f\\xc0\\x63\\x27\\x45\\x92\\x74\\x84\\x4f\\xbd\\x7b\\x02\\xd4\\xc8\\x8a\\x24\\xb1\\x65\\xb9\\x63\\xf2\\x4e\\xc0\\x91\\x3c\\x80\\x3e\\x08\\x43\\x72\\xca\\x96\\x2c\\x1f\\x92\\x93\\xd9\\xa9\\xd4\\x13\\xd4\\x6d\\xab\\xe9\\x6c\\x78\\x23\\xe1\\x33\\xf2\\xca\\x58\\x4d\\x4a\\x13\\x8d\\x58\\xf4\\x01\\x72\\x8e\\xcc\\x2b\\x03\\x94\\xa0\\x5c\\x2d\\xd2\\xd0\\x6f\\x5e\\x96\\x3f\\xb9\\x82\\xc9\\xd1\\x23\\x2d\\x93\\x6f\\xf6\\xd1\\x81\\x79\\x6a\\x47\\x72\\x09\\x72\\x90\\x14\\x69\\xa3\\x23\\x9b\\xaa\\x5e\\x9f\\x20\\x10\\x45\\x26\\x95\\x3e\\x37\\x56\\x6c\\x37\\x8d\\x60\\x26\\x6e\\x38\\xe8\\xad\\x40\\x93\\x84\\xc5\\x95\\x4e\\x40\\xd8\\xc1\\x82\\x56\\xad\\x68\\xa8\\xc7\\xf5\\x0d\\x15\\x18\\x59\\x50\\x11\\x27\\x2c\\x07\\x50\\x74\\x55\\x47\\x7e\\xe2\\x65\\x17\\x00\\xdf\\xb7\\xc1\\x15\\x68\\xd2\\x28\\x92\\x79\\x6c\\x3b\\xb0\\xda\\x42\\x49\\x98\\x8c\\x3f\\x5e\\xc0\\x6b\\x53\\x2a\\xe8\\x9c\\x81\\x67\\x61\\x0d\\x5a\\x17\\x00\\x97\\x55\\xd0\\xfc\\x61\\x21\\xe5\\x25\\x89\\x64\\x9a\\x25\\x70\\x00\\x5a\\x9c\\x8f\\xb2\\xf7\\x8c\\xdf\\xa2\\x23\\x33\\xba\\xda\\x0f\\xda\\xd2\\xc0\\x07\\xed\\xba\\xd2\\xb4\\x52\\x56\\xba\\x50\\x55\\xd8\\x35\\x8b\\x3a\\xeb\\x5b\\x77\\x7c\\xcd\\xa2\\xa0\\xf1\\xa2\\x59\\x12\\xdb\\x79\\x51\\x4b\\xf0\\x6d\\xb4\\xef\\xa7\\xdb\\xda\\x2d\\xdf\\x95\\x2b\\xbc\\x45\\x95\\x59\\x78\\xd5\\x80\\xd6\\x60\\x4c\\x87\\x2b\\x6d\\x1f\\x01\\x10\\xfd\\x58\\x55\\x0c\\x95\\x67\\x0e\\x6a\\xba\\x72\\x18\\xf0\\xe8\\xad\\xa1\\xb3\\xf9\\x64\\x63\\x37\\x16\\xd4\\x3e\\x4b\\xa9\\xc9\\xde\\xee\\xfe\\xee\\x60\\xcd\\x47\\x57\\x03\\x27\\xbe\\x08\\x7e\\xc9\\x01\\x8d\\x2f\\x03\\x68\\x3b\\x16\\xed\\xc6\\x43\\xc2\\xb5\\x63\\xb6\\x08\\x0a\\x00\\xb3\\xb2\\xe5\\x70\\xd0\\xa1\\x5e\\xe7\\x34\\xe6\\xd6\\x0a\\x82\\x4f\\xcd\\x4d\\x3a\\x2f\\x2c\\x22\\xc0\\xde\\xee\\xa7\\xdd\\x21\\x61\\x3a\\x1a\\x90\\x2b\\x29\\x76\\x35\\x4c\\x1f\\xe0\\x33\\x0a\\x15\\x0c\\xb4\\x92\\x05\\x74\\xa9\\x43\\x12\\x78\\x2c\\x0c\\xc3\\xb1\\x88\\x2c\\xb0\\xa5\\xcd\\x82\\x6a\\x57\\x86\\x77\\x7c\\xcd\\xb5\\x6b\\xe3\\x20\\x67\\xe4\\x05\\x76\\xd4\\x61\\xd4\\x7a\\x09\\x13\\xbe\\x64\\xfb\\x0b\\x46\\x13\\xbd\\xc0\\x44\\x0a\\x21\\xc5\\x08\\x9b\\xa2\\x19\\x56\\x62\\xbf\\x69\\x1b\\x53\\x68\\xe7\\x72\\x0b\\xaf\\x16\\xee\\xb7\\xf5\\x09\\xb5\\xd4\\xae\\x0d\\x13\\xfd\\xa1\\x79\\xa7\\x56\\xb2\\xd6\\xc4\\xf8\\xe2\\x62\\xf2\\x43\\xa5\\x57\\x2b\\x70\\x71\\xad\\x33\\x97\\xde\\x12\\xe0\\x4a\\x6c\\x01\\xef\\xe8\\x26\\xa0\\xd7\\xaa\\x69\\x2b\\xe9\\x90\\x85\\xb5\\x6d\\xde\\x4a\\xd6\\x9b\\x52\\xdf\\xaf\\x6b\\x2b\\xf9\\x55\\x16\\xd0\\x6d\\x8e\\x4e\\x93\\x15\\xb9\\xa2\\x42\\xbb\\x52\\xbc\\x1d\\x33\\xd4\\x8e\\x61\\x4f\\x66\\x37\\xfc\\xc8\\x68\\xcc\\x72\\x05\\xdc\\x83\\xd1\\xc6\\xf8\\x59\\xee\\xea\\x2c\\xd0\\x14\\xcc\\xad\\x5b\\x39\\x50\\x28\\x2d\\x53\\xb2\\xb0\\xaf\\x5d\\x2d\\x4f\\xb4\\x27\\x63\\x0c\\xa7\\xc7\\xd5\\xfe\\xe4\\x2c\\x43\\x0e\\x67\\x7f\\xf3\\xec\\xf8\\xd7\\x1a\\xdf\\x40\\xba\\x57\\x70\\xe6\\xa3\\x90\\x6c\\x61\\x37\\x12\\x2e\\x90\\x58\\xd8\\x47\\xb0\\x23\\x5e\\xda\\x41\\x82\\x00\\xe9\\x30\\x49\\x80\\xb4\\x2b\\x76\\xac\\x0f\\x04\\x81\\xaf\\xf6\\xf9\\x50\\x9d\\xe5\\x1d\\x90\\xce\\x62\\xeb\\x64\\x93\\x23\\xd2\\xee\\x19\\xcc\\x82\\x45\\x9f\\x47\\x05\\x3a\\x2e\\xa2\\x42\\x0a\\x1e\\xd1\\x84\\xff\\x87\\xc5\\xd8\\x15\\x17\\x73\\xcc\\x40\\xcf\\x89\\xa8\\x62\\x23\\x08\\x7c\\x0a\\xe4\\x7f\\x41\\x9b\\x57\\x61\\x8e\\xa3\\x96\\x12\\x94\\x0f\\x08\\x75\\x19\\xfe\\x88\\xcf\\x6b\\x9f\\xb9\\x40\\xba\\x8d\\x9b\\x93\\xf6\\x45\\x9b\\xe1\\x75\\x3b\\x99\\xbb\\xd9\\x62\\xa4\\x4b\\x0a\\x64\\x1d\\x24\\x59\\xaf\\xa7\\x58\\xaf\\xf5\\xec\\x06\\x66\\x84\\xa8\\xb0\\x5b\\x23\\xcb\\xda\\x36\\x30\\x27\\x9b\\x2b\\x96\\x73\\x22\\x7c\\xbf\\xd9\\xa7\\xd1\\xc4\\x9c\\x74\\x97\\x0c\\xd9\\x75\\x2a\\x64\\xa7\\x89\\x90\\x5f\\x34\\x0d\\x12\\x8a\\x2f\\x5a\\x73\\x91\\xaa\\x17\\x1e\\x86\\x34\\x3b\\xc0\\x58\\x87\\xc6\\xae\\xb5\\x1a\\xa6\\xf5\\x21\\xb9\\x9e\\x18\\x55\\xa7\\xab\\x39\\x6a\\x5b\\x71\\xc6\\x74\\x94\\x9d\\xcb\\xe8\\xb2\\x43\\xeb\\xe9\\x88\\x65\\x39\\x8b\\xd0\\x1b\\x77\\x71\\x38\\xc1\\xd1\\x8d\\x15\\x7b\\xfa\\xee\\xa2\\x4c\\xfa\\x87\\xcc\\x98\\xd2\\x3d\\xfa\\xa3\\xf5\\xd7\\x19\\xcb\\xf7\\x92\\x65\\xda\\x3b\\x08\\xa6\\x34\\xba\\xbc\\xa2\\x79\\x0c\\xfe\\x33\\xaa\\xf9\\x94\\x27\\x5c\\xaf\\xc0\\x05\\x90\\x33\\xa8\\x28\\x10\\x12\\x53\\xef\\x10\\x8a\\x51\\xba\\x86\\xaa\\xbe\\xdb\\xb7\\xf7\\x94\\x81\\x1f\\xce\\x8a\\xc0\\x19\\xe5\\xc6\\xea\\xf7\\x5d\\x73\\x31\\x37\\x27\\xca\\xbc\\xe3\\x30\\xf4\\x7f\\xf7\\x26\\x9e\\xbb\\xb6\\xd6\\xc4\\x0b\\x3a\\xc2\\xde\\xd7\\xda\\x6b\\x9b\\x21\\xb8\\xc5\\xa2\\xce\\x8a\\xb8\\xdc\\x37\\x3c\\xeb\\x45\\x5d\\x47\\xe3\\x6d\\xaf\\xa8\\xcb\\x72\\x76\\xae\\x65\\xd6\\x51\\x2c\\x06\\x07\\xbb\\x21\\x12\\x33\\x65\\x33\\x69\\x98\\xf0\\x8d\\xa1\\x95\\xb8\\x60\\x16\\x94\\xf3\\x60\\x72\\xe2\\x7d\\x67\\xb2\\x12\\x3e\\xc1\\xdc\\x48\\x87\\xc4\\x99\\xf0\\x25\\x13\\x4c\\xa9\\x7d\\x08\\xba\\x14\\x99\\x6d\\xfa\\x6f\\x7b\\xdb\\x0e\\xcd\\xdb\\xb1\\x14\\x66\\x37\\x2c\\xeb\\x0d\\x6c\\x67\\x5d\\xf8\\x90\\xe9\\x08\\xfd\\xc3\\x01\\x23\\x87\\xa6\\x5d\\x76\\xfa\\xf5\\x60\\x4d\\x94\\x53\\xb5\\xc0\\xae\\xb3\\xec\\x9a\\x6b\\xdb\\x39\\x79\\x82\\x48\\xbd\\x61\\xf3\\xdb\\x79\\x4e\\x23\\x46\\x32\\x96\\x73\\x69\\x84\\x51\\x21\\x74\\x2c\\xaf\\x04\\x99\\xb2\\x39\\x17\\xca\\x91\\x02\\xb0\\x36\\x2d\\xcd\\x20\\xea\\xc3\\x95\\x07\\x66\\x1b\\x93\\xb3\\x0a\\xec\\x88\\x2d\\x08\\x8a\\x64\\x79\\x34\\xed\\x9c\\xeb\\xf1\\x2a\\x90\\x58\\x40\\x27\\xec\\xe1\\xe2\\x29\\x1c\\xb6\\xb5\\xf9\\xdc\\x94\\xf7\\x0a\\x01\\x4f\\x8e\\x59\\x42\\x57\\x98\\xf7\\x09\\x1d\\xa9\\xf9\\x7f\\x58\\xae\\x06\\x1d\\xc4\\xb5\\xb0\\x31\\x93\\xfb\\xee\\xc6\\x79\\x00\\xc8\\x29\\x8d\\x16\\xed\\x02\\xc5\\x7d\\x20\\xec\\x8e\\x57\\x1f\\x08\\x6b\\x33\\x48\\x1f\\x08\\xeb\\x03\\x61\\x9f\\xb9\\xfa\\x40\\x58\\x1f\\x08\\xab\\x5d\\x5b\\x6b\\x25\\xf5\\x81\\xb0\\xc6\\x57\\x1f\\x08\\xbb\\xfd\\xea\\x03\\x61\\x77\\xb8\\xfa\\x40\\xd8\\x1d\\xaf\\x3e\\x10\\x76\\xf3\\xd5\\x07\\xc2\\xda\\x4d\\xa6\\x0f\\x84\\xf5\\x81\\x30\\x7b\\xfd\\xf1\\xbc\\x83\\xee\\xea\\x03\\x61\\x6b\\x83\\xf4\\x81\\xb0\\x3e\\x10\\x76\\xe7\\x6b\\x6b\\x4d\\xbc\\x3e\\x10\\x86\\x57\\x1f\\x08\\xab\\x5e\\x7f\\x2c\\x51\\xe7\\xc2\\x48\\x13\\x63\\x50\\xb6\\x6f\\x2a\\x0c\\x66\\xa9\\xe5\\xb1\\xcf\\xb2\\x84\\xab\\x4d\\x94\\xe1\\x61\\x22\\x0c\\x5b\\x12\\x8e\\xe9\\x20\\xaa\\xd0\\x47\\x14\\x9e\\x5d\\x44\\xa1\\x1b\\x6f\\x5c\\x07\\x9e\\xb8\\xd6\\x3c\\xd9\\x06\\xda\\x2f\\x16\\x39\\x53\\x0b\\x99\\x34\\xde\\xe8\\x95\\x4d\\xfe\\x96\\x0b\\x9e\\x16\\xa9\\xd9\\x73\\xca\\xec\\x67\\xbe\\xf4\\x11\\x7d\\x55\\x76\\x5a\\x86\\x40\\x3f\\x3a\\x05\\xcd\\x8d\\x3c\\x66\\x80\\x22\\x4a\\x79\\x62\\x96\\x11\\x8a\\x3e\\x17\\x74\\x69\\xf6\\xba\\x2a\\xa2\\x88\\x31\\xe8\\x51\\x16\\x9a\\x12\\xdf\\x8c\\xfd\\x93\\x7c\\x4f\\x8a\\x97\\xed\\xf8\\x4d\\x3b\\x69\\x89\\x38\\x9f\\x30\\xca\\x37\\x5f\\x37\\x1a\\x63\\x9e\\x67\\xdd\\xf0\\xe5\\x1f\\xce\\x26\\x87\\x01\\x5f\\xa6\\xc2\\xb1\\x65\\x2e\\x96\\x32\\x59\\x62\\x27\\x5b\\xb8\\xc9\\x68\\x45\\x8f\\xc8\\xa4\\xdb\\xeb\\xf7\\xad\\x74\\xfb\\x2e\\x64\\x44\\x5b\\xf5\\xb5\\xaa\\x7b\\x18\\x25\\xb5\\xea\\xa2\\x99\\xc3\\x5a\\x22\\x9c\\xfc\\x9d\\x95\\xd4\\xd6\\xdc\\xad\\xbd\\xe2\\xd8\\xfe\\x38\\x10\\xc0\\x7b\\x81\\x17\\xef\\x8c\\xc0\\x3b\\xb6\\xcf\\xb7\\x13\\xc1\\xa1\\x85\\xe0\\x5a\\x2c\\x69\\x49\\xb2\\x84\\x96\\x4d\\x92\\x60\\x05\\x7e\\x04\\xb9\\x71\\xb8\\x60\\xd1\\xe5\\x99\\x0d\\x86\\xee\\x29\\xc6\\x7c\\x26\\xcb\\x9c\\xeb\\x45\\x31\\x1d\\x47\\x32\\xdd\\x37\\xc7\\x18\\xff\\x6f\\x9a\\xc8\\xe9\\x7e\\x4a\\x95\\x66\\xf9\\x7e\\x2c\\x23\\x2b\\x96\\x46\\x91\\x19\\x85\\x8b\\xf9\\x38\\x8d\\x07\\xd0\\x86\\xf7\\xa4\\xda\\x94\\x31\\x80\\x62\\x30\\xcf\\xb7\\x06\\x1c\\x99\\x32\\xc3\\x11\\x25\\x18\\xe9\\x01\\x9e\\x9b\\x99\\xde\\xbd\\x1b\\xe7\\x86\\x57\\x6b\\x31\\xd2\\x32\\x10\\xfd\\xf0\\x41\\xe8\\x9e\\x73\\x91\\x0e\\xbc\\x11\\x4f\\x2d\\xd8\\xdc\\x59\\xd2\\x45\\x07\\x41\\xe6\\x2d\\x0a\\x30\\x6f\\x8d\\x3a\\xbb\\x2d\\x41\\xe5\\x2d\\x84\\x5e\\xee\\x20\\x90\\xdc\\x45\\x10\\xb9\\xbb\\x00\\xf2\\x17\\x40\\x28\\x7e\\xca\\x81\\xe3\\x0e\\xbd\\x6b\\x1d\\x05\\x8c\\x1f\\x22\\x58\\xdc\\xc9\\x5b\\xb7\\x0d\\x12\\x3f\\x5c\\x80\\xb8\\x9b\\xd7\\xed\\xd2\\xdc\\x78\\xaa\\x41\\xe1\\x0e\\xbc\\xe4\\x5d\\x7a\\xc8\\x3b\\xf3\\x8e\\x7f\\xb1\\x20\\x70\\xfb\\x00\\xf0\\x16\\x04\\x7f\\x5b\\x13\\x99\\x0b\\xae\\x39\\x4d\\x8e\\x58\\x42\\x57\\xe7\\x2c\\x92\\x22\\x6e\\x2c\\xc7\\x6a\\xc0\\x98\\xfe\\xfc\\x28\\x1c\\xd6\\x7a\\xb0\\xaa\\x15\\x15\\x0b\\x6a\\xf1\\xbf\\x8d\\xdd\\x86\\x15\\x24\\x2e\\x72\\x61\\xd5\\x16\\x08\\x3a\\xe0\\x2c\\x9b\\x40\\xeb\\x5d\\xc9\\xfc\\x32\\x91\\x34\\x56\\xfb\\x99\\xc4\\xff\\x2b\\xeb\\x25\\x82\\x42\\x09\\x7c\\x56\\xbb\\x4a\\x89\\xc7\\x76\\x95\\x61\\x79\\x49\\x97\\x8b\\xf8\\xa3\\xbc\\x22\\x72\\xa6\\x99\\x20\\x7b\\x5c\\xb8\\x75\\x1c\\x04\\xc6\\x66\\xe9\\xb7\\xf4\\xdb\\xda\\x7c\\xfb\\xf2\\x85\\xbb\\xf9\\xf9\\x39\\x24\\xc1\\xf5\\xaa\\xd4\\x97\\xf7\\x0f\\xdb\\x07\\x7d\\xde\\x41\\x6c\\x6f\\x9c\\x15\\x49\\xd5\\x49\\x8c\\x8e\\xe3\\x2a\\xbf\\x79\\x59\\x22\\x18\\xbf\\x84\\x71\\xfd\\x69\\xa3\\x22\\x26\\xb6\\xe4\\xec\\xf9\\x2d\\x5a\\xeb\\xd4\\x96\\xaa\\xea\\xe7\\x53\\x59\\x3e\\xe7\\x4f\\xbe\\x38\\x9c\\xf4\\xee\\xe4\\xed\\x72\\xca\\x3c\\x52\\x7a\\xc8\\x16\\x2a\\xba\\x4f\\x34\\x25\\xa4\\x57\\x74\\xef\\x71\\x05\\x45\\xa8\\x3f\\xe4\\x34\\x62\\x93\\xce\\x75\\x04\\x77\\x9c\\x48\\x5c\\xe4\\xd4\\x32\\x40\\xaf\\xf2\\xb9\\xc3\\x23\\x18\\x8b\\xf1\\x34\\xf9\\xc2\\x5d\\x28\\x89\\x9d\\x15\\x49\\xb2\\x42\\x9f\\x43\\xa5\\xcc\\x19\\xa3\\xf0\\xf5\\xaa\\x59\\x70\\xfc\\x6f\\x78\\x4a\\xa9\\x58\\x66\\xb9\\xb4\\x32\\x33\\x2f\\x84\\x30\\x3c\\xb8\\x6c\\x43\\x06\\x8a\\x24\\x60\\x37\\xd3\\x4a\\x6d\\xae\\xe2\\x73\\x33\\x7d\\x23\\xff\\xa0\\x6c\\xb7\\xcc\\x01\\xac\\x0c\\x68\\x7e\\x3d\\x93\\x79\\xc4\\xa7\\xc9\\x8a\\x2c\\x68\\xe2\\x7b\\xce\\x50\\x72\\xc9\\x93\\xc4\\x0e\\x33\\x26\\xe7\\x4c\\x63\\xe0\\x02\\x65\\x67\\x22\\xc5\\x1c\\x26\\x47\\x85\\xeb\\x75\\xc8\\x22\\xf3\\xdb\\x28\\x61\\x54\\x14\\x19\\x3e\\xcf\\x48\\xe2\\x95\\x2c\\x72\\xf7\\xbc\\xb1\\x0f\\x7f\\x78\\x09\\x2c\\x78\\x32\\x0c\\x3a\\xaa\\xdd\\xba\\xb0\\xa5\\x8b\\x46\\x19\\x05\\xe0\\x9d\\xc3\\xaa\\x1e\\x86\\x63\\xca\\x25\\xcb\\x73\\x1e\\xdb\\x68\\x02\\x7e\\x96\\xe5\\x72\\xc9\\x63\\x8c\\xa1\\x38\\xb2\\x41\\xef\\x66\\xec\\x99\\xe3\\xcf\\xb3\\x90\\x62\\x24\\xd8\\x9c\\x82\\xa2\\x62\\x4f\\x11\\xae\\x19\\x8e\\x83\\xb9\\x05\\x22\\x86\\x2e\\x3a\\x46\\xc3\\x97\\x59\\xa5\\x6e\\x7e\\xc9\\xb1\\xff\\x6f\\x40\\x39\\xb2\\x27\\x24\\x91\\x90\\x12\\x5a\\x08\\xae\\xb1\\xa7\\xfc\\xa2\\xd0\\x24\\x96\\x57\\x62\\x60\\x7d\\x56\\x5c\\x11\\x4a\\xa6\\x4c\\xd3\\x20\\xa9\\xd3\\x0a\\x38\\x45\\x98\\xa0\\xd3\\xc4\\xac\\x39\\x64\\x2b\\x5d\\x6c\\x24\\x10\\x99\\x31\\xaa\\x8b\\x9c\\x91\\x39\\xd5\\x6c\\xa3\\x9e\\x83\\xef\\x7b\\x3b\\x79\\xb9\\xb2\\x0e\\xd6\\x19\\x29\\x84\\x62\\x2d\\xc5\\x7b\\x67\\xca\\xd1\\xdf\\xff\\xda\\x8c\\x47\\xf0\\x94\\xc9\\x42\\x3f\\x88\\xf5\\x77\\xb5\\xe0\\xd1\\x22\\x54\\x66\\x79\\xca\\x14\\x91\\x45\\xcd\\x2c\\x7e\\x69\\x7f\\xb6\\x79\\x85\\x7a\\x13\\x70\\xd3\\xd5\\xd4\\x7d\\xbc\\xc1\\xfb\\x65\\xdb\\xb2\\xae\\x67\\xf6\\x05\\x6d\\xa7\\x21\\x69\\xfb\\xe8\\xf4\\xfc\\xf7\\x37\\x07\\xff\\x3a\\x7e\\x63\\xcf\\xa7\\x08\\x85\\x7e\\x21\\xf8\\xbf\\x0b\\x46\\x68\\x2a\\x8d\\x2e\\x9c\\x84\\x09\\x82\\x43\\xb0\\xe8\\x83\\x0f\\xe0\\x24\\x77\\x9b\\x4a\\xd8\\x50\\x20\\x43\\x8f\\xfc\\xf6\\x09\\x93\\xd0\\x69\\xff\\xcb\\xe7\\x4b\\x3e\\x76\\xef\\x30\\xdf\\x95\\x02\\xb2\\x34\\x82\\xde\\x61\\x94\\x08\\xa6\\xcd\\xc9\\x43\\x8d\\x12\\x7b\\xc9\\x71\\x31\\x4f\\x42\\x65\\xb2\\x19\\xbb\\x6a\\x6b\\x13\\xb5\\xb5\\x88\\x46\\xe5\\x1b\\x4c\\x9a\\x1a\\x46\\x9d\\xf4\\x30\\x2b\\xe7\\xd0\\x51\\xe7\\x9f\\x92\\x6b\\x3b\\x33\\x00\\x5b\\x33\\x3b\\x33\\x00\\x55\\x8f\\x93\\x09\\xa1\\x71\\x9c\\x83\\x9a\\x02\\xa7\\x3e\\xad\\x75\\x00\\xcd\\xca\\x8c\\x9d\\x21\\x79\\x41\\xbe\\x23\\xd7\\xe4\\x3b\\x30\\x0b\\xfe\\xde\\xb6\\x4f\\x52\\x5b\\x85\\xbd\\x8b\\x04\\x1c\\x63\\x8d\\x9e\\x4c\\x3a\\xa2\\xf8\\x2f\\x0b\\xaa\\x61\\x44\\x43\\x55\\x2d\\xc9\\x94\\x5b\\x35\\x94\\x5d\\x6b\\x96\\x1b\\xb5\\xc8\\xae\\xc4\\xa3\\x76\\x98\\x32\\x13\\x7c\\xc0\\x6d\\x86\\x6e\\xf2\\x93\\x59\\x35\\xe9\\xe7\\x7e\\x1b\\xcd\\xfc\\xdc\\xd8\\xf7\\xa7\\x96\\x0b\\x55\\xbb\\xb9\\x94\\xa3\\xa5\\x54\\x47\\x8b\\x2a\\x1b\\x33\\x0a\\x86\\xaa\\x08\\xa7\\x58\\x02\\x1b\\xc7\\x84\\xdc\\x05\\x6f\\x91\\x5a\\xb0\\x3d\\xdb\\xb8\\x5d\\xb4\\xb9\\xb2\\x9e\\xb7\\xad\\x54\\xcd\\xf0\\x07\\x39\\x6f\\x15\\x83\\x00\\xba\\x29\\x93\\xf1\\x98\\x1c\\xd3\\x68\\x01\\xd3\\x8a\\x03\\x99\\x61\\x2c\\x10\\x18\\x6c\\x41\\x97\\x66\\xe1\\xed\\x6f\\x31\\x8e\\x0d\\xda\\x8a\\xf7\\x8e\\xc2\\x5e\\x32\\xe7\\x29\\xa2\\x02\\x5b\\x90\\xce\\x58\\x9e\\x63\\x0e\\xf5\\x74\\xe5\\x52\\xd9\\x5a\\x2f\\x5e\\xab\\x93\\x94\\xe5\\x52\\xcb\\x48\\xb6\\x68\\x82\\x55\\xaf\\xcb\\x80\\xe1\\x80\\x08\\x19\\xee\\x5d\\x4b\\xf9\\xf7\\x47\\x93\\x21\\xb9\\x38\\x9c\\x40\\xeb\\xa2\\xf3\\xc3\\x8b\\x49\\x55\\xc3\\xde\\xb9\\x38\\x9c\\xec\\x3c\\x2a\\x29\\x88\\x73\\xb3\\x81\\x43\\xb5\\xc1\\x20\\x15\\x87\\x49\\xc2\\x95\\x1e\\xa5\\x34\\x1b\\x5d\\xb2\\x55\\x43\\x99\\xda\\x85\\x5c\\x1f\\xf9\\x15\\xee\\xe4\\x85\\x90\\xcc\\x29\\xcd\\xee\\x3d\\x5a\\xce\\x68\\xcc\\xfb\\x02\\xa0\\xbb\\x5f\\x7d\\x01\\xd0\\x1d\\xaf\\xbe\\x00\\xa8\\x2f\\x00\\x5a\\xbf\\xb6\\x26\\x63\\xb2\\x2f\\x00\\x7a\\x5e\\xa1\\xdb\\xbe\\x00\\xe8\\xfe\\xd7\\xa3\\x47\\x6c\\xfb\\x02\\xa0\\xcd\\x57\\x5f\\x00\\xd4\\x17\\x00\\xdd\\xed\\xea\\x0b\\x80\\xee\\x7f\\x6d\\x5d\\xae\\x49\\x5f\\x00\\x74\\xaf\\xab\\x2f\\x00\\x5a\\xbf\\xfa\\x02\\xa0\\x1b\\xae\\xbe\\x00\\xe8\\x86\\xab\\x2f\\x00\\x5a\\xbf\\xfa\\x02\\xa0\\xfb\\x5d\\x7d\\x01\\x50\\x5f\\x00\\xf4\\xac\\xf3\\x22\\x49\\x5f\\x00\\x64\\xaf\\xbe\\x00\\xe8\\x59\\x64\\x7f\\x91\\xbe\\x00\\xe8\\x4e\\x57\\x5f\\x00\\xd4\\x17\\x00\\x35\\xb9\\xfa\\x02\\xa0\\xe7\\xe2\\x94\\xe9\\x0b\\x80\\xfa\\x02\\xa0\\x3f\\x8e\\xa2\\xdb\\x17\\x00\\xf5\\x05\\x40\\x7d\\x01\\x50\\x5f\\x00\\x74\\xeb\\x2c\\xfa\\x02\\xa0\\xe7\\x60\\x02\\xe6\\x4c\\xf1\\xff\\xb0\\x89\\x4c\\x78\\xb4\\x6a\\x9d\\xf0\\x77\\x66\\x5b\\xcb\\x2a\\x3b\\x2c\\xc9\\x60\\xdc\\x20\\xb5\\xaa\\x45\\x11\\xc7\\x96\\xd5\\xae\\x9c\\x05\\x84\\x0b\\x6b\\x58\\x7c\\x7b\\xdd\\x2f\\x40\\x82\\xad\\xa8\\x63\\x71\\x2f\\x78\\xda\\x3c\\x92\\x02\\x83\\x18\\xab\\x11\\xc9\\xd7\\xcc\\x6f\\xd1\\xda\\x44\\x08\\x5f\\xa4\\xa3\\xd4\\xea\\xdd\\xb0\\x14\\xce\\xef\\x04\\x2d\\x3d\\x07\\xe3\\x37\\x6e\\x10\\x9a\\x65\\x09\\x67\\x6a\\x4c\\xce\\x7d\\x8b\\x13\\xe0\\x5e\\xea\\x15\\x89\\xb2\\x62\\x48\\x52\\x96\\xca\\x7c\\xd5\\xc2\\x9a\\xe8\\x40\\xe1\\xac\\xac\\x5a\\x47\\x24\\x3b\\xc3\\x31\\x1d\\x19\\x8c\\x11\\x91\\x65\\xc9\\x0a\\x95\\xa9\\xb2\\x72\\xd0\\x53\\x8d\\x3b\\xe6\\x12\\x83\\xba\\x53\\xcb\\xf2\\xe0\\xba\\x62\\x86\\x9d\\x4a\\x7d\\x66\\x37\\xfc\\xa3\\xa5\\xad\\xdf\\x94\\xa0\\x4d\\xb5\\x4c\\x79\\xd4\\x84\\x61\\x23\\x8f\\xed\\x90\\x5b\\xdf\\x39\\x43\\x9b\\x1c\\x6f\\xf8\\x14\\x5c\\xd7\\x2a\\x33\\x83\\xe4\\xe5\\x90\\x49\\xce\\x68\\xbc\\x82\\x21\\xa1\\x99\\x4f\\x60\\x15\\x3f\\xc1\\x44\\xef\\x28\\xa1\\xbc\\x79\\x54\\xbe\\x9a\\x38\\x75\\x08\\x63\\x11\\xb3\\x15\\xca\\xd4\\x29\\xc8\\xc0\\xf5\\xe4\\x1b\\xfa\\xb4\\x24\\x8e\\x87\\x60\\xec\\xbe\\xc2\\x1f\\x0f\\x31\\x8f\\xd7\\x90\\x1c\\x54\\x4a\\x50\\xbc\\xb9\\x0a\\x2d\\xee\\x8f\\xa2\\x54\\x7e\\x05\\xa1\\x49\\xb6\\xb8\\x5d\\xfd\\x35\\x13\\x39\\x5a\\x09\\x9a\\xf2\\xc8\\x6d\\x8c\\x03\\x5c\\x3b\\x63\\xee\\x54\\x15\\x60\\x37\\x36\\x8e\\x67\\x1e\\x92\\xa6\\x85\\xa6\\xd3\\x84\\x8d\\xc9\\x09\\x96\\xd2\\x48\\x01\\x9d\\xee\\x21\\xff\\xc2\\x86\\x35\\xdc\\x26\\x6a\\x9a\\x61\\xd5\\x3e\\xbd\\xa2\\x65\\x6a\\xc5\\xc6\\xd3\\x03\\x0b\\x82\\x65\\x43\\x4c\\x98\\x9d\\x2f\\x05\\x23\\x4c\\xe8\\x7c\\x65\\xd6\\x6e\\x22\\xe3\\x73\\xb3\\x7c\\x95\\xbb\\x5b\\x57\\x13\\xb5\\xcc\\xa8\\xe8\\x22\\x9b\\xa2\\x65\\x26\\x45\\x37\\xf9\\x0f\\xed\\x73\\x1f\\xd6\\x83\\xb8\\x41\\x81\\x5f\\x98\\xd6\\x58\\x59\\x55\\xc3\\xc3\\x36\\x9c\\x4a\\x27\\xf8\\x27\\x32\\x36\\xe2\\x2b\\x67\\x61\\x2b\\x31\\x6b\\xfd\\xc1\\x01\\x49\\xe9\\x25\\x18\\xd0\\x54\\x97\\x72\\x8d\\x2e\\x29\\x4f\\xcc\\x11\\x2a\\xcb\\x03\\x5a\\xea\\x8a\\xee\\xea\\x40\\xf0\\x77\\x5d\\x35\\x45\\xda\\xee\\xa0\\x2e\\xab\\x9e\\x08\\x74\\x3e\\x4a\\x79\\xb3\\x0a\\x7e\\xb2\\xa6\\x03\\xbe\\x81\\xb1\\x82\\x64\\x2b\\xb3\\x27\\x52\\x7a\\x0d\\x16\\x29\\x4d\\x65\\x21\\xb4\\xd9\\x29\\x91\\x4c\\xb3\\x42\\x57\\x65\\x26\\x88\\xdf\\x7b\\x9b\\xaa\\x91\\x14\\x33\\x3e\\xb7\\x2e\\xae\\xfd\\x94\\x0a\\x3a\\x67\\x23\\x3f\\xec\\xa8\\x64\\xbd\\xfb\\xed\\xec\\xd4\\x56\\x6c\\x87\\xc6\\xae\\xc0\\x65\\xd2\\x45\\xae\\x38\\xd5\\x9a\\xe5\\xe2\\x15\\xf9\\xaf\\xbd\\x8f\\x5f\\x7d\\x1a\\x0d\\xbe\\xdf\\xdb\\xfb\\xf0\\x62\\xf4\\x8f\\xdf\\xbe\\xda\\xfb\\x38\\x86\\x7f\\xfc\\x65\\xf0\\xfd\\xe0\\x93\\xfb\\xe3\\xab\\xc1\\x60\\x6f\\xef\\xc3\\x4f\\x6f\\x7f\\xb8\\x98\\x1c\\xff\\xc6\\x07\\x9f\\x3e\\x88\\x22\\xbd\\xc4\\xbf\\x3e\\xed\\x7d\\x60\\xc7\\xbf\\xdd\\x71\\x90\\xc1\\xe0\\xfb\\x3f\\x37\\x9e\\x72\\x6b\\x0f\\x74\\x77\\xfe\\xe7\\x8e\\xbc\\xcf\\x5f\\xc4\\xf7\\x6c\\xb3\\x34\\x3b\\x3a\\x8b\\x36\\xc3\\x7c\\xed\\x34\\x5a\\xff\\xd0\\x6d\\xa7\\xd1\\x49\\x49\\x30\\x33\\xfc\\x38\\x5c\\x11\\x99\\x72\\xad\\xad\\x96\\x4c\\xc3\\xba\\xb2\\x9a\\xf1\\x61\\xf9\\x00\\x9f\\x21\\xa7\\xe7\\x2a\\xac\\xc9\\x0a\\x6c\\x16\\xe9\\x1c\\xad\\x60\\xfc\\x08\\xc2\\xd3\\x2c\\x61\\x29\\x13\\x1a\\xce\\xf3\\xc8\\x69\\x82\\x60\\x0d\\x8e\\xcb\\x99\\x44\\x54\\x18\\x9d\\x9d\\x5d\\x47\\x8c\\xc5\\xf6\\x61\\x3d\\xeb\\xf8\\xfc\\xd5\\xb3\\x8e\\xe7\\xc8\\x3a\\x14\\x8b\\x8a\\x9c\\xeb\\xd5\\xa1\\x14\\x9a\\x5d\\x37\\x8a\\x77\\xde\\x14\\xf0\\x3d\\xaf\\x0e\\x6d\\x4d\\x33\\x9b\\xbb\\x6a\\xbf\\x23\\x32\\xc3\\x4a\\xcd\\x1b\\x31\\x90\\x16\\xb2\\x48\\x62\\x40\\x18\\x28\\x04\\x84\\x80\\x10\\xac\\x82\\x69\\x8c\\xcf\\x80\\x92\\x08\\x1a\\x64\\xfd\\x71\\x2e\\xe2\\x82\\x43\\xff\\xbb\\xe0\\x4b\\x9a\\x30\\xa1\\x83\\x5f\\x4c\\x20\\xc6\\x10\\xfe\\xa8\\x91\\x9b\\xe8\\x91\\x4d\\x6c\\xd0\\x7e\\x26\\x39\\x5f\\xf2\\x84\\xcd\\xd9\\xb1\\x8a\\x68\\x02\\x5c\\xa9\\x1b\\x41\\x70\\x70\\xc3\\xe8\\xb0\\x44\\xb9\\x4c\\x94\\xd1\\xd8\\x0d\\x23\\x26\\xd4\\x85\\xd3\\xc0\\x8e\\x9d\\x53\\x2e\\x48\\x6a\\x98\\x6a\\xe6\\x7e\\xac\\x30\\x2e\\x67\\x78\\x7b\\x46\\x73\\xb3\\x14\\x3e\\xfe\\x06\\x56\\xf1\\x54\\xca\\xc4\\xd6\\x15\\x27\\xab\\x72\\x7c\\x8e\\xc6\\x81\\x90\\xbf\\x0b\\x76\\xf5\\xbb\\x19\\x4d\\x91\\x59\\x42\\xe7\\x3e\\xec\\x66\\x4c\\xe5\\x7a\\xe4\\xbc\\x1c\\xfa\\xc6\\x17\\x80\\xa2\\xdd\\x82\\x11\\x9a\\x5c\\xd1\\x95\\x2a\\x83\\x90\\xe5\\x18\\x5c\\xbd\\x22\\x2f\\x07\\xb0\\xf1\\xa8\\x22\\x7e\\x8c\\x98\\x7c\\x3d\\x80\\x54\\xba\\xc3\\x83\\xc9\\xef\\xe7\\xbf\\x9e\\xff\\x7e\\x70\\xf4\\xf6\\xe4\\x94\\x9c\\x4a\\xcd\\x50\\x62\\x05\\xd6\\x8b\\x15\\x36\\x76\\x96\\xde\\x37\\x37\\x96\\x6a\\x0c\\x16\\x12\\x64\\x86\\x8b\\x58\\x5e\\xa9\\xc6\\x1e\\x4a\\xdc\\x7e\\x86\\x78\\x8c\\x8a\\x66\\x4e\\x1a\\x9a\\x51\\xe8\\xef\\xdc\\x42\\x3e\\xac\\x65\\x6b\\x87\\x83\\x82\\x80\\x8e\\xe3\\xfd\\x38\\x97\\x19\\x12\\xc1\\x05\\x8c\\x43\\x1f\\xd9\\x51\\x2d\\x0f\\xc4\\x55\\x9d\\xc1\\xfa\\xce\\xaa\\x03\\xce\\x73\\x2a\\x74\\x19\\x39\\x2d\\xd7\\xcc\\x36\\x96\\x1e\\xb7\\x5e\\x8e\\xc7\\x13\\xdb\\x5d\\xd8\\xf8\\x34\\xee\\x0e\\x33\\xe0\\x20\\x8e\\x59\\x5c\\x21\\xff\\xb3\\xab\\xf5\\x39\\x74\\x2f\\x17\\x84\\xa4\\xc8\\xe4\\xdd\\xf9\\xc9\\xff\\xad\\xed\\xe3\\x55\\xd6\\xae\\xe8\\xa0\\x1b\\x28\\x97\\x5c\\x66\\x9d\\xad\\xee\\x19\\x4b\\xe5\\xb2\\x5f\\xdf\\x6d\\x59\\x5f\\x2f\\x2d\\xbb\\x49\\x75\\x3d\\x2b\\x44\\x28\\xd0\\x44\\x30\\x3e\\x49\\x65\\xcc\\xc6\\x64\\xe2\\x73\\x6e\\xaa\\xdf\\x86\\x70\\x91\\x39\\x23\\xe6\\x16\\xa1\\x39\\x4d\\x92\\x55\\xa8\\x4c\\x69\\x89\\x58\\x1f\\x15\\x30\\xb1\\x90\\x91\\xcf\\x68\\xa2\\x1e\\x9b\\x1b\\xb7\\x91\\x8d\\x46\\x8f\\x78\\x6b\\x8c\\xdd\\x4e\\x96\\xc3\\x8f\\x46\\x62\\x26\\xa4\\xb6\\xca\\xb0\\x99\\x25\\x00\\xb4\\xe5\\x32\\x22\\x68\\x59\\x07\\x85\\x0d\\x15\\xf9\\xa6\\x30\\xef\\xc7\\x89\\x46\\xae\\x1c\\xb1\\x27\\x7e\\x64\\x0c\\x99\\x16\\x8a\\xa9\\xcd\\xa2\\xb1\\xb4\\xb5\\xcd\\xe8\\x39\\xa3\\x31\\xc4\\x1c\\x32\\xaa\\x17\\x98\\x97\\x9c\\x52\\x75\\xc9\\x62\\xfc\\xc0\\xaa\\x66\\x3e\\xec\\x01\\x6e\\x5a\\xf7\\xa8\\x0b\\x33\\x6f\\x17\\xe1\\x00\\x95\\x0c\\xb3\\xa5\\x21\\x36\\xc2\\xe2\\x47\\x5e\\xf5\\x16\\x87\\xd0\\x10\\xe5\\x9d\\x48\\x56\\x67\\x52\\xea\\xd7\\x1e\\xac\\xa6\\x93\\x1d\\xf0\\x8b\\xd5\\x96\\xab\\x61\\x27\\x50\\x27\\x29\\x3c\\x77\\x04\\xab\\x01\\x87\\x2a\\xc4\\xc9\\x39\\x2a\\x57\\xfc\\xa9\\x1f\\xa9\\xbc\\x10\\x07\\xea\\x87\\x5c\\x16\\x8d\\x85\\xd8\\x9a\\xb2\\xf9\\xc3\\xc9\\x11\\xb0\\xa2\\xc2\\xa6\\xfd\\x09\\x9d\\xaf\\x32\\xc9\\xd1\\x45\\x75\\x83\\x61\\xf0\\xde\\x26\\x2e\\x86\\x67\\xa2\\xcc\\x31\\x23\\x6f\\xe9\\x8a\\xd0\\x44\\x49\\x47\\x4b\\x1b\\x94\\xaa\\xd9\\x8b\\xc4\\x1a\\xa3\\xe6\\xeb\\xa9\\xd4\\x8b\\x35\\x2b\\xd4\\x1c\\xa8\\xf5\\xdf\\x0d\\x83\\x2c\\xc0\\x32\\x56\\xcf\\xc5\\xda\\xcf\\x35\\x44\\x3c\\xb2\\x9c\\x45\\x2c\\x66\\x22\\x7a\\xec\\x65\\x7f\\xec\\xe4\\x39\\xd8\\x3a\\xa7\\x52\\x98\\x83\\xd9\\xc9\\xe6\\x39\\xf1\\x59\\x93\\x96\\xa4\\xe1\\x56\\x81\\x90\\x96\\xb5\\xfe\\x28\\x64\\x61\\xc2\\xb1\\x2c\\x14\\xcb\\x31\\x65\\x34\\x2f\\x18\\xae\\xe4\\x4f\\xc5\\x94\\x25\\x86\\xf2\\xc6\\x24\\x05\\xb8\\x4c\\xaa\\xd1\\xf1\\xc0\\x53\\x3a\\x67\\x84\\x6a\\xbf\\xd3\\xb4\\x24\\x4c\\xa8\\x22\\xb7\\x8b\\xc8\\x35\\x89\\x25\\x2b\\x31\\xae\\xa8\\x22\\xef\\x4f\\x8e\\xc8\\x0b\\xb2\\x67\\x9e\\x35\\x80\\xfd\\x33\\xa3\\x3c\\x81\\x04\\x4d\\x48\\xf8\\xa8\\xd9\\xa8\\x33\\x37\\x04\\x4c\\x09\\x36\\x2f\\x91\\x39\\x32\\x89\\x21\\x11\\x92\\xa8\\x22\\x5a\\xb8\\x39\\x19\\xbb\\xd7\\x99\\xcd\\xb6\\xa8\\x08\\xe2\\x26\\xdb\\xb9\\xd7\\x1f\\x97\\x43\\xbd\\x57\\x2c\\xef\\x8c\\x41\\xbd\\x6f\\xc0\\xa0\\x42\\x35\\xca\\xec\\xb9\\x2a\\xf5\\x70\\x63\\xa5\\x4c\\xd3\\x98\\x6a\\x6a\\x19\\x97\\xbb\\x61\\x6b\\x97\\xf4\\x8f\\xcd\\xbe\\x14\\x7b\\xc3\\x45\\x71\\x8d\\x2e\\xd2\\xee\\x5c\\x2d\\xe7\\xc7\\x30\\x2c\\xec\\x21\\xa0\\x3a\\xac\\x3a\\x26\\xc6\\xf9\\xfc\\xa1\\x20\\xc5\\xe5\\xa4\\xb2\\x57\\x86\\x37\\xa8\\x89\\xc0\\x27\\x5c\\x1a\\x92\\x51\\x4e\\xa8\\x88\\x65\\xba\\xf6\\x30\\xc8\\x79\\xa2\\xd1\\x22\\x7c\\x40\\xbf\\xfb\\xaa\\xd7\\x96\\x38\\x85\\x12\\xb6\\x64\\x2d\\xc0\\x70\\x6b\\x3b\\xef\\x8d\\x19\\xcd\\x10\\xc7\\xed\\x08\\x18\\x9e\\x24\\x74\\xca\\x12\\x9b\\x66\\x85\\xa9\\x99\\xeb\\x3b\\xf0\\xb1\\x2b\\xbb\\x72\\x99\\x74\\x57\\x8a\\x7e\\x26\\x13\\x86\\xa5\\x12\\x8e\\x10\\x66\\xf8\\x27\\x41\\x07\\x18\\xa4\\x2b\\x3a\\x80\\x35\\x58\\xa1\\x03\\xd8\\xb5\\x4f\\x81\\x0e\\x45\\x0b\\x51\\x4f\\xea\\x74\\x30\\x7a\\x43\\x95\\x0e\\x20\\xbc\\xb7\\x9d\\x0e\\x8a\\x45\\x91\\x4c\\xb3\\x49\\x2e\\x8d\\xd9\\xd9\\x99\\x6c\\xb2\\xc3\\x96\\x71\\x3e\\x74\\x6c\\x6c\\x48\\xbc\\x04\\x59\\x50\\xbd\\x99\\xe6\\x41\\x91\\x14\\xd5\\x28\\x24\\x5c\\xa5\\xd4\\xff\\x0a\\x64\\x16\\xb0\\x9e\\xba\\x20\\x73\\xa3\\x54\\x02\\x81\\xe6\\x97\\xf6\\x8b\\xa7\\x2c\\x0e\\xba\\xa8\\x33\\x6e\\xe1\\xec\\xec\\x44\\x1a\\xc9\\x88\\x26\\xd0\\xec\\xa0\\xdd\\x96\\x23\\xf5\\x6d\\x57\\x1f\\x38\\x28\\x8d\\x83\\x18\\x25\\x7c\\x16\\xe4\\x09\\x53\\x70\\xb4\\x38\\x17\\xa6\\x90\\x31\\x0b\\xa2\\xce\\x98\\x7b\\x78\\x81\\x25\\x54\\x70\\x9f\\xab\\xca\\x33\\x7a\\x85\\xcd\\x02\\x61\\x71\\xe5\\xd7\\x5a\\x5a\\x9c\\xe1\\xb7\\xbe\\x85\\x82\\x99\\x20\\x13\\x31\\x17\\x73\\xf0\\xab\\x0d\\x49\\xce\\x12\\xac\\xe7\\xb3\\x4c\\xe0\\x12\\x2d\\xc8\\x5d\\x38\\x12\\x6e\\x50\\x77\\x1e\\xdc\\xa3\\x5d\\x5a\\xb1\\x1d\\x39\\xcc\\x15\\xe6\\x33\\x64\\xb7\\x5c\\x91\\x9d\\x37\\x8e\\x00\\x2d\\x30\\xe7\\xb7\\x51\\xc2\\xec\\xe0\\x1b\\xfa\\xd5\\x44\\x4f\\xe7\\x25\\x17\\xb1\\x2d\\x7d\\xab\\x10\\xcb\\xd9\\xb9\\x56\\x0f\\x86\\xa2\\x4a\\x1e\\x87\\xbc\\xe5\\x15\\xf9\\x28\\x88\\x27\\x16\\x19\\x35\\xde\\x1e\\x67\\xa8\\x32\\x3b\\x1f\\xdd\\xe8\\x76\\xc7\\xab\\x7f\\x48\\x7d\\x98\\xf7\\x02\\xd6\\xde\\x3c\\x77\\x64\\x2c\\xf7\\xf5\\xfb\\xdc\\xbb\\x3c\\x2a\\xd8\\xa6\\xe5\\x7e\\x5d\\x5b\\x31\\xbf\\xe0\\xb0\\x4e\\xa5\\x8f\\xcc\\xb6\\xd6\\x5c\\xcc\\x55\\x68\\xc9\\x54\\x3b\\x5b\\x6d\\x36\\x65\\xdc\\x0a\\xcf\\x72\\x99\\xba\\xbc\\xe2\\xba\\x69\\x50\\x2d\\xd9\\x7d\\x2a\\x66\\x48\\x62\\xd4\\x89\\x27\\x6e\\x84\\xcc\\x53\\x45\\x0f\\x73\\x43\\x09\\xcd\\x69\\x72\\x9e\\x35\\x6f\\x04\\x40\\xd6\\x40\\xa7\\xdf\\x9e\\x1f\\x54\\x87\\x06\\x61\\x6d\\x33\\xca\\x19\\x7c\\x4f\\x68\\x9c\\x72\\xa5\\xc0\\x11\\xc6\\xa6\\x0b\\x29\\x2f\\xc9\\xde\\x06\\x04\\xdd\\x20\\xcb\\x4a\\xf1\\xb9\\xda\\xb7\\x7b\\x7e\\x64\\x66\\x3f\\x20\\x5c\\x24\\x3e\\x93\\x09\\xec\\x60\\xa1\\x7d\\x12\\x3b\\x3c\\x24\\xf2\\xb3\\x80\\x35\\xb4\\x8d\\x56\\x6c\\xb2\\xc2\\xfa\\x34\\xb1\\xb5\\x8a\\xd9\\x05\\x8f\\xce\\xb0\\xd7\\x97\\xa7\\x5d\\x99\\xdf\\x67\\x97\\xe8\\xd4\\xee\\xed\\x3a\\x16\\xf2\\x46\\x3a\\xa2\\xf6\\xf8\\xe8\\x44\\xb2\\xca\\x45\\xc4\\x54\\x77\\x10\\xac\\x3f\\x96\\x63\\x92\\x98\\x61\\x45\\x3c\\x83\\xec\\x27\\x7a\\x63\\x3a\\x1c\\xf8\\xa5\\x77\\x01\\x58\\xc5\\xfe\\x74\\x37\\xd4\\xa8\\xab\\xb5\\x46\\x50\\xca\\x34\\x42\\x23\\xdd\\x70\\x34\\x60\\x81\\x4e\\x85\\x58\\x48\\x21\\x73\\xdc\\xa2\\x46\\x88\\x4a\\x01\\x5b\\x1a\\x58\\x14\\x46\\xf3\\x60\\x4d\\x2c\\x8b\\x0e\\xa6\\x7a\\x58\\x46\\x89\\xc3\\x40\\x20\\x00\\x33\\x20\\x16\\x5b\\x39\\x87\\x2b\\xae\\x17\\xd0\\x4d\\x61\\x51\\x8b\\x1a\\xc2\\x4c\\x72\\xa6\\x20\\x00\\x23\\x08\\xcb\\x73\\x99\\xdb\\x84\\x2c\\xe7\\xb7\\xb6\\x85\\x56\\x13\\x19\\x43\\x46\\x97\\xd9\\x24\\xd4\\xfc\\xb5\\xab\\xc2\\x40\\x75\\xd9\\xbb\\xc8\\xe3\\x63\\xb2\\xd9\\x8c\\x45\\xa0\\x68\\x85\\x04\\x46\\xae\\xbd\\x57\\xb6\\x97\\x70\\x15\\x7c\\x5a\\xba\\xde\\x47\\x29\\xbf\\x36\\x4f\\x09\\x7f\\x55\\xeb\\xa0\\x28\\xa4\\x18\\x6d\\xfe\\x7a\\x30\\x26\\xe4\\x44\\xf8\\xfc\\xdb\\xa1\\x59\\xc5\\xf0\\x4e\\x97\\x7a\\xa6\\xcd\\x2b\\x86\\x8d\\xb3\\xe0\\x05\\x42\\xc7\\x99\\xd1\\x0e\\xf3\\xa2\\x83\\x1d\\xdf\\xc6\\x1d\\x4e\\x42\\x97\\x78\\xa7\\xec\\x00\\x5c\\xe3\\x76\\x50\\xb3\\xf4\\x4e\\x07\\x68\\xe3\\x2a\\x37\\xb7\\x7c\\x29\\x77\\xf9\\xd3\\x08\\x80\\x90\\xb6\\x7c\\xce\\x22\\x93\\xf5\\xdd\\x8c\\xee\\x76\\xf5\\xdd\\x8c\\xee\\x78\\xf5\\xdd\\x8c\\xfa\\x6e\\x46\\xeb\\xd7\\xd6\\xa4\\x0c\\xf6\\xdd\\x8c\\x9e\\x17\\x0e\\x65\\xdf\\xcd\\xe8\\xfe\\xd7\\xa3\\xc3\\x4f\\xf6\\xdd\\x8c\\x36\\x5f\\x7d\\x37\\xa3\\xbe\\x9b\\xd1\\xdd\\xae\\xbe\\x9b\\xd1\\xfd\\xaf\\xad\\x03\\xce\\xed\\xbb\\x19\\xdd\\xeb\\xea\\xbb\\x19\\xad\\x5f\\x7d\\x37\\xa3\\x1b\\xae\\xbe\\x9b\\xd1\\x0d\\x57\\xdf\\xcd\\x68\\xfd\\xea\\xbb\\x19\\xdd\\xef\\xea\\xbb\\x19\\xf5\\xdd\\x8c\\x9e\\x35\\xc8\\x3b\\xe9\\xbb\\x19\\xd9\\xab\\xef\\x66\\xf4\\x2c\\xa0\\xac\\x49\\xdf\\xcd\\xe8\\x4e\\x57\\xdf\\xcd\\xa8\\xef\\x66\\xd4\\xe4\\xea\\xbb\\x19\\x3d\\x17\\xa7\\x4c\\xdf\\xcd\\xa8\\xef\\x66\\xf4\\xc7\\x51\\x74\\xfb\\x6e\\x46\\x7d\\x37\\xa3\\xbe\\x9b\\x51\\xdf\\xcd\\xe8\\xd6\\x59\\xf4\\xdd\\x8c\\x9e\\x83\\x09\\xa8\\x74\\xcc\\x1b\\x01\\x46\\xde\\x05\\xdb\\xc6\\xe6\\x2c\\x07\\xa5\\xe4\\xd3\\x62\\x36\\x63\\x39\\x70\\x2e\\x78\\xf2\\x5a\\x5a\\x55\\x09\\xe3\\x57\\x0f\\xe5\\x32\\x3d\\x04\\x98\\x1c\\x5b\\xde\\x71\\xc3\\xcf\\x6d\\xed\\x3a\\x00\\x3b\\x96\\x89\\xc5\\xc7\\xef\\x5e\\x6f\\x00\\xd2\\x69\\x9c\\x6f\\xd8\\x34\\xa5\\x16\\xe6\\xfc\\x4e\\x34\\x8b\\xc2\\xdf\\x40\\xf0\\x4d\\xe5\\x46\\x96\\xee\\x51\\x22\\x95\\x4d\\x88\\x06\\x62\\x45\\x0b\\x2a\\x04\\x73\\xf6\\x1e\\xd7\\xe0\\x47\\x99\\x32\\x26\\x88\\xcc\\x98\\x8d\\x81\\x53\\xa2\\xb8\\x98\\x27\\x8c\\x50\\xad\\x69\\xb4\\x18\\x9b\\x27\\x09\\x47\\xec\\x32\\x79\\xd9\\x7e\\xa2\\x74\\xce\\x68\\xea\\xd2\\xb8\\x53\\xca\\x71\\x28\\x42\\xa3\\x5c\\x2a\\x45\\xd2\\x22\\xd1\\x3c\\xf3\\x83\\x11\\xc5\\xa0\\xfe\\x02\\x05\\x95\\x27\\x06\\xe4\\xcb\\x95\\x19\\xcf\\xc3\\xf2\\x69\\x76\\x5a\\x32\\x44\\x32\\x03\\x6b\\x73\\x08\\xd8\\xd0\\x69\\xa6\\x57\\xc4\\xbc\\x72\\x62\\x01\\x61\\x73\\xa5\\x49\\x94\\x70\\x90\\xd6\\xf0\\x44\\x2c\\xb5\\x85\\xf1\\x86\\x4e\\x56\\x0b\\x3b\\x53\\x65\\xa7\\x2a\\x62\\x50\\x5b\\x33\\xad\\x08\\x24\\x08\\x97\\x03\\xda\\xa1\\x62\\xae\\xac\\x9a\\xaf\\x86\\x84\\x3a\\x98\\x2d\\x24\\xb4\\x9b\\x29\\x90\\xda\\x49\\x16\\x1c\\xdd\\x7e\\x14\\x0c\\x17\\xc0\\x8b\\xba\\xc6\\x40\\xb6\\x06\\x09\\x73\\xe5\\x13\\x3a\\xf7\\x9b\\x73\\x58\\x49\\xfe\\x2f\\x15\\x0a\\xdb\\x02\\xa1\\x76\\x0c\\x60\\x01\\x04\\x5b\\x9a\\x3d\\xc0\\x22\\x66\\xe4\\x2b\\xbd\\x61\\xd7\\x3f\\xf8\\xa6\\xd7\\x34\\x9f\\x33\\xed\\xcb\\x05\\x9a\\x66\\x91\\x57\\x93\\x4f\\x42\\x20\\xe0\\xd0\\x10\\x29\\x49\\x06\\xd4\\xb1\\xcd\\x44\\x82\\x8a\\xab\\x4d\\x48\\xc3\\x38\\x43\\x0b\\xb0\\xb6\\xe9\\x06\\xa7\\x18\\x61\\xf2\\x66\\xd9\\x81\\x26\\xa3\\x11\\x53\\x64\\xef\\x64\\x72\\x38\\x24\\x93\\x93\\x23\\x9b\\xa1\\x29\\x67\\x9b\\x2a\\x9c\\x2d\\x0f\\xc3\\x1d\\x78\\x13\\xe6\\xb1\\xc7\\x6e\\x0b\\x86\\x0f\\xaa\\x42\\xed\\xb3\\x27\\x5e\\xbf\\x82\\xb6\\x32\\x9b\\x38\\x00\\xa8\\x5c\\x1e\\x16\\x9d\\x28\\xec\\x90\\x65\\x7d\\x42\\xdc\\x97\\x6c\\xd8\\xcd\\xc7\\xca\\x42\\x45\\x87\\x48\\xe4\\x7e\\xe1\\x27\\x62\\xa9\\x64\\xeb\\x31\\x5c\\x44\\x1d\\x18\\x2c\\xc8\\xeb\\xb5\\xa2\\x0f\\x48\\x12\\xb5\\xd9\\x35\\x8d\\xb2\\x6a\\x5a\\x59\\x48\\x81\\x2a\\xf6\\x96\\x29\\x45\\xe7\\x6c\\xd2\\x30\\xbc\\x75\\x93\\x1f\\x00\\x22\\x5c\\x25\\x3b\\x00\\x06\\x94\\x54\\x5a\\x97\\x85\\xd9\\xc2\\x55\\xe5\\x9b\\xa4\\x38\\x27\\xbf\\xb3\\xae\\x72\\xae\\x35\\x03\\x56\\x02\\x30\\x80\\xb0\\xd8\\x75\\x94\\x80\\xdd\\x5a\\xce\\xf1\\x5b\\x37\\x48\\xf9\\x63\\xa3\\x4a\\x88\\x18\\x33\\x80\\xa7\\x8c\\x4c\\x73\\xce\\x66\\x64\\xc6\\x21\\xad\\x18\\x12\\x7d\\x87\\x88\\x0a\\x45\\xd1\\xf7\\xa4\\x14\\xcb\\xb1\\x5b\\x11\\x5a\\x50\\x6e\\x5e\\x63\\xf2\\x8b\\x9d\\x98\\xce\\x0b\\x81\\xdd\\xa8\\xac\\x72\\x0f\\x65\\xb0\\x7c\\x46\\xe6\\x90\\x28\\x6c\\x6d\\x94\\xbf\\xbe\\xf8\\xc7\\xdf\\xc9\\x74\\x65\\x14\\x29\\xd8\\x90\\x5a\\x6a\\x9a\\xf8\\x97\\x4c\\x98\\x98\\x1b\\x5a\\xa1\\x50\\xa8\\x16\\x72\\x7a\\x0a\\x40\\x3f\\x11\\x9c\\xf8\\xcb\\xaf\\x2f\\xa7\\x55\\xcd\\x6e\\x3f\\x66\\xcb\\xfd\\x80\\x7e\\xa3\\x44\\xce\\xc7\\xe4\\xd0\\xd7\\x4d\\x16\\x59\\x0c\\x7e\\xfe\\xe6\\x20\\xde\\xdd\\x6d\\xb3\\x6e\\x1a\\x43\\x3a\\x78\\x32\\xb2\\x90\\x57\\x68\\x61\\x6e\\xd8\\x3d\\x65\\x4d\\x58\\x26\\xb3\\x22\\xc1\\x50\\xc7\\x6b\\x5f\\x02\\x5d\\x28\\xb6\\x5e\\xa8\\xb8\\xf1\\x5c\\x80\\x73\\xde\\x0e\\x51\\xe3\\xa3\\x36\\x3f\\xdc\\x3d\\x52\\xda\\x02\\x18\\xeb\\x3e\\xf6\\x28\\x65\\xc0\\x4c\\x5e\\xd3\\x24\\x99\\xd2\\xe8\\xf2\\x42\\xbe\\x91\\x73\\xf5\\x4e\\x1c\\xe7\\xb9\\xcc\\xab\\x73\\x49\\xa8\\x91\\xd1\\x8b\\x42\\x5c\\x62\\x0f\\x09\\x8f\\xe3\\x20\\xe7\\x36\\x81\\xc0\\xc1\\x7e\\x6f\\x7a\\x61\\x2c\\xea\\x77\\xa2\\xdf\\x19\\xdf\\xe5\\x28\\xec\\x9a\\x97\\x16\\xb6\\xad\\x27\\xc3\\x1d\\x19\\x8e\\xaf\\xc2\\xcd\\xf6\\xf5\\x8b\\xbf\\x7e\\x8b\\x5b\\x97\\xc8\\x9c\\x7c\\xfb\\x02\\x6a\\x08\\xd4\\x10\\x0f\\x31\\x48\\x54\\xa3\\x9e\\xa4\\x34\\x49\\x0c\\x23\\x0f\\x37\\xa5\\x21\\xf4\\xa6\\x4d\\xf8\\xe0\\x7b\\x50\\xb7\\xdf\\x6e\\x77\\x56\\xe0\\x2f\\x2e\\x7e\\x05\\x29\\xc2\\xb5\\x62\\xc9\\x6c\\x88\\xa5\\x53\\xde\\x98\\xde\\x05\\x75\\x64\\xd7\\x72\\x1f\\xa8\\x5f\\xdb\\x02\\xb5\\x7b\\x29\\x93\\x22\\x65\\x47\\x6c\\xc9\\xbb\\x68\\x02\\x58\\x19\\xcd\\x39\\x98\\x12\\xae\\x40\\x0e\\x4e\\x13\\x19\\x5d\\x92\\xd8\\x7e\\x19\\x64\\x55\\xd5\\xe1\\xca\\x9f\\x6e\\x3f\\xd7\\xf0\\xfd\\x2b\\x19\\x65\\x29\\xcd\\x32\\xa3\\x03\\x40\\x85\\x66\\x4e\\xaf\\x2a\\xc4\\x80\\x33\\x09\\x98\\x0a\\x4f\\xbf\\x9f\\x2b\\xbe\\x91\\xe1\\x9b\\x8d\\x87\\x68\\x9c\\x86\\xd6\\x3e\\x32\\x52\\xce\\xbe\\xa3\\xbe\\x7e\\xe5\\x80\\xee\\x34\\x64\\xf0\\x6f\\xac\\x72\\x5a\\x53\\xcc\\x3d\\xdc\\xa6\\xdf\\x18\\xa8\\x00\\x98\\xed\\x03\\x2c\\xf9\\xd1\\xfa\\x8e\\x92\\xd6\\xe9\\x74\\x15\\xba\\x88\\x5b\\x9a\\xe3\\x51\\x92\\xb1\\x5c\\x71\\x65\\xe4\\xf2\\xcf\\x70\\xa0\\xb0\\x2b\\x62\\xe9\\x78\\x7e\\x1c\\x22\\xe0\\xe1\\x06\\x8c\\xe7\\xf6\\x9c\\xd2\\xd8\\x29\\x38\\x20\\xb0\\x42\\xc4\\xb7\\xde\\xa0\\xd6\\x56\\xb5\\xda\\xf3\\x62\\x0a\\xfb\\x07\\x6e\\xbf\\x4f\\xa7\\xd5\\x0e\\x25\\xf1\\x63\\xf3\\xd8\\x9f\\xcb\\x65\\xa8\\xb2\\x58\\xf3\\x89\\xe7\\xb1\\x78\\xd7\\x73\\xe2\\xac\\xf0\\x7e\\x4f\\x95\\xb1\\xfa\\xc9\\x77\\xc4\\x3f\\x80\\xa3\\xda\\xc5\\xad\\xb2\\xd0\\x8a\\xd5\\x89\\x27\\x2c\\xb0\\x05\\xac\\x01\\x39\\x26\\x98\\xb4\\x61\\xce\\x84\\xfd\\x29\\xd9\\x7d\\xb5\\xfb\\xa8\\xdc\\x15\\x49\\x94\\xcb\\x8c\\xce\\x5b\\x75\\x2a\\xaa\\x51\\xaa\\x3e\\x6c\\x08\\xa3\\x61\\xec\\xa7\\x80\\x95\\x64\\xf6\\x2e\\xc3\\x49\\x1c\\x4a\\x10\\x60\\x40\\x61\\x30\\xdf\\x11\\xd8\\x5a\\x16\\xd0\\x68\\x8e\\x5c\\xd1\\x15\\xa1\\xb9\\x2c\\x44\\x6c\\xdd\\xa1\\xde\\x1f\\xfd\\xb6\\xf6\\xe0\\x53\\x29\\x58\\xd9\\xb7\\xb4\\x8a\\xc2\\x01\\x01\\x28\\x2e\\xc8\\xcb\\xf1\\xcb\\x17\\xcf\\x45\\xc4\\xc1\\x1b\\xd6\\x44\\xdc\\xa9\\x17\\x71\\xc8\\x9f\\x1e\\xf5\\x5d\\x1d\\x9e\\x7f\\x47\\xef\\xfb\\xd6\\xfa\\x66\\x4a\\xb8\\x7e\\xee\\xc0\\xc0\\xe1\\xa3\\xab\\x9c\\x6b\\x16\\xb4\\x27\\xdc\\x03\\x8b\\xc7\\x18\\x96\\x01\\xe6\\xc4\\x60\\x53\\x9f\\x8c\\x96\\x44\\x6a\\x07\\xf2\\xa1\\x8a\\xe9\\x17\\xe4\\x5b\\x96\\x41\\xc1\\x71\\xdb\\xe4\\x1a\\x53\\xb7\\xb0\\xb0\\x90\\x50\\x3b\\x3b\\x64\\x0f\\xef\\xdc\\xc5\\xca\\xfc\\xc1\\xa3\\x6e\\x2d\\x4b\\xb4\\xe3\\xeb\\xac\\x05\\x82\\x68\\x0d\\x04\\x22\\xa3\\xe0\\xbc\\xcb\\x3a\\xa4\\xe0\\xbf\\xd8\\x82\\x2e\\x19\\x20\\x12\\xf0\\x84\\xe6\\x09\\x84\\xc8\\xcf\\x71\\xee\\x64\\x5a\\x68\\xc2\\xc4\\x92\\xe7\\x52\\x80\\x9f\\x18\\x4a\\x36\\xa6\\x09\\x0b\\xbb\\x73\\xff\\x79\\xef\\xe7\\x83\\x33\\xc8\\xbf\\x19\\x60\\x3f\\x18\\x37\\xcb\\x42\\x39\\x70\\x9e\\x70\\x26\\xc1\\x70\\x9f\\x5d\\x3e\\x37\\x0f\\x43\\x43\\xe0\\xb9\\x6e\\x5e\\xe6\\x39\\x69\\xa1\\x0b\\x6c\\x3a\\x73\\x1d\\x25\\x85\\xe2\\xcb\\xc7\\xe2\\x24\\x16\\x2a\\xe2\\x88\\x37\\x5a\\xe7\\x1a\\x6c\\x45\\x49\\xa8\\x35\\x04\\x8a\\x32\\x4c\\xf0\\x19\\x80\\xee\\x5d\\xe5\\x2b\\x59\\xc3\\x94\\x0d\\xeb\\xb3\\x22\\x29\\x9f\\x2f\\xb4\\xcd\\xf6\\xac\\x45\\x0e\\x82\\x10\\x54\\x0a\\x6e\\xde\\xc7\\xf4\\x5e\\x19\\xb1\\x7b\\x90\\x70\\xaa\\xee\\xab\\x72\\xad\\x95\\x4b\\xda\\x51\\x6c\\xe7\\x7e\\xe9\\x72\\x8b\\x9c\\x53\\xc6\\x3c\\x08\\x3d\\x95\\x27\\x13\\x1b\\x41\\x73\\x74\\xe3\\xe2\\x7f\\x30\\xb1\\xc6\\x9b\\x25\\x98\\x28\\x83\\x3f\\x41\\x77\\xe3\\x8c\\x04\\x70\\x41\\x2e\\xa1\\x04\\x98\\x3f\\x60\\x54\\x81\\x45\\x22\\xa4\\x18\\x2d\\x02\\x38\\xa7\\x4c\\xc6\\xf7\\x2c\\x25\\x6c\\x6a\\x78\\x34\\x32\\x39\\x36\\x53\\x90\\x2c\\x64\\x12\\xbb\\xe6\\xdb\\xe8\\xcb\\x99\\x32\\x7d\\xc5\\x98\\x20\\x27\\x13\\xa0\\x9f\\x79\\x45\\x2c\\xe7\\xda\\x4c\\x45\\x0c\\x2b\\xf8\\xae\\xef\\x9b\\xe8\\x79\\xdf\\x0d\\xd6\\xc2\\x2a\\x69\\xa3\\xd2\\xfb\\x37\\x6d\\x7d\\xe6\\x7f\\xf4\\x34\\x73\\x19\\xd9\\x74\\x2a\\x97\\x0c\\x48\\x1a\\xc7\\x39\\x53\\x2d\\x80\\x8f\\x1e\\xc1\\x4e\\x6d\\xc5\\x4a\\x79\\xa3\\xc6\\x3f\\xd5\\xc0\\x88\\x27\\x9b\\x73\\x2d\\x81\\xfa\\x0e\\x47\\x15\\x36\\xde\\x03\\x73\\xb0\\x93\\xc9\\x61\\x0b\\xee\\xb5\\xfb\\xde\\xc6\\x45\\xcc\\x50\\xbb\\xbb\\x8a\\xf0\\x2c\\x2a\\x63\\xae\\x63\\x52\\x86\\x1b\\x83\\x42\\x09\\xd4\\x18\\xef\\x17\\xeb\\x6a\\xaa\\x26\\x06\\x4c\\xad\\x25\\x93\\x26\\x02\\x87\\x31\\x6c\\xc5\\x96\\x62\\x5b\\x77\\x0e\\x04\\x1d\\x32\\x19\\x43\\x67\\xa6\\x92\\x1a\\xca\\xfd\\x22\\x24\\x88\\x4b\\x96\\x40\\x26\\x6f\\x53\\x47\\x86\\x3e\\x09\\xb9\\xc6\\x98\\xc0\\xf5\\xee\\xd2\\x0f\\x03\\x2e\\xbe\\x46\\xcc\\x07\\xa3\\xe5\\xe4\\xe4\\xa8\\xcb\\xed\\x92\\xf1\\x78\\xeb\\xb6\\xcb\\x7b\\x75\\xef\\x92\\xfe\\xdb\\x5f\\x12\\x30\\xfd\\x3e\\xf7\\x96\\x18\\x6c\\xb2\\x30\\x7d\\xf6\\x6f\\x48\\x53\\x97\\x9a\\xd8\\xbe\\x8f\\x3e\\x13\\x76\\x53\\x42\\x07\\x70\\x91\\xea\\x93\\x86\\xe6\\xef\\x59\\x91\\xc0\\x26\\x2d\\x93\\x7b\\x7d\\x66\\x32\\xf5\\x79\\xa1\\xa0\\x0d\\xd0\\x25\\xe5\\x09\\x22\\x66\\xca\\x9b\\x87\\x74\\xe1\\xf7\\x44\\xd2\\x18\\xcb\\x3d\\x2e\\x59\\x2e\\x58\\x42\\x52\\x19\\x17\\x09\\x7a\\xf3\\x7c\\x7f\\xe1\\xb7\\xef\\x8e\\xde\\xbf\\x39\\x76\\x49\\x58\\xac\\x5c\\xce\\x21\\xa1\\x44\\xb0\\x2b\\x18\\x5d\\x80\\x42\\x12\\x59\\xe0\\x2e\\x5f\\xf6\\x63\\xce\\x93\\xc3\\xe2\\x44\\x33\\x14\\x1d\\x13\\xee\\x85\\x52\\xae\\xf9\\x1c\\x01\\x36\\x4b\\xb5\\x70\\x9a\\x33\\x7a\\x29\\x0b\\x4d\\x96\\x45\\x22\\x58\\x5e\\xf6\\xc7\\x64\\x4b\\x26\\xd0\\x07\\x6b\\x7e\\x60\\x1e\\x1b\\x62\\x35\\xf2\\xbc\\x02\\x91\\x69\\x81\\xd3\\x1c\\xec\\x27\\x8d\\xac\\x26\\x6f\\x4b\\x8c\\xe0\\xcb\\xa0\\x39\\x74\\xa5\\x85\\xe4\\xed\\xd0\\xa5\\x4e\\xf3\\x0a\\x50\\x4b\\xb1\\x9c\\x78\\x1d\\xb2\\xd4\\xa1\\x4b\\x62\\x1a\\xcd\\xb9\\xcb\\x80\\xb1\\x89\\x2f\\x0f\\x77\\x1c\\xee\\xef\\x6e\\xa9\\x56\\x88\\x56\\xe1\\x5b\\xec\\x80\\x4e\\xf6\\x4d\\x64\\x7c\\x83\\xd5\\x50\\xea\\x5d\\x70\\x7f\\xd8\\x32\\x5b\\x4b\\x42\\x09\\xba\\xdb\\x47\\x0e\\xfe\\x06\\x32\\x65\\x9b\\xb0\\xc1\\x7b\\x0b\\x4d\\xb0\\x3c\\x26\\x45\\x92\\x9c\\xb3\\x28\\x67\\xf7\\x0d\\x33\\x54\\x39\\xc5\\x49\\x6d\\xac\\x9b\\x2c\\x80\\xc0\\x9c\\x05\\x4c\\x10\\x7b\\xb3\\x28\\xf1\\x07\\x82\\x3c\\xa7\\xb2\\x16\\x37\\x2b\\x12\\x48\\x0d\\xa7\\x62\\xe5\\x08\\x0e\\xb3\\x57\\x41\\x4c\\x97\\x2b\\x97\\x65\\x86\\xdc\\xa7\\xb2\\x0a\\x8a\\xf9\\x87\\xf9\\xe6\\x6b\\x54\\x29\\xcc\\x3c\\xe0\\x22\\xe6\\x4b\\x1e\\x17\\x34\\x81\\x07\\x81\\x51\\x66\\x13\\xb6\\xa8\\xc5\\x31\\xc7\\xb3\\x9c\\x3a\\xf4\\xe3\\xfb\\xe6\\x30\\x97\\x67\\x72\\x1f\\xe7\\xfd\\x27\\x9c\\xde\\x8a\\x8b\\xf9\\x08\\x3e\\x31\\x0f\\xb6\\x33\\x1c\\x49\\x31\\xa2\\x23\\xb3\\x6d\\x9e\\x88\\xdd\\x02\\xf8\\xfd\\xef\\xc0\\x30\\x38\\x73\\xeb\\xeb\\xd8\\x90\\x22\\x4c\\xc8\\x62\\xbe\\x00\\x62\\xe5\\x29\\x75\\x50\\x9a\\x09\\xd3\\x80\\x92\\x68\\xf3\\x19\\x30\\x89\\xcd\\xfe\\x36\\xb6\\x56\\x46\\x88\\x1a\\x59\\xdd\\x1b\\x4f\\xc4\\x76\\x69\\xea\\xe0\\xad\\x25\\xe3\\x07\\x6c\\xc6\\xd2\\x48\\xdf\\x7b\\x07\\xca\\x25\\xcb\\x97\\x9c\\x5d\\xed\\x5b\\xcd\\x6f\\x64\\x64\\xc2\\x08\\x29\\xa2\\xf6\\x81\\xb0\\xfb\\x7f\\x42\\xeb\\xe8\\xe2\\xdd\\xd1\\x3b\\x68\\x39\\x6e\\xbd\\xee\\x4e\\x54\\x19\\x51\\xa0\\xc6\\x84\\x66\\xfc\\x67\\x96\\x2b\\x00\\x55\\xbe\\xe4\\x22\\x1e\\x92\\x82\\xc7\\xdf\\x3f\\x60\\xc2\\x17\\x17\\xbc\\xcc\\x62\\x6d\\xc5\\xb5\\xde\\x58\\xae\\x64\\xab\\xe8\\xf9\\x7f\\x70\\x7b\\x06\\x12\\x74\\xca\\x12\\x29\\xe6\\x01\\x06\\x00\\x48\\xf3\\x13\\xc1\\xf5\\x5a\\x77\\x66\\x44\\x3a\\x05\\x0f\\x8f\\xcc\\x63\\xc8\\x15\\xe6\\x32\\xaf\\x84\\x33\\xcc\\x78\\x80\\xff\\x18\\x64\\x1c\\x1b\\x96\\xc6\\x2b\\xe3\\x41\\x1a\\x97\\x2a\\x75\\x24\\x4c\\x04\\x72\\xe5\\xc2\\x0e\\x1e\\xdb\\xe1\\x4a\\xa2\\x2c\\x5e\\x50\\x11\\xc3\\x9f\\x51\\x24\\xf3\\xd8\\xce\\x97\\x6b\\x9f\\xde\\x8c\\xc9\\x70\\x98\\x81\\x05\\x62\\xc8\\x70\\x34\\x2a\\xea\\x4f\\x06\\x35\\x2d\\x4f\\x2b\\xa9\\xb0\\x4e\\x6b\\x2f\\x04\\xff\\x77\\xc1\\x08\\x4d\\xa5\\x61\\xc4\\xf5\\x26\\x10\\x35\\x8a\\xa4\\x74\\x05\\xb2\\x10\\xa6\\xfa\\xc6\\x95\\x6b\\xd8\\x1a\\x5b\\x35\\x24\\x67\\xcc\\x28\\x5d\\x25\\x4c\\xc0\\x90\\xbc\\xa9\\xe2\\x06\\x0c\\xcd\\x5c\\xce\\xb1\\xa0\\xd9\\x7e\\x84\\xb3\\xcf\\x99\\x92\\x45\\x1e\\xb1\\x33\\x8c\\x71\\xa6\\x2e\\x9f\\x6e\\xfd\\x65\\xcc\\xaa\\x68\\x7a\\xc9\\x04\\xfa\\x94\\x0c\\x69\\x20\\x8c\\x5b\\xe4\\xb0\\x06\\xd1\\x82\\xc5\\x05\\x48\\x95\\xe9\\x8a\\xcc\\x38\\x76\\x86\\x01\\xd1\\xce\\xe7\\x0b\\xa6\\xb4\\xb3\\x8d\\xf6\\x21\\x47\\xad\\x6c\\xb2\\xe7\\x26\\x00\\xdb\\x37\\x48\\x66\\x2f\\xbd\\xb0\\x29\\x05\\xdc\\x72\\x38\\xb2\\x54\\xbb\\x7a\\x2d\\xd4\\x06\\x55\\x91\\xba\\xb3\\x5c\\xa7\\xb4\\x1a\\x93\\x37\\xe6\\x51\\xb8\\x9f\\x82\\x8e\\x1b\\xbc\\x46\\x5c\\x88\\x31\\x5b\\x37\\x32\\x99\\x51\\xb5\\x80\\x7e\\x34\\xf5\\x25\\xb0\\xcd\\x2c\\xa2\\x22\\x37\\x0c\\x03\\x31\\xe6\\x69\\x1c\\x1b\\xee\\x9a\\x93\\x1c\\x5b\\xce\\x6f\\xf2\\x3b\\xb6\\xac\\xcf\\x31\\x93\\x1d\\x05\\xf2\\xee\\xa9\\x08\\xb1\\x03\\x5f\\x6f\\x61\\x08\\x1f\\xd5\\x38\\x01\\xae\\xa4\\x11\\x58\\x0e\\xd7\\xcd\\x28\\xdc\\x3e\\xe0\\x6f\\xb8\\xc2\\xc3\\x89\\xa4\\xe6\\xe1\\xfd\\x46\\x61\\xf9\\x36\\x12\\x90\\xe6\\xf3\\xf6\\x8e\\xbb\\xdd\\x83\\x7c\\x5e\\xe0\\x41\\xb7\\x5c\\xb8\\x44\\xa4\\x1f\\xd7\\xf2\\xee\\x41\\x99\\x32\\xb6\\xea\\xe1\\xdb\\xa3\\xb0\\xd0\\x2f\\xac\\x60\\x72\\x65\\x92\\x63\\xf2\\x73\\xdb\\x30\\x4b\\x3d\\xce\\x62\\x18\\x7a\\x19\\xbc\\x29\\xfb\\xc9\\x18\\xa6\\x91\\x2c\\x9d\\x49\\xe0\\x9f\\xe6\\x34\\x5f\\x2e\\xb2\\x42\\x5b\\x49\\x18\\x00\\x74\\x45\\x0b\\x2a\\xe6\\xe0\\x26\\x91\\x85\\x19\\xef\\xcf\\x7f\\x86\\x19\\xe5\\x2c\\x2e\\x22\\xdb\\x8c\\xc7\\xed\\xda\\x3f\\xbb\\xa0\\x83\\x85\\xd3\\x03\\x76\\xa5\\x22\\x9a\\xb9\\x39\\x87\\xaf\\xa5\\x56\\x42\\xd3\\xeb\\x57\\x84\\x8f\\xd9\\x98\\xec\\xfc\\x39\\xf8\\x6a\\x07\\x9f\\x9e\\xe5\\xd2\\x3c\\xc2\\x16\\x18\\xc1\\xac\\x12\\xae\\x21\\xd1\\x67\\x27\\xbc\\x7b\\x4c\\x8e\\xcd\\x33\\x20\\x10\\xeb\\x09\\x18\\xd4\\xc0\\x4c\\x4b\\xf2\\x0d\\x49\\xce\\xe6\\x34\\x8f\\x13\\xeb\\x30\\xbc\\x0a\\x0a\\xa7\\x3c\\xc1\\xd8\\x35\\x57\\x5a\\x59\\x6f\\x41\\x0b\\xe6\\xa4\\xa9\\xba\\x34\\xac\\xc8\\x1c\\xae\\x51\\x4c\\x35\\x1d\\x05\\xa7\\x7a\\x1f\\x4d\\xad\\x91\\x45\\x09\\x1f\\x51\\xbb\\xbb\\x4a\\xae\\xb5\\xff\\x27\\x5b\\x7f\\x3c\\xa2\\xfe\\x2e\\x6e\\x94\\x72\\xc0\\xeb\\x6e\\xae\\xea\\x3c\\x35\\x2f\\x71\\x0b\\xb0\\xf8\\xea\\x01\\x3e\\x2e\\x3b\\x48\\x00\\x0d\\xa0\\xff\\x52\\xa9\\x32\\x79\\x3e\\x6a\\xf1\\xd0\\x6f\\x38\\xd2\\xc7\\xa7\\x17\\x67\\xbf\\x4e\\xde\\x9d\\x9c\\x5e\\xf4\\x27\\xbb\\x3f\\xd9\\xfd\\xc9\\x6e\\x71\\xb2\\x99\\x58\\xb6\\x3e\\xd5\\xce\\x7a\\xda\\x94\\xb7\\x50\\x87\\x7c\\x0d\\x4a\\xf0\\x9e\\x51\\x76\\xe8\\xb1\\x58\\xfe\\x4c\\x8d\\x32\\x6d\\xfd\\xda\\x36\\xe8\\xba\\x21\\x8d\\xc3\\xde\\x80\\xaa\\xfb\\xe1\\x93\\x4f\\x0f\\x7d\\xc4\\xe4\\xce\\x0e\\x93\\xe6\\x42\\xc7\\xca\\xa6\\x55\\x0b\\xbb\\x87\\x1e\\xfe\\x7e\\x72\\x74\\x7c\\x7a\\x71\\xf2\\xfa\\xe4\\xf8\\xec\\x51\\xb3\\x9d\\x5a\\x82\\xa1\\x56\\xe5\\x72\\x43\\x29\\x99\\xe5\\x6c\\xc9\\x65\\xa1\\x92\\x95\\x47\\x6d\\xdf\\xcc\\x04\\xd6\\x13\\x66\\x45\\x0c\\x1e\\x0f\\x07\\x4c\\xbf\\xf1\\x67\\xbd\\xb0\\xed\\x56\\xd8\\x56\\x93\\xbf\\x5a\\xe0\\x60\\x75\\xb5\\x7d\\x5f\\xe7\\x32\\xed\\x68\\x0b\\x9f\\xa3\\x2f\\xc6\\x05\\xdb\\x36\\xed\\xa7\\x5d\\x0b\\x99\\x53\\x11\\x3d\\x56\\x79\\x2c\\xf1\\x79\\x8c\\x3e\\x9a\\x66\\xba\\x45\\x1b\\x9d\\x4e\\x40\\xb6\\xbb\\xc1\\xa3\\xc6\\x84\\xb3\\xb7\\x34\\xfb\\x89\\xad\\xce\\x58\\x4b\\xb8\\xad\\x2a\\xbd\\x59\\xc2\\x22\\x23\\xe8\\xc8\\x25\\x5b\\x61\\x76\\xf1\\xa1\\x7b\\x58\\x3b\\xd0\\xe8\\x2d\\xc4\\x28\\xbf\\x64\\x6d\\xf0\\xe3\\xbb\\x04\\x17\\xbf\\x64\\x2d\\x32\\xa7\\xdd\\xb5\\x06\\x80\\x6d\\x96\\x10\\xf4\\x34\\xb3\\xa6\\x5b\\x05\\xf9\\xfd\\x05\\xc0\\xd4\\x9f\\x6f\\x1c\\xa5\\x7a\\x75\\xb8\\x0a\\x2e\\x7c\\xdb\\xf1\\x4a\\x60\\x24\\x7d\\x55\\x91\\x5d\\x9e\\x89\\x10\\xac\\x69\\x86\\xbd\\xe9\\x42\\x0f\\x56\\xc9\\xe8\\x88\\x34\\x6d\\xfb\\x70\\x12\\x5c\\xc2\\x6e\\xf9\\xea\\x6e\\xc9\\x58\\x31\\xe7\\xc2\\x03\\x3a\\xc6\\xaf\\x1c\\x06\\x88\\xf2\\xcd\\x33\\xa1\\x1d\\xf5\\xb0\\xfa\\xa7\\x4d\\x6b\\xf9\\x6f\\xff\\x61\\x42\\xa7\\x2c\\x51\\x1f\\x76\\x77\\xbf\\xfb\\xe9\\xf8\\xd7\\x7f\\xee\\xee\\xfe\\xf6\\xdf\\xe1\\xb7\\x20\\x0a\\x31\\xbc\\x5d\\xbd\\x05\\x00\\x4d\\x84\\x8c\\xd9\\x29\\x3c\\x03\\xfe\\xb4\\xea\\xda\\x01\\x86\\x50\\xec\\x17\\x80\\x47\\x30\\xc6\\xd4\\x3b\\xff\\x67\\x26\\xe3\\xfa\\x5f\\xaa\\x15\\xf2\\xe6\\x56\\x0a\\x06\\x58\\xa2\\x16\\xe5\\x71\\x78\\x75\\x27\\x1e\\x4a\\x5e\\xd2\\xf1\\x51\\xb5\\xa3\\xfa\\x7e\\x52\\xd1\\x82\\xa5\\x88\\xfd\\xf7\\xda\\x91\\x00\\x1a\\x7c\\x3b\\xe0\\x13\\x01\\x68\\x11\\x46\\x33\\xad\\xc2\\xb0\\xee\\x2c\\x5f\\xee\\x6c\\x95\\x80\\xf1\\x2b\\xd8\\x31\\xc1\\x80\\x22\\x96\\x5a\\x78\\x90\\xbd\\x80\\xf5\\x69\\x2e\\xbe\\x01\\xed\\xc1\\xe4\\x84\\x2c\\x91\\xc2\\x5b\\x43\\x1c\\x17\\xde\\x7c\\xfd\\x45\\x79\\x9c\\x0f\\xa2\\xd6\\xab\\xd2\\x5f\\x61\\x5a\\x99\\xfb\\xde\\x22\\x84\\x28\\x0f\\x15\\xc9\\x8c\\x61\\xb3\\x87\\x1f\\x8e\\xa3\\xac\\x18\\xda\\x1b\\xc6\\x29\\x4b\\x65\\xbe\\xf2\\x7f\\xfa\\xca\\xe4\\x91\\xd2\\x32\\xa7\\x73\\x28\\x0c\\xc3\\x9f\\xe3\\xcf\\xfc\\x5f\\xf8\\xc3\\xca\\x03\\xd6\\x7f\\x8d\\xa6\\x70\\x19\\x4b\\xb5\\x1c\\xb9\\x21\\xd2\\x4d\\x79\\x6d\\x21\\x6f\\x73\\xa4\\xdf\\x12\\xd6\\x16\\xb5\\xc5\\x2b\\xab\\x5e\\xd5\\x0d\\xe9\\x3d\\x71\\xa8\\x70\\x7a\\x2a\\x82\\x3d\\x69\\x2b\\xe6\\x87\\x65\\x16\\x1b\\x78\\x03\\xc4\\xd2\\x58\\x96\\x8d\\x91\\x26\\xcb\\xab\\x43\\x6e\\x16\\xf3\\x25\\x57\\xb2\\x45\\xf9\\x9b\\x1f\\xe8\\xe6\\x8c\\x47\\x0b\\xda\\x83\\x59\\x5c\\xde\\x6d\\x76\\x9d\\x01\\xb8\\x9e\\x3f\\xaf\\x35\\xb6\\xff\\xb2\\x4d\\x17\\x3f\\xbc\\x32\\xaa\\x35\\xcb\\xc5\\x2b\\xf2\\x5f\\x7b\\x1f\\xbf\\xfa\\x34\\x1a\\x7c\\xbf\\xb7\\xf7\\xe1\\xc5\\xe8\\x1f\\xbf\\x7d\\xb5\\xf7\\x71\\x0c\\xff\\xf8\\xcb\\xe0\\xfb\\xc1\\x27\\xf7\\xc7\\x57\\x83\\xc1\\xde\\xde\\x87\\x9f\\xde\\xfe\\x70\\x31\\x39\\xfe\\x8d\\x0f\\x3e\\x7d\\x10\\x45\\x7a\\x89\\x7f\\x7d\\xda\\xfb\\xc0\\x8e\\x7f\\xbb\\xe3\\x20\\x83\\xc1\\xf7\\x7f\\x6e\\x3d\\xf5\\x0e\\xb0\\xae\\xf1\\xea\\x12\\xf1\\xba\\x3a\\x62\\x27\\xdb\\xef\\x0b\\xb6\\x79\\xc1\\xcb\\x6d\\xaf\\xae\\xcf\\xff\\x99\\xe3\\x9a\\x41\\x56\\x8f\\x13\\xd7\\x5b\\x73\\xc0\\x31\\x2d\\xf4\\x21\\x3c\\x39\\xf8\\xa4\\x6a\\xc1\\x98\\x37\\x2d\\x9e\\x9b\\x9c\\xfb\\x23\\x38\\x77\\x7c\\x1b\\x58\\x58\\xd7\\x52\\x13\\x9d\\xe5\\x32\\x75\\xb0\\x14\\x10\\xde\\xc0\\x02\\x4a\\x7b\\xdf\\x25\\x6b\\xd5\\x4c\\x1c\\xaf\\xde\\x19\\xd4\\x3b\\x83\\x6e\\xb8\\x3e\\xeb\\x0c\\xc2\\x22\\x82\\xed\\xf5\\x04\\x31\\xb1\\x6c\\x1a\\xc2\\xd8\\x18\\x41\\x77\\xb6\\x4e\\x08\\xfe\\x78\\xb7\\x80\\xda\\xd8\\x1d\\xf5\\xb2\\x7f\\x72\\x99\\x4c\\x83\\x02\\x2d\\xdd\\x1c\\xc3\\x24\\x07\\x49\\x42\\xb8\\xc0\\x83\\x0f\\x03\\xf8\\x5a\\x2c\\x86\\xa6\\x8d\\x2b\\x22\\x5e\\x9a\\x29\\xf8\\xaa\\xab\\x0a\\x78\\x32\\xe4\\x16\\x73\\x31\\xb7\\x85\\x51\\x28\\x4a\\x6c\\xf4\\x89\\x8b\\x12\\x76\\xda\\x2b\\x87\\x65\\xaf\\x02\\xaa\\x94\\x8c\\xa0\\x29\\x18\\x56\\x5a\\x79\\x4c\\x4a\\x3b\\x6d\\x98\\x8d\\xa6\\x97\\x10\\x6d\\x8c\\x58\\xcc\\x44\\xc4\\x6c\\x1f\\x83\\x4a\\xaf\\x68\\x2a\\xc8\\xb1\\x58\\xba\\x5e\\x0e\\x71\\x81\\xc9\\x20\\xc8\\xfe\\x36\\x8f\\xf1\\xbc\\x12\\x10\\xcc\\x46\\xb4\\x41\\xb0\\x20\\x0f\\x01\\xb8\\xbe\\xb7\\xb0\\x29\\xa4\\x62\\xc8\\x59\\xe9\\x65\\x6d\\xd6\\x4e\\xb6\\xb5\\x14\\x6f\\x2f\\x33\\x7d\\x64\\xab\\x95\\x32\\xb4\\x26\\x2c\\x4b\\xf7\\x73\\x55\\x48\\x3e\\x87\\x60\\x60\\x7b\\xf1\\xf9\\x87\\x13\\x9d\\x1d\\x89\\xcd\\x6e\\x44\\xe6\\x3d\\x62\\x27\\x5d\\x8a\\xc9\\x2e\\x82\\x25\\x59\\xce\\x66\\xfc\\xba\\xa3\\x73\\x7a\\x10\\xd4\\x13\\xf2\\x98\\x09\\xcd\\x67\\x1c\\x3b\\x66\\x67\\x39\\xcb\\x98\\x00\\x57\\x2b\\x94\\x68\\x18\\xde\\x6f\\x25\\x65\\x19\\x9c\\xde\\xc6\\x64\\x1e\\x54\\xb8\\xbb\\x65\\x65\\xe7\\x9b\\x94\\xfd\\x9e\\x8f\\x91\\x9e\\x8f\\x35\\xbe\\x1e\\x88\\x8f\\xd9\\x9d\\xbb\\x3d\\x4c\\x0c\\x32\\xcf\\xdb\\x67\\xbf\\x1f\\x56\\x53\\xd9\\x6d\\x17\\xf7\\xb6\\x25\\xc4\\xb5\\x02\\x7d\\xcf\\x1a\\xb5\\xc4\\xe4\\x35\\xac\\x63\\xcb\\x09\\xd6\\xec\\xa3\\xde\\x44\\x52\\x2a\\xe8\\x1c\\x5b\\x51\\x68\\xe9\\xc1\\xab\\x64\\xee\\xdb\\x89\\xd5\\xf3\\xee\\x41\\x8f\\x77\\x25\\x5e\\xf0\\x65\\x2e\\x93\\x84\\xe5\\x8a\\x24\\xfc\\x92\\x91\\x23\\x96\\x25\\x72\\x95\\xda\\xdc\\xd7\\x98\\x9c\\x6b\\xaa\\xcd\\xae\\x3e\\x67\\xba\\x59\\xd8\\xb7\\x1d\\xaa\\x8d\\xab\\x42\\xef\\x08\\xfb\\x1f\\xcb\\xda\\xa1\\x28\\x9c\\x64\\xb6\\x82\\xf2\\x9d\\x00\\xa6\\x71\\x00\\x9d\\x8d\\x86\\xe4\\x94\\x2d\\x59\\x3e\\x24\\x27\\xb3\\x53\\xa9\\x27\\xa8\\x7d\\x57\\x13\\xee\\xf0\\x46\\xc2\\x67\\xe4\\x95\\xb1\\xeb\\x94\\x26\\x1a\\xbb\\xcb\\x04\\x05\\xea\\x32\\xaf\\x0c\\x50\\xe2\\x16\\x76\\x51\\x9f\\xb7\\x5e\\x7b\\x0e\\x23\\xf9\\xca\\xf3\\x46\\x91\\x8c\\x56\\xcb\\xe4\\xdb\\x77\\xb5\\x5e\\xa0\\x03\\xac\\x27\\x2d\\xa1\\xac\\x83\\xfd\\x8d\\xb8\\x0a\\x0e\\x89\\x0f\\xac\\x40\\x2e\\x48\\xce\\x54\\x26\\x85\\x62\\x55\\x98\\x51\\x3f\\x23\\xb4\\x76\\xbb\\xc5\\x30\\x6e\\x2c\\x3c\\xdb\\x8a\\xcd\\x4c\\x2a\\x0d\\x25\\xb4\\xdd\\x34\\x85\\x9b\\xb8\\xe1\\xa0\\x22\\x99\\x26\\x09\\x8b\\x2b\\x5d\\x01\\xb1\\x9b\\x15\\xad\\x7a\\x08\\x2c\\x1a\\x8a\\xef\\x6f\\x83\\x85\\xca\\x95\\x1a\\xe7\\xca\\xfd\\xbe\\xc3\\xa4\\xeb\\xe1\\xe4\\xda\\x8b\\xdf\\x54\\xd9\\x5c\\x1e\\x4c\\x90\\x23\\xc1\\x06\\x58\\x03\\x3c\\x07\\x18\\x7c\\x15\\x34\\x82\\x5a\\x48\\x79\\x49\\x22\\x99\\x66\\x09\\x1c\\x9d\\x16\\x27\\xab\\xec\\x43\\xe7\\xb7\\xd2\\xc8\\x8c\\xae\\xf6\\x83\\x16\\x75\\xf0\\x41\\xbb\\x0e\\x75\\xad\\x14\\xb1\\x2e\\xd4\\x30\\x76\\xcd\\xa2\\xce\\x7a\\xd8\\x1e\\x5f\\xb3\\x28\\x68\\xc2\\x0c\\x90\\x6c\\x91\\x43\\x88\\x30\\x27\\xb6\\x7d\\x6f\\xfd\\xd6\\x21\\x87\\xae\\xdc\\xfc\\x2d\\x6a\\xe9\\xc2\\xab\\x86\\x62\\x09\\x63\\x3a\\xb4\\x7f\\xfb\\x08\\x68\\x9c\\x02\\xb6\\x10\\xd6\\xd7\\x85\\x30\\x1a\\x7e\\x33\\xe2\\xd1\\x5b\\x83\\xbe\\xf4\\x89\\xd4\\x6e\\x2c\\x68\\x91\\x26\\xa5\\x26\\x7b\\xbb\\xfb\\xbb\\x83\\x35\\xff\\x63\\x0d\\x32\\xfe\\x22\\xf8\\x25\\x07\\xa8\\xd3\\x0c\\x70\\x43\\x59\\xb4\\x1b\\x0f\\x09\\xd7\\x2e\\xd3\\x1a\\xe1\\x9e\\x60\\x56\\xb6\\xe8\\x6f\\x48\\x94\\x24\\x3a\\xa7\\x31\\xb7\\x6a\\x0c\\x7c\\x6a\\x6e\\xd2\\x79\\x61\\xb9\\xfc\\xde\\xee\\xa7\\x5d\\xdb\\xda\\xeb\\x4a\\x8a\\x5d\\x0d\\xd3\\x1f\\x93\\x0b\\xc4\\x89\\xf1\\x03\\xad\\x64\\x01\\xb8\\x50\\x48\\x82\\x2c\\xe1\\x11\\xd7\\xc9\\x0a\\x38\\x16\\x91\\x05\\x62\\x52\\x19\\x79\\x61\\x8b\\x0d\\x8f\\xaf\\xb9\\x76\\xcd\\x75\\xe4\\x8c\\xbc\\xc0\\xee\\x7a\\x88\\xe1\\x44\\x15\\x74\\x58\\xdf\\x5f\\x30\\x9a\\xe8\\x05\\x26\\x89\\x08\\x29\\x46\\xd8\\x20\\xd5\\xb0\\x12\\xfb\\x4d\\xdb\\x78\\x49\\x3b\\x77\\x62\\x78\\xb5\\x70\\x2d\\xae\\x4f\\xa8\\xa5\\xe5\\x60\\x98\\xe8\\x0f\\xcd\\xbb\\xb6\\x93\\x35\\xf4\\xba\\x8b\\x8b\\xc9\\x0f\\x95\\xbe\\xed\\xc0\\xc5\\xb5\\xce\\x5c\\xea\\x0e\\x78\\x03\\x58\\x3e\\x93\\x79\\xba\\x05\\xbc\\xa3\\x9b\\x60\\x65\\xab\\x06\\xee\\xa4\\x43\\x16\\xd6\\xb6\\x91\\x3b\\xd9\\x8c\\x46\\x78\\xf7\\x0e\\xee\\xe4\\x57\\x59\\x00\\x18\\x08\\x9d\\x26\\x2b\\x8f\\xc4\\xa0\\x98\\x26\\x3b\\x66\\xa8\\x1d\\xc3\\x9e\\xcc\\x6e\\xf8\\x91\\xd1\\x18\\x81\\x32\\x94\\x66\\xb4\\x91\\xea\\x16\\x5e\\x9d\\x05\\xd1\\x82\\xb9\\x75\\x2b\\x07\\x0a\\xa5\\x65\\x4a\\x16\\xf6\\xb5\\xab\\xa5\\x97\\xf6\\x64\\x8c\\xe1\\xf4\\xb8\\xba\\xa6\\x9c\\x65\\xc8\\xe1\\xec\\x6f\\x9e\\x1d\\xff\\x5a\\xe3\\x1b\\x48\\xf7\\x4a\\x13\\x8f\\x28\\x24\\x5b\\xd8\\x23\\x8a\\x0b\\x24\\x16\\xe2\\xce\\x74\\xc4\\x4b\\x3b\\x48\\x7e\\x20\\x1d\\x26\\x40\\x90\\x76\\x85\\x9c\\xf5\\x81\\x20\\xa8\\xd7\\x3e\\xd7\\xab\\xb3\\x9c\\x0a\\xd2\\x59\\xde\\x00\\xd9\\xe4\\x64\\xb5\\x7b\\x06\\xbd\\x2f\\xe8\\xcf\\x01\\x77\\x8c\\x8b\\xa1\\x46\\x54\\x48\\xc1\\x23\\x9a\\xf0\\xff\\xb0\\x18\\x3b\\xe4\\x63\\xfe\\x1c\\xe8\\x39\\x11\\x55\\x6c\\x04\\x41\\x5d\\x61\\x1b\\x7b\\x06\\xd5\\x8a\\xe6\\x38\\x6a\\x29\\x41\\xf9\\xf0\\xc8\\x67\\xf8\\xbc\\xf6\\x59\\x19\\xa4\\xdb\\x9c\\x00\\xd2\\xbe\\x20\\x35\\xbc\\x6e\\x27\\x73\\x37\\x5b\\x8c\\x74\\x49\\x81\\xac\\x83\\x04\\xf2\\xf5\\xf4\\x71\\x04\\xab\\x82\\x02\\x4f\\x64\\xe1\\xc0\\x8c\\x10\\x5e\\x73\\x6b\\x64\\x99\\xd1\\x49\\x3a\\x7d\\x75\\x74\\xc7\\xe7\\x44\\xf8\\xde\\xf3\\x0e\\x4b\\x78\\x9d\\x20\\x41\\xfe\\x83\\x6d\\x55\\xef\\x9c\\xc6\\x4e\\xe8\\x51\\x31\\x67\\xe4\\xa5\\xf9\\xe5\\xdf\\xff\\xf6\\xb7\\x6f\\xfe\\x36\\xc6\\xe1\\x7d\\x2e\\x84\\x20\\x27\\x07\\xa7\\x07\\xbf\\x9f\\xff\\x7c\\x08\\x25\\xb8\\x6d\\xa9\\xda\\x51\\xa2\\x67\\xd7\\x69\\x9e\\x9d\\x26\\x79\\x7e\\xd1\\x14\\x4f\\x28\\x2c\\x69\\xcd\\x45\\xaa\\x11\\x06\\x18\\x32\\x44\\x11\\xb5\\x1a\\x66\\x80\\xe6\\x87\\x48\\xb7\\xa1\\xbb\\xd6\\x1c\\xb5\\xad\\x38\\x63\\x3a\\xca\\xce\\x65\\x74\\xd9\\xa1\\xf5\\x74\\xc4\\xb2\\x9c\\x45\\xe8\\x8d\\xbb\\x38\\x9c\\xe0\\xe8\\xc6\\x8a\\x3d\\x7d\\x77\\x51\\x16\\x34\\x40\\xd6\\x4f\\x09\\xd9\\xf7\\xa3\\xf5\\xd7\\x19\\xcb\\xf7\\x92\\x65\\xda\\x3b\\x08\\xa6\\x34\\xba\\xbc\\xa2\\x79\\x0c\\xfe\\x33\\xaa\\x39\\x00\\x14\\x23\\xc2\\x60\\xce\\x6c\\xb3\\x38\\x4c\\x2b\\x44\\x28\\x35\\xd7\\x8c\\x1b\\x79\\x39\\xba\\x29\\x9c\\xd3\\x15\\x1c\\x63\\x28\\x02\\x67\\x94\\x27\\xe0\\xa7\\xb5\\x7d\\xb0\\x31\\xef\\x28\\xca\\xbc\\xe3\\x30\\xf4\\x9c\\xf7\\x26\\x9e\\xbb\\xb6\\xd6\\xc4\\x0b\\xfa\\x74\\xdf\\xd7\\xda\\x6b\\x9b\\xfd\\xb8\\xc5\\xa2\\xce\\x8a\\xb8\\xbc\\xd2\\x32\\xbf\\x17\\x75\\x1d\\x8c\\xb7\\xbd\\xa2\\x2e\\xcb\\xd9\\xb9\\x96\\x8d\\xfa\\x6e\\x90\\xf5\\x58\\x0c\\x0e\\x76\\x43\\x24\\x66\\xca\\x66\\xd2\\x30\\xe1\\x1b\\x43\\x2b\\x71\\x01\\x87\\x90\\x0a\\x28\\x41\\x74\\xbe\\x33\\x59\\x09\\x9f\\x60\\xde\\xa7\\x47\\xc9\\xb7\\xf0\\xac\\xfb\\x2a\\xc4\\x64\\x75\\x1d\\xc7\\x87\\xe6\\xed\\x58\\x0a\\xb3\\x1b\\x96\\xb5\\x14\\xb6\\xdf\\x39\\x7c\\xc8\\x74\\x84\\xfe\\xe1\\x80\\x91\\x03\\x3e\\xa9\\x9d\\x7e\\x3d\\x58\\x13\\xe5\\x54\\x2d\\xb0\\x17\\x38\\xbb\\xe6\\xda\\xa2\\xbf\\x4e\\x64\\x5c\\xef\\xe0\\x3f\\xcf\\x69\\xc4\\x48\\xc6\\x72\\x2e\\x8d\\x30\\x2a\\x84\\x8e\\xe5\\x95\\x20\\x53\\x36\\xe7\\x42\\x39\\x52\\x00\\x44\\xbb\\xa5\\x19\\x44\\x7d\\xb8\\xf2\\xf0\\x73\\x63\\x72\\x56\\x81\\x54\\xb1\\xc5\\x4e\\x91\\x2c\\x8f\\xa6\\x9d\\x73\\x3d\\x5e\\x05\\x12\\x0b\\xe8\\x84\\xb0\\xfa\\x9e\\xc2\\x61\\xcf\\xb0\\xcf\\x4d\\x79\\xaf\\x10\\xf0\\xe4\\x98\\x25\\x74\\x85\\x39\\xad\\x33\\x2e\\xc0\\x72\\xcc\\xd5\\xa0\\x83\\xb8\\x16\\x76\\xbd\\x73\\xdf\\xdd\\x38\\x0f\\xae\\x48\\xce\\x68\\xb4\\x68\\x17\\x62\\xee\\x03\\x61\\x77\\xbc\\xfa\\x40\\x58\\x9b\\x41\\xfa\\x40\\x58\\x1f\\x08\\xfb\\xcc\\xd5\\x07\\xc2\\xfa\\x40\\x58\\xed\\xda\\x5a\\x2b\\xa9\\x0f\\x84\\x35\\xbe\\xfa\\x40\\xd8\\xed\\x57\\x1f\\x08\\xbb\\xc3\\xd5\\x07\\xc2\\xee\\x78\\xf5\\x81\\xb0\\x9b\\xaf\\x3e\\x10\\xd6\\x6e\\x32\\x7d\\x20\\xac\\x0f\\x84\\xd9\\xeb\\x8f\\xe7\\x1d\\x74\\x57\\x1f\\x08\\x5b\\x1b\\xa4\\x0f\\x84\\xf5\\x81\\xb0\\x3b\\x5f\\x5b\\x6b\\xe2\\xf5\\x81\\x30\\xbc\\xfa\\x40\\x58\\xf5\\xfa\\x63\\x89\\x3a\\x17\\x46\\x9a\\x18\\x83\\xb2\\x7d\\x7d\\xde\\x04\\x42\\x17\\x3c\\xb2\\xd1\\x28\\x39\\xab\\xd4\\x74\\xe1\\xa3\\xc6\\x65\\xbf\\x8d\\x00\\xe2\\xc4\\x95\\x15\\xd9\\xb8\\x53\\x19\\xcd\\xda\\x58\\xfb\\xd5\\xb2\\x27\\x5e\\x26\\xe3\\x32\\x1c\\x12\\xc4\\x41\\xd0\\xac\\x6e\\x5e\\x7f\\xf7\\x68\\x95\\x65\\x6d\\x82\\x1f\\x0f\\x13\\xf8\\xd8\\x92\\x28\\x51\\x07\\xc1\\x8e\\x3e\\xd0\\xf1\\xec\\x02\\x1d\\xdd\\x38\\x09\\x3b\\x70\\x10\\xb6\\x16\\x15\\x36\\xfe\\x7f\\xb1\\xc8\\x99\\x5a\\xc8\\xa4\\xf1\\x46\\xaf\\x6c\\xf2\\xb7\\x5c\\xf0\\xb4\\x48\\xa1\\xeb\\xad\\xd9\\xcf\\x7c\\xe9\\x13\\x0d\\x54\\xd9\\x56\\x1f\\x38\\x36\\xfa\\x2a\\x83\\xf6\\xb8\\xae\\x2d\\x2e\\xd4\\xa2\\xda\\x36\\xf7\\xaa\\x88\\x22\\xc6\\xa0\\x2d\\x5c\\x68\\xe1\\x7c\\x33\\xf6\\x4f\\xf2\\x6d\\x40\\x5e\\xb6\\xe3\\x37\\xed\\x84\\x38\\x42\\xab\\xc2\\x28\\xdf\\x7c\\xdd\\x68\\x8c\\x79\\x9e\\x75\\xc3\\x97\\x7f\\x38\\x9b\\x1c\\x06\\x7c\\x99\\x0a\\xc7\\x96\\xb9\\x58\\xca\\x04\\xa8\\x4a\\xf1\\x26\\xa3\\xac\\x3d\\x22\\x93\\x6e\\x6f\\x76\\xb4\\x32\\x39\\xba\\x90\\x11\\x6d\\xb5\\xea\\xaa\\xdf\\xcc\\xe8\\xce\\x55\\xcf\\xd1\\x1c\\xd6\\x12\\x11\\xfc\\xef\\xac\\x3b\\xb7\\xe6\\x6e\\xed\\xf5\\xd9\\xf6\\xc7\\x81\\x00\\xc4\\x0e\\xbc\\x78\\x67\\x04\\xde\\x39\\xb7\\xad\\xab\\xac\\x08\\x0e\\x0d\\x17\\xd7\\xd5\\x4a\\x4b\\x92\\x25\\xb4\\xec\\x4b\\x05\\x2b\\xf0\\x23\\xc8\\x8d\\xc3\\x05\\x8b\\x2e\\xcf\\x6c\\x8c\\x76\\x4f\\x31\\xe6\\xf5\\xc9\\x39\\xd7\\x8b\\x62\\x3a\\x8e\\x64\\xba\\x6f\\x8e\\x31\\xfe\\xdf\\x34\\x91\\xd3\\xfd\\x94\\x2a\\xcd\\x72\\xa3\\x62\\x5a\\xb1\\x34\\x8a\\xcc\\x28\\x5c\\xcc\\xc7\\x69\\x3c\\x18\\x93\\x8f\\x02\\xab\\xeb\\xcb\\x3e\\x98\\x01\\xb6\\x84\\x79\\xbe\\xc3\\xf9\\x98\\x32\\xc3\\x11\\x25\\xf8\\x0e\\x02\\x08\\x3d\\x33\\xbd\\x71\\x1b\\xa0\\xe6\\xd6\\x62\\xa4\\x65\\x7c\\xfc\\xe1\\x63\\xe3\\x3d\\xe7\\x22\\x1d\\x38\\x49\\x9e\\x5a\\x0c\\xbc\\xb3\\x5c\\x90\\x0e\\x62\\xdf\\x5b\\x14\\xf7\\xde\\x1a\\x75\\x76\\x5b\\x62\\xdd\\x5b\\x88\\x76\\xdd\\x41\\x7c\\xbb\\x8b\\xd8\\x76\\x77\\x71\\xed\\x2f\\x00\\x0a\\xfd\\x94\\xe3\\xd9\\x1d\\x3a\\xfd\\x3a\\x8a\\x63\\x3f\\x44\\x0c\\xbb\\x93\\xb7\\x6e\\x1b\\xbb\\x7e\\xb8\\xb8\\x75\\x37\\xaf\\xdb\\xa5\\xb9\\xf1\\x54\\x63\\xd5\\x1d\\x38\\xef\\xbb\\x74\\xdc\\x77\\xe6\\xb4\\xff\\x62\\xb1\\xe9\\xf6\\x71\\xe9\\x2d\\x88\\x49\\xb7\\x26\\x32\\x17\\x5c\\x73\\x9a\\x1c\\xb1\\x84\\xae\\xce\\x59\\x24\\x45\\xdc\\x58\\x8e\\xd5\\xb0\\x48\\xfd\\xf9\\x51\\x38\\xac\\xf5\\x60\\x55\\x0b\\x3d\\x16\\xd4\\x42\\xae\\x1b\\xbb\\x0d\\x0b\\x5b\\x5c\\x94\\xc3\\xaa\\x2d\\x10\\x6f\\xc6\\x59\\x6e\\x65\\xdc\\x82\\x6c\\x8d\\xab\\x0c\\xab\\x5e\\xba\\x5c\\xc4\\x1f\\xe5\\x15\\x91\\x33\\xcd\\x04\\xd9\\xe3\\xc2\\xad\\xe3\\x20\\x30\\x36\\x4b\\xbf\\xa5\\xdf\\xd6\\xe6\\xdb\\x97\\x2f\\xdc\\xcd\\xcf\\xcf\\x21\\x09\\xae\\x57\\xa5\\xbe\\xbc\\x7f\\xd8\\x3e\\xe8\\xf3\\x0e\\x62\\x7b\\xe3\\xac\\x48\\xaa\\x4e\\x62\\x74\\x1c\\x57\\xf9\\xcd\\xcb\\x12\\x34\\xfa\\x25\\x8c\\xeb\\x4f\\x1b\\x15\\x31\\xb1\\x95\\x70\\xcf\\x6f\\xd1\\x5a\\x67\\xdc\\x54\\x55\\x3f\\x9f\\x61\\xf3\\x39\\x7f\\xf2\\xc5\\xe1\\xa4\\x77\\x27\\x6f\\x97\\x53\\xe6\\x91\\xb2\\x56\\xb6\\x50\\xd1\\x7d\\xa2\\x99\\x2a\\xbd\\xa2\\x7b\\x8f\\x2b\\xa8\\x8d\\xfd\\x21\\xa7\\x11\\x9b\\x74\\xae\\x23\\xb8\\xe3\\x44\\xe2\\x22\\xa7\\x96\\x01\\x7a\\x95\\xcf\\x1d\\x1e\\xc1\\x58\\x8c\\xa7\\xc9\\xd7\\x13\\x43\\xa5\\xee\\xac\\x48\\x92\\x15\\xfa\\x1c\\x2a\\xd5\\xd7\\x18\\x85\\xaf\\x17\\xf3\\x82\\xe3\\x7f\\xc3\\x53\\x4a\\xc5\\x32\\xcb\\xa5\\x95\\x99\\x79\\x21\\x84\\xe1\\xc1\\x65\\xe7\\x37\\x50\\x24\\x01\\x8c\\x9a\\x56\\x4a\\x86\\x15\\x9f\\x9b\\xe9\\x1b\\xf9\\x07\\xd5\\xc4\\x65\\x6a\\x62\\x65\\x40\\xf3\\xeb\\x99\\xcc\\x23\\x3e\\x4d\\x56\\x64\\x41\\x13\\xdf\\xe6\\x87\\x92\\x4b\\x9e\\x24\\x76\\x98\\x31\\x39\\x67\\x1a\\x03\\x17\\x28\\x3b\\x13\\x29\\xe6\\x30\\x39\\x2a\\x5c\\x7b\\x49\\x16\\x99\\xdf\\x46\\x09\\xa3\\xa2\\xc8\\xf0\\x79\\x46\\x12\\xaf\\x64\\x91\\xbb\\xe7\\x8d\\x7d\\xf8\\xc3\\x4b\\x60\\xc1\\x93\\x61\\xd0\\xc4\\xee\\xd6\\x85\\x2d\\x5d\\x34\\xca\\x28\\x00\\xef\\x1c\\xf8\\xf6\\x30\\x1c\\xd3\\xe1\\xa3\\xab\\xa0\\x85\\x51\\x96\\xcb\\x25\\x8f\\x31\\x86\\xe2\\xc8\\x06\\xed\\xb2\\xb1\\x4d\\x91\\x3f\\xcf\\x42\\x8a\\x91\\x60\\x73\\x0a\\x8a\\x8a\\x3d\\x45\\xb8\\x66\\x38\\x0e\\xe6\\x16\\x88\\x18\\x1a\\x17\\x19\\x0d\\x5f\\x66\\x95\\x72\\xfe\\x25\\xc7\\x96\\xcb\\x01\\xe5\\xc8\\x9e\\x90\\x44\\x42\\xa6\\x6a\\x21\\xb8\\xc6\\x36\\xfe\\x8b\\x42\\x93\\x58\\x5e\\x89\\x81\\xf5\\x59\\x71\\x45\\x28\\x99\\x32\\x4d\\x83\\x5c\\x53\\x2b\\xe0\\x14\\x61\\x82\\x4e\\x13\\xb3\\xe6\\x90\\x8a\\x75\\xb1\\x91\\x40\\x64\\xc6\\xa8\\x2e\\x72\\x46\\xe6\\x54\\xb3\\x8d\\x7a\\x0e\\xbe\\xef\\xed\\xe4\\xe5\\xca\\x3a\\x58\\x67\\xa4\\x10\\x8a\\xb5\\x14\\xef\\x9d\\x29\\x47\\x7f\\xff\\x6b\\x33\\x1e\\xc1\\x53\\x26\\x0b\\xfd\\x20\\xd6\\xdf\\xd5\\x82\\x47\\x8b\\x50\\x99\\xe5\\x29\\x53\\x44\\x16\\x35\\xb3\\xf8\\xa5\\xfd\\xd9\\xe6\\x15\\xea\\x4d\\xc0\\x4d\\x57\\x53\\xf7\\xf1\\x06\\xef\\x57\\x1d\\x8e\\xa1\\xec\\xef\\x0d\\x19\\xe4\\x47\\xa7\\xe7\\xbf\\xbf\\x39\\xf8\\xd7\\xf1\\x9b\\x31\\x39\\xa6\\xd1\\x22\\xc4\\xe4\\x10\\x84\\x02\\xd3\\x00\\x46\\xb1\\xa0\\x4b\\x46\\x28\\x29\\x04\\xff\\x77\\x61\\xc3\\xca\\x7b\\xfe\\xb7\\x83\\x4e\\x11\\xe9\\x1b\\x4a\\x5f\\xc3\\x6d\\x1a\\xed\\xf8\\x8d\\x4d\\xef\\x60\\x34\\x9b\\xb1\\x25\\x15\\x83\\x36\\x35\\x6b\\xea\\x93\\x8f\\x65\\xaf\\xd0\\x44\\x00\\x85\\x0b\\x12\\xeb\\x8f\\xde\\x1d\\x9f\\x43\\xc2\\x7e\\x96\\x23\\x52\\x09\\x64\\x78\\xc1\\xf7\\x30\\xd2\\x94\\x99\\x5f\\xd8\\xfe\\xc4\\x63\\x72\\x20\\x56\\xf8\\x25\\x9e\\x29\\xae\\x48\\xc2\\x95\\x66\\x20\\xf5\\xac\\xda\\xe6\\xa2\\xe4\\x3b\\x2f\\xc6\\xf0\\xbf\\x1d\\x42\\xe3\\x38\\x37\\x7a\\x9d\\x4f\\x5c\\x8b\\xd6\\x32\\x49\\x51\\xf3\\xe3\\xd3\\x24\\x78\\x01\\xc1\\x34\\xe6\\xa9\\xbd\\x95\\xb1\\x9d\\x39\\x48\\x12\\x88\\x90\\xa1\\x18\\x54\\x3a\\xa7\\x9a\\xcd\\x79\\x44\\x52\\x96\\xcf\\x19\\xc9\\xa8\\x8e\\x16\\x24\\xa5\\x2b\\x12\\xc9\\x3c\\x2f\\x32\\xec\\x66\\x10\\x53\\x4d\\xc7\\xe4\\xb5\\xcc\\x49\\xea\\x0e\\xb1\\xd9\\xf3\\x46\\x0e\\x9f\\x6f\\xce\\x1c\\x28\\x4f\\x76\\xf8\\x4f\\xae\\x54\\xc1\\xd4\\xfe\\xcb\\x17\\xdf\\x7e\\xfd\\xb7\\xbf\\x3d\\xab\\x06\\x78\\x3e\\xb5\\x17\\xf2\\x5e\\x82\\x06\\x78\\xd4\\xad\\x02\\xae\\x3a\\x36\\x44\\xe4\\x62\\x9e\\x84\\xfb\\xab\\x99\\x00\\x68\\x6b\\x65\\xb6\\xb5\\x31\\x47\\xe5\\x1b\\x4c\\x9a\\x9a\\x9a\\x9d\\x34\\xe2\\x2b\\xe7\\xd0\\x51\\xfb\\xaa\\x52\\x0e\\x3a\\xc3\\xca\\xf2\\x06\\x19\\x76\\x24\\x3e\\x99\\xb8\\x83\\x69\\xf5\\x9c\\xb4\\xd6\\xc6\\x36\\x2b\\x73\\xa0\\x86\\xe4\\x05\\xf9\\x8e\\x5c\\x93\\xef\\xc0\\xd0\\xfa\\x7b\\xdb\\x66\\x5f\\x6d\\x4d\\xa0\\x2e\\x52\\x9a\\x8c\\x7d\\x7f\\x32\\xe9\\x88\\xe2\\xbf\\x18\\xa6\\x69\\x46\\x34\\x54\\xd5\\x92\\x4c\\xb9\\x55\\xec\\xd9\\xb5\\x66\\xb9\\x51\\x34\\xed\\x4a\\x3c\\x6a\\x9b\\x34\\x33\\xc1\\x07\\xdc\\x66\\x18\\x78\\x38\\x99\\x55\\xd3\\xa8\\xee\\xb7\\xd1\\xcc\\xcf\\x7f\\x94\\x4a\\x9f\\x5a\\x2e\\x54\\x6d\\xf8\\x53\\x8e\\x96\\x02\\xe3\\xaf\\xb0\\x31\\x23\\x37\\x94\\x2e\\x0f\\x98\\x22\\xb1\\x84\\xac\\x2e\\x4c\\x71\\x5e\\xf0\\x16\\xc9\\x1a\\xdb\\xb3\\x8d\\xdb\\xc5\\xef\\x2b\\xeb\\x79\\xdb\\x4a\\xd5\\x5c\\x29\\x60\\x03\\x59\\x15\\x2b\\xc0\\xe8\\xca\\x64\\x6c\\xb5\\x33\\x33\\xad\\x38\\x90\\x19\\xb7\\xa8\\x67\\xd6\\x6b\\xe3\\xfd\\xcd\\xb0\\x97\\xcc\\x79\\x8a\\xa8\\xc0\\x22\\x93\\x19\\xcb\\x73\\xcc\\x4a\\x9f\\xae\\x5c\\x72\\x60\\xeb\\xc5\\x6b\\x75\\x92\\xb2\\x5c\\x6a\\x19\\xc9\\x16\\x9d\\xdc\\xaa\\xd1\\x6e\\x3b\\x1c\\x10\\x21\\xc3\\xbd\\x6b\\x29\\xff\\xfe\\x68\\x32\\x24\\x17\\x87\\x13\\xe8\\x6e\\x75\\x7e\\x78\\x31\\xa9\\xda\\x2c\\x3b\\x17\\x87\\x93\\x9d\\x47\\x25\\x05\\x71\\x0a\\x1f\\xb8\\xa8\\x1b\\x0c\\x52\\x71\\x41\\x19\\x6d\\x72\\x94\\xd2\\x6c\\x74\\xc9\\x56\\x0d\\x65\\x6a\\x17\\x72\\x7d\\xe4\\x57\\xb8\\x93\\x17\\x42\\x32\\xa7\\x34\\xbb\\xf7\\x68\\x39\\xa3\\x31\\x7f\\xa0\\x4a\\x2f\\x97\\x76\\xeb\\x9f\\xb9\\xb9\\xe4\\x2b\\x95\\x4b\\x16\\xa3\\x96\\xee\\x7e\\xc1\\x44\\x9c\\x49\\x6e\\xf4\\xc5\\xbe\\x0e\\xec\\xfe\\xbf\\xee\\xeb\\xc0\\xee\\x7c\\xf5\\x75\\x60\\x7d\\x1d\\xd8\\xfa\\xb5\\x35\\x89\\xb3\\x7d\\x1d\\xd8\\xf3\\x8a\\xe0\\xf7\\x75\\x60\\xf7\\xbf\\x1e\\x3d\\x70\\xdf\\xd7\\x81\\x6d\\xbe\\xfa\\x3a\\xb0\\xbe\\x0e\\xec\\x6e\\x57\\x5f\\x07\\x76\\xff\\x6b\\xeb\\x52\\x8e\\xfa\\x3a\\xb0\\x7b\\x5d\\x7d\\x1d\\xd8\\xfa\\xd5\\xd7\\x81\\xdd\\x70\\xf5\\x75\\x60\\x37\\x5c\\x7d\\x1d\\xd8\\xfa\\xd5\\xd7\\x81\\xdd\\xef\\xea\\xeb\\xc0\\xfa\\x3a\\xb0\\x67\\x9d\\x1e\\x4b\\xfa\\x3a\\x30\\x7b\\xf5\\x75\\x60\\xcf\\x22\\x09\\x90\\xf4\\x75\\x60\\x77\\xba\\xfa\\x3a\\xb0\\xbe\\x0e\\xac\\xc9\\xd5\\xd7\\x81\\x3d\\x17\\xa7\\x4c\\x5f\\x07\\xd6\\xd7\\x81\\xfd\\x71\\x14\\xdd\\xbe\\x0e\\xac\\xaf\\x03\\xeb\\xeb\\xc0\\xfa\\x3a\\xb0\\x5b\\x67\\xd1\\xd7\\x81\\x3d\\x07\\x13\\x30\\x67\\x8a\\xff\\x87\\x4d\\x64\\xc2\\xa3\\x55\\xeb\\x2c\\xc5\\x33\\xdb\\xf8\\x58\\xd9\\x61\\x49\\x06\\xe3\\x06\\xa9\\x55\\x2d\\x2a\\x4f\\xb6\\xac\\xe0\\xe6\\x2c\\x20\\x5c\\x58\\x78\\xe3\\x9b\\x3f\\x7f\\x01\\x12\\x6c\\x45\\xf1\\x8d\\x7b\\xc1\\xd3\\xe6\\x91\\x94\\x91\\x6b\\x40\\x80\\xe4\\x6b\\xe6\\xb7\\x68\\x6d\\x22\\x84\\x2f\\xd2\\x51\\x3e\\xf8\\x6e\\x58\\x11\\xe9\\x77\\x82\\x96\\x9e\\x83\\xf1\\x1b\\x37\\x08\\xcd\\xb2\\x84\\x33\\x35\\x26\\xe7\\xbe\\x01\\x0f\\x70\\x2f\\xf5\\x8a\\x44\\x59\\x31\\x24\\x29\\x4b\\x65\\xbe\\x6a\\x61\\x4d\\x74\\xa0\\x70\\x56\\x56\\xad\\x23\\x92\\x9d\\xe1\\x98\\x8e\\x0c\\xc6\\x88\\xc8\\xb2\\x64\\x85\\xca\\x54\\x59\\x4a\\xea\\xa9\\xc6\\x1d\\x73\\x89\\x41\\xdd\\xa9\\x65\\x79\\x70\\x5d\\x31\\xc3\\x4e\\xa5\\x3e\\xb3\\x1b\\xfe\\xd1\\x72\\xed\\x6f\\xca\\x2a\\xa7\\x5a\\xa6\\x3c\\x6a\\xc2\\xb0\\x91\\xc7\\xb6\\xcf\\x29\\x3f\\x94\\x69\\x56\\x68\\x56\\x61\\xdb\\x48\\x2c\\xd4\\xe4\\xb8\\x0a\\x4d\\xb8\\xf6\\xd9\\xe0\\x91\\x14\\x33\\x3e\\xb7\\xaa\\xf8\\x3e\\x76\\x74\\x1f\\xf9\\xf7\\x19\\x05\\x5d\\xd4\\x9f\\x60\\x2a\\x78\\x94\\x50\\xde\\x3c\\x6e\\x5f\\x4d\\xad\\x3a\\x84\\xb1\\xa0\\x42\\xb7\\x4c\\xae\\x82\\x1c\\x5d\\x4f\\xad\\xa1\\x4f\\x5c\\xe2\\x78\\x4c\\xc6\\xee\\x2b\\xfc\\xf1\\x10\\x33\\x7d\\x8d\\xfd\\x01\\x4a\\xe7\\x86\\x05\\xfd\\x28\\x4a\\xf5\\x58\\x10\\x9a\\x64\\x8b\\xdb\\x15\\x64\\x33\\x91\\xa3\\x95\\xa0\\x29\\x8f\\xdc\\x8e\\x39\\x48\\x12\\x19\\xa1\\x41\\x54\\x55\\x91\\xdd\\xd8\\x38\\x9e\\x79\\x48\\x9a\\x16\\x9a\\x4e\\x13\\x36\\x26\\x27\\x58\\x21\\x24\\x45\\xb2\\x32\\xbb\\x49\\x31\\xed\\x02\\x1f\\x76\\xf9\\x1b\\xe7\\x60\\xb5\\x4f\\xc0\\x68\\x99\\x7c\\xb1\\x51\\x1b\\x82\\x05\\xc1\\x6a\\x28\\x26\\xcc\\x29\\x93\\x82\\x11\\x26\\x74\\xbe\\x32\\x6b\\x37\\x91\\xf1\\xb9\\x59\\xbe\\xca\\xdd\\xad\\x8b\\xa4\\x5a\\xe6\\x5c\\x74\\x91\\x6f\\xd1\\x32\\xd7\\xa2\\x9b\\x0c\\x89\\xf6\\xd9\\x11\\xeb\\x61\\xde\\xa0\\x6e\\x31\\x4c\\x7c\\xac\\xac\\x6a\\x26\\xe3\\xf1\\x86\\x53\\xe9\\x54\\x83\\x89\\x8c\\x8d\\x80\\xcb\\x59\\xd8\\x0a\\xcf\\xda\\x87\\x70\\x40\\x52\\x7a\\x09\\x26\\x36\\xd5\\xa5\\xe4\\xa3\\x4b\\xca\\x13\\x73\\x84\\x36\\xd4\\xe3\\xb7\\x4b\\x9c\\xe8\\x40\\x35\\xe8\\xba\\x18\\x8c\\xb4\\xdd\\x41\\x5d\\x16\\x73\\x11\\xe8\\xdc\\x95\\xf2\\x66\\xe8\\x0f\\x64\\x4d\\xf0\\xbe\\x81\\xb1\\x82\\x74\\x2c\\xb3\\x27\\x52\\x7a\\x0d\\x36\\x2b\\x4d\\x65\\x21\\x34\\x56\\x78\\xa1\\x7c\\xf6\\x4c\\x1f\\x93\\xd6\\xb6\\x4e\\xf2\\x92\\x6e\\xd8\\x0e\\x8d\\x5d\\x09\\xcc\\xa4\\x8b\\x6c\\x72\\xaa\\x35\\xcb\\xc5\\x2b\\xf2\\x5f\\x7b\\x1f\\xbf\\xfa\\x34\\x1a\\x7c\\xbf\\xb7\\xf7\\xe1\\xc5\\xe8\\x1f\\xbf\\x7d\\xb5\\xf7\\x71\\x0c\\xff\\xf8\\xcb\\xe0\\xfb\\xc1\\x27\\xf7\\xc7\\x57\\x83\\xc1\\xde\\xde\\x87\\x9f\\xde\\xfe\\x70\\x31\\x39\\xfe\\x8d\\x0f\\x3e\\x7d\\x10\\x45\\x7a\\x89\\x7f\\x7d\\xda\\xfb\\xc0\\x8e\\x7f\\xbb\\xe3\\x20\\x83\\xc1\\xf7\\x7f\\x6e\\x3c\\xe5\\xd6\\x3e\\xea\\xee\\x3c\\xd4\\x1d\\xf9\\xa7\\xbf\\x88\\x77\\xda\\xe6\\x71\\x76\\x74\\x16\\x6d\\x0e\\xfa\\xda\\x69\\xb4\\x1e\\xa4\\xdb\\x4e\\xa3\\x93\\x92\\x60\\x88\\xf8\\x71\\xb8\\x22\\x32\\xe5\\xda\\x18\\x70\\x46\\xad\\xa1\\x61\\xe5\\x59\\xcd\\x3c\\xb1\\x7c\\x00\\x6a\\x2f\\x29\\x94\\x88\\x05\\x55\\x5b\\x81\\x55\\x23\\x9d\\x2b\\x16\\xcc\\x23\\x41\\x78\\x9a\\x25\\x2c\\x65\\x42\\xc3\\x79\\x1e\\x39\\x4d\\x10\\xec\\xc5\\x71\\x39\\x93\\x08\\x35\\x76\\x76\\x1d\\x31\\x16\\xdb\\x87\\xf5\\xac\\xe3\\xf3\\x57\\xcf\\x3a\\x9e\\x23\\xeb\\x50\\x2c\\x2a\\x72\\xae\\x57\\x87\\x52\\x68\\x76\\xdd\\x28\\x22\\x5a\\xe5\\x1c\\xe7\\xd5\\x01\\xad\\x41\\x66\\x73\\x5a\\xed\\x77\\x44\\x66\\x58\\xc1\\x59\\x83\\xc8\\x5a\\xc8\\x22\\x89\\xa1\\x2c\\xbb\\x10\\x10\\x10\\x42\\xbc\\x0d\\xa6\\x31\\x5a\\x03\\x0a\\x21\\x68\\x8b\\xf5\\x87\\xb8\\xf8\\x0b\\x86\\x85\\xfe\\x5d\\xf0\\x25\\x4d\\x98\\xd0\\xc1\\x2f\\x26\\x10\\x71\\x08\\x7f\\x74\\xd7\\x33\\xaf\\xa9\\xba\\x2c\\x0f\\x3c\\x1b\\x65\\x32\\x2e\\xcf\\xf7\\xbe\\x7b\\x25\\xf8\\x88\\x5d\\xeb\\xa7\\x68\\xa4\\x83\\xfe\\x34\\xc9\\xf9\\x92\\x27\\x6c\\xce\\x8e\\x55\\x44\\x13\\xe0\\x6b\\xdd\\x88\\x92\\x83\\x1b\\x46\\x87\\x85\\xcf\\x65\\xa2\\x8c\\xce\\x6f\\x58\\x39\\xa1\\x2e\\x64\\x07\\x96\\xf0\\x9c\\x72\\x81\\x08\\x57\\x99\\xfb\\xb1\\xc2\\xd8\\x9f\\x91\\x0e\\x19\\xcd\\xcd\\x02\\xfb\\x18\\x1f\\xd8\\xd5\\x53\\x29\\x13\\x5b\\xbb\\x9c\\xac\\xca\\xf1\\x6d\\x15\\xbf\\x90\\xbf\\x0b\\x76\\xf5\\xbb\\x19\\x4d\\x91\\x59\\x42\\xe7\\x3e\\xb4\\x67\\x8c\\xed\\x7a\\x74\\xbe\\x1c\\xfa\\xc6\\x17\\x80\\xc2\\xe0\\x82\\x11\\x9a\\x5c\\xd1\\x95\\x2a\\x03\\x9d\\x01\\x96\\x9b\\x7a\\x45\\x5e\\x0e\\x60\\x3b\\x53\\x45\\xfc\\x18\\x31\\xf9\\x7a\\x00\\xe9\\x7a\\x87\\x07\\x93\\xdf\\xcf\\x7f\\x3d\\xff\\xfd\\xe0\\xe8\\xed\\xc9\\x29\\x39\\x95\\x9a\\xa1\\xcc\\x0b\\xec\\x9f\\xc8\\x3b\\x98\\xcc\\x2c\\xbd\\xff\\x6f\\x2c\\xd5\\x18\\x6c\\x2c\\xc8\\x3e\\x17\\xb1\\xbc\\x52\\x8d\\xbd\\xa0\\xb8\\xfd\\x0c\\xf1\\x18\\x15\\xcd\\xdc\\x3c\\x34\\xa3\\xd0\\xe1\\xbc\\x85\\x84\\x59\\xcb\\x08\\x0f\\x07\\x05\\x11\\x1f\\xc7\\xfb\\x71\\x2e\\x33\\x24\\x82\\x0b\\x4a\\x07\\x0e\\x92\\x4a\\xd8\\x2b\\xac\\x6c\\x83\\xf5\\x9d\\x55\\x07\\x9c\\xe7\\x54\\xe8\\x32\\x3a\\x5b\\xae\\x99\\x6d\\xad\\x3e\\x6e\\xbd\\x1c\\x8f\\x27\\xf8\\xbb\\xf0\\x12\\xd0\\xb8\\x3b\\x5c\\x82\\x83\\x38\\x66\\x71\\x85\\xfc\\xcf\\xae\\x9e\\xe8\\xd0\\xbd\\x5c\\x10\\xf6\\x22\\x93\\x77\\xe7\\x27\\xff\\xb7\\xb6\\x8f\\x57\\x59\\xbb\\xc2\\x86\\x6e\\x30\\x6e\\x72\\x99\\x75\\xb6\\xba\\x67\\x16\\x43\\xa5\\x5f\\xdf\\xad\\x58\\x5f\\x2f\\x2d\\xbb\\x49\\xa7\\x3d\\x2b\\x44\\x15\\x9c\\xb4\\x1c\\x9f\\xa4\\x32\\x66\\x63\\x32\\xf1\\x79\\x3d\\xd5\\x6f\\x03\\xa8\\x32\\x9a\\x33\\x62\\x6e\\x11\\x9a\\xd3\\x24\\x59\\x85\\x2a\\x9a\\x96\\x88\\x27\\x52\\x41\\x59\\x0b\\x19\\xf9\\x8c\\x26\\xea\\xb1\\xb9\\x71\\x1b\\xd9\\x68\\xf4\\x88\\xb7\\xc6\\x5c\\xee\\x64\\x39\\xfc\\x68\\x24\\x66\\x42\\x6a\\xab\\x58\\x9b\\x59\\x02\\x72\\x5d\\x2e\\x23\\x82\\xb6\\x79\\x50\\x3c\\x51\\x91\\x6f\\x0a\\x73\\x8b\\x9c\\x68\\xe4\\xca\\x11\\x7b\\xe2\\x47\\xc6\\xb0\\x6c\\xa1\\x58\\x5d\\x41\\xb7\\xa2\\xb1\\xb4\\xd6\\xcd\\xe8\\x39\\xa3\\x31\\x44\\x2d\\x32\\xaa\\x17\\x98\\xfb\\x9c\\x52\\x75\\xc9\\x62\\xfc\\xc0\\xaa\\x66\\x3e\\x70\\x02\\x8e\\x5e\\xf7\\xa8\\x0b\\x33\\x6f\\x17\\x23\\x01\\x95\\x0c\\x33\\xb2\\x21\\xba\\xc2\\xe2\\x47\\x5e\\xf5\\x16\\x87\\xd0\\x10\\xe5\\x9d\\x48\\x56\\x67\\x52\\xea\\xd7\\x1e\\x10\\xa7\\x93\\x1d\\xf0\\x8b\\xd5\\x96\\xab\\x81\\x2b\\x50\\x27\\x29\\x3c\\x77\\x04\\xab\\x01\\x87\\x2a\\xc4\\xe2\\x39\\x2a\\x57\\xfc\\xa9\\x1f\\xa9\\xbc\\x10\\x07\\xea\\x87\\x5c\\x16\\x8d\\x85\\xd8\\x9a\\xb2\\xf9\\xc3\\xc9\\x11\\xb0\\xa2\\xc2\\xa6\\x16\\x0a\\x9d\\xaf\\x00\\x04\\x6c\\x1d\\xc9\\xd9\\x1b\\x06\\xef\\x6d\\x72\\x64\\x78\\x26\\xca\\x3c\\x36\\xf2\\x96\\xae\\x08\\x4d\\x94\\x74\\xb4\\xb4\\x61\\xad\\xba\\x15\\x6a\\x4d\\x5c\\xf3\\xf5\\x54\\xea\\xc5\\x9a\\x6d\\x6b\\x0e\\xd4\\xfa\\xef\\x86\\x41\\xa6\\x61\\x99\\x0f\\xc0\\xc5\\xda\\xcf\\x35\\xc4\\x4c\\xb2\\x9c\\x45\\x2c\\x66\\x22\\x7a\\xec\\x65\\x7f\\xec\\x04\\x3d\\xd8\\x3a\\xa7\\x52\\x98\\x83\\xd9\\xc9\\xe6\\x39\\xf1\\x99\\x99\\x96\\xa4\\xe1\\x56\\x81\\xa0\\x98\\xb5\\xfe\\x28\\x64\\x7a\\xc2\\xb1\\x2c\\x14\\xcb\\x31\\x2d\\x35\\x2f\\x18\\xae\\xe4\\x4f\\xc5\\x94\\x25\\x86\\xf2\\xc6\\x24\\x05\\x1c\\x51\\xaa\\xd1\\x9d\\xc1\\x53\\x3a\\x67\\x84\\x6a\\xbf\\xd3\\xb4\\x24\\x4c\\xa8\\x22\\xb7\\x8b\\xc8\\x35\\x89\\x25\\x2b\\x71\\xb4\\xa8\\x22\\xef\\x4f\\x8e\\xc8\\x0b\\xb2\\x67\\x9e\\x35\\x80\\xfd\\x33\\xa3\\x3c\\x81\\x24\\x50\\x48\\x2a\\xa9\\xd9\\xa8\\x33\\x37\\x04\\x4c\\x09\\x36\\x2f\\x91\\x39\\x32\\x89\\x21\\x11\\x92\\xa8\\x22\\x5a\\xb8\\x39\\x19\\xbb\\xd7\\x99\\xcd\\xb6\\x70\\x09\\x22\\x2f\\xdb\\xb9\\xd7\\x1f\\x97\\x43\\xbd\\x57\\x2c\\xef\\x8c\\x41\\xbd\\x6f\\xc0\\xa0\\x42\\x35\\xca\\xec\\xb9\\x2a\\xf5\\x70\\x63\\xa5\\x4c\\xd3\\x98\\x6a\\x6a\\x19\\x97\\xbb\\x61\\x6b\\x97\\xf4\\x8f\\xcd\\xbe\\x14\\x7b\\xc3\\x45\\x71\\x8d\\x85\\x02\\xdd\\xb9\\x5a\\xce\\x8f\\x61\\x58\\x12\\x39\\xaa\\xc3\\xaa\\x63\\xf2\\x5d\\xec\\xbc\\x29\\x41\\x92\\xcc\\x49\\x65\\xaf\\x0c\\x6f\\x50\\x13\\x81\\x4f\\x50\\x4c\\x86\\x61\\x46\\x39\\xa1\\x22\\x96\\xe9\\xda\\xc3\\x8c\\x12\\xc9\\x2a\\x3d\\x10\\xc6\\xa4\\xdf\\x7d\\xd5\\x6b\\x4b\\x9c\\x42\\x09\\x5b\\xb2\\x16\\x28\\xc1\\xf5\\x9e\\x0f\\x66\\x34\\x43\\x1c\\xb7\\x23\\x60\\x78\\x92\\xd0\\x29\\x4b\\x6c\\xa2\\x16\\xa6\\x7f\\xae\\xef\\xc0\\xc7\\xae\\x1e\\xcb\\x65\\xd2\\x5d\\xb9\\xfb\\x99\\x4c\\x18\\x96\\x63\\x38\\x42\\x98\\xe1\\x9f\\x04\\x1d\\x60\\x90\\xae\\xe8\\x00\\xd6\\x60\\x85\\x0e\\x60\\xd7\\x3e\\x05\\x3a\\x14\\x2d\\x44\\x3d\\xa9\\xd3\\xc1\\xe8\\x0d\\x55\\x3a\\x80\\xf0\\xde\\x76\\x3a\\x28\\x16\\x45\\x32\\xcd\\x26\\xb9\\x34\\x66\\x67\\x67\\xb2\\xc9\\x0e\\x5b\\xc6\\x0c\\xd1\\xb1\\xb1\\x21\\x75\\x13\\x64\\x41\\xf5\\x66\\x9a\\x07\\x85\\x58\\x54\\xa3\\x90\\x70\\xd5\\x58\\xff\\x2b\\x90\\x59\\xc0\\x7a\\xea\\x82\\xcc\\x8d\\x52\\x09\\x2f\\x9a\\x5f\\xda\\x2f\\x9e\\xb2\\x38\\xe8\\xa2\\x96\\xb9\\x85\\xb3\\xb3\\x13\\x69\\x24\\x23\\x9a\\x40\\x17\\x88\\x76\\x5b\\x8e\\xd4\\xb7\\x5d\\x7d\\xe0\\xa0\\xfc\\x0e\\x62\\x94\\xf0\\x59\\x90\\x69\\x4c\\xc1\\xd1\\xe2\\x5c\\x98\\x42\\xc6\\x2c\\x88\\x65\\x63\\xf6\\xe2\\x05\\x96\\x69\\xc1\\x7d\\xae\\xf2\\xcf\\xe8\\x15\\x2e\\xac\\x1c\\x57\\x7e\\xad\\xa5\\xc5\\x32\\x7e\\xeb\\x7b\\x4b\\x98\\x09\\x32\\x11\\x73\\x31\\x07\\xbf\\xda\\x90\\xe4\\x2c\\xc1\\x9a\\x41\\xcb\\x04\\x2e\\xd1\\x82\\xdc\\x85\\x23\\xe1\\x06\\x75\\xe7\\xc1\\x3d\\xda\\x25\\x26\\xdb\\x91\\xc3\\x6c\\x63\\x3e\\x43\\x76\\xcb\\x15\\xd9\\x79\\xe3\\x08\\xd0\\x02\\x8c\\x7f\\x1b\\x25\\xcc\\x0e\\xbe\\xa1\\x5f\\x4d\\xf4\\x74\\x5e\\x72\\x11\\xdb\\xf2\\xba\\x0a\\xb1\\x7c\\x37\\x27\\xd4\\x83\\xa1\\x70\\x93\\xc7\\x21\\x6f\\x79\\x45\\x3e\\x0a\\xe2\\x89\\x45\\x46\\x8d\\xb7\\xc7\\x19\\xaa\\xcc\\xce\\x47\\x37\\xba\\xdd\\xf1\\xea\\x1f\\x52\\x1f\\xe6\\xbd\\x80\\xb5\\x37\\xcf\\x1d\\x19\\xcb\\x7d\\xfd\\x3e\\xf7\\x2e\\x8f\\x0a\\xe8\\x69\\xb9\\x5f\\xd7\\x56\\xcc\\x2f\\x38\\xac\\x53\\xe9\\x23\\xb3\\xad\\x35\\x17\\x73\\x15\\x5a\\x32\\x34\\x49\\x2a\\xce\\xf0\\x4d\\xa6\\x8c\\x5b\\x61\\xdf\\xbb\\x6b\\xdd\\x84\\xa8\\x95\\x05\\x3f\\x15\\x33\\x24\\x31\\xea\\xc4\\x13\\x37\\x42\\xe6\\xa9\\xa2\\x87\\xb9\\xa1\\x84\\xe6\\x34\\x39\\xcf\\x9a\\x37\\x1b\\x20\\x6b\\xc0\\xd6\\x6f\\xcf\\x0f\\xaa\\x43\\x83\\xb0\\xb6\\x39\\xe9\\x0c\\xbe\\x27\\x34\\x4e\\xb9\\x52\\xe0\\x08\\x63\\xd3\\x85\\x94\\x97\\x64\\xef\\xd6\\x9e\\x6b\\x23\\xc5\\xe7\\x6a\\xdf\\xee\\xf9\\x91\\x99\\xfd\\x80\\x70\\x91\\xf8\\xac\\x28\\xb0\\x83\\x85\\xf6\\x69\\xf0\\xf0\\x90\\xc8\\xcf\\x02\\xd6\\xd0\\x76\\xa0\\xb1\\xc9\\x0a\\xeb\\xd3\\xc4\\x9e\\x33\\x66\\x17\\x3c\\x3a\\xc3\\x5e\\x5f\\x9e\\x76\\xa5\\x84\\x9f\\x5d\\xa2\\x53\\xbb\\xb7\\xeb\\x78\\xcb\\x1b\\xe9\\x88\\xda\\xe3\\xa3\\x13\\xc9\\x2a\\x17\\x11\\x53\\xdd\\xc1\\xbc\\xfe\\x58\\x8e\\x49\\x62\\x86\\x55\\xf7\\x0c\\xb2\\x9f\\xe8\\x8d\\x49\\x76\\xe0\\x97\\xde\\x05\\xf0\\x16\\xfb\\xd3\\xdd\\x50\\xa3\\xae\\x56\\x2b\\x41\\x31\\xd4\\x08\\x8d\\x74\\xc3\\xd1\\x80\\x05\\x3a\\x15\\x62\\x21\\x85\\xb4\\x35\\x72\\x46\\x88\\x4a\\x01\\x5b\\x1a\\x58\\x14\\x46\\xf3\\x60\\x4d\\x2c\\x8b\\x0e\\xa6\\x7a\\x58\\x46\\x89\\xc3\\x40\\x20\\x80\\x3f\\x68\\xdf\\x24\\x11\\xe7\\x70\\xc5\\xf5\\x02\\x3a\\x36\\x2c\\x6a\\x51\\x43\\x98\\x49\\xce\\x14\\x04\\x60\\x04\\x61\\x79\\x2e\\x73\\x9b\\x90\\xe5\\xfc\\xd6\\xb6\\x54\\x6b\\x22\\x63\\xc8\\xe8\\x32\\x9b\\x84\\x9a\\xbf\\x76\\x55\\x18\\xa8\\x2e\\x9b\\x3a\\x79\\x0c\\x4e\\x36\\x9b\\xb1\\x08\\x14\\xad\\x90\\xc0\\xc8\\xb5\\xf7\\xca\\x16\\x16\\xb6\\x08\\xc1\\x6c\\x30\\xdb\\x14\\x2a\\xe5\\xd7\\xe6\\x29\\xe1\\xaf\\xc2\\x90\\xb8\\x6d\\x1d\\xb1\\xf9\\xeb\\xc1\\x98\\x90\\x13\\xe1\\x33\\x78\\x87\\x66\\x15\\xc3\\x3b\\x5d\\xea\\x99\\x36\\xaf\\x18\\x76\\x14\\x83\\x17\\x08\\x1d\\x67\\x46\\x3b\\xcc\\x8b\\x0e\\x76\\x7c\\x1b\\x77\\x38\\x09\\x5d\\xe2\\x9d\\xb2\\x03\\x70\\x8d\\xdb\\x41\\xcd\\xd2\\x3b\\x1d\\xa0\\x8d\\xab\\xdc\\xdc\\xf2\\xa5\\xdc\\xe5\\x4f\\x23\\x00\\x42\\xda\\xf2\\x39\\x8b\\x7e\\xd6\\x51\\x9b\\xa7\\xf3\\x60\\xb4\\x40\\x7b\\xf7\\x01\\xb7\\x89\\x8c\\x11\\xfd\\xd0\\xa3\\xb7\\x25\\x2b\\x87\\xc6\\xe8\\x6b\\xa2\\x03\\x1d\\x4f\\x48\\x2c\\x1e\\x08\\x61\\x11\\x6d\\x73\\x9c\\x98\\x18\\x55\\x3b\\x71\\xbe\\x85\\x34\\x4b\\x18\\xa0\\xae\\x04\\x23\\x97\\x80\\x32\\x41\\x5f\\xa8\\x61\\x59\\xc1\\xe6\\x5b\\x4b\\x59\\x30\\xc6\\x21\\xf9\\x1f\\x38\\x94\\x3e\\x11\\xd5\\xe1\\xc4\\x4d\\xfc\\xcf\\xd1\\x42\\xe4\\xca\\x35\\x89\\x83\\xe2\\x54\\x2d\\x9d\\xeb\\x82\\xc4\\x7c\\x06\\x75\\x92\\xda\\x3e\\x32\\xa3\\x39\\x4d\\x0d\\x8b\\x57\\xc4\\x92\\x60\\xca\\xe6\\x1c\\x13\\x22\\x3d\\x63\\xdb\\x35\\xea\\x9e\\xc5\\xe6\\x18\\x22\\x33\\xe4\\x9a\\xa4\\x7c\\xbe\\xc0\\x8d\\x42\\x28\\x20\\xea\\x10\\x17\\x54\\x4c\\x24\\x8d\\xa1\\xb9\\x2c\\x91\\x39\\xb9\\xa2\\x79\\x6a\\xe4\\x06\\x8d\\x16\\x10\\xa1\\xa4\\x82\\xc4\\x45\\x0e\\xfd\\x52\\x34\\xa3\\xf1\\x6a\\xa4\\x34\\xd5\\x46\\x53\\x66\\xb9\\x35\\x28\\xdd\\xfc\\xfb\\xe6\\x58\\xb7\\x5e\\x7d\\x73\\xac\\x3b\\x5e\\x7d\\x73\\xac\\xbe\\x39\\xd6\\xfa\\xb5\\x35\\xd9\\xa1\\x7d\\x73\\xac\\xe7\\x05\\x6b\\xda\\x37\\xc7\\xba\\xff\\xf5\\xe8\\x68\\xa6\\x7d\\x73\\xac\\xcd\\x57\\xdf\\x1c\\xab\\x6f\\x8e\\x75\\xb7\\xab\\x6f\\x8e\\x75\\xff\\x6b\\xeb\\x70\\x98\\xfb\\xe6\\x58\\xf7\\xba\\xfa\\xe6\\x58\\xeb\\x57\\xdf\\x1c\\xeb\\x86\\xab\\x6f\\x8e\\x75\\xc3\\xd5\\x37\\xc7\\x5a\\xbf\\xfa\\xe6\\x58\\xf7\\xbb\\xfa\\xe6\\x58\\x7d\\x73\\xac\\x67\\xdd\\x33\\x80\\xf4\\xcd\\xb1\\xec\\xd5\\x37\\xc7\\x7a\\x16\\xc8\\xe8\\xa4\\x6f\\x8e\\x75\\xa7\\xab\\x6f\\x8e\\xd5\\x37\\xc7\\x6a\\x72\\xf5\\xcd\\xb1\\x9e\\x8b\\x53\\xa6\\x6f\\x8e\\xd5\\x37\\xc7\\xfa\\xe3\\x28\\xba\\x7d\\x73\\xac\\xbe\\x39\\x56\\xdf\\x1c\\xab\\x6f\\x8e\\x75\\xeb\\x2c\\xfa\\xe6\\x58\\xcf\\xc1\\x04\\x54\\x3a\\xe6\\x8d\\xb0\\x41\\xef\\x02\\x63\\x64\\xd3\\xd3\\x03\\xd4\\x80\\x69\\x31\\x9b\\xb1\\x1c\\x38\\x17\\x3c\\x79\\x2d\\xad\\xaa\\x44\\x6c\\xac\\x87\\x72\\x99\\x1e\\x02\\x22\\x92\\xad\\xe4\\xb9\\xe1\\xe7\\x16\\xa6\\x00\\x30\\x3c\\xcb\\x1c\\xf2\\xe3\\x77\\xaf\\x37\\x60\\x26\\x35\\xce\\x37\\x6c\\x9a\\x3d\\x0d\\x73\\x7e\\x27\\x9a\\x45\\xe1\\x6f\\x20\\xf8\\xa6\\xca\\x32\\x4b\\xf7\\x28\\x91\\xca\\xe6\\xbe\\x03\\xb1\\xa2\\x05\\x15\\x82\\x39\\x7b\\x8f\\x6b\\xf0\\xa3\\x4c\\x19\\x13\\x44\\x66\\xcc\\xc6\\xc0\\x29\\x51\\x5c\\xcc\\x13\\x46\\xa8\\xd6\\x34\\x5a\\x8c\\xcd\\x93\\x84\\x23\\x76\\x99\\xa7\\x6e\\x3f\\x51\\x3a\\x67\\x34\\x75\\x19\\xfb\\x29\\xe5\\x38\\x14\\xa1\\x51\\x2e\\x95\\x22\\x69\\x91\\x68\\x9e\\xf9\\xc1\\x88\\x62\\x50\\x6a\\x83\\x82\\xca\\x13\\x03\\xf2\\xe5\\xca\\xe4\\xf6\\x61\\xf9\\x34\\x3b\\x2d\\x19\\x82\\xd6\\x81\\xb5\\x39\\x04\\x20\\xf1\\x34\\xd3\\x2b\\x9f\\xe1\\xcb\\xc8\\x8c\\xe7\\x4a\\x93\\x28\\xe1\\x20\\xad\\xe1\\x89\\x58\\x55\\x0d\\xe3\\x0d\\x9d\\xac\\x16\\x76\\xa6\\xca\\x4e\\x55\\xc4\\xa0\\xb6\\x66\\x5a\\x61\\xbe\\x6c\\x39\\xa0\\x1d\\x2a\\xe6\\xca\\xaa\\xf9\\x6a\\x48\\xa8\\x43\\x54\\x43\\x42\\xbb\\x99\\x02\\xa9\\x9d\\x64\\xc1\\xd1\\xed\\x47\\xc1\\x70\\x01\\x92\\x6c\\x99\\x50\\x5c\\x6e\\x74\\x28\\x7e\\x70\\x9b\\x73\\x58\\xa9\\xf3\\x28\\x15\\x0a\\xdb\\x2f\\xa3\\x76\\x0c\\x60\\x01\\x04\\x5b\\x9a\\x3d\\xc0\\x22\\x66\\xe4\\x2b\\xbd\\x61\\xd7\\x3f\\xf8\\xa6\\x0f\\x84\\xe2\\x5b\\xa6\\x14\\x9d\\xb3\\x49\\xc3\\x40\\xc3\\x4d\\x16\\x19\\xc4\\x1a\\xca\\x85\\x81\\xad\\x90\\x54\\x7a\\x92\\x85\\x79\\x9b\\x55\\x35\\x88\\xa4\\x38\\x27\\xaf\\xfc\\x5c\\xe5\\x5c\\x6b\\x06\\x8b\\x0a\\xd8\\x7b\\x10\\x11\\xad\\x97\\xe6\\xef\\xd6\\xb2\\x3f\\xdf\\xba\\x41\\xca\\x1f\\x1b\\xa6\\x2e\\x62\\xcc\\xc5\\x9c\\x32\\x32\\xcd\\x39\\x9b\\x91\\x19\\x87\\x04\\x4f\\x48\\xb9\\x1c\\x22\\x14\\x13\\x45\\x2f\\x80\\x52\\xc6\\xde\\x95\\xc2\\xe9\\xb2\\x6e\\x5e\\x63\\xf2\\x8b\\x9d\\x98\\xce\\x0b\\x11\\xd1\\x00\\xe5\\x16\\x6a\\x4f\\xf9\\x8c\\xcc\\x21\\x65\\xd3\\x6a\\x8b\\x7f\\x7d\\xf1\\x8f\\xbf\\x93\\xe9\\xca\\x88\\x34\\xd0\\xac\\xb4\\xd4\\x34\\xf1\\x2f\\x99\\x30\\x31\\x37\\xb4\\xc2\\xe3\\x59\\xad\\x9e\\xf4\\x14\\x80\\x36\\x20\\x38\\xf1\\x97\\x5f\\x5f\\x4e\\xab\\x32\\x76\\x3f\\x66\\xcb\\xfd\\x80\\x7e\\xa3\\x44\\xce\\x37\\x35\\xce\\x6a\\x9e\\xcc\\xdd\\xd0\\x24\\xda\\xb0\\xcd\\xba\\xe9\\xf8\\xe8\\x30\\xc1\\xc8\\x42\\x5e\\xa1\\xae\\xbf\\x61\\xf7\\x94\\x85\\x58\\x99\\xcc\\x8a\\x04\\x9d\\xce\\xaf\\x7d\\xdd\\x71\\xa1\\xd8\\x7a\\x75\\xe0\\xc6\\x73\\x01\\x6e\\x52\\x3b\\x44\\x1d\\x51\\x1d\\x33\\x75\\xdd\\x23\\xa5\\xad\\x3a\\xb1\\x8e\\x3c\\x0f\\x0d\\x06\\x86\\xd0\\x6b\\x9a\\x24\\x53\\x1a\\x5d\\x5e\\xc8\\x37\\x72\\xae\\xde\\x89\\xe3\\x3c\\x97\\x79\\x75\\x2e\\x09\\x35\\xdc\\x72\\x51\\x88\\x4b\\x6c\\xfd\\xe0\\xc1\\x13\\xe4\\xdc\\x86\\x72\\x5d\\x89\\xc3\\xa6\\x17\\xc6\\x4a\\x7a\\xc7\\x84\\x9d\\x19\\x54\\x8e\\xc2\\xae\\x79\\x69\\xeb\\xd8\\x22\\x2e\\xdc\\x91\\xe1\\xf8\\x2a\\xdc\\x6c\\x5f\\xbf\\xf8\\xeb\\xb7\\xb8\\x75\\x89\\xcc\\xc9\\xb7\\x2f\\x20\\x9b\\x5b\\x0d\\xf1\\x10\\x03\\x6f\\x33\\x82\\x22\\xa5\\x49\\x62\\xcc\\x86\\x70\\x53\\x1a\\x42\\x6f\\xda\\x84\\x0f\\xbe\\x07\\x75\\xfb\\xed\\x76\\x67\\x55\\xea\\xe2\\xe2\\x57\\xd0\\xa3\\xb8\\x56\\x2c\\x99\\x0d\\xb1\\x5e\\xc9\\x9b\\x35\\xbb\\x20\\x18\\x76\\x2d\\xf7\\x81\\xa2\\xb1\\x2d\\x50\\x80\\x96\\x32\\x29\\x52\\x76\\xc4\\x96\\xbc\\x8b\\xee\\x7e\\x95\\xd1\\x9c\\xa9\\x9f\\x70\\x05\\xa5\\x61\\xd3\\x44\\x46\\x97\\x24\\xb6\\x5f\\x06\\xf9\\x2d\\x75\\x8c\\xf0\\xa7\\xdb\\xa8\\x35\\x7c\\xff\\x4a\\x6e\\x4f\\x4a\\xb3\\xcc\\x57\\x0f\\xe5\\xf4\\xaa\\x42\\x0c\\x38\\x93\\x00\\x64\\xf0\\xf4\\x1b\\xb5\\xe2\\x1b\\x19\\xbe\\xd9\\x78\\x88\\xc6\\x09\\x41\\xed\\x7d\\xd4\\xe5\\xec\\x3b\\x6a\\xc7\\x57\\x0e\\xe8\\x4e\\x43\\x06\\xff\\xc6\\x7a\\x93\\xb5\\x7a\\x49\\x5f\\x72\\xe7\\x37\\x06\\x2a\\x00\\x66\\xfb\\x00\\x4b\\x7e\\xb4\\x86\\xa2\\xa4\\x75\\x62\\x53\\x85\\x2e\\xe2\\x96\\x9e\\x76\\x94\\x64\\x2c\\x57\\x5c\\x19\\xb9\\xfc\\x33\\x1c\\x28\\x6c\\x66\\x58\\xba\\x00\\x1f\\x87\\x08\\x78\\xb8\\x01\\x58\\xb9\\x3d\\xa7\\x9c\\xc8\\xd8\\x0e\\x08\\xac\\x10\\x41\\xa5\\x37\\xa8\\xb5\\x55\\xad\\xb6\\x43\\x81\\xfa\\xd8\\xac\\xf2\\xe7\\x92\\x9a\\x55\\x4e\\x69\\x3e\\xf1\\xac\\x12\\xef\\x7a\\x4e\\x0c\\x12\\xde\\xef\\xa9\\xf2\\x47\\x3f\\xf9\\x8e\\xd8\\x00\\x30\\x46\\xbb\\xb8\\x55\\x4e\\x58\\x31\\x1e\\xf1\\xa0\\x04\\x2a\\xbd\\xb5\\x03\\xc7\\x04\\xa3\\xe0\\xe6\\x4c\\xd8\\x9f\\x92\\xdd\\x57\\xbb\\x8f\\xca\\x24\\x91\\x44\\xb9\\xcc\\xe8\\xbc\\x55\\x97\\x9f\\x1a\\xa5\\xea\\xc3\\x86\\x10\\x14\\xc6\\x0c\\x82\\xef\\x3d\\x20\\x1b\\xdc\\xc5\\xe2\\x12\\x61\\x07\\xf0\\x93\\x30\\x3a\\xea\\x08\\x6c\\x0d\\x04\\xac\\xd4\\xbe\\xa2\\x2b\\x42\\x73\\x59\\x88\\xd8\\xfa\\x97\\xbc\\x83\\xef\\x6d\\xed\\xc1\\xa7\\x52\\xb0\\xb2\\x6b\\x68\\x15\\xc1\\x02\\x3c\\xfa\\x5c\\x90\\x97\\xe3\\x97\\x2f\\x9e\\x8b\\xa4\\x82\\x37\\xac\\x49\\xaa\\x53\\x2f\\xa9\\x90\\x3f\\x3d\\xea\\xbb\\x3a\\x2c\\xfc\\x8e\\xde\\xf7\\xad\\x75\\xb1\\x94\\x50\\xf7\\xdc\\x01\\x69\\xc3\\x47\\x57\\x39\\xd7\\x2c\\x68\\x0e\\xb8\\x07\\x86\\x8b\\xb1\\x0f\\x03\\xbc\\x86\\xc1\\xa6\\x1e\\x13\\x2d\\x89\\xd4\\x0e\\x20\\x43\\x15\\xd3\\x2f\\xc8\\xb7\\x2c\\x83\\x82\\xe3\\xb6\\xc9\\xc3\\xa5\\x6e\\x61\\x61\\x21\\xa1\\x76\\x76\\xc8\\x1e\\xde\\xb9\\x8b\\xa5\\xce\\x83\\x47\\xdd\\x5a\\x96\\x68\\xc7\\xd7\\x59\\x0b\\xf4\\xcd\\x5a\\x55\\x7d\\x46\\xc1\\x07\\x97\\x75\\x48\\xc1\\x7f\\xb1\\x05\\x5d\\x32\\x28\\xf1\\xe6\\x09\\xcd\\x13\\x88\\x39\\x9e\\xe3\\xdc\\xc9\\xb4\\xd0\\x84\\x89\\x25\\xcf\\xa5\\x48\\x99\\xd0\\x04\\x72\\xe0\\xa7\\x09\\x0b\\x7b\\x63\\xff\\x79\\xef\\xe7\\x83\\x33\\x48\\x68\\x18\\x58\\xb0\\x0a\\x3b\\xcb\\x42\\x39\\x60\\x9b\\x70\\x26\\xc1\\x70\\x9f\\x5d\\x3e\\x37\\x0f\\x43\\x43\\xe0\\xb9\\x6e\\x5e\\xe6\\x39\\x69\\xa1\\x0b\\x6c\\xd8\\x72\\x1d\\x25\\x85\\xe2\\xcb\\xc7\\xe2\\x24\\xb6\\xf6\\xfe\\x88\\x37\\x5a\\xe7\\x1a\\x0e\\x40\\x49\\xa8\\xb5\\x92\\x7e\\x70\\xad\\x6f\\x28\\x03\\x5c\\x0b\\x98\\xec\\x2a\\x5f\\x1a\\x18\\xc6\\xc0\\xad\\xeb\\xc9\\xa2\\x6c\\x60\\xfa\\x9c\\xc3\\x62\\x5c\\x53\\x21\\x00\\x51\\xe6\\x71\\x9d\\x50\\x42\\xc6\\xec\\xfe\\x78\\x3c\\xd5\\xf4\\x1e\\x3b\\x04\\xc6\\xcc\\x83\\x3a\\x41\\x15\\x2d\\x58\\x5c\\x24\\xb6\\x9b\\x37\\xc0\\xa6\\x1a\\xf3\\x81\\x96\\xf8\\x7c\\x02\\xfa\\x07\\x9d\\xcc\\x3c\\xd8\\x81\\x18\\x81\\x73\\x10\\x69\\xee\\x7e\\x9f\\x3b\\x68\\x04\\xf7\\x81\\xaa\\x8d\\x08\\x46\\xa9\\x19\\x6b\\x48\\xa8\\x52\\x45\\x8a\\x47\\x02\\x5b\\x23\\xcc\\xb8\\x56\\x65\\xb3\\x70\\xab\\x1d\\x9b\\x83\\x71\\xcf\\xb2\\xad\\x16\\xf4\\x3d\\x67\\x09\\x6c\\xae\\x16\\x34\\xde\\x3d\\x0d\\xc6\\x41\\x42\\x2b\\xf7\\x97\\xdd\\x70\\x36\\x61\\x02\\xa2\\x6d\\x3e\\x8f\\x53\\x82\\x97\\x74\\xc6\\xa1\\xbd\\x12\\xb5\\xf4\\x3e\\xdf\\xf0\\x4b\\x54\\x1d\\xf0\\x0e\\x00\\x8e\\xa1\\x53\\x96\\xa8\\xfa\\x40\\xd3\\x72\\x51\\x2c\\x5e\\xa9\\x25\\x7c\\xcb\\xfe\\xb9\\x54\\x29\\x3e\\x17\\xd0\\x59\\xd3\\x8c\\x76\\xcf\\x1e\\x9a\\x8d\\x6d\\xa6\\x2e\\xfa\\xe3\\x36\\xe6\\x6a\\x95\\x2c\\xac\\x94\\x66\\xb6\\x11\\x3b\\xd5\\x32\\xe5\\xd1\\x3d\\x46\\x92\\xf7\\x9c\\x72\\xad\\x22\\xbb\\x52\\xe9\\xfb\\xee\\x7c\\xcd\\xe3\\xa3\\x02\\xaf\\xc6\\x98\\x9c\\xcb\\xd4\\xa6\\x38\\x89\\xa0\\xbf\\x97\\x6b\\xb3\\x6a\\x24\\x46\\xce\\x0c\\x2d\\x20\\xf1\\x88\\x97\\xd1\\x78\\xe8\\x87\\xe3\\x6a\\xad\\xe1\\x39\\x5e\\x25\\xb7\\x61\\x5c\\x00\\xa6\\xb4\\x6d\\x5e\\x65\\x92\\xc8\\x2b\\x48\\x2c\\xc6\\x71\\xdd\\xde\\x86\\x14\\x98\\x57\\x64\\x54\\xeb\\x59\\x3b\\xae\\xc2\\x89\\xde\\xfe\\x1c\\x7b\\xef\\xf0\\xf3\\x4f\\xc1\\xfc\\x1c\\x00\\xea\\x3b\\x39\\x0a\\xff\\x3c\\x99\\x1c\\x86\\x7f\\xbe\\x57\\x86\\x4a\\xf6\\x83\\xfa\\xd4\\xaa\\xfd\\x1a\\x6e\\xbe\\x2b\\x44\\xce\\xbe\\xe9\\xae\\x19\\xb6\\x3c\\xfa\\xcc\\xd7\\x87\\x0b\\x2a\\x5c\\x20\\xeb\\xc6\\xe7\\xad\\x54\\xa4\\x93\\x72\\x3a\\x0b\\x9a\\x33\\x8b\\x2c\\x67\\x38\\xb9\\xca\\x68\\x74\\xe3\\x2c\\x3c\\x8c\\xdb\\xad\\x37\\xdc\\x3a\\x53\\x55\\x64\\xae\\x53\\x77\\x02\\x37\\xfa\\x99\\x94\\xdb\\xee\\xc3\\x5f\\x7e\\xbb\\x23\\x31\\x3f\\xf7\\x9b\\x4d\\xa4\\xbd\\xfd\\x37\\x95\\x86\\x7e\\x77\\xfa\\xc5\\xe6\\x76\\x5f\\x77\\xfb\\x6d\\xd0\\x31\\xef\\x4e\\xf7\\xdf\\xd4\\xad\\xf7\\xae\\x4f\\x73\\x5d\\xde\\xee\\xf6\\x62\\xf5\\xd5\\xbe\\xc3\\xed\\xb0\\xa4\\xf7\\xc3\\x44\\x68\\xcc\\xc2\\x9b\\xba\\xbb\\x1a\\x38\\xa9\\x9a\\x3b\\xa7\\x9a\\x19\\xfb\\x35\\x05\\xe0\\x06\\x90\\x53\\x0b\\xc0\\x26\\xe6\\xa4\\x02\\x2b\\x55\\xe4\\x39\\x13\\xd0\\x2f\\xbf\\x80\\x4c\\x47\\xd7\\x07\\x1f\\x99\\x34\\x30\\x5b\\x0b\\xe1\\x89\\x38\\xf4\\xe4\\xc0\\xcb\\x42\\x9b\\x01\\x97\\x52\\x80\\xf5\\x0c\\x60\\xac\\x67\\x05\\x24\\x34\\x02\\xeb\\x47\\x98\\x3a\\x29\\xcc\\x3c\\x5e\\x6d\\xc2\\xe1\\x90\\x19\\x13\\x41\\x17\\x7c\\xab\\x35\\x8f\\xcc\\x1e\\xaa\\x20\\x73\\xa0\\x22\\x30\\x4e\\xe3\\x3f\\x65\\x09\\xd5\\x33\\x99\\xa7\\x23\\xa7\\x1e\\x8e\\x2a\\x4a\\x02\\x39\\x84\\xd4\\x1a\\xe5\\xec\\x2b\\xcc\\x6f\\x45\\xb8\\x4d\\x11\\x27\\x2c\\x90\\xe6\\xfe\\x55\\x45\\x8c\\xe0\\x54\\xa4\\x10\\x39\\x8b\\xe4\\x5c\\x40\\xe5\\xb1\\xfd\\x16\\xe4\\x9a\\x77\\x0e\\x51\\x65\\x24\\x29\\x11\\x45\\x92\\xdc\\x3f\\x0f\\xa1\\xa1\\x12\\x20\\x97\\x2c\\x5f\\x30\\x7a\\xcf\\xcd\\x5b\\x4b\\x69\\xb1\\x63\\x94\\x5d\\x49\\x95\\x45\\x2e\\xb0\\x2a\\xaf\\x7b\\x88\\x51\\x8d\\x65\\x04\\xb5\\x6d\\x18\\x62\\x77\\x89\\xcb\\x14\\x04\\xba\\xd1\\xf4\\x28\\x99\\xf3\\x25\\x13\\x0e\\x8c\\xfc\\x30\\xa1\\xbe\\xb3\\xb6\\xc3\\x5f\\xb5\\x80\\xe8\\x85\\x96\\x3e\\x69\\x81\\x50\\x1d\\x40\\x22\\x43\\x8e\\x93\\x8d\\x97\\x86\\xe3\\x04\\xb7\\xd8\\xbe\\xdc\\x89\\xeb\\x81\\x76\\x97\\x3b\\x21\\x6f\\x00\\x9b\\x42\\x0e\\xcb\\x57\\x4a\\x9d\\x6f\\xb5\\x82\\xb9\\x49\\x22\\xc8\\x6e\\x71\\xa6\\x88\\xcd\\x6a\\xf9\\xfc\\x23\\x6c\\x4a\\x9a\\xe1\\x41\\x9b\\x86\\xb1\\xea\\xb2\\x07\\x87\\x2d\\x09\\x9b\\x18\\xf6\\xbf\\x42\\x25\\xe7\\x64\\x56\\x7d\\x12\\xaf\\xc0\\xf1\\x43\\xed\\x13\\xa8\\xdf\\xa5\\x3d\\x38\\x91\\xb1\\xd1\\xc2\\x86\\xc4\\x2f\\x65\\xd8\\x96\\xdc\\xc6\\x5b\\xf0\\x4c\\x06\\x87\\x11\\x95\\xb4\\x3c\\x67\\x2a\\x93\\xd8\\x15\\x20\\x7c\\xec\\x30\\xf0\\x7f\\x71\\x5d\\x49\\xb6\\xc3\\xfe\\x6e\\xfe\\x68\\x20\\x6e\\xdb\\x7f\\x58\\x2e\\x37\\xea\\xf0\\x73\\xae\\xc7\\x97\\xdf\\x82\\x02\\xcf\\xc4\\x82\\x8a\\x08\\x6d\\xa7\\xfd\\x4b\\x96\\xa9\\x7d\\xc5\\xe7\\xa8\\xaf\\xff\\xfd\\xdb\\x6f\\x41\\x79\\x77\\x24\\xd9\\x3f\\x3b\\x3e\\x38\\x7a\\x7b\\x3c\\x4e\\xe3\\x27\\xa4\\xc9\\x67\\x54\\x6b\\x96\\x8b\\x57\\xe4\\xbf\\xf6\\x3e\\x7e\\xf5\\x69\\x34\\xf8\\x7e\\x6f\\xef\\xc3\\x8b\\xd1\\x3f\\x7e\\xfb\\x6a\\xef\\xe3\\x18\\xfe\\xf1\\x97\\xc1\\xf7\\x83\\x4f\\xee\\x8f\\xaf\\x06\\x83\\xbd\\xbd\\x0f\\x3f\\xbd\\xfd\\xe1\\x62\\x72\\xfc\\x1b\\x1f\\x7c\\xfa\\x20\\x8a\\xf4\\x12\\xff\\xfa\\xb4\\xf7\\x81\\x1d\\xff\\x76\\xc7\\x41\\x06\\x83\\xef\\xff\\x7c\\xcf\\x89\\x36\\xac\\x4b\\x69\\x5b\\x8b\\xd2\\xaa\\xfe\\xa4\\xc3\\x9a\\x93\\x2c\\x67\\x2c\\x05\\xf6\\xd7\\x24\\x5b\\xab\\xea\\x25\\xad\\x0d\\xe5\\x04\\xac\\xfd\\xcb\\xf0\\x44\\xf7\\x34\\x31\\x37\\x6c\\x52\\x21\\xeb\\x4c\\xe4\\x15\\x64\\x58\\x72\\x69\\x94\\x9f\\x31\\x79\\x07\\x72\\x90\\x9c\\xb2\\x25\\xcb\\x87\\x6e\\xd4\\x37\\xe6\\xa6\\x89\\xbf\\x27\\x74\\xc3\\x6d\\xba\\xa3\\x61\\x8e\\x7f\\xc3\\x35\\x71\\x73\\x6f\\x41\\x3c\\xec\\x68\\x62\\x27\\x0f\\xfc\\x69\\x4c\\x7e\\xa6\\x39\\x97\\x85\\xb2\\xba\\x48\\x08\\x04\\x8e\\x29\\x64\\x5e\\x92\\x80\\x57\\xc2\\x06\\x78\\xfc\\x20\\xbe\\x32\\xcc\\xc5\\x78\\x3c\\x6d\\x0e\\x3c\\xbf\\x3e\\xdc\\x2c\\x12\\xb8\\x36\\x2b\\xb5\\x74\\x8f\\xca\\x5d\\xaa\\xeb\\x1a\\x86\\x38\\x0a\\x83\\x8d\\xfc\\xdf\\x49\\x34\\x15\\x4e\\x14\\x86\\x71\\xf3\\x00\\xde\\x7a\\x6a\\x91\\x4d\\x18\\x59\\xf0\\xb9\\x4b\\xa8\\x86\\xf7\\x47\\xf3\\x35\\xf8\\xd4\\xef\\x90\\x06\\x4b\\xda\\xe4\\x98\\x36\\xcd\\xeb\\xcf\\xea\\xef\\xd7\\x62\\x5b\\x54\\x91\\x96\\x43\\xb0\\x66\\x57\\x51\\x54\\x9e\\x9b\\x1d\\xdc\\x27\\x20\\x44\\x46\\x51\\xce\\x35\\x8f\\x68\\xb2\\x03\\xc2\\xc9\\x7d\\x15\\x25\\x85\\xd1\\x13\\xc3\\x6f\\x73\\x46\\xf4\\x95\\xc4\\xa7\\xd0\\x84\\x5c\\xb2\\xd5\\x95\\xcc\\x63\\x27\\x9f\\xdd\\x13\\xcb\\xb5\\x50\\xda\\x3d\\x92\\x33\\x7b\\x80\\xd1\\xcd\\x90\\xa7\\x2c\\x27\\x53\\xe6\\x3c\\xe8\\xb5\\x9b\\x57\\x63\\x72\\x20\\x56\\x36\\xfc\\x28\\xc2\\x22\\xc3\\x00\\xff\\x0d\\x74\\x04\\xd4\\xa2\\x2a\\x9b\\xc4\\x0a\\x31\\xf7\\x34\\xaa\\x2d\\x20\\xce\\x66\\xef\\xb2\\x51\\xc0\\xfc\\x29\\x70\\xd2\\xdf\\xb9\\x97\\x65\\x6e\\xab\\x9c\\xe0\\x74\\xe4\\x58\\xa3\\x25\\xdd\\xd7\\x0f\\xc2\\x2d\\x8c\\x7e\\xc3\\x05\\x53\\xea\\x07\\xb3\\x94\\x6d\\xd4\\xd5\\xea\\xee\\xa0\\xa0\\x96\\xd8\\xb1\\xa1\\x52\\xaa\\x4c\\x29\\x66\\xe6\\x48\\x61\\x8c\\xd8\\xb0\\x61\\x19\\x97\\x77\\x8e\\xc9\\x01\\x7c\\x00\\x39\\xf1\\x46\\xf3\\x82\\x2a\\x3a\\x33\\x18\\xd7\\xaa\\xde\\x76\\x1e\\xef\\x38\\x38\\x3d\\x72\\xb9\\xcb\\xa8\\x29\\xa8\\x2a\\x90\\x3a\\xaa\\xcc\\xd5\\x99\\x80\\xa6\\x67\\x33\\x68\\xd9\\xbf\\x0b\\x0a\\x1d\\x74\\x77\\x2e\\xf2\\x82\\xed\\x34\\x53\\x95\\x10\\xa2\\x7f\\xff\\x6f\\xdf\\xbe\\x00\\x6d\\xc9\\x3f\\x6f\\x04\\xcf\\x6b\\xa2\\x2a\\xdd\\x3f\\x47\\xa6\\x51\\x76\\x4c\\x3d\\x31\\xe8\\x2c\\xdc\\x0f\\x8e\\xe0\\xce\\xee\\xb0\\x41\\x2b\\xa8\\xed\\x85\\x65\\xf2\\x34\\x6f\\xe4\\x5a\\x6d\\x94\\x0b\\xd3\\x3c\\x0b\\x66\\x54\\x4e\\xf7\\xe2\\xfe\\xdd\\xcd\\xda\\x24\\xb0\\x54\\x9e\\xdb\\x45\\x94\\xab\\x1c\\x0d\\x57\\x45\\xe1\\x92\\xf8\\xe7\\x04\\x9e\\x5d\\x6c\\x82\\x61\\x3f\\x86\\x74\\x58\\x60\\x5c\\x10\\x15\\x00\\xf6\\xb8\\xca\\x5a\\xa4\\xfe\\x36\\xe0\\x37\\x68\\xbc\\x42\\x5a\\x5d\\x2b\\xff\\xf6\\x59\\x65\\x24\\xcb\\xb9\\x9d\\xa8\\xa8\\x7d\\xe9\\x6b\\xc8\\x6d\\xc2\\xb4\\xab\\xcd\\x01\\xf0\\x29\\x8f\\x1a\\xe3\\x60\\xfe\\xa1\\x1f\\x8a\\x6f\\xf9\\x01\\x95\\x39\\xa8\\x15\\xb8\\xc9\\xab\\x20\\x39\\x32\\x66\\x84\\x2e\\x29\\x4f\\xb0\\x0f\\x8a\\x31\\xe9\\xa4\\xaa\\x38\\xd9\\x71\\x42\\x91\\x14\\xaa\\x48\\xe1\\x19\\xa9\\x91\\x2e\\x28\\x33\\x3e\\x8a\\xb2\\x26\\x55\\x60\\x13\\x96\\x5b\\xab\\x52\\xcd\\x0c\\x8f\\x56\\x82\\xa6\\x3c\\x72\\x6f\\x78\\x90\\xb8\\xc6\\x6f\\xb5\\xba\\x54\\x37\\xb6\\x77\\x93\\xf3\\x34\\x2d\\xb4\\x99\\xe6\\x3d\\x51\\x4d\\x1f\\x99\\x1f\\x05\\x0b\\x19\\xc6\\xcd\\xd9\\x35\\x8d\\x74\\xb2\\x02\\x47\\x55\\xf5\\x26\\xbd\\xc8\\x65\\x31\\x5f\\x10\\x4a\\xe0\\xef\\x73\\xf8\\x6a\\x4c\\x4e\\xb4\\xb1\\x25\\xa1\\x59\\xbb\\x85\\x6b\\xe0\\x1a\\xe5\\x77\\x21\\xf8\\xbf\\x0b\\x96\\xac\\x08\\x87\\x7e\\x42\\x3e\\x66\\x52\\x1d\\x36\\x40\\x8f\\x87\\x4e\\x33\\x41\\x77\\x1b\\xd4\\x02\\x18\\x8b\\x1d\\xe4\\x81\\x35\\xed\\x6f\\x98\\x3c\\xda\\xed\\xa0\\x3d\\x18\\x81\\x4f\\xef\\x9f\\xc4\\xf3\\x48\\xfc\\xb3\\x41\\xf6\\x5f\\x1b\\xb6\\xd9\\x34\\x93\\x6a\\x1d\\x8b\\x6d\\xf3\\x0a\\xf3\\x20\\x7c\\x1c\\xd5\\xd7\\x18\\x4c\\x95\\x32\\x01\\x0b\\x1a\\x35\\x1e\\x9d\\x9e\\xff\\xfe\\xe6\\xe0\\x5f\\xc7\\x6f\\x1e\\xbc\\x96\\x04\\x67\\xd9\\x9a\\x18\\x78\\x16\\x82\\x9c\\x57\\xdb\\xff\\x2c\\x30\\xd9\\x2a\\x7b\\xb6\\xf9\\x7b\\x3e\\x5a\\x13\\x8e\\x8a\\x80\\x69\\xd3\\x8f\\xa8\\xda\\xc7\\xb9\\x3e\\x6a\\xdd\\x61\\x4f\\x6b\\x87\\xdd\\x1a\\x09\\x56\\x0e\\x03\\xa8\\xa5\\xf0\\xf1\\x37\\x5a\\xa6\\x39\\xb4\\x2b\\xfb\\x6f\\x91\\x61\\x55\\xa1\\xd3\\x05\\x4b\\x33\\x63\\x1f\\x77\\x46\\xaf\\xaa\\x74\\x0e\\x87\\xff\\x0c\\xe1\\xdc\\xad\\x77\\x27\\x20\\x0a\\x3a\\x46\\xb4\\xfb\\x65\\x98\\xb4\\x03\\x79\\xa7\\xe8\\xec\\xa5\\x44\\xb0\\xab\\xea\\xc3\\x5c\\x4a\\x8f\\xfb\\xc5\\x54\\x16\\xc2\\xf6\\xc4\\x77\\x83\\xff\\x82\\x28\\x1e\\x36\\x27\\x05\\x10\\xc2\\x13\\xa6\\x9d\\x75\\x57\\x5d\\x73\\x5b\\x6d\\x8e\\x8d\\xa2\\xec\\x7d\\xa8\\x38\\x84\\x61\\x9d\\x0d\\xbf\\x99\\x32\\xf2\\x1d\\x40\\x9c\\xd0\\x94\\xfd\\x73\\xf4\\x9d\\x67\\x4a\\xf0\\xf7\\xd0\\x1e\\xd2\\xda\\xc7\\xa5\\x43\\xab\\x2a\\x23\\xc7\\xe8\\xc4\\x80\\x1c\\x7f\\xdb\\x1f\\x4d\\x8a\\x8a\\x03\\xdc\\x99\\xa5\\xdc\\xe7\\x03\\x18\\x95\\x48\\x80\\x5a\\xe4\\x9a\\x49\\x1a\\x4b\\x16\\x7e\\x6e\\xa3\\x07\\xd5\\x49\\xef\\xb1\\xf1\\x7c\\x4c\\xb4\\x94\\x00\\x4d\\x82\\x58\\xeb\\x07\\x82\\xb0\\x6b\\xae\\xc0\\x62\\xae\\xbf\\x62\\x68\\x28\\xdb\\xf4\\x1d\\x7c\\x84\\xbc\\x12\\x55\\xa0\\x10\\x2c\\x5d\\xb6\\x29\\x53\\xca\\x5a\\x88\\x41\\x9a\\x0a\\x5d\\x4a\\xee\\x52\\xe3\\xa8\\x80\\xe0\\x0f\\x46\\x2a\\x3c\\x71\\xa6\\x2b\\x92\\x72\\x05\\x4d\\x72\\x00\\x4f\\x31\\x2e\\x12\\xbc\\x39\\x46\\x24\\x12\\x84\\x27\\x43\\x57\\x83\\x59\\x5b\\x28\\x86\\xaa\\x54\\x66\\x97\\x83\\xd6\\x14\\x00\\x23\\x2e\\x52\\xb9\\x64\\xf1\\x6d\\xca\\x95\\xed\\x8d\\x02\\xe5\\xf5\\xf3\\xba\\xa6\\xe8\\x4b\\x2c\\x2a\\xde\\xfd\\xca\\x53\\x82\\x82\\xb4\\x5c\\x26\\x24\\x4b\\xa8\\x60\\xb6\\x46\\xdf\\x7b\\x24\\xd6\\xf9\\x74\\x53\\x9c\\xfa\\x6e\\x72\\x5c\\x8c\\x59\\x01\\x89\\x2e\\x97\\x6c\\x75\\x6f\\xb6\\xdd\\x40\\xad\\x58\\x7f\\x38\\xbe\\x47\\x4a\\xb3\\xfb\\x99\\x22\\x66\\x33\\xb4\\x76\\x35\\xef\\x9e\\xe1\\x40\\x24\\x2b\\x7d\\xcb\\x6b\\xc5\\xd4\\x3e\\xd9\\x14\\xb8\\x8a\\xf5\\x2a\\x1f\\x00\\x32\\xc5\\x90\\xbc\\x13\\xaf\\xb1\\x54\\x77\\x88\\x8e\\xe6\\x31\\x39\\x11\\x44\\xc9\\xd4\\x96\\x08\\x5f\\x6b\\x35\\xc4\\x66\\x8c\\x94\\xa8\\x62\\xaa\\x98\\xed\\x76\\x67\\x0c\\x0d\\x1b\\xf1\\xb4\\x21\\xdd\\x8c\\xe5\\x29\\xd7\\x61\\x6a\\xaf\\xd9\\x72\\xf8\\x98\\x4e\\x31\\x4f\\xf6\\xff\\x64\\xa9\\x37\\xc2\\x97\\x6e\\xe2\\xe1\\xb8\\xbf\\xed\\x18\\x84\\xc1\\x5a\\xba\\x32\\x77\\xcf\\x6a\\x63\\x55\\xec\\xe8\\x4a\\x98\\xaf\\x2a\\x88\\x20\\x25\\x0e\\x7d\\x41\\x64\\x9e\\xcb\\x22\\x73\\x32\\xa4\\xda\\xaf\\xb9\\x6c\\x52\\xe8\\x04\\x09\\xfa\\x07\\xab\\x43\\x7b\\xa6\\x05\\xd6\\x38\\x2b\\x05\\x63\\x6c\\xf4\\x51\\xa5\\x86\\x1b\\xf9\\x62\\x5e\\x08\\xd7\\xdb\\x98\\x81\\x0f\\x31\\x48\\xac\\xdc\\x49\\xd8\\x9c\\x46\\xab\\x9d\\xea\\x73\\x36\\xa5\\xb1\\xa2\\xc9\\xc9\\x53\\xec\\x0b\\x85\\xcf\\x2b\\x0b\\xb4\\xa1\\x8e\\x1b\\x4c\\x6a\\x74\\x1c\\xa0\\x9d\\xa4\\xec\\x14\\x9d\\xff\\xd2\\x21\\x8c\\x60\\x98\\x3e\\x6f\\x11\\x66\\xfc\\xdb\\xb7\\x7f\\x1b\\xb9\\x44\\x02\\x98\\xca\\x83\\x6c\\x28\\x9f\\x86\\xda\\xa9\\x63\\xbc\\xb2\\x66\\x46\\x13\\xe0\\x2a\\x83\\xf5\\x05\\x49\\x57\\xfa\\x26\\xfd\\xd3\\x6f\\xf3\\x1d\\x6f\\x1e\\xc4\\x2d\\x40\\x39\\xc4\\x03\\x92\\x8b\\x8b\\x79\\x5b\\x67\\xf1\\xce\\x79\\x75\\x28\\xbb\\x1b\\x65\\x46\\xff\\x5d\\x94\\x45\\xdb\\x96\\xb7\\xa1\\xc2\\x10\\x90\\xd8\\x12\\x05\\xaa\\x98\\xcb\\x39\\x95\\xdc\\xd5\\x2c\\xc7\\xfa\\xf8\\x86\\xc0\\xc1\\x49\\xf1\\xc4\\x55\\x9a\\xae\\xdc\\xe9\\xae\\x4e\\x0b\\xb4\\x05\\xcd\\x7c\\xb9\\x52\\x99\\xb5\\xec\\x8f\\x23\\xd5\\x46\\xed\\xac\\xe7\\x44\\x33\\xaf\\x98\\xd6\\xdf\\x33\\x32\\x6f\\x19\\x74\\xe6\\xa7\\x1a\\xfd\\xa8\\x20\\xd9\\x6d\\x8e\\x05\\x62\\xd3\\x40\\x9b\\x49\\xd0\\x36\\x2c\\xeb\\x37\\x2a\\xc0\\x15\\xcd\\x63\\x55\\x75\\x1b\\x59\\x28\\x33\\xeb\\xfa\\xb1\\x51\\x33\\xa7\\x45\\x4c\\x64\\x5c\\xce\\xc0\\xbb\\x76\\xab\\x8e\\xa2\\x27\\xe4\\x0c\\xaa\\x52\\x13\\x5e\\xbf\\xcc\\x7c\\x01\\xce\\x3d\\x41\\x35\\x71\\x5e\\xd0\\x3c\\x86\\x90\\x41\\xb9\\x11\\x7a\\x1f\\xcb\\xa6\\xab\\x3b\\x1f\\x8b\\xeb\\xf6\\x54\\x1e\\x48\\xf4\\x43\\x1e\\x03\\xd6\\x53\\xf5\\xd3\\xa0\\x19\\x33\\xb5\\xce\\x19\\x34\\x0e\\x1a\\xf7\\x39\\xff\\x23\\x2b\\xb2\\xb5\\x54\\xcd\\x36\\x6a\\x51\\xbd\\xeb\\xf0\\x42\\x26\\x31\\x28\\x30\\xb6\\x37\\xb8\\x7b\\x94\\x61\\x7c\\x39\\x9f\\x16\\xda\\xe6\\xe2\\x45\\x32\\x4d\\xab\\xc0\\x5c\\x18\\x9e\\x57\\x63\\x52\\x22\\x33\\x85\\x79\\x12\\xc0\\x89\\xc7\\x84\\x9c\\x33\\x06\\x6b\\x17\\xce\\x03\\x34\\x68\\x27\\xe2\\xac\\x10\\x90\\x33\\xc2\\xcc\\x46\\xc2\\x0d\\xf2\\x40\\xb9\\x47\\xcd\\x0f\\x96\\xcd\\xd8\\x6e\\x99\\x1a\\xba\\x73\\xe0\\x43\\xe1\\x61\\x62\\x35\\x2a\\x9e\\x28\\x17\\x69\\x96\\x25\\x1c\\xeb\\xf8\\x6b\\x36\\x07\\xd4\\xac\\x97\\xa9\\xfd\\xb6\\x84\\xcd\\xd0\\xc2\\x86\\x37\\xe0\\xb8\\xfe\\x54\\x4c\\x59\\x82\\xc9\\x68\\x68\\xb1\\x62\\x02\\xdc\\x95\\x19\\x62\\xc1\\x33\\x3c\\xd5\\x54\\xfb\\x9f\\x83\\x6f\\xa3\\x6e\\xb6\\xbf\\x32\\x12\\xe9\\x25\\xba\\x3a\\xe4\\x15\\xa4\\x1e\\xfe\\x70\\x72\\xe4\\x75\\x17\\x73\\xd7\\xeb\\x73\\xcc\\x1b\\xff\\x1a\\xef\\x52\\x4c\\xcf\\x79\\x4c\\xa6\\x58\\x1d\\x64\\x24\\xe1\\x9e\\x60\\x57\\x88\\x37\\x60\\x1d\\x36\\x3e\\x78\\xbb\\x74\\x75\\xf8\\x38\\x9a\\x7f\\xb8\\x1d\\x72\\x40\\xbe\\xc1\\x31\\xc1\\xf8\\xc1\\xd4\\x8f\\x29\\xb7\\xf5\\xc8\\xef\\xce\\x76\\x5d\\x4e\\xe4\\xd5\\x28\\xbf\\x1a\\x8d\\x46\\x23\\x5b\\x44\\x00\\xda\\xf3\\xb0\\x42\\x03\\x2f\\xd5\\x53\\x19\\xf3\\xd9\\xaa\\x46\\x09\\xf0\\x20\\xf8\\x47\\xc0\\x8e\\xa4\\x62\\x65\\x67\\x37\\x26\\xa7\\x52\\x33\\x87\\xa1\\xe1\\x1d\\x03\\x65\\xcf\\x64\\xf3\\x8a\\x10\\xcb\\x86\\x54\\x6b\\xa9\\xc6\\xce\\xd3\\xe2\\xd2\\x74\\xef\\x6f\\xc1\\xb7\\xcb\\xf9\\x6a\\x83\\xf9\\xb9\\xa1\\x1e\\xa1\\x6d\\x12\\xf4\\xa6\\x12\\x07\\x17\\xd2\\xf3\\x0d\\xfa\\xe4\\x0c\\x37\\x29\\x40\\x34\\xdc\\xb0\\x30\\x4e\\x0e\\xd9\\x5d\\x63\\x43\\x7b\\x98\\x0a\\xc2\\xae\\x33\\x89\\x4d\\xad\\xc0\\xcd\\x3f\\x91\\xf1\\x7a\\x0e\\x2c\\x2a\\x5b\\x59\\x86\\x95\\x9c\\x95\\x53\\x63\\x0d\\x3d\\x4c\\xbb\\x76\\x44\\x20\\x53\\x6a\\x86\\xf4\\xd3\\xd9\\xab\\xed\\x93\\x01\\x44\\x9e\\x60\\x68\\x90\\x77\\x42\\x12\\x36\\x9b\\x19\\x8b\\x52\\x0a\\xc2\\xb2\\x05\\x4b\\x59\\x4e\\x93\\xea\\x83\\x2c\\x14\\xdc\\x2b\\xc3\\x6e\\x73\\xb3\\x4b\\x31\\xcf\\x34\\xa5\\x19\\x72\\x5b\\x60\\x9e\\x31\\xcf\\x01\\x52\\x97\\x57\\xf2\\xbf\\x77\\xde\\x89\\x33\\x29\\xf5\\x5b\\xae\\xc0\\xa6\\xb4\\x19\\x37\\xe8\\x01\\xd8\\xd9\\x64\\x68\\xb8\\xef\\xca\\xba\\xfa\\xb6\\x3b\\xf9\\xc1\\x92\\xac\\x09\\xfa\\x04\\x0e\\x3a\\xe1\\xb5\\x86\\x83\\x18\\xa6\\xe5\\x0d\\x77\\xa3\\x4c\\xeb\\x7c\\x95\\x49\\x2e\\xf4\\x3a\\x5a\\x8e\\x07\\x59\\x7e\\x6f\\x91\\xa2\\xc1\\x10\\x76\\x42\\xcb\\x27\\xfc\\x91\\xb7\\x74\\xe5\\x5d\\xc2\\x36\\x8f\\xb9\\x26\\x63\\xd1\\x35\\x60\\xbf\\x03\\x0c\\xb7\\xba\\x10\\x36\\x4b\\x38\\x01\\xe4\\xe0\\xf0\\xe3\\x61\\x90\\x3d\\x5c\\x49\\x78\\xa9\\xff\\x5c\\xd3\\x4b\\xa6\\x48\\x96\\xb3\\x88\\xc5\\x10\\x7e\\x44\\x9f\\x2a\\xd5\\x15\\x48\\xf6\\x96\\x8b\\xfe\\x84\\xb8\\x17\\x6c\\x99\\x53\\x09\\xe7\\xa4\\xe5\\xa6\\x39\\x09\\x72\\xe0\\x2c\\x7a\\x52\\xb9\\x45\\x40\\xc7\\x35\\x7b\\x89\\x42\\xd0\\x59\\x8a\\x11\\x34\\x10\\x2f\\x94\\xcb\\x8e\\xcf\\x5d\\x5e\\x61\\x45\\x00\\x59\\xaf\\x3d\\x8a\\x4d\\xa8\\x23\\x36\\x56\\xa2\\xdb\\x61\\x46\\x75\\x12\\xaa\\xc8\\x99\\x2f\\x83\\x8d\\x25\\x2b\\x9b\\x89\\x53\\x45\\xde\\x9f\\x1c\\x91\\x17\\x64\\x0f\\x4a\\xc0\\x3d\\x0c\\xa0\\x4f\\x64\\xa8\\xd7\\x29\\xcf\\xdc\\x10\\x55\\x97\\x92\\x45\\x1d\\x15\\x12\\x79\\x51\\x3d\\x92\\x80\\xae\\x46\\x48\\xb3\\x8b\\xb7\\x72\\x8f\\x37\\xdd\\x8f\\xcd\\x80\\x1e\\x7c\\x29\\x55\\x07\\x3c\\xe8\\x7d\\x03\\x1e\\x14\\x2a\\xd6\\x66\\x7b\\x55\\x69\\x85\\x7b\\x28\\x65\\x9a\\x02\\xa2\\x2d\\xf2\\x26\\x77\\xc3\\x56\\xae\\xde\\x1f\\x9d\\x43\\x55\\xab\\x21\\x3b\\xd8\\x54\\xe7\\xc7\\x30\\xa0\\x0b\\x27\\x58\\x35\\x1e\\x6d\\x87\\x78\\xdd\\x76\\x70\\xbc\\xe0\\x33\\x40\\x09\\x2e\\xe0\\xe9\\x41\\x28\\x73\\x2a\\x62\\x99\\xae\\x3d\\xcd\\xac\\x26\\x18\\x6f\\xc1\\x6a\\xf6\\xdb\\xee\\xa6\\xab\\x55\\xfe\\x44\\xbb\\xec\\x09\\xb0\\xf1\\x3b\\xc0\\x57\\x7b\\x03\\xbe\\x02\\xae\\xfc\\x4e\\x40\\xe7\\x01\\x20\\x0f\\xac\\x99\\xad\\xad\\xe1\\x37\\x5b\\x27\\x43\\xe4\\x32\\x69\\x98\\xf5\\x50\\xcd\\x11\\x91\\x89\\x45\\xca\\x70\\xaf\\x6d\\x06\\xde\\xda\\xb7\\xd6\\x0d\\x73\\x51\\xeb\\xec\\x65\\x95\\xd5\\xde\\x1a\\xdc\\x39\\xdb\\xfa\\xd6\\x45\\x23\\x29\\x4d\\xea\\x6f\\x0d\\x75\\xd3\\x95\\xb7\\x06\\xb9\\xbb\\x8d\\x6f\\x5d\\x2d\\x93\\xef\\x40\\x98\\xd8\\x01\\x89\\xb4\\xc5\\xfa\\xb6\\x5d\\x65\\x1d\\x49\\xb7\\x2c\\xc3\\x05\\x27\\xd4\\xd3\\xe2\\xa3\\x6d\\xb0\\x16\\xb1\\x9a\\xee\\xa1\\x59\\xb7\\x8c\\x68\\x02\\x88\\x16\\x4d\\xd7\\x99\\xd4\\xd7\\xba\\x3e\\x64\\x50\\xf1\\x43\\xcd\\x6c\\xe1\\xb3\\xa0\\x6e\\x95\\x22\\x0c\\xb8\\x2c\\x03\\xe5\\xb5\\xa0\\xb8\\x75\\xd3\\xd9\\x5f\\xba\\xb4\\x4a\\x23\\x7f\\xcb\\x32\\xda\\xf0\\xd7\\x5a\\x02\\x8a\\x53\\xd9\\x6e\\x90\\xc2\\x04\\x19\\xa6\\xcd\\x64\\x54\\x2f\\x86\\x04\\x52\\x75\\xf8\\xd2\\xa7\\xd6\\x5c\\xa2\\x29\\xb5\\x5b\\xa9\\xcd\\x75\\x3b\\xd6\\x3d\\xda\\x65\\x4c\\xdb\\x91\\xc3\\x80\\x1c\\x9f\\x21\\xff\\xe2\\x8a\\xec\\xbc\\x71\\x04\\xd8\\x79\\xca\\x0c\\x7a\\x07\\xdf\\xc7\\xaf\\x1d\\x7a\\xb1\\x2e\\xb9\\x88\\x6d\\x6b\\x9d\\x0a\\x69\\x7c\\x1d\\x38\\xea\\x86\\xce\\xc3\\xe4\\xce\\x3a\\xcd\\x19\\x38\\x7b\\x3d\\x69\\xc8\\xa8\\xf1\\x66\\xb0\\x29\\x0a\\x2e\\x51\\x65\\x74\\x83\\x92\\xe9\\x7c\\x2a\\xee\\x21\\xf5\\x61\\xde\\x0b\\x58\\x69\\x01\\x20\\x1b\\x42\\x6e\\xb8\\xcf\\xbd\\x4b\\xb3\\x24\\xa9\\x36\\xac\\x77\\x0d\\x0d\\xa5\\x25\\xfb\\x3d\\xf0\\xb1\\xf1\\x39\\x82\\xab\\x04\\x2a\\xbc\\xf6\\x4d\\x4f\\xac\\x5d\\x08\\x36\\x24\\x17\\x35\\xd5\\x7b\\x08\\xab\\x63\\x8b\\xaa\\xd7\\xa4\\x13\\xd6\\xf0\\xa5\\x34\\x5f\\x91\\x1f\\x4e\\x8e\\x2c\\x68\\x8f\\x75\\x74\\xee\\x85\\x31\\xf8\\x01\\x46\\xa9\\x31\\x12\\x91\\xb2\\x74\\x8a\\xde\\x4f\\xb5\\x5e\\xc8\\x5e\\x81\\x44\\xf3\\xf9\\x7c\\x05\\x8f\\x6f\\x31\\x68\\xeb\\xe6\\x87\\x90\\x21\\x06\\x84\\x7b\\xf7\\x1c\\x90\\x21\\xac\\x01\\x23\\x56\\x9b\\xb5\\xf6\\x2f\\x32\\x43\\xec\\x03\\xa7\\xcd\\x59\\x41\\x67\\x2e\\x5f\\xb2\\x21\\x61\\x4b\\x26\\x6c\\x56\\xe5\\x0a\\xee\\x30\\xb2\\x8d\\x8b\\x28\\x29\\x62\\xf7\\x38\\xe8\\x71\\xa0\\xf4\\xa3\\x89\\xc3\\x66\\xc8\\xcb\\x8d\\x71\\x97\\xdb\\x76\\xb4\\x6a\\x65\\x44\\x23\\x12\\x52\\xcb\\x13\\x77\\x6e\\xf1\\x94\\x16\\x32\\x89\\x09\\xf5\\xc7\\xcf\\xa7\\x22\\xc7\\xee\\x39\\x6b\\xe9\\xaa\\x90\\x83\\x6b\\x53\\xaa\\x0a\\x51\\x82\\xb5\\xb8\\xfb\\xf7\\xea\\x0a\\x93\\xe3\\x78\\x03\\x0b\\x31\\xe8\\xfc\\x76\\x09\\x2d\\x44\\xb4\\xf8\\xa3\\x6c\\x99\\x0d\\xd4\\xf7\\x81\\x20\\x4a\\x2e\\x59\\x2e\\x58\\x42\\x32\\x9a\\xd3\\x94\\x41\\x9b\\x1b\\xe7\\x40\\x78\\xf8\\x4a\\x85\\x76\\x78\\xdc\\x2d\\xb0\\xb4\\x47\\xe8\\xdc\\x78\\x84\\xe2\\x8a\\x36\\xd8\\xc6\\x1b\\x33\\x46\\xa8\\x9b\\x12\\xf6\\x6a\\x6c\\xb4\\x8c\\xa4\\x8b\\x72\\x08\\xa0\\x68\\x27\\xaf\\x86\\x5d\\x2e\\xb7\\xe3\\xdd\\xaa\\xf0\\x79\\x1d\\xd8\\x7e\\xbf\\xe0\\x80\\x25\\xce\\xa7\\xcb\\xf3\\xb8\\xaf\\x33\\xd1\\x29\\x94\\xeb\\xe8\\xfa\\xbb\\x6a\\xcd\\x51\\x57\\x6d\\x45\\xfa\\xc0\\x91\\x84\\xc6\\x7c\\x17\\xa0\\xb8\\x9e\\x94\\xff\\x6f\\x9e\\x2a\\x7a\\x98\\x33\\xa8\\x91\\xa3\\xc9\\x79\\xc6\\xa2\\x0e\\xec\\x8f\\x1f\\xde\\x9e\\x1f\\x54\\x07\\x05\\xa1\\x84\\x85\\x67\\x0b\\x06\\xdf\\x07\\xa8\\x1d\\x57\\x6c\\xba\\x90\\xf2\\x92\\xec\\x6d\\x40\\x1e\\x0b\\x92\\xa5\\x14\\x9f\\xab\\x7d\\xbb\\xbd\\x47\\x66\\xde\\x03\\xc2\\x05\\xb4\\x88\\xf2\\x42\\xd5\\xb7\\xd6\\x72\\x0f\\x89\\xfc\\x2c\\x60\\xad\\x6c\\xa6\\xb5\\x15\\xc3\\xeb\\xd3\\x3c\\x6d\\x95\\x90\\xd6\\x9a\\x27\\xad\\x2f\\x46\\xf3\\xea\\xac\\xcf\\x2c\\xc8\\x4d\\x08\\x74\\x1b\\xa9\\x86\\xee\\x9e\\x47\\x21\\x89\\x75\\x46\\x18\\x0d\\xbc\\x03\\x3a\\xfc\\x58\\x8e\\x16\\x76\\x34\\xe0\\xb3\\x4a\\xb3\\xc5\\xd2\\x8c\\xf4\\xa1\\xdc\\x5d\\x68\\xfa\\x6e\\x7f\\xba\\x1b\\x9a\\x1d\\xd5\\x9a\\x20\\xa8\\xe7\\xb6\\x89\\x73\\x88\\xc8\\xe7\\xf2\\x4b\\xa6\\x8c\\x2c\\xa4\\x90\\xb9\\x45\\x1a\\x29\\xb1\\x74\\x80\\xcd\\x60\\x12\\x2f\\xac\\x80\\xe5\\xb7\\xc1\\x54\\x83\\xb2\\x63\\x97\\xc6\\x3b\\x4b\\xe8\\x1c\\x9a\\x46\\xd7\\x00\\x71\\x80\\xb9\\xca\\x02\\x63\\xbe\\xe1\\xcd\\xae\\x1c\\xcc\\x35\\x44\\x85\\x7e\\x6c\\x0a\\xb9\\x98\\x0b\\xf5\\xda\\x84\\x6a\\xc8\\x91\\x39\\x30\\xf3\\x9e\\x61\\x7a\\xed\\x6e\\x05\\x86\\xa3\\xcc\\xe3\\xf4\\x55\\x7a\\xde\\x20\\xaa\\x10\\x18\\x39\\xef\\x1e\\xf7\\xa5\\x5f\\x41\\x85\\xbd\\xcd\\x03\\x4d\\xf9\\xb5\\x79\\x4a\\xf8\\xab\\x10\\xf0\\x03\\xca\\xaa\\xc4\\x68\\xf3\\xd7\\x83\\x31\\x21\\x27\\xa5\\x5d\\x3b\\x34\\xab\\x18\\xde\\x19\\x34\\x2b\\x15\\xf0\\xc5\\x29\\x22\\x76\\xe0\\x0b\\x84\\x71\\x28\\xdb\\x77\\xb4\\xcd\\xfe\\x6e\\xde\\x2d\\xc0\\x07\\x92\\x3b\\x3a\\xea\\x10\\x50\\xb6\\xc3\\x99\\x85\\x76\\xe2\\xbb\\x4d\\x80\\x19\\x6c\\xe3\\x0e\\x82\\xcc\\xeb\\x32\\xfa\\xc1\\x45\\xfb\\x43\\xf2\\x30\\xc5\\xf2\\x25\\x8f\\xd8\\x41\\x14\\xc9\\x42\\xb4\\xca\\xd1\\x3d\\x62\\xe6\\x15\\xa8\\x66\\xf1\\x79\\x65\\x4c\\x8c\\x47\\xc4\\xf0\\x2d\\xa6\\xc4\\xd3\\x84\\x53\\x44\\xfa\\xae\\xde\\x89\\x25\\xa2\\xe5\\x38\\x10\\xcf\\xa8\\xcd\\xd0\\x6e\\x19\\xa5\\x19\\x6d\\x96\\x6f\\xdb\\x92\\x42\\x6d\\x0b\\xbc\\xd6\\xdf\\x78\\x93\\x84\\xab\\x51\\xd0\\x86\\x32\\xd6\\x8a\\xb7\\xee\\x56\\x39\\xa7\\xa9\\xba\\x2c\\xf1\\xcf\\x19\\x20\\x01\\xf9\\xc3\\x14\\x7c\\x6e\\x5f\\x74\\x44\\xf1\\xa9\\x8d\\x30\\xd1\\x1b\\x50\\x57\\x1b\\xbe\\x67\\x5e\\xfe\\x40\\xbd\\xfe\\x3f\\x47\\xa7\\xed\\xea\\x9d\\x7c\\xeb\\x67\\x84\\x98\\x59\\xd8\\xa1\\xbd\\xaa\\x1e\\x22\\x63\\x86\\x08\\x61\\xe6\\xc9\\x43\\x92\\x53\\xdb\\xd5\\x92\\x22\\x13\\x4a\\x18\\x45\\x9f\\x0a\\xd9\\x0b\\xea\\xcb\\x06\\x50\\x07\\x59\\xe6\\x12\\x20\\xab\\x1f\\xe2\\xba\\xa4\\x8c\\x0a\\x15\\xa0\\xc0\\x31\\x18\\xda\\x39\\xf5\\xfc\\x7c\\x50\\x10\\xda\\xd5\\xb6\\xde\\x83\\x3d\\xe7\\x92\\xae\\xde\\xa1\\x74\\x5e\\x44\\x9a\\x14\\x5a\\x99\\xcf\\xf1\\xe1\\x8e\\x61\\xde\\xe1\\xf1\\x39\\x9b\\x73\\xa5\\x73\\x0b\\x98\\x67\\x06\\x2c\\x27\\x61\\xbd\\x42\\xfe\\x96\\x4b\\xb6\\x22\\x3f\\xfe\\x74\\xfc\\xeb\\xef\\x6f\\xde\\x1d\\x1e\\xbc\\xf9\\xfd\\xed\\xc1\\xe1\\x8f\\x27\\xa7\\xc7\\x1f\\x3f\\x9e\\xff\\x7a\\x7e\\x71\\xfc\\xf6\\xe3\\xc7\\x43\\x04\\xf9\\xb5\\x88\\x78\\xe7\\x4c\\x7f\\xfc\\x68\\x77\\xaa\\xfa\\xf8\\xf1\\x22\\xca\\x78\\xf6\\xf1\\xe3\\xc4\\xf9\\x40\\xb0\\xe9\\xe9\\xff\\x39\\x3a\\x05\\xfe\\x89\\xc0\\x4c\\x3e\\x29\\x0c\\x64\\x2b\\x12\\x1d\\xe6\\xbd\\xa0\\xaa\\x4c\\x41\\xad\\x54\\x89\\x36\\x68\\x94\\xd3\\x54\\xdc\\x6d\\x44\\x25\\x6f\\x75\\xd8\\x17\\xe0\\x0c\\x76\\xdd\\xca\\x9d\\x97\\xb6\\x04\\x0c\\x98\\x32\\x7d\\xc5\\x2c\\x92\\xd8\\x46\\x1c\\x7c\\x5a\\x2f\\xf7\\xb7\\x69\\xe9\\x1b\\x3a\\x22\\x3b\\xa4\\x9f\\x25\\x67\\x57\\x08\\xfb\\xca\\xe7\\x82\\x26\\x41\\x5b\\x6e\\x40\\x16\\x44\\x74\\xb9\\x75\\xb4\\x7d\\x50\\x92\\x32\\x19\\xfb\\x16\\xe4\\x35\\xaf\\xfd\\x9a\\xc7\\xbe\\x52\\xfc\\x89\\xfd\\x14\\x58\\x4c\\x26\\x27\\x47\\xe4\\xe5\\x18\\x95\\x9c\\x93\\x23\\x6c\\xef\\xb2\\x11\\xec\\xdd\\x59\\xaa\\x46\\xa0\\xa2\\xf4\\xdd\\x50\\x93\\x51\\x6e\\x80\\x26\\xcc\\xa8\\xc1\\x0e\\x28\\xa6\\xb1\\x4c\\x29\\xbf\\x67\\x8b\\xb2\\xcf\\x54\\x5d\\xce\\x8a\\x24\\x59\\x91\\x7f\\x17\\x34\\x41\\x1d\\x60\\x22\\xe3\\x75\\xce\\xb4\\xf3\\x9d\\xfb\\xe8\\x9f\\xe3\\xef\\xfc\\x3c\\xfe\\x39\\xf6\\x08\\x0c\\x40\\xb6\\x7f\\x8e\\xd5\\x32\\x1a\\x7f\\x67\\x31\\x0a\\x89\\xbd\\x69\\x63\\x06\\xf5\\x5a\\x8d\\xae\\xd5\\x67\\xf1\\x37\\xf0\\x6c\\x0a\\xfa\\xee\\x83\\x14\\x69\\x06\\xed\\x99\\x7f\\xc8\\x69\\xc4\\x26\\x2c\\xe7\\xa0\\x32\\x49\\x11\\xb7\\x29\\xd9\\x74\\x5b\\x86\\xc4\\x0e\\xb5\\x9b\\x0b\\xa2\\x70\\x58\\x4f\\x02\\xc1\\x58\\x8c\\x4a\\xa2\\x9d\\x05\\x23\\x73\\x33\\x09\\x58\\x18\\xd4\\x02\\x01\\x1a\\x23\\xca\\x19\\xc5\\x44\\x7c\\x8b\\x93\\xe1\\xa0\\x98\\xc7\\xd6\\x7d\\xe6\\x82\\xc3\\x46\\xe3\\x17\\x6c\\x8e\\x21\\x5e\\x1b\\x47\\xc0\\x30\\x32\\x72\\x59\\x84\\x4f\\xf4\\xb1\\x4d\\xa5\\x65\\x46\\x78\\x9a\\xb2\\xd8\\x28\\x40\\xc9\\x8a\\x2c\\x39\\x45\\xce\\x0f\\x95\\x9e\\x78\\x4e\\xf7\\x84\\x24\\x12\\xbc\\xf1\\x85\\xe0\\xd6\\x39\\xb7\\x28\\x34\\x89\\xe5\\x95\\x18\\x94\\x0d\\xf8\\xf1\\x01\\xc6\\x5a\\xe1\\xc9\\xb0\\x52\\xf6\\x0c\\xaf\\x44\\x32\\x20\\x6c\\x15\\x6d\\xc4\\xe9\\x4b\\x30\\xc3\\xca\\x6d\\x56\\xf7\\xd8\\x44\\x3c\\x04\\x77\\x40\\x50\\x51\\xc7\\x41\\x1c\\x82\\x77\\x09\\x1a\\x80\\x21\\x27\\x26\\x34\\xa1\\x95\\x16\\xdc\\xf6\\xa5\\x1c\\x2f\\xc1\\xbc\\x3c\\xe4\\x62\\xe1\\x80\\xe6\\xd7\\x33\\x99\\x47\\x7c\\x9a\\xac\\xc8\\x82\\x26\\x65\\x3b\\xee\\x90\\x36\\x60\\x45\\x86\\xaf\\x9f\\x48\\x31\\x0f\\x05\\x35\\x42\\xb3\\x43\\x7d\\x3a\\xa3\\xa2\\xc8\\xf0\\x79\\x46\\xbe\\xad\\x64\\x71\\x83\\xc1\\xf0\\xcd\\x0b\\xf7\\xaa\\x8f\\x00\\x96\\x7a\\xaf\\xb0\\x91\\x96\\x09\\xc3\\xf5\\x69\\x73\\x52\\x36\\x56\\x83\\xef\\xaa\\x70\\xf4\\x26\\x84\\x78\\x8c\\x9a\\xdb\\x0b\\x87\\xbc\\x62\\x76\\xc4\\x85\\x9f\\x3f\\x58\\x1a\\x5a\\x53\\x28\\x47\\x37\\xa7\\x1d\\xbf\\x81\\x5a\\xc0\\x15\\x31\\x52\\xcb\\x22\\xab\\x85\\xb8\\x06\\x3a\\xe7\\x59\\xc2\\xc8\\x77\\x97\\x6c\\x35\\x44\\x4c\\x5d\\x54\\x42\\xfe\\x19\\x74\\x3a\\xf3\\xa8\\x84\\xd8\\xfb\\x40\\xe6\\xe4\\x3b\\xf7\\xaf\\x7f\\x3e\\x60\\xfd\\x6e\\x1b\\x2f\\x2a\\xbe\\x54\\xeb\\xc8\\xd7\\x31\\xd6\\x08\\x55\\x41\\x76\\x91\\xb2\\xb6\\x7c\\x48\\x4b\\x24\\xd7\\x98\\x1c\\x03\\x5a\\x03\\x6a\\xa4\\xb6\\xdb\\x53\\x92\\x54\\x6e\\x56\\x56\\xb3\\xa9\\x02\\xb4\\x82\\xff\\x25\\xa8\\x1d\\x3a\\x95\\xb6\\xc0\\x9a\\x01\\xd2\\xf5\\x8c\\xe5\\xe5\\x27\\xc0\\x60\\x4e\\xe5\\xf1\\x35\\x8b\\x0a\\xfd\\x90\\x80\\x91\\x78\\x5d\\xb2\\xf6\\xbd\\xf4\\x7f\\x62\\x1e\\x05\\x1c\\x69\\x63\\xb4\\x70\\x5f\\xb7\\x51\\x9e\\xce\\x20\\x75\\xef\\x76\\xda\\x5e\\xb2\\x95\\xf2\\x7d\\x0e\\x2e\\x71\\x74\\x8b\\x30\\xe0\\xf7\\xaf\\x13\\x64\\xc7\\xd7\\x5c\\x69\\xf5\\xbf\\x5d\\x23\\xff\\x74\\xea\\xf8\\x37\\x0e\\xed\\x16\\x13\\x46\\x0f\\x7a\\x5c\\x98\\x3f\\xe1\\x31\\x0f\\x4d\\x70\\xf7\\x02\\xad\\xa9\\xfe\\xce\\x51\\x22\\xe8\\x62\\x41\\xcd\\x3b\\xed\\x2a\\x9b\\xbc\\x25\\x05\\x94\\xf1\\x85\\xed\\x10\\xca\\xb4\\x23\\xfc\\x31\\xee\\x4f\\xa4\\x21\\xd0\\xe5\\xd8\\x28\\x79\\x55\\x31\\x63\\x3f\\xb2\\x37\\x71\\x00\\xf6\\xe5\\x4b\\x9a\\x30\\x61\\xbb\\x43\\x25\\x71\\x44\\x73\\x0c\\xd1\\x5b\\x4c\\x6f\\x65\\x1b\\xcc\\x59\\x30\\x5b\\x23\\xe3\\x2c\\x27\\x2b\\x57\\x59\\xd9\\x50\\x1e\\xcd\\x35\\x8f\\x8a\\x84\\xe6\\xc4\\x9c\\xc7\\xb9\\xcc\\xef\\x09\\xfd\\x8d\\x57\\xab\\x35\\x29\\xb7\\x68\\x23\\x75\\x0e\\xaf\\x2a\\x7f\\xaf\\x8f\\x58\\xef\\x35\\x62\\xb5\\x17\\x63\\x32\\x71\\x44\\x2f\\x0d\\x0f\\xca\\x5e\\xb5\\x41\\x9d\\x9c\\x39\\xde\\xe4\\x19\\x45\\xd8\\xad\\x42\\x57\\x01\\xb3\\xe6\\xe0\\xff\\x1e\\x04\\xc2\\xc3\\x9f\\xcc\\x31\\xf9\\x97\\xc7\\x38\\x19\\x92\\xd2\\x67\\x0c\\x15\\xbb\\xf6\\x99\\xf6\\xd8\\xd8\\xe5\\x2a\\x0f\\xf5\\x4c\\xe6\\x6c\\xc9\\x72\\xb2\\x17\\x4b\\x84\\xfc\\x58\\xf2\\x48\\x0f\\xc6\\xe4\\xff\\x6f\\x34\\x45\\x70\\x22\\x3b\\x75\\xd2\\x1e\\x33\\x5f\\xa5\\x5c\\xf6\\xcc\\x78\\x41\\xf6\\xe0\\x67\\xa1\\x2a\\x39\\x70\\x81\\x22\\xdb\\x8c\\xe7\\x89\\x65\\xc3\\xb4\\x88\\x70\\x6f\\x88\\x6e\\x57\\xd8\\x28\\x6a\\x8a\\xb5\\xad\\xe1\\x25\\xbf\\xf4\\x1c\\xd2\\xf3\\x44\\xae\\xec\\x29\\xad\\x78\\x6e\\x7d\\x9c\\xc5\\xb1\\x50\\xbf\\x71\\xfe\\x07\\x7c\\xf4\\x24\\x67\\x73\\x38\\x7f\\x78\\x7a\\x1e\\xf0\\xf4\\x69\\x99\\xc9\\x44\\xce\\x57\\xe7\\x59\\xce\\x68\\x7c\\x28\\x85\\xd2\\x39\\xb0\\x86\\x36\\x2d\\x16\\x6e\\x1a\\x33\\x00\\xe7\\x5c\\xc8\\x2b\\x42\\x6d\\x02\\x9b\\x9c\\x61\\x93\\x0a\\x59\\xcc\\x17\\x08\\x37\\x03\\x3f\\x24\\x34\\xca\\x25\\x00\\xce\\xe2\\x70\\xd6\\xe8\\x54\\x1e\\xfb\\xce\\xb9\\x0f\\x3c\\x3a\\x0d\\x8c\\x02\\x0e\\x8f\\x2b\\xba\\xb2\\x87\\x89\\x4e\\x79\\xcc\\x54\\x90\\xc1\\xed\\x26\\x83\\xa1\\x9f\\x1b\\xdf\\x1f\\xb8\\xf2\\xc1\\xe9\\xd1\\x7d\\xfb\\x9a\\x3e\\xa2\\x42\\x7b\\xc3\\xab\\x78\\xcd\\x08\\xa9\\x5e\\xd2\\xd7\\x6b\\xa4\\x40\\x37\\x9a\\x4a\\xab\\xa9\\x62\\x3b\\x25\\x47\\x99\\x27\\x82\\x2d\\x93\\xd2\\xeb\\xf3\\x4b\\x76\\xd5\\xe0\\x97\\xee\\x45\\x7f\\x62\\xf7\\x4f\\x05\\x1b\\x81\\x3d\\xfa\\x5e\\x28\\xaa\\xb9\\x9a\\x41\\x03\\xe4\\x07\\xd4\\xc7\\xa1\\x24\\xa3\\x59\\x9f\\x56\\xbc\\xaa\\x95\\x4d\\xe1\\x68\\xae\\x64\\xde\\xe3\\xe7\\x56\\x36\\x8b\\xcd\\xff\\x2b\\xed\\x20\\x9b\\xfe\\x09\\x25\\x22\\xbe\\xc5\\xab\\x39\\x41\\x91\\x6d\\x7b\\xae\\x65\\x19\\x87\\xc6\\x48\\x45\\x91\\x4e\\x59\\xee\\xcf\\x3e\\x3a\\x03\\x78\\x5e\\xc3\\x8f\\xac\\x9d\\xfd\\x27\\x88\\xd9\\x0b\\xe4\\x39\\xbe\\x36\\x9a\\x87\\x6a\\x96\\xa8\\x84\\x57\\x65\\xa9\\xea\\x83\\x62\\x78\\xcc\\x25\\x70\\xd6\\x96\\xa1\\xd2\\x3d\\xd8\\x62\\xbd\\x97\\x9f\\x34\\xe5\\x73\\xe5\\xd5\\x26\\x95\\x12\\xaf\\xc6\\x09\\x95\\x78\\xd5\\xd3\\xc8\\x6f\\x7c\\xfd\\x5a\\x0b\\xe2\\xb0\\x1c\\xd2\\x3a\\x85\\xd4\\x10\\x15\\x78\\x74\\x60\\x03\\x6c\\x9b\\x15\\xec\\x70\\x33\\x82\\xa7\\x2a\\x6f\\x14\\x99\\x9b\\xf0\\x77\\x6d\\x1b\\x8c\\x37\\xde\\x9f\\x78\\xb5\\xcb\\xd7\\xc4\\x6b\\x64\\x5e\\xa9\\xd5\\xef\\x1d\\xb1\\x1a\\x0f\\xd2\\xf6\\xb0\\xe1\\xd5\\xd0\\xa0\\x2e\\xaf\\xca\\x86\\xba\\x2c\\x4d\\x6b\\xdc\\x59\\x15\\xd3\\xba\\x64\\x76\\xa5\\x61\\xdd\\xea\\xd9\\xad\\xb3\\x3d\\xf1\\x6a\\x63\\xe3\\x96\\x57\\x85\\x10\\xf2\\x1e\\xd6\\x2e\\x25\\x16\\xc9\\xd5\\x9e\\x8e\\x8d\\x36\\xef\\x89\\x18\\x92\\x53\\xa9\\xcd\\x7f\\x02\\xf3\\xf7\\x48\\x32\\x75\\x2a\\x35\\x7c\\xb2\\x15\\xa4\\xc4\\x57\\xe8\\x90\\x90\\xae\\x93\\x27\\x36\\xc6\\x30\\x7c\\xd3\\x86\\x68\\x8d\\xc4\\x73\\x04\\xdb\\x60\\x58\\x9c\\x08\\x22\\x73\\x47\\x31\\x6f\\x5d\\x28\\x3b\\x44\\x18\\x56\\xb0\\x08\\x64\\x37\\x1a\\x27\\x66\\x9c\\x90\\xce\\xb7\\x0c\\x67\\x87\\x82\\xec\\x2f\\xfc\\x06\\xb0\\xa2\\xb3\\x04\\x0a\\x04\\xe2\\x22\\xc7\\x36\\x52\\x46\\xd7\\xd4\\x6c\\xce\\x23\\x92\\xb2\\x7c\\xce\\x08\\x00\\x7a\\x76\\xb1\\x7c\\x6d\\xe4\\x0a\\x5e\\x2d\\xa5\\x4b\\x38\\x99\\x16\\x7b\\x09\\x44\\x36\\xa8\\x58\\x1d\\xaa\\x00\\x38\\x1e\\x8a\\xb5\\x94\\x82\\x25\\xf5\\xff\\x78\\x1f\\xf4\\xff\\x4b\\x32\\xca\\x73\\x68\\x3b\\x65\\x63\\xc7\\xe1\\x77\\x36\\xfa\\x12\\x0e\\x63\\x46\\x58\\xf3\\x2d\\x51\\x41\\x18\\xd6\\x79\\x99\\xd1\\xeb\\x8a\\xc7\\x90\\x5c\\x01\\x54\\xb3\\xe1\\x89\\xde\\xfd\\xb1\\x73\\xc9\\x56\\x3b\\xc3\\xb5\\xad\\xb7\\x73\\x22\\x76\\xca\\xc0\\x70\\x65\\xb3\\x79\\x21\\x0c\\x19\\x84\\x3b\\xf0\\xdd\\xce\\x97\\xd3\\x55\\x5a\\x09\\xdb\\x2e\\x9a\\x76\\xd6\\x27\\xd4\\x70\\x5f\\x95\\x8b\\xf7\\x53\\x03\\x4c\\x47\\xb2\\x56\\x4d\\xf9\\xb6\\x32\\x9e\\xd3\\x96\\xb4\\x55\\xd2\\x4b\\xf1\\xa7\\x30\\xe9\\x3f\\x09\\x10\\xf7\\x15\\x34\\x96\\x75\\x30\\x62\\x19\\x36\\x09\\x9b\\x97\\x29\\x33\\x34\\x89\\xb0\\xef\\x2e\\xae\\x2a\\x0c\\x62\\x56\\xd3\\xd9\\x18\\x89\\x94\\x97\\x45\\xe6\\x76\\x05\\x24\\x19\\x00\\x46\\x90\\x88\\x64\\x6a\\xad\\x0e\\x7c\\x3e\\x38\\x56\\xec\\x96\\x1b\\xd9\\x40\\x1e\\x6e\\x5f\\xbf\\x39\\x6c\\xb7\\xcb\\x8a\\x39\\x53\\x9d\\xb0\\xf7\\x3b\\x78\\x58\\xff\\xfb\\xbc\\x82\\xcf\\x79\\x09\\x67\\x67\\xb1\\xff\\x68\\xea\\xdd\\xe5\\x33\\x99\\x4f\\x79\\x1c\\x83\\x29\\x8d\\x0f\\xf2\\xc9\\x7f\\x35\\x42\\x9b\\x33\\x51\\xb1\\xbe\\xc6\\xf5\\x3b\\x36\\xa4\\xe4\\xd7\\xcd\\x35\\xb1\\xab\\x31\\x01\\x02\\x7e\\x00\\x0a\\x4a\\x2c\\xcd\\x87\\xfe\\xd1\\x37\\x10\\xd4\\xbf\\xa1\\x75\\x5b\\x1a\\x86\\x21\\x8a\\x24\\xf1\\xf0\\xdb\\x68\\x58\\xa0\\x57\\x12\\x0e\\xa8\\x75\\xe7\\xcf\\xcd\\x91\\xd5\\x55\\x42\\x6f\\x04\\xf0\\x5d\\xef\\xfa\\x64\\xa6\\x52\\x7d\\xc5\\x13\\x31\\x91\\x71\\xd5\\x85\\x51\\xc1\\xf2\\xb5\\xd5\\x50\\x0e\\x04\\x78\\x2f\\x40\\x03\\xf6\\x29\\x55\\x4d\\x8a\\x60\\xdb\\x49\\x99\\x16\\xb2\\xa5\\xa5\\x44\\xb9\\x09\\x5e\\x95\\x6a\\x99\\xf2\\xa8\\x01\\x2b\\x01\\xf7\\x49\\x6b\\x1e\\xb2\\xfb\\x16\\x07\\x0a\\x5c\\x7d\\x98\\x5e\\x30\\xcf\\x19\\x56\\xbd\\xc3\\xf1\\x82\\xe3\\x66\\x81\\xfd\\x0b\\xc1\\x96\\xcc\\x6c\\xab\\x98\\x2b\\x0b\\xbc\\xea\\xb2\\x95\\xfe\\x7b\\xcd\\xbb\\xf2\\xff\\x3b\\x92\\xa7\\x52\\x3b\\x07\\xe0\\x7f\\x3b\\x0f\\x3a\\x8a\\xb2\\x6b\\x9e\\x16\\x69\\xd9\\x28\\x80\\xc4\\x7c\\xe6\\xda\\x52\\xb9\\x24\\xa9\\xaa\\xeb\\xa1\\xea\\x01\\xb3\\x47\\x44\\xd3\\x7c\\x0e\\xc9\\xd2\\xd6\\xf5\\xe0\\x24\\xd6\\x3c\\x91\\x53\\x9a\\x90\\x94\\x0b\\xf3\\x18\\x9b\\x07\\x51\\xf9\\xcc\\xcf\\xc4\\xfe\\x79\\xcb\\x83\\x40\\xac\\xf2\\x39\\x9f\\x26\\xcc\\xfa\\x36\\x6a\\x1d\\x33\\x83\\x1f\\xd7\\x6e\\x84\\xa3\\x95\\x40\\x2b\\xae\\x05\\x15\\xe4\\x2d\\x17\\x47\\xce\\x31\\xfa\\xda\\x1c\\xd9\\x6b\\x9a\\x66\\x09\\xc3\\x5a\\x68\\xf2\\xcd\\xe8\\x3f\\x52\\x30\\x62\\x73\\x7d\\x86\\xc4\\x2d\\x8f\\x4d\\x01\\xd3\\x92\\xbc\\x1c\\xba\\x06\\x22\\x41\\x97\\x51\\xe0\\x63\\x55\\x0e\\xea\\x9c\\xb2\\x8a\\x7c\\xbd\\xff\\xf5\\xfe\\xcb\\x57\\x46\\x1d\\xc5\\x88\\x1f\\x55\\x16\\xeb\\x6d\\x9d\\x1a\\x2f\\xc7\\xe4\\x13\\x31\\x33\\x78\\x69\\xff\\xfb\\xb5\\xfd\\xef\\x37\\xe4\\x13\\xf9\\x44\\xc8\\x84\\x4c\\x48\\xf8\\x5f\\xf3\\x1f\\xf2\\x89\\x8c\\x0c\\x11\\x82\\xa9\\xbe\\x1c\\x56\\x19\\x57\\x05\\x6a\\xdc\\xee\\x05\\x10\\x23\\x38\\x34\\xb0\\x8a\\x48\\xa6\\x0c\\xa6\\xfa\\xf5\\xff\\x0e\\x21\\x9a\\xb9\\x26\\x52\\xd8\\x3b\\x5f\\xee\\xc1\\x94\\x06\\xe4\\x0a\\xfc\\xf3\\x29\\xbd\\x44\\xdf\\xd4\\x41\\xa4\\x0b\\x9a\\x98\\x87\\xef\\x7d\\x33\\x7a\\x39\\x20\\x52\\x54\\x6f\\x5f\\x72\\x09\\xdd\\x78\\xec\\x0c\\xf7\\x5e\\x0e\\xc6\\x6b\\x53\\xfe\\x7a\\xc3\\x94\\x2b\\xb3\\x85\\x59\\x50\\xb1\\x82\\xa1\\x6f\\xde\\xef\\x6e\\xab\\x1f\\x88\\xd5\\x15\\x5d\\xf9\\x0d\\xef\\xe4\\xe6\\x9c\\x2f\\x7d\\xef\\xde\\x00\\xed\\x09\\x12\\x17\\x60\\xff\\x72\\x07\\xe0\\x87\\x83\\xae\\x08\\xd7\\x63\\x72\\xa2\\x77\\x77\\x15\\x84\\x1d\\xd0\\x6d\\xe0\\x9a\\x0c\\x1f\\x85\\xc0\\xc4\\x40\\x78\\xd8\\x1b\\x2f\\x6a\\x85\\x0d\\x0d\\x60\\x30\\x3b\\x8d\\x10\\xdd\\xab\\x4b\\x30\\x5e\\xa9\\x3f\\x25\\x1d\\xa8\\x49\\x7e\\xac\\x0a\\x6c\\xc8\\xfa\\xa9\\xaf\\x1f\\x5c\\x9f\\x83\\x79\\xeb\\xe9\\xae\\xf5\\xb0\\x74\\x6c\\xe8\\xd2\\xaa\\x64\\xe5\\xc9\\x2f\\xdf\\x69\\x08\\xe9\\x80\\x4e\\x7a\\x12\\x2b\\x3e\\x21\\xea\\xa7\\xc8\\xc7\\x9d\\xea\\xb9\\xfc\\xb8\\x03\\x71\\x40\\xaf\\x8a\\x5b\\xa8\\x00\\xab\\xde\\x58\\x98\\x59\\xb7\\x8d\\x03\\x28\\xc4\\x03\\x11\\x97\\xd9\\x57\\x0d\\xe7\\x0f\\x0d\\x69\\xc1\\xfc\\x9c\\x43\\x48\\x32\\x5f\\x7f\\x93\\x20\\x43\\xab\\x92\\xd0\\x6b\\x4e\\x61\\x80\\x78\\x4f\\x0e\\x70\\x03\\x2b\\x88\\xa3\\xde\\x65\\x5e\\x37\\xd2\\x2e\\xe8\\x7d\\x00\\x0a\\x93\\x8f\\x27\\xa5\\xd8\\x39\\xd3\\xdc\\x6e\\x0f\\x36\\xba\\xbd\\x5d\\x27\\x4c\\xbf\\xac\\x27\\xb3\\x0d\\x29\\x75\\x65\\xac\\x09\\x51\\x7e\\xcd\\x26\\x81\\x12\\xac\\x70\\xff\\x04\\x3d\\x7a\\x5f\\x6e\\x80\\xbc\\xb5\\xc7\\x45\\x55\\xc9\\xf5\\xc2\\x6e\\xa4\\xf2\\x99\\x52\\xe3\\x73\\x7f\\xa9\\xf3\\x0f\\x6f\\xc7\\x57\\xe4\\x26\\x68\\x69\\x4d\\x84\\xc5\\xd7\\xc3\\xda\\xec\\xed\\xe7\\x7f\\x6b\\x22\\x43\\xbe\\x7e\\x75\\x3f\\xe1\\x60\\xff\\x7b\\x51\\x59\\xe6\\x8d\\xab\\xfb\\xb7\\xbd\\x72\\x96\\x03\\xc8\\x85\\xd8\\x70\\x08\\xa0\\x6e\\xaa\\x8c\\x8b\\x8f\\xbd\\x40\\x53\\x5c\\x17\\x14\\x4b\\xad\\x04\\xbb\\xb2\\xf9\\xaf\\x37\\xbf\\x54\\xa0\\x9b\\x3b\\xe6\\x3e\\x34\\xf2\\x87\\x16\\xd0\\x2c\\x35\\xcd\\x0a\\x80\\x46\\x30\\x84\\x74\\x9a\\xf6\\x37\\x7b\\xdf\\x90\\x11\\x79\\x31\\x30\\xbb\\x41\\xe0\\xb6\\x02\\x62\\x86\\xa2\\xcc\\x88\\x06\\x9b\\xce\\xad\\x17\\x46\\x79\\x32\\x94\\x51\\x43\\x6c\\xb0\\x99\\x24\\x75\\x21\\x74\\x1f\\xc5\\xdb\\xd3\\xe6\\x71\\x95\\xee\\xc7\\x92\\x05\\x42\\xc6\\xec\\x60\\x06\\xfd\\x7f\\x56\\x4d\\x11\\xbe\\xeb\\x32\\xe1\\x74\\x6d\\xcc\\x40\\x36\\x2c\\xe4\\x15\\xb9\\xb2\\x59\\xda\\xb0\\xe5\\x6c\\xb1\\x61\\x38\\x91\\x7d\\xf3\\x87\\xdf\\x53\\xc0\\xcf\\x3c\\x4b\\xb6\\x2a\\x84\\x67\\xa5\\xf6\\x18\\x29\\x58\\xf6\\x77\\x21\\x7c\\xd1\\x88\\xfc\\x28\\x85\\xcc\\x5f\\xa1\\x76\\x64\\x86\\x54\\x25\\x2b\\xbe\\xf9\\x71\\xc8\\x6a\\x42\\x30\\x97\\x8a\\x40\\x50\\x46\\xbd\\x39\\x01\\xeb\\xf0\\xd5\\xe7\\x46\\xf1\\x36\\x24\\x24\\x8c\\xc7\\x9e\\x8f\\xdd\\x36\\x38\\xa2\\xd6\\xdf\\x90\\x99\\xec\\x11\\xd2\\xd7\\x5c\\x53\\xe6\\x5b\\x78\\x5d\\xdb\\x9d\\x6c\\x5c\\xdb\\xff\\xb6\\x3c\\xd5\\x6d\\x68\\x97\\xe2\\x5c\\xeb\\x23\\x63\\x56\\xee\\xc4\\x4c\\x4f\\x71\\x29\\x70\\xe9\\x6e\\x3b\\x16\\x50\\x90\\xda\\x7c\\xcf\\x37\\xb4\\xf7\\x0c\\x25\\x2f\\x20\\x2f\\xa1\\xcb\\x0d\\x1b\\x8e\\x78\\xeb\\x76\\x45\\xc8\\x32\\xcc\\x8b\\x68\\xbd\\x35\\x71\\x57\\xf8\\xfa\\x5d\\x18\\x75\\x48\\x68\\x22\\xc1\\xd9\\x62\\xf8\\xac\\xf9\\x88\\xc5\\xf6\\xc6\\x99\\x74\\x3e\\x99\\x35\\xff\\xc5\\x02\\x4a\\x96\\xcb\\xcc\\x9c\\x61\\x65\\xaf\\xd5\\x37\\xad\\x7b\\x81\\x3b\\x6c\\xd3\\x56\\x5b\\x12\\x9f\\xf9\\xfc\\xf7\\x64\\x90\\x37\\xd1\\x41\\xb2\\x9e\\x1f\\xcb\\x19\\xd1\\x97\\x0c\\xe4\\x1f\\xac\\x1c\\x3a\\xaa\\xc6\\x40\\x17\\x6b\\xce\\xd8\\x42\\x14\\xf4\\x49\\x96\\x1d\\xa7\\x5d\\x54\\x16\\x9b\\x21\\x47\\x34\\x09\\xb5\\x29\\xa3\\x91\\xf1\\x98\\xe5\\x28\\x60\\xa7\\xac\\x52\\xb6\\xe4\\xf3\\x5d\\xc8\\x2f\\xe5\\x9d\\x58\\xae\\x04\\x79\\xdd\\x38\\xd0\\x3f\\xb1\\x4c\\x7e\\x67\\x5a\\x44\\x97\\x4c\\x3b\\x7f\\x76\\x0e\\x95\\x16\\x59\\xa1\\xc9\\x94\\x26\\x54\\x44\\x66\\xf3\\xd6\\xf3\\x1b\\xb4\\xc4\\xc1\\xf0\\x97\\xf0\\x14\\xc4\\xfe\\xf1\\xe5\\x34\\x38\\x74\\x90\\x8d\\xc9\\x85\\xd2\\x66\\x34\\x4c\\xd3\\x2c\\x27\\x78\\x90\\x28\\x39\\x34\\x47\\xd4\\x0d\\xb0\\xee\\x4c\\x80\\xa1\\xec\\xbf\\xd1\\x45\\x6f\\x85\\x01\\x63\\xda\\xd6\\xeb\\x05\\x7e\\x75\\x4b\\xe7\\x9a\\x00\\xc3\\xb2\\xf4\\x2a\\x9b\\x18\\x13\\xe8\\x8f\\x7a\\x32\\xab\\x2f\\xd9\\x4e\\xb5\\x68\\xd4\\xd5\\x21\\xed\\x0c\\xf1\\xad\\xcd\\xca\\xd9\\x22\\x5e\\xeb\\xed\\xb0\\xcd\\x57\\x82\\xb7\\x12\\x31\\xd4\\xb6\\xd7\\x07\\xf6\\x77\\x54\\x9f\\x60\\xd4\\x21\\x37\\x3a\\xa8\\xad\\xb7\\x8f\\x7e\\xa2\\x37\\x59\\xbc\\x0f\\x7d\\x66\\xd6\\xec\\xfb\\xf6\\x0e\\xb7\\x75\\x95\\xbf\\xca\\xc9\\x21\\xf3\\x86\\x26\\xae\\x22\\xc6\\x76\\xc7\\xb5\\xc8\\xf8\\x62\\x77\\xb7\\xf4\\x0c\\xc0\\x51\\x40\\xce\\x52\\xda\\x2e\\x86\\x8b\\x56\\x6c\\x07\\xb2\\xe7\\x54\\x3f\\xa2\\x59\\x92\\xe0\\x61\\x2d\\x4d\\x28\\xa3\\x0a\\x87\\x1d\\xe3\\x38\\x8c\\x50\\xf5\\x62\\x6c\\xfc\\xe1\\x86\\x36\\x73\\xe8\\x28\\x5b\\x79\\x4c\\xcb\\x21\\x99\\x16\\x9a\\xcc\\xf9\\xd2\\x08\\x80\\x3b\\x39\\x3d\\xd0\\xb1\\xb3\\x60\\x49\\x46\\x72\\x16\\x17\\x91\\xc5\\x72\\x00\\xe9\\x74\\x10\\x5a\\x68\\x90\\xb9\\xee\\xb9\\xc3\\x4e\\x85\\xa0\\x3b\\xd8\\xf6\\x54\\x54\\x85\\x0f\\x9f\\xc1\\x01\\x01\\x45\\x8b\\xcf\\x08\\x5b\\xb2\\x7c\\x45\\x32\\xa9\\x14\\x1c\\x43\\x60\\x5b\\x58\\xd0\\x08\\xb1\\x33\\x0f\\xbf\\x0d\\xd6\\x04\\xcc\\xca\\x29\\xf0\\x3b\\x56\\x83\\xdf\\x01\\x0b\\x57\\x56\\x58\\xd1\\xc3\\x38\\xf4\\xbe\\xd9\\x7f\\xb9\\xff\\xf2\\x76\\x63\\x6c\\x02\\xff\\x2b\\x3d\\x74\\xee\\xbf\\x27\\xb3\\x0d\\x36\\x67\\x39\\x97\\xca\\xce\\xb9\\x8f\\x13\\xef\\x6b\\xf0\\xb5\\x7d\\x33\\x08\\x7c\\x79\\xdf\\xec\\x7f\\xbd\\xff\\x72\\xcf\\xcc\\xf5\\xeb\\x81\\x99\\x75\\xe0\\xa5\\xfb\\x3a\\xf0\\xd2\\xf9\\x5f\\xda\\x19\\x31\\x55\\xf1\\xd3\\x9d\\x08\\x5b\\xbd\\x7a\\x25\\xf3\\xd8\\x66\\xe9\\xba\\x4a\\x48\\x33\\x23\\x44\\x3e\\x34\\xb2\\x21\\x75\\xbc\\x1c\\xb7\\x5d\\xd5\\x4b\\xb0\\xab\\xd1\\x5d\\xc8\\x35\\xf9\\x4b\\x2a\\x73\\xf6\\x97\\xe0\\xfe\\x1b\\xfd\\x6b\\xcd\\xdd\\x66\\x8f\\xdc\\xfc\\xad\\x79\\x8a\\x64\\xdb\\x04\\xc9\\x6e\\xba\\xc8\\x61\\x07\\xa2\\x36\\x39\\xcd\\xbb\\x6f\\x5c\\xe3\\x4e\\x1c\\xca\\x26\\x8f\\xa1\\x53\\x37\\xb5\\x49\\x8e\\xd3\\x55\\x58\\x13\\x3d\\x65\\x46\\xa5\\x45\\x1f\\x58\\x09\\x9c\\x78\\xcf\\x46\\xc5\\x4a\\xcb\\x9c\\xce\\xd9\\xbe\\x7d\\x6c\\x93\\x0a\\xe6\\xc7\\xc8\\x45\\xfe\\x19\\x5b\\x3e\\x55\\x32\\x85\\x10\\x92\\xca\\x36\\x83\\x72\\x65\\xe9\\x2e\\x87\\x14\\xb8\\x00\\x8d\\xa0\\xa2\\x13\\x08\\x59\\x01\\x3d\\x0d\\x6a\\x45\\x9f\\x48\\x3a\\xf2\\x03\\xb7\\xba\\xa4\\x57\\xea\\x38\\xa1\\x4a\\xf3\\xe8\\x5f\\x89\\x8c\\x2e\\xcf\\xb5\\xb1\\x7a\\x5a\\xab\\x16\\x9b\\x46\\xad\\xac\\xa9\\x20\\x07\\xbf\\x9c\\x93\\x23\\xae\\x2e\\xcb\\x7e\\xcf\\xae\\x07\\x7e\\x58\\x44\\x49\\x3d\\x76\\xb5\\xc5\\xd3\\x20\\x29\\x8d\\x16\\xa8\\xba\\x5a\\x1f\\xb4\\xeb\\x5f\\xd6\\xdd\\x59\\xf9\\x13\\xbd\\x52\\x0c\\xa7\\x0f\\xfd\\x74\\xcd\\xd7\\xac\\x39\\x0b\\x7e\\x34\\x2c\\x4d\\x7c\\x9d\\x93\\xa3\\x47\\x48\\x5e\\x9e\\xa9\\x8b\\xc6\\x40\\xdd\\xeb\\x5d\\xf0\\x5c\\x3b\\x05\\xc4\\x85\\x48\\x18\\x56\\x1b\\x21\\x26\\x79\\xb5\\xb3\\x1d\\xec\\xa1\\x95\\x2c\\xc8\\x15\\x45\\xbb\\x1a\\x38\\xec\\x98\\x5c\\xf0\\xec\\x15\\x39\\x0e\\x7a\\x44\\x6d\\x1a\\xca\\x68\\x1f\\x1e\\x91\\xd6\\x1a\\xd4\\xb0\\xe7\\x30\\x19\\xc9\\x30\\x64\\x5b\\xe7\\x44\\x8e\\x51\\xb5\\x52\\xaf\\xc8\\x0e\\xbb\\xd6\\x7f\\xdd\\x19\\x92\\x9d\\xeb\\x99\\x32\\xff\\x11\\x7a\\x06\\x3d\\xe5\\x6c\\x0f\\x71\\xa3\\xe3\\x89\\x19\\xcb\\x4b\\xd3\\x11\\x7f\\xb0\\x0e\\x06\\xd5\\xfd\\x96\\x25\\x17\\xef\\x8e\\xde\\xbd\\x02\\x5d\\x3e\\x96\\xc6\\xea\\xcb\\x72\\xb6\\x34\\x3a\\xa5\\x85\\x36\\xb3\\xbc\\x31\\x20\\x03\\xa4\\xcf\\x44\\x32\\xcd\\x72\\x99\\xf2\\xa0\\x00\\x19\\x8e\\x5c\\x93\\x13\\x40\\xba\\xc8\\x80\\x03\\xc3\\x16\\x36\\x43\\x27\\xfb\\xc9\\x0f\\xe7\\xb6\\x54\\xf0\\x81\\xb8\\xcb\\x66\\x3a\\x99\\x11\\x89\\x89\\x02\\x55\\x08\\x04\\xae\\xfc\\x4d\\x66\\xfb\\xd8\\x51\\x04\\xe0\\x4a\\x95\\x1b\\xc6\\x68\\xe6\\xf6\\xab\\xfd\\x98\\x2d\\xf7\\x55\\x4c\\x5f\\x0e\\xe1\\x31\\xb8\\x1b\\x56\\xb5\\x39\\x51\\x45\\x76\\x5e\\xee\\x8c\\xc9\\x39\\x4f\\x79\\x42\\xf3\\xc4\\xb6\\xea\\xb6\\x43\\x94\\xf7\\x19\\x43\\xc1\\x0d\\x08\\xe6\\xef\\x8b\\x1d\\xb2\\x87\\x18\\x04\\xa0\\x6e\\x24\\xcc\\x21\\xd2\\x79\\x04\\x56\\x48\\xd2\\x19\\x34\\xd2\\x2e\\x49\\x07\\xce\\x78\\xd2\\xda\\x21\\x4f\\x80\\x4b\\xd2\\xf8\\x9d\\x48\\x1a\\x67\\x6e\\x57\\x37\\x87\\x1b\\xcd\\x15\\xf0\\xe5\\x85\\xf5\\x67\\xce\\x64\\x6e\\x8d\\x40\\x7f\\x8b\\x03\\x3a\\xe2\\xc2\\xaa\\x2d\\x6f\\xcd\\xd2\\xab\\xad\\x11\\x3f\\xa4\\x03\\xf0\\x3d\\xe2\\xa5\\x48\\x37\\xf4\\x75\\xa3\\x41\\x2a\\x02\\xf6\\xb8\\x3e\\x39\\x72\\x4c\\x3c\\x63\\xb9\\xe2\\x4a\\x1b\\x16\\x15\\x57\\x54\\x03\\x8e\\xfa\\xc2\\xde\\x41\\x4a\\xff\\x23\\x05\\x39\\xfe\\xd7\\xb9\\x9d\\xd6\\x60\\x0b\\x89\\xdd\\x90\\xd3\\xd1\\xff\\x14\\x39\\x33\\x1a\\x51\\x6b\\xf5\\xcb\\x8f\\x54\\x57\\xb9\\xcc\\xe7\\xe4\\x88\\x6a\\x8a\\x9a\\x17\\x72\\x2a\\x59\\x82\\x83\\x61\\x8f\\x7d\\x28\\xda\\x72\\xc8\\x6f\\x0d\\x95\\x67\\xf2\\xf8\\xda\\x8f\\xd9\\x41\\xa7\\xcd\\xd1\\xc4\\xcd\\xcf\\xdf\\x9f\\x9d\\x3c\\x82\\xee\\x14\\x81\\xb8\\x9d\\xbf\\x95\\x71\\x47\\x0a\\x54\\x30\\xa0\\x13\\x79\\x00\\xd6\\x7a\\x88\\x9f\\x93\\xd4\\x3c\\x89\\x9c\\x4a\\xc1\\x86\\xe4\\x8c\\xd1\\x98\\x18\\xee\\x66\\xff\\xf9\\x4b\\xce\\xf5\\x7d\\xf1\\xaf\\xca\\xab\\xb5\\xe8\\x77\\x8b\\xd8\\x09\\x21\\xdc\\x60\\x8e\\x08\\x61\\x87\\x7e\\x00\\xe8\\x04\\xa6\\x63\\x75\\x80\\x69\\x22\\xa7\\xc4\\x32\\x8b\\xc7\\x7c\\xfb\\xf7\\x67\\x27\\x9d\\xbd\\xfc\\xfb\\xb3\\x13\\xf7\\xee\\xe6\\x9f\\x72\\xb6\\x9d\\xaf\\xdd\\xa1\\xf1\\x50\\xda\\x0e\\xaf\\x6b\\xca\\x7e\\xa9\\xce\\x95\\x8d\\x94\\xea\\x06\\xc1\\xdd\\xad\\x81\\x71\\x57\\x76\\xc0\\x63\\xd1\\xfc\\x92\\x8b\\xc6\\x35\\x80\\x55\\x6e\\x03\\x4d\\x94\\x3c\\x24\\x56\\x10\\x44\\x03\\x24\\xbe\\xf8\\x15\\x49\\x8b\\x44\\x03\\xea\\x11\\xec\\x35\\xb3\\xf9\\x20\\x5b\\xcc\\xed\\x3a\\x62\\x11\\x40\\x09\\x39\\x62\\x18\\x8e\\x88\\x5f\\xb9\\x3a\\x14\\xff\\x8b\\xcd\\x3f\\x78\\x4b\\x05\\x9d\\x9b\\xdb\\x41\\x02\\x92\\x14\\xff\\x0c\\x36\\xf9\\x1e\\x3a\\xdd\\x85\\xff\\x8a\\x2e\\x29\\x4f\\xe8\\x94\\x27\\x5c\\x83\\x3e\\x37\\x18\\x3b\\x6d\\x1e\\x4b\\x15\\x60\\xca\\x8f\\xc6\\xfd\\x3a\\x55\\x6d\\xbd\\xda\\x1a\\xe2\\xc3\\x00\\xbc\\x21\\xd9\\x33\\xdf\\xed\\x5f\\x19\\x56\\x3f\\x18\\x03\\xdf\\x87\\x1b\\x01\\x8d\\xbe\\xa6\\xfc\\x9e\\x7d\\x4e\\xf9\\x7d\\x14\\x3d\\x15\\xd6\\xfb\\x75\\xc3\\x0e\\x6f\\xeb\\xba\\x93\\x19\\x69\\xa3\\xee\\x04\\x5f\\x58\\xd0\\xd1\\x67\\xae\\x3e\\x61\\x97\\xfd\\x16\\x0a\\x14\\x9c\\x9d\\x86\\xbf\\x6f\\xab\\x42\\x7d\\x99\\x83\\x13\\x3f\\xbf\\x83\\x43\\xb0\\x17\\xa6\\x5d\\xe9\\x4e\\xc8\\x55\\x0e\\xe7\\x74\\x0d\\x0f\\x2e\\x8d\\x5f\\xd5\\xca\\xe7\\xf1\\x64\\x9d\\x5b\\x5e\\xee\\x40\\xa7\\xe1\\xf7\\xe6\\x3c\\x35\\x01\\xd7\\xc0\\xab\\x35\\xfb\\xf5\\x3b\\xb8\\x1b\\xba\\xb8\\xd1\\x1c\\x59\\x50\\x48\\xc1\\xc7\\xa4\\xf1\\x39\\x6b\\xf9\\x9a\\x11\\xcb\\x16\\xb3\\xf6\\x99\\xed\\x66\\x98\\xd7\\xe7\\xd5\\xa8\\xcd\\x21\\xcb\\x16\\xe4\\xf5\\xf9\\x06\\x36\\x89\\x55\\x05\\xe6\\xbd\\x15\\xc6\\x72\\x76\\x15\\x49\\xf8\\x8c\\x69\\xde\\x88\\x08\\x8f\\xcc\\x28\\x53\\x29\\xb8\\x96\\xb9\\x7a\\x04\\x36\\xe7\\x1e\\xdd\\x8d\\xe2\\xe6\\x46\\x33\\xfb\\xf3\\xcc\\x11\\x85\\xbc\\x0d\\x3e\\xa5\\x24\\x92\\x49\\xc2\\x22\\x97\\xeb\\x0f\\x4b\\xec\\x7f\\xb6\\xc1\\x11\\x63\\x33\\x10\\xd4\\xf8\\xf2\\x5b\\x70\\xc5\\x58\\xa7\\xcb\\x3e\\x6e\\xbb\\xfd\\xb3\\xe3\\x83\\xa3\\xb7\\xc7\\xe3\\x34\\xfe\\xd3\\x42\\x5e\\x8d\\xb4\\x1c\\x15\\x8a\\x8d\\xb8\\x6e\\xa7\\x6f\\x3d\\x22\\x9e\\x48\\x07\\x9e\\x6e\\xbd\\xe8\\xca\\xc9\\xad\\x17\\x66\\xc9\\x4a\\x50\\xeb\\xf7\\xaa\\x84\\x9d\\x77\\x71\\xe7\\x5c\\x4a\\xbd\\x0e\\x3c\\x3f\\x2b\\x92\\x04\\xd7\\x56\\xe7\\x8c\\x0d\\x43\\xff\\xf6\\x3d\\x61\\xf9\\xcb\\x6b\\xbb\\x74\\xe1\\xd2\\xcd\\x5b\\x21\\xd1\\x97\\xd5\\x8c\\xb7\\xe5\\x80\\xb4\\xd7\\x15\\x9a\\x6a\\xda\\x64\\x6d\\x1d\\xca\\xf1\\xaa\\x2b\\x71\\x5e\\xf9\\x1c\\x03\\x22\\x7a\\x61\\xd6\\xe5\\x92\\xad\\x08\\x40\\x47\\xcc\\x64\\x0e\\x6d\\x5c\\xaa\\xfb\\x93\\xe9\\x08\\x88\\xb7\\x5f\\x28\\x96\\x8f\\xad\\xc2\\xb1\\x25\\x84\\x6f\\xa3\\x8a\\xc0\\x8b\\x9c\\xb1\\x59\\x97\\x64\\x3f\\x63\\xb3\\x4d\\x54\\xb7\\x1f\\x03\\xd6\\xad\\x4f\\x8f\\x33\\xfa\\x4a\\xa1\\x17\\x98\\x1b\\x8b\\x18\\xdb\\x48\\xdb\\x8d\\xcb\\x60\\xb1\\x3f\\xb6\\x84\\xee\\xad\\x50\\x1b\\xba\\x40\\x16\\x6a\\xd3\\x21\\x92\\xac\\x2d\\x5e\\xe8\\xb6\\xb4\\x8b\\xa4\\xef\\x1d\\x06\\x91\\x4b\\x63\\xc5\\xb2\\xab\\xfd\\x2b\\x99\\x5f\\x72\\x31\\x1f\\x5d\\x71\\xbd\\x18\\x21\\xa5\\xd4\\x3e\\x20\\xfe\\xef\\xff\\x09\\xfe\\x63\\xa3\\xc8\\x07\\x71\\x6c\\xf3\\xdf\\x0a\\xc5\\x66\\x45\\x82\\x99\\x69\\x6a\\x4c\\x68\\xc6\\x7f\\x66\\xb9\\x82\\x2c\\xcb\\x4b\\x2e\\xe2\\x21\\x29\\x78\\xfc\\x7d\\xd3\\x15\\x23\\x5d\\x9c\\x16\\x73\\xf6\\xbb\\x39\\x28\\xd0\\xd3\\x89\\x2b\\xdb\\x99\\xd1\\x8a\\xd1\\xdc\\xf1\\xa4\\x9c\\xc6\\x52\\x61\\xdf\\x27\\x43\\xaa\\xca\\x11\\xf8\\xff\\xd8\\x7b\\xd7\\xe6\\xb8\\x71\\x2b\\x61\\xf8\\x7b\\x7e\\x05\\x4a\\x9b\\x2a\\x49\\x93\\xee\\xb6\\x3d\\xc9\\x26\\x1b\\x3f\\xd9\\x4c\\x29\\x96\\x3d\\x8f\\x76\\x7c\\xd1\\x2b\\x79\\x66\\x6a\\x1f\\xdb\\xbb\\x83\\x26\\xd1\\xdd\\x88\\x48\\x80\\x43\\x80\\x92\\x3b\\x99\\xfc\\xf7\\xb7\\x70\\x0e\\x00\\x02\\xec\\x1b\\xbb\\x9b\\xba\\x79\\xc8\\x2f\\xb6\\xd8\\x24\\x08\\x1c\\x1c\\x9c\\xfb\\x85\\xa6\\x39\\x17\\x0f\\xe5\\x04\\xec\\xaa\\x1d\\x70\\x91\\xee\\x06\\xc9\\x86\\x03\\x02\\xc6\\x89\\xd5\\x03\\x7b\\xcf\\xba\\xb1\\x7d\\xcc\\x0f\\x75\\xd6\\x13\\x6c\\x7b\\x6f\\xa3\\x7f\\xe2\\xd8\\x9f\\x56\\x84\\x25\\x9f\\xab\\x9f\\xb3\\x21\\x7e\\x65\\x58\\xa4\\x35\\x5c\\xfb\\x40\\x9e\\x6d\\xae\\xbb\\x0b\\xe4\\xe9\\xd6\\x20\\x7f\\x07\\xe1\\x39\\xb7\\x8a\\x71\\xe4\\x01\\xcb\\xcc\\xb7\\x6b\\x07\\xbb\\x47\\x50\\xef\\x2f\\x19\\xdf\\x8e\\x84\\x56\\x73\\x1f\\xe8\\x49\\xa8\\x5c\\xa1\\x3c\\x10\\xc0\\x90\\x2a\\x39\\x7b\\x1a\\xc4\\xc8\\xd7\\x4d\\xb0\\x5c\\xb5\\x87\\x44\\x0a\\x61\\xfb\\x23\\xbc\\x2b\\x98\\xb8\\xd4\\x34\\xb9\\xda\\xd3\\xab\\xdb\\x4b\\x55\\xbf\\x32\\xa9\\xea\\x96\\x02\\x81\\x1c\\x8a\\x62\\xe2\\x9d\\x0d\\x7f\\xab\\x83\\xbd\\xf1\\x90\\x3f\\x42\\x02\\x8c\\xcd\\xfe\\xde\\xd0\\x62\\x7f\\xeb\\xaa\\x1b\\xa9\\x21\\x41\\xf9\\xdb\\xd6\\xa0\\x0a\\xc9\\x41\\x85\\x2c\\xa0\\xd8\\x98\\x4d\\x41\\x05\\x38\\xde\\xbd\\xc4\\xb3\\xef\\xf9\\xb6\\x2c\\xa6\\xbb\\x18\\x98\\x60\\xc0\\x98\\xa2\\xe6\\xe6\\xce\\x98\\xeb\\x9a\\x56\\x2a\\xa6\\xb1\\x14\\x94\\x2d\\x91\\x2c\\x05\\x49\\x6c\\xb9\\x07\\x90\\x47\\x82\\x22\\x06\\x81\\xac\\x22\\x88\\x4c\\xb4\\xcb\\x1a\\xf5\\x55\\xa3\\x9e\\x3e\\x7d\\xfa\\x14\\x2b\\xe1\\xfc\\xe9\\x4f\\x7f\\x22\\xb2\\x84\\x5e\\xa4\\x09\\xcf\\x17\\x1f\\x84\\xa7\\xfe\\xfd\\xd9\\xb3\\x11\\xf9\\xef\\x93\\x37\\xaf\\x21\\xa3\\xa1\\xd0\\x0a\\xab\\xbe\\xe1\\xc8\\xe6\\x81\\xe8\\x65\\x35\\x20\\xff\\x75\\xf9\\xee\\x6d\\x5d\\xa3\\x21\\xfe\\x15\\x54\\x73\\xbf\\xbc\\xb8\\x2f\\xc8\\xd3\\x3f\\xfe\\xe1\\x0f\\x23\\x72\\xca\\x4b\\xc8\\xe8\\xe2\\xcc\\xf7\\x9c\\xf7\\xa6\\x16\\x5a\\x32\\xac\\xdc\\x03\\x35\\x54\\x9c\\xc4\\xc5\\x7d\\x7b\\x47\\x9b\\x9f\\x9c\\xf3\\xe9\\x4c\\xdb\\x8c\\x58\\x83\\x90\\x19\\x4f\\x34\\x26\\x8f\\x21\\x59\\x73\\x2d\\xed\\xb1\\xa5\\x88\\x6d\\xd2\\x63\\xa5\\x3f\\x98\\xdc\\x80\\x64\\xfc\\x8a\\x91\\x89\\xfa\\xb6\\x94\\x55\\x51\\x97\\x79\\xb4\\x8d\\x98\\x6d\\xa2\\x0c\\x0e\\x56\\xef\\x95\\x62\\xfa\\x91\\x87\\xad\\xee\\x65\\x6a\\x8e\\x70\\x1b\\x46\\x6a\\x08\\xac\\x36\\xbd\\xb5\\x2e\\x75\\x58\\x50\\xee\\x93\\x61\\x20\\x02\\x30\\xea\\x01\\xea\\x6d\\x3d\\x29\\x79\\xe1\\xa9\\x8a\\xab\\x39\\x52\\x94\\xf2\\xef\\x88\\x02\\x90\\x8b\\x1c\\x90\\x67\\xc8\\x15\\x86\\x9d\\xb4\\x99\\xc2\\x81\\x77\\xcb\\xe5\\x53\\xdb\\xa6\\xf3\\xee\\xb6\\xed\\x64\\xb3\\xd8\\x0e\\x2c\\xe3\\xca\\x7c\\x02\\x8a\\xfd\\xac\\xf9\\x72\\xdd\\xcb\\xd8\\x60\\xa9\\x42\\x7c\\xa9\\xc4\\xc2\\xdb\\xb6\\xb0\\x8a\\x25\\x97\\xb6\\x09\\xa8\\xad\\xaf\\x58\\x8f\\x81\\xe5\\x01\\x6c\\x1d\\x1c\\xfb\\xac\\x83\\x92\\x07\\x44\\x14\\x6f\\xad\\x98\\xae\\x2c\\x68\\x20\\x8a\\xde\\x7c\\x1b\\x1a\\x54\\xc2\\x0a\\x73\\x5a\\x5e\\x19\\xc5\\xd5\\x52\\x97\\x11\\x39\\x37\\x93\\xf4\\xa5\\x74\\xb0\\xd8\\xf1\\x35\\x3a\\x36\\x73\\x3a\\x87\\xcf\\x5a\\xc1\\x0d\\x3e\\x72\\x38\\x1a\\x1d\\xe2\\xf1\\x93\\x25\\x51\\x9a\\x96\\xf6\\x2c\\x99\\xfb\\x5f\\x46\\x95\\xf5\\x37\\xb4\\x50\\x58\\xf5\\xd7\\x48\\xaa\\x50\\x11\\x5b\\x42\\xee\\xba\\x9e\\x39\\x12\\x44\\x2d\\xac\\xfb\\xca\\xe8\\x64\\x08\\x80\\xd9\\x79\\x80\\x07\\x5e\\x15\\xdd\\xee\\xbe\\x3d\\xe5\\x0f\\xa2\\x64\\x77\\xbe\\x87\\xc0\\x81\\x57\\xd3\\xa7\\x9a\\x36\\x3c\\x1b\\xad\\xe4\\x0d\\xdb\\x15\\x2a\\x63\\x8f\\x4a\\xc0\\x58\\xde\\x05\\xd6\\x12\\xce\\x50\\x00\\x0b\\xdb\\x83\\x3e\\x5e\\x39\\x02\\xaf\\x2e\\xa4\\x09\\xbc\\xf6\\x97\\x29\\xf0\\xda\\xc7\\x89\\x8c\\x57\\x84\\xc3\\xce\\x93\\x8c\\xc0\\xb4\\x0c\\x0c\\x79\\xd4\\xa4\\xde\\x02\\xe8\\xd5\\x57\\x04\\xc7\\x1a\\x1b\\xdb\\xba\\x06\\xcd\\x82\\xd0\\xb1\\x92\\x59\\xa5\\xf1\\xd5\\xfa\\xc7\\x90\\xfb\\xc1\\xa0\\xae\\x66\\x38\\xb0\\x3c\\xff\\x58\\xc0\\x0b\\x41\\x0a\\x40\\xf6\\xb1\\x0f\\x5b\\xc4\\x6b\\x6f\\xb2\\xb1\\x8f\\x11\\xe2\\x57\\x64\\x80\\xd8\\x1b\\xce\\x5e\\x61\\xeb\\x02\\xd6\\x6e\\x30\\x9f\\x71\\x77\\x33\\x63\\x36\\x04\\x22\\x90\\xfb\\x0c\\x35\\x35\\x34\\x02\\x84\\x4a\\x27\\xc2\\x61\\xe1\\x9c\\xf4\\x5e\\xcc\\x8c\\x89\\xe2\\xfb\\xdb\\x12\\x14\\x27\\x47\\x2f\\x7c\\x7a\\xbc\\x0b\\xbb\\x3b\\x13\\x9a\\x95\\x13\\x9a\\xb0\\xe3\\xd0\\xc6\\xc0\\x8a\\x19\\xcb\\x59\\x69\\x00\\x65\\x9f\\x73\\x39\\xda\\x33\\x2a\\x52\\x5b\\x76\\x2a\\x61\\x25\\x9c\\x60\\xf6\\x59\\xb3\\xd2\\x00\\xf5\\xc5\\xe5\\x19\\x49\\x4b\\x7e\\xcd\\x4a\\x45\\x8e\\xfe\\x06\\xe5\\x04\\xb1\\xdc\\xd4\\xf1\\x23\\x0c\\x83\\xc5\\x85\\xdc\\x87\\x05\\x04\\x3e\\xdc\\x4d\\xea\\x07\\x0c\\xe5\\x68\\xb8\\x08\\xe8\\x4c\\xbd\\x55\\xae\\x36\\x96\\xd9\\x56\\x15\\xda\\x8e\\x46\\xe6\\x40\\x00\\x0b\\x05\\xea\\x0b\\x1d\\xad\\xd1\\xb7\\xe9\\x8a\\xd9\\x43\\xe3\\xad\\x44\\xe3\\xc0\\x54\\x91\\x92\\x4d\\x8d\\x36\\x56\\x06\\x45\\xfb\\xb0\\x4c\\xca\\xbd\\x25\\x37\\x74\\x9f\\x50\\x52\\x3b\\xab\\xd6\\xe5\\x7e\\x4c\\xac\\x5e\\x29\\xaf\\x79\\xea\\xc4\\x21\\x2c\\x8c\\xef\\x4b\\xc3\\x15\\x54\\x05\\xc5\\x0b\\xa8\\x52\\x32\\xe1\\x60\\x6a\\x0a\\xb6\\x06\\xb5\\x54\\x10\\x9a\\xe2\\x56\\x68\\xce\\xdd\\x1c\\xba\\xc9\\x24\\x34\\x14\\xda\\xa9\\x0f\\x2b\\xe9\\x84\\x21\\xca\\x94\\x9d\\x57\\xe3\\x8c\\xab\\xd9\\x65\\xa7\\x2e\\x91\\x65\\x03\\x63\\x50\\xe2\\x42\\xa4\\xca\\x4a\\xcf\\x88\\x62\\x42\\x71\\xdb\\x36\\x1f\\xc5\\x2d\\x2e\\xa1\\xcb\\x82\\xd9\\x06\\xf7\\x76\\x78\\x28\\x24\\x64\\xc3\\x43\\x33\\x7e\\xf7\\xd3\\xdb\\x7a\\x1e\\xb6\\x58\\x09\\x76\\x81\\x4e\\xd9\\xf7\\xa2\\x88\\xee\\x27\\x34\\xcb\\x94\\x95\\x6f\\x7d\\x8f\\x13\\xc7\\x7b\\x50\\x42\\x75\\x05\\x4c\\x10\\x2b\\xb8\\x41\\x18\\x37\\x7b\\x08\\xc1\\x41\\xe2\\xe5\\x1b\\xf2\\x2c\\x5d\\x98\\x0a\\xca\\x0d\\x4b\\xe1\\x1e\\x82\\x66\\xd6\\xee\\x05\\x0f\\x21\\xcc\\xc4\\x41\\xa4\\xbb\\xc7\\x56\\x28\\xbd\\xfb\\xe7\\xf1\\xb9\\x7f\\x6e\\x27\\xa7\\xa2\\x6e\\x31\\x4a\\xe1\\xe6\\x10\\x32\\xb4\\xd0\\xb5\\x51\\xd9\\xb6\\xb9\\x8e\\xd1\\x38\\x86\\xb4\\x21\\x4c\\xf3\\xde\\x5c\\xc0\\x38\\xbf\\x13\\x6d\\x7b\\x51\\x74\\x63\\xdd\\x6d\\x0e\\x0a\\xa2\\x98\\x51\\xc5\\x81\\x42\\x0d\\x2d\\xfc\\x92\\xe0\\x48\\x59\\x1d\\xd9\\x9f\\xf3\\x45\\xba\\x56\\xf3\\x74\\x60\\xe7\\x78\\xf3\\x50\\x91\\x54\\x26\\x95\\x51\\xbe\\x6a\\xb0\\xd7\\x01\\x17\\xfb\\x75\\x2b\\xfc\\xb2\\xda\\x27\\xa5\\xf2\\x46\\xdc\\xd0\\x32\\x3d\\x39\\xdf\\x29\\x37\\x37\\x16\\xce\\xea\\xb1\\x42\\xd1\\xdb\\xdd\\x26\\xe6\\x3e\\x1d\\x43\\xc1\\x5b\\x5b\\xdb\\xb0\\xf7\\xf6\\x2d\\x1d\\x22\\xa4\\xe6\\xcb\\xcc\\x6d\\x5a\\x1a\\x22\\xdb\\xd2\\x9b\\xb7\\xad\\xc1\\xae\\x77\\x10\\xf6\\x0e\\xc2\\xe8\\x7a\\x48\\x0e\\xc2\\x33\\x74\\x10\\x86\\x9d\\x7e\\x23\\xf2\\x62\\x2d\\xb4\\x06\\xe2\\x5f\\x84\\x8f\\xe9\\xb4\\x26\\xa9\\x28\\x89\\x37\\xf3\\x79\\x1b\\xc2\\x3f\\x1e\\xde\\x1a\\xeb\\x02\\x85\\xc1\\xd1\\x5c\\x90\\xcb\\xbe\\x04\\x7f\\xd4\\x03\\xf0\\x27\\x01\\x2c\\xf7\\xd0\\x0a\\xf1\\x8a\\x09\\x7e\\x9d\\xaf\\x86\\x55\\x6a\\xd1\\x31\\x1d\\x78\\xb8\\x0b\\x99\\xda\\xde\\x06\\xd0\\x74\\x03\\x1b\\x08\\x0c\\x7c\\x67\\x40\\xe1\\xd2\\x4d\\x41\\x3a\\x2f\\x68\\xc2\\x80\\xbe\\x79\\xf1\\xa7\\x13\\x27\\xc1\\x9e\\x08\\x40\\x3a\\x42\\x02\\x02\\x88\\x00\\xd0\\x39\\xdf\\x07\\x1b\\x48\\x67\\x18\\x61\\xae\\x5a\\xe3\\xd9\\x77\\xa4\\x66\\x45\\x51\\x1c\\xd5\\x21\\x82\\x4a\\x66\\x2c\\xa7\\xf0\\xdf\\x57\\x0e\\x04\\x86\\x36\\x1a\\xe5\\x41\\x33\\x2c\\x01\\xc7\\xca\\x5c\\x11\\x39\\x19\\x44\\x91\\xae\\x07\\xd7\\xcf\\x0e\\xf6\\x73\\x36\\x90\\xee\\xfc\\x94\\xc4\\x9d\\xa3\\xf3\\xbd\\x9d\\x3d\\xa4\\x09\\xb0\\xf3\\xc8\\xb7\\x63\\xce\\x50\\xdd\\x03\\xd3\\xd5\\xbd\\xf7\\x11\\x14\\xc0\\x3f\\x10\\xc2\\x0f\\x06\\x38\\x5d\\x3b\\x71\\x77\\x75\\xde\\x0e\\xbc\\xd7\\xe0\\x11\\x08\\x7f\\xbd\\xf3\\xf6\\x4b\\x74\\xde\\x06\\x8c\\xd1\\x11\\xba\\x25\\x8e\\xdc\\xd0\\x25\\xe0\\xbc\\xb9\\x63\\xe6\\x94\\x1a\\xab\\xc3\\x38\\x57\\xae\\xf3\\xe3\\xca\\x32\\x0e\\x5d\\x3a\\x1c\\x8d\\x0e\\x0f\\x9d\\x77\\xd7\\xe2\\x7d\\xa5\\x27\\xc3\\xff\\x20\\x4c\\x24\\x32\\x75\\x0d\\x7c\\x27\\xbc\\x54\\x1a\\xc4\\xbd\\xda\\xdc\\x16\\xce\\x25\\x77\\xdf\\x0a\\xc3\\x9f\\x60\\xec\\x2e\\xb6\\x7a\\x6f\\xda\\xe2\\x4a\\x12\\xbe\\xba\\x05\\x21\\xa6\\x16\\x5d\\x7c\\xe1\\x43\\x0b\\x22\\x5f\\xcf\\xda\\xca\\x30\\xee\\x77\\x45\\x32\\x9e\\x73\\xdb\\xff\\xde\\x1c\\x74\\xa6\\xb4\\x22\\x47\\x78\\x73\\x94\\x14\\xd5\\xc0\\x3e\\x30\\xca\\x59\\x2e\\xcb\\xf9\\xc0\\x3f\\x64\\x7e\\x8c\\xde\\xb2\\x4f\\x1c\\x63\\xbf\\x93\\xaa\\x2c\\x99\\xd0\\xd9\\xfc\\x4b\\x96\\x80\\x1c\\x10\\x1f\\x88\\x00\\xe4\\xf7\\x78\\x9f\\x8a\\x23\\xf5\\x15\\xa3\\x56\\xed\\xf1\\x05\\xb3\\x79\\xd0\\x5f\\xc0\\x57\\xa3\\x55\\x83\\xda\\x2f\\x6e\\xee\\x32\\x71\\x4d\\xae\\x69\\xb9\\x65\\xe5\\xf8\\x65\\x57\\x87\\x32\\x4f\\xca\\xaf\\xb9\\x92\\x3b\\xbb\\x45\\x83\\x81\\x42\\xf0\\x5c\\x7a\\x23\\xb4\\x39\\x6c\\xb2\\xd2\\x45\\xa5\\x2d\\x45\\x77\\x27\\xd0\\x55\\x19\\xf7\\x27\\xaf\\x21\\x1c\\x3e\\xdb\\xa5\\x8b\\x52\\x7c\\x15\\x54\\x6b\\x56\\x8a\\xe7\\xe4\\x7f\\x8e\\x3e\\xfe\\xee\\x97\\xe1\\xf1\\x37\\x47\\x47\\x1f\\x9e\\x0e\\xff\\xfc\\xe9\\x77\\x47\\x1f\\x47\\xf0\\x9f\\xaf\\x8e\\xbf\\x39\\xfe\\xc5\\xfd\\xf1\\xbb\\xe3\\xe3\\xa3\\xa3\\x0f\\xdf\\xbd\\xf9\\xf6\\xfd\\xf9\\xcb\\x4f\\xfc\\xf8\\x97\\x0f\\xa2\\xca\\xaf\\xf0\\xaf\\x5f\\x8e\\x3e\\xb0\\x97\\x9f\\x5a\\x0e\\x72\\x7c\\xfc\\xcd\\x6f\\xf7\\x9e\\x3a\\x15\\xf3\\x77\\x7b\\x92\\x42\\xbc\\x86\\x1d\\xb2\\xe4\\x78\\xc4\\x4e\\xd0\\xaf\\xd1\\x56\\x82\\x0b\\x3d\\x94\\xe5\\x10\\x87\\x7e\\x0e\\xc5\\x82\\xf7\\xfc\\x80\\x43\\xaf\\xae\\xcf\\x7f\\x2d\\x06\\xd4\\xe5\\xf6\\x9d\\x50\\x7f\\xcf\\x07\\x1c\\x5c\\x9f\\xa7\\xbc\\x83\\x34\\x63\\x37\\x52\\x9c\\x26\\xa3\\x59\\x5e\\xc8\\x92\\x96\\x73\\x92\\x5a\\x6b\\xe6\\x7c\\x49\\x05\\xa2\\xa0\\x04\\xd1\\xde\\x25\\x85\\x61\\x1e\\x29\\x2f\\xef\\x21\\xd3\\x78\\xef\\x8a\\x42\\x2c\\xe5\\x55\\xde\\x51\\x3d\\x21\\x18\\x2b\\xdc\\x8c\\x1b\\xa8\\xbc\\x6f\\xab\\xf6\\xbb\\x90\\x22\\xfb\\x98\\x75\\x68\\x8c\\x69\\x72\\x85\\x1a\\x94\\xdf\\x2d\\x94\\x1b\\x83\\xd4\\xfa\\x83\\x03\\x1b\\x12\\x91\\x33\\x2a\\xbc\\x61\\x1f\\x62\\x5b\\x64\\xca\\xcc\\x56\\xba\\x87\\x71\\xec\\xc8\\x08\\x8f\\x9e\\x76\\x1b\\x40\\x58\\x77\\xa4\\x92\\x25\\x79\\x03\\x02\\xd0\\xbd\\xee\\x3e\\xe9\\xa4\\x56\\x08\\xff\\x07\\x7b\\x6d\\xa4\\xbe\\x8e\\x32\\x51\\xdd\\x70\\x2e\\x80\\x48\\x4b\\xd0\\x37\\x6d\\x5d\\xaf\\x09\\x34\\xd9\\xaa\\x23\\xc4\\x22\\xc9\\x02\\x36\\xf2\\xa5\\x3b\\x96\\xce\\x7f\\x6b\\xb6\\xd3\\x8c\\x8a\\xb2\\x29\\x18\\xa6\\x33\\x85\\x71\\x2b\\x3c\\x81\\x3e\\x50\\xa0\\x9b\\xc2\\x76\\xf8\\x2d\\x7c\\x1f\\x34\\xea\\xaf\\x94\\xf9\\x92\\x14\\xf1\\x33\\xf5\\x87\\xb0\\x4d\\xd6\\x18\\x71\\xc2\\x75\\xd7\\x8e\\x35\\x6a\\xf3\\xcb\\xa5\\x5f\\x59\\x6d\\xcf\\x80\\x94\\x65\\xa7\\x7e\\xaa\\x0a\\x94\\x14\\xfb\\x15\\x2b\\x6a\\xcb\\x09\\x44\\x56\\x04\\xfd\\x7a\\x5c\\x4b\\x9a\\x05\\x44\\x15\\x3c\\x8b\\x31\\xd5\\x75\\x9e\\xf0\\x0b\\xaf\\x84\\x0d\\x28\\xbc\\x77\\xb4\\x7b\\x74\\xd2\\xc7\\x9e\\x32\\x47\\x57\\x92\\x46\\x27\\xf2\\x45\\xe7\\x52\\x85\\x8f\\xdc\\xdc\\xbf\\xdf\\x6b\\x1d\\x04\\x1a\\xb1\\xd5\\xb0\\x47\\x46\\x1c\\x10\\x4a\\x7d\\x5b\\x34\\x47\\x13\\x5c\\xd4\\xc1\\x7b\\x6f\\x51\\xb2\\xec\\x36\\x99\\x27\\xb6\\xc2\\x13\\x8f\\x3a\\xf8\\xe0\\xb0\\x78\\x34\\x20\\xb7\\x6a\\xe8\\xbb\\x57\\xd7\\x76\\x09\\x32\\x66\\x13\\x0c\\x7c\\xc2\\x77\\xc0\\x60\\x60\\x33\\xc2\\x52\\x96\\x31\\xcd\\x82\\xb6\\xf3\\x05\\x36\\xca\\x2e\\x59\\x2e\\xaf\\x6d\\x9b\\xd6\\xef\\x95\\x75\\x9b\\xf3\\xc9\\x73\\x42\\x8f\\xa3\\xbc\\x63\\x65\\xfb\\x20\\x33\\x96\\x62\\x9a\\x58\\xd0\\x5b\\xb0\\xac\\x84\\x1a\\x90\\xf1\\xb1\\x0b\\x6b\\xb5\\x5d\\x30\\x4b\\xb0\\xad\\xd9\\x26\\x5f\\x60\\xce\\x2a\\x99\\x01\\x00\\xd4\\xaa\\x2a\\x65\\x4e\\x94\\xa0\\x85\\x9a\\x49\\x0d\\x96\\x13\\x5a\\xd0\\x84\\xeb\\x39\\xd1\\x25\\x4d\\xae\\xcc\\x23\\xe0\\x4e\\x85\\xcf\\x0d\\x48\\x72\\x6c\\xa3\\xdc\\x43\\xf0\\xc5\\x99\\x6b\\x7a\\x56\\xca\\x6a\\x3a\\x83\\x54\\x2a\\x7c\\x2a\\xc9\\xa8\\x72\\xab\\x5f\\xfa\\xbe\\x55\\xe5\\x15\\x49\\xe7\\x82\\xe6\\x3c\\xf1\\x2d\\x44\\x4a\\x79\\xcd\\x15\\x97\\xd6\\xe1\\xe5\\xc6\\x3d\\xf7\\xcd\\x18\\xd0\\x89\\xf6\\x22\\xa3\\x3c\\x27\\x47\\x8a\\x31\\xf2\\xd2\\xa1\\x04\\xfe\\x72\\x89\\x02\\x25\\x1a\\x14\\xcb\\x38\\xb6\\xce\\xd6\\x7d\\xb4\\xf5\\x07\\xcc\\x9d\\x9a\\x02\\xfb\\x88\\x05\\x94\\x09\\xcc\\xcc\\x97\\x7e\\xf4\\xd8\\x6f\\xd7\\xf2\\x39\\xc9\\x12\\xe2\\xde\\x5c\\x27\\x20\\x26\\x52\\x19\\x04\\xc6\\x9c\\x9c\\x9f\\xa9\\x50\\xcd\\xb5\\xdd\\x14\\x71\\x24\\xf8\\x21\\x93\\x62\\x1a\\xd6\\xbf\\xab\\x31\\xd3\\xd0\\x7a\\x01\\x6d\\x31\\xaf\\x79\\x5a\\xd1\\x0c\\xa9\\xbc\\x9d\\xcc\\x8b\\xcb\\x33\\x7c\\x9d\\x4f\\x67\\x7a\\x78\\xc3\\xc0\\x08\\x8a\\xcc\\xb0\\x3e\\x33\\xee\\xa3\\x7c\\x21\\xe0\\x96\\x2b\\xe0\\x0a\\xda\\x1a\\xdb\\xd0\\xa0\\x0c\\xad\\x27\\xe9\\x1c\\xea\\xef\\xda\\x18\\xcf\\x28\\x26\\xc7\\x55\\xab\\xc7\\x21\\x96\\x41\\x1c\\xa6\\x77\\xe2\\xfb\\x24\\x1a\\xc9\\x08\\xac\\xc4\\x06\\xc4\\x80\\xa9\\x8b\\x73\\x83\\xa6\\x8f\\x75\\xeb\\x0d\\x7f\\x5b\\xd7\\x0d\\x20\\x41\\x2e\\xde\\xbd\\x51\\xf0\\xbd\\xc9\\xb3\\xd7\\x35\\x9a\\xbc\\x67\\x79\\x91\\x51\\xdd\\x4d\\x84\\xc9\\xc1\\x8f\\x81\\x15\\x3c\\xf0\\x21\\x9b\\xe3\\x48\\x45\\x3a\\xa4\\x99\\xc1\\xc8\\xf3\\x1f\\x5e\\xd8\\x04\\x37\\x3c\\x60\\x51\\x14\\xdb\\xfb\\xba\\x55\\xa9\\xeb\\x52\\x6d\\x84\\xa5\\xa5\\x47\\x0b\\x4a\\xaa\\x8d\\x59\\x0a\\xc4\\xc8\\x7e\\x19\\x4c\\x15\\x37\\x02\\x5b\\x05\\x9b\\x3f\\xce\\x7f\\x78\\x31\\x20\\x7c\\xc4\\x46\\xee\\x2f\\xff\\xa8\\xa3\\x86\\x5a\\x4e\\x31\\xcf\\xc1\\x27\\xd2\\x00\\x3e\\xc3\\x54\\x42\\x1b\\x70\\xf8\\xee\\x4f\\x7f\\x31\\x93\\x34\\xbf\\xfe\\x75\\xf8\\x97\\xa0\\xa5\\xd1\\x5f\\x7f\\x32\\xc4\\xb5\\x34\\x0f\\xc4\\x77\\xc3\\x30\\x73\\xa0\\x7b\\xe6\\xaf\\x9f\\xce\\x65\\x7a\\x59\\xb0\\x64\\x84\\xcb\\x52\\x3f\\x61\\xb0\\x00\\x61\\x42\\x1b\\x91\\xfb\\x5c\\x42\\x80\\x19\\x4f\\x11\\xcb\\xe1\\xdb\\x25\\xfb\\xbb\\xf3\\x13\\xd8\\xae\\xa9\\x96\\x90\\x24\\x54\\x33\\x01\\x0c\\xc0\\xe5\\x1b\\x0b\\xa9\\xf1\\x75\\xec\\xb7\\x0a\\xf3\\x3f\\x9a\\x84\\x1d\\x50\\xb5\\x94\\x70\\xcc\\x91\\x94\\x9c\\x08\\xc2\\x3e\\x73\\x05\\xe5\\x67\\x70\\xad\\x00\\x0e\\x6a\\x63\\xd8\\x1d\\x4f\\x33\\xc3\\x1a\\x08\\xfb\\x6a\\x43\\xd0\\x82\\xd5\\xcc\\xed\\x2b\\x21\\xf5\\x57\\x7e\\xfb\\x5d\\x7c\\x22\\xf6\\x33\\x27\\xf4\\x5a\\xf2\\x94\\x54\\xd0\\x3e\\xcb\\x9c\\x40\\x01\\x06\\xee\\xba\\x83\\xe1\\x78\\x4e\\x72\\xae\\x34\\xbd\\x62\\x23\\x72\\x69\\x78\\x56\\x18\\x68\\x80\\xd0\\x13\\x04\\x9a\\xd1\\xb0\\x94\\x54\\x42\\xf3\\x0c\\x7e\\xad\\xc7\\x31\\x53\\x0e\\x79\\xd9\\xd9\\x84\\xa8\\x2a\\x81\\x1e\\xbd\\x25\\x1b\\x3a\\xee\\x68\\x9f\\x5a\\xa0\\x31\\xf5\\x5a\\x06\\x7e\\xb3\\x67\\x14\\xd5\\xa8\\x22\\x85\\x57\\xb1\\xe3\\xaf\\xb0\\xe8\\xb5\\x10\\x5e\\x6d\\xe6\\x29\\x45\\x52\\x73\\x44\\x00\\x26\\x74\\xd9\\x36\\x4c\\x30\\x73\\x71\\x40\\xa8\\xd1\\x59\\xbf\\x81\\x60\\x09\\x53\\x8a\\x96\\x73\\x6c\\x8a\\xca\\x7d\\xef\\x46\\x1b\\xf9\\x0a\\x9c\\x3a\\xa7\\xa2\\x82\\x01\\x4a\\x86\\x2d\\x76\\xab\\x04\\xa0\\x43\\xc9\\xb8\\x94\\x57\\x4c\\xf8\\x4c\\x02\\xb3\\x8b\\x71\\x5c\\x75\\x1d\\x3c\\x8a\\xdd\\xa7\\x49\\x32\\xa3\\x62\\xca\\xea\\x64\\xf2\\x9c\\xa6\\x00\\xfb\\xef\\xbc\\xa4\\xe5\\xd6\\x63\\x20\\x40\\x27\\x46\\x60\\xe1\\x1a\\x40\\x31\\x36\\xfc\\xc9\\x7b\\x3f\\x3e\\x0a\\x5f\\x0e\\x77\\x50\\xbb\\x27\\xcc\\x92\\x78\\xb6\\x13\\x4d\\x24\\xdd\\xd8\\xc3\\xf7\\xb7\\x84\\x0f\\x41\\xa0\\xb8\\xc7\\x18\\xee\\x9c\\x69\\x9a\\x52\\x4d\\x3b\\x8b\\xe3\\x7e\\x43\\x7d\\xf3\\x4f\\x1b\\xdb\\x01\\xe8\\x10\\xc4\\x7c\\x58\\x1e\\xeb\\x44\\x49\\x59\\xf0\\xb0\\xbc\\x00\\x50\\x83\\x99\\xdb\\x7d\\x28\\x4f\\xa5\\x0d\\x5e\\x5b\\xdf\\x23\\x86\\x67\\x83\\xac\\x46\\xb3\\x4c\\xde\\xd8\\x82\\x75\\x6e\\x34\\x24\\x59\\x2c\\x25\\x69\\x05\\x62\\x5f\\x4d\\xd2\\xf6\\xf1\\x8d\\x77\\xe2\\x3a\\x31\\x1b\\xdd\\x19\\x94\\xdf\\xd7\\x21\\x00\\x49\\x1c\\xa2\\xbd\\x54\\x40\\x43\\x5e\\xc7\\x84\\xe6\\xd8\\x4a\\xdf\\xd5\\x83\\xb0\\xc0\\xaf\\x04\\x1e\\xd5\\xc6\\x36\\xc0\\x3e\\x4d\\x99\\x56\\x75\\x70\\x25\\x72\\x13\\x43\\x22\\x2d\\x2f\\xb7\\xb6\\x04\\x60\\x35\\x76\\x6b\\xac\\x3a\\xbe\\x5c\\x52\\xc4\\x8d\\x53\\xd2\\x72\\x0b\\xc3\\xbf\\xee\\x7d\\x67\\xba\\xf3\\x21\\x61\\x17\\xdc\\x37\\x32\\xdd\\xdf\\x19\\xd5\\x68\\xe7\\x5a\\x0f\\x5c\\x27\\x9d\\x60\\x02\\x92\\x02\\x5b\\x0f\\x3e\\x00\\xae\\x79\\x15\\x55\\xcb\\x40\\x16\\x30\\xa3\\xd7\\xbb\\x5b\\x55\\x6b\\xc9\\x74\\xe8\\x7b\\xb6\\xc1\\xe7\\x86\\xf0\\xb9\\xe1\\xb3\\x7d\\xed\\xd7\\xfb\\x07\\x2f\\xba\\x6b\\xcf\\x20\\xc6\\x78\\x42\\x1d\\x38\\x2c\\x0c\\x69\\xbd\\xec\\xc4\\x9f\\xd0\\x28\\xa6\\xe4\\xc7\\xb5\\xfc\\xd7\\x06\\x68\\xf8\\xa0\\x18\\x9b\\x56\\xcb\\xb8\\xa1\\x9a\\xcf\\xc9\\x57\\x91\\xc4\\x65\\x25\\x5b\\xaf\\x0d\\x63\\x32\\xd3\\x91\\x53\\x8f\\x47\\x76\\xe3\\x5d\\x55\\xaf\\xf8\\xf1\\xe3\\xc6\\x60\\x20\\xea\\x2d\\xd7\\x1a\\x5d\\xd2\\x94\\x17\\xbf\\x8d\\xa8\\x0c\\xed\\xf8\\x7d\\xaa\\xaa\\x41\\xe6\\x52\\x66\\x99\\x6b\\xe1\\x8e\\x1a\\x72\\x23\\xc4\\x09\\xda\\x07\\xa1\\xd3\\x64\\xe0\\xcd\\x10\\x5e\\xde\\x17\\xec\\xc6\\x0b\\x76\\x54\\x61\\xd5\\x52\\xe7\\xb2\\x07\\x53\\x89\\x8b\\x3b\\x5b\\x36\\xde\\x08\\x7a\\xe0\\xc3\\xef\\x27\\x62\\x8e\\x93\\x3f\\x0d\\x80\\x8b\\x06\\x06\\x32\\x35\\x9f\\x32\\x3a\\x80\\xa0\\xe3\\xcc\\x48\\x21\\xc1\\x06\\xf8\\xef\\x34\\x58\\x9a\\x96\\xc1\\x53\\x17\\x6c\\x62\\x2d\\x03\\xe1\\xad\\x76\\xef\\x22\\x3f\\x8c\\x5e\\x1c\\xd5\\x51\\x92\\x56\\x4c\\x0e\\x2a\\x65\\x5a\\xa8\\x47\\x8f\\xc4\\x51\\x45\\x8d\\xd1\\xa2\\x82\\x3d\\xcb\\x66\\xb0\\x67\\xe8\\x41\\x87\\xc1\\x07\\xdd\\x85\\x1f\\x40\\x6d\\x18\\x2e\\x76\\x8f\\x29\\xae\\x87\\xd9\\xa1\\x63\\x78\\xf3\\xea\\x2e\\x8a\\x01\\x02\\x39\\x21\\x8a\\xab\\x0b\\x77\\x70\\x44\\x76\\x4e\\xce\\xcf\\x60\\x60\\xa7\\x61\\x4e\\xe1\\x0f\\x27\\x79\\x78\\xbf\\xe6\\x98\\x19\\xba\\x50\\x57\\xb4\\x02\\x8c\\x0c\\xdf\\x5d\\x12\\xe6\\x56\\x1f\\xce\\xef\\xa0\\x7d\\x93\\x75\\x17\\xb9\\xf4\\x65\\xc3\\xb8\\x4e\\xce\\xcf\\xf0\\x8b\\x23\\xe8\\xe0\\x4b\\xc5\\xdc\\xca\\x84\\x7a\\xc6\\xcb\\x74\\x58\\xd0\\x52\\xcf\\xd1\\xc8\\x32\\x88\\xbe\\xe6\\x73\\x38\\x3b\\x00\\x47\\xa7\\x9e\\xec\\x7d\\x3a\\xbe\\x85\\x57\\xb4\\x47\\x00\\x3e\\xe7\\x27\\xb2\\x8e\\xbe\\x95\\x3b\\xf3\\xd0\\x20\\xb2\\x6f\\x46\\xa9\\xbb\\x22\\x88\\x84\\x1d\\x7f\\x9c\\x8d\\xe5\\x51\\x40\\x24\\xa2\\xd1\\xb7\\x25\\x3f\\x18\\xf2\\xaf\\xe2\\xe8\\x1b\\x14\\x07\\x40\\xd6\\xb7\\x76\\x31\\x19\\xa6\\xb9\\x79\\xd9\\x12\\x8c\\x14\\x66\\xa4\\x01\\xe1\\x13\\xc3\\x88\\xa5\\x18\\xda\\xe4\\x7a\\x6f\\xc4\\xb7\\xf2\\xa9\\x0b\\x53\\x45\\x83\\x03\\x1c\\xdd\\xe0\\x2b\\xe1\\xab\\xfe\\x94\\x93\\x23\\x21\\x05\\x9e\\x7c\\x7c\\xf6\\x18\\xe3\\x73\\x57\\x58\\xa0\\xe1\\x11\\xcf\\xcd\\x43\\xbb\\x44\\x40\\x69\\x9c\\x98\\xc0\\x45\\x6a\\xb6\\x1d\\xd8\\x1e\\x58\\x2c\\x54\\x95\\x24\\x8c\\x79\\x1b\\x57\\xd8\\xd7\\xbe\\xa6\\x4c\\x76\\xca\\x39\\xd5\\xc9\\x8c\\x29\\xa2\\x24\\xd4\\x47\\x55\\x9a\\x66\\x59\\x6d\\x5b\\xb2\\x80\\x92\\x20\\xe9\\x38\\x3b\\x7f\\x20\\x00\\x45\\xd9\\xe8\\xd6\\xcc\\x56\\x64\\xd4\\xda\\x72\\x26\\x95\\x48\\x30\\x02\\x8c\\xeb\\x79\\xd8\\x19\\x35\\x12\\xf6\\x40\\xa1\\x56\\x68\\x72\\xe2\\x13\\xb4\\x2e\\x07\\x8a\\xb1\\x07\\x26\\x90\\xd6\\x39\\x12\\xd3\\x99\\xeb\\x3d\\x0e\\xba\\x9a\\x2d\\x02\\x68\\xe8\\xe8\\x98\\x26\\x57\\x37\\xb4\\x4c\\x15\\x24\\xda\\x53\\xcd\\xb1\\x17\\xe3\\x00\\xa5\\x8e\\x50\\x88\\x10\\x87\\x87\\xa1\\xa3\\x96\\x8b\\xa6\\x7c\\x13\\x4e\\xe4\\x28\\x98\\xf5\\x82\\xdc\\x73\\xec\\xe5\\x1d\\xc5\\x7c\\x97\\xbe\\x7a\\x62\\x84\\x56\\x5a\\xe6\\x54\\xf3\\x04\\x4c\\x51\\x7c\\x12\\x78\\x17\\x72\\xdf\\xdd\\xc2\\x3b\\x89\\x91\\x0b\\x00\\x5f\\xb1\\x0b\\xb7\\x78\\xb0\\x5c\\x02\\x5a\\x32\\xf1\\x60\\xae\\x6e\\x99\\xcb\\xe7\\x15\\xb0\\x26\\xfb\\xa1\\xf7\\xe8\\xaf\\x06\\x2f\\x58\\xc9\\x18\\xe1\\xb9\\x11\\x60\\x29\\x34\\xd0\\x9e\\xf8\\x9c\\x7f\\xe7\\x72\\x59\\x07\\x14\\x23\\xa5\\xff\\x08\\x7e\\xae\\xe0\\x29\\xb4\\xa7\\x65\\x99\\xbc\\x51\\x44\\xdf\\x48\\xaf\\xf4\\xd7\\xde\\x04\\x9b\\xdc\\x3e\\x68\\x88\\x74\\xf6\\x1d\\x73\\xd4\\x0c\\x58\\x82\\x73\\x34\\x30\\xb8\\x73\\xc3\\xb2\\xcc\\xfc\\xbb\\xee\\x34\\xa9\\xd1\\xb2\\x19\\xf1\\xa9\\xc0\\xf4\\x67\\xae\\x9c\\x05\\xc6\\xc6\\xb3\\x1f\\xa5\\xa5\\x2c\\x0a\\x6b\\x4b\\xcd\\x8f\\x9b\\x33\\x02\\xd7\\x65\\x79\\xcd\\x14\\x78\\xef\\x5d\\x84\\xbc\\x01\\xc3\\x94\\x09\\x56\\x52\\x0d\\x8e\\x10\\x5b\\xd4\\x11\\x08\\x4a\\xf3\\x13\\xd1\\x36\\x2e\\x9d\\x5c\\x08\\x2e\\x74\\x04\\xad\\x07\\x8f\\xfd\\x15\\x2c\\x16\\x06\\x52\\x0e\\x61\\xd4\\x08\\x0b\\xe7\\x1c\\x93\\xef\\x15\\x2e\\xc8\\x9f\\x59\\x1f\\xcd\\xdf\\x4a\\x67\\x40\\xb3\\xaf\\x55\\x1b\\x46\\xe4\\xe8\\x24\\x2b\\x66\\xc1\\xa8\\xa1\\x94\\xee\\xb3\\xa5\\xe2\\x99\\x46\\xdf\\x7b\\x51\\x4a\\xa5\\xde\\xba\\x57\\xb6\\xf9\\x74\\x2f\\xc1\\xaf\\x1b\\xa6\\x97\\xe0\\x7b\\x09\\x7e\\x87\\xab\\x97\\xe0\\x9b\\x57\\x2f\\xc1\\x37\\x2f\\x4f\\xe0\\x6f\\x05\\x2c\\x5e\\xbc\\x89\\x79\\xc9\\x3a\\x00\\x91\\xb7\\x52\\x5b\\x17\\x2b\\x88\\x78\\x74\\xa5\\xa5\\x88\\x02\\x23\\xb9\\xa1\\xf3\\x91\\x60\\xda\\x56\\xd4\\x71\\x46\\xc1\\x0b\\x37\\xde\\xb7\\xa5\\x11\\x76\\xac\\x6c\\x1c\\x1c\\x56\\x77\\xf2\\x5d\\x2d\\x9f\\xe0\\x2b\\x5a\\x22\\xff\\xad\\x3d\\xbe\\x70\\xff\\x50\\x59\\x7f\\xa7\\xf9\\x1d\\xf2\\xeb\\xc2\\x01\\x12\\x36\\x22\\x97\\xcc\\xb5\\x30\\x89\\x3e\\xbe\\x58\\x35\\x25\\x65\\x9a\\xf2\\x4c\\xd5\\x0c\\xf7\\xfd\\x0a\\x06\\xbe\\x3b\\x43\\x7d\\x48\\x78\\xe6\\x73\\x22\\xba\\xd5\\x12\\xeb\\x24\\xa7\\x20\\xf0\\x2c\\x8c\\xe8\\xac\\x1f\\x58\\xe5\\x72\\x38\\x9b\\x90\\x0b\\x96\\xc8\\x6b\\x56\\x22\\x6c\\x5f\\x7e\\x2e\\xa8\\x30\\x9a\\xd0\\x2b\\xca\\x33\\x03\\x59\\x07\\xe1\\xda\\xb8\\x0a\\xed\\xbc\\x62\\x17\\x5f\\x60\\xd1\\xf6\\x68\\x6d\\xb7\\x31\\xb7\\x93\\xb2\\x05\\x77\\xcc\\xf3\\x36\\x90\\xa8\\x28\\xd9\\x35\\x97\\x95\\x72\\x71\\xa7\\x95\\x46\\xa6\\xa4\\xb4\\xd5\\x3d\\x66\\x7c\\xea\\xbb\\x6e\\xfa\\x70\\xb0\\x92\\x25\\xb2\\x4c\\x6b\\xf4\\x55\\x9a\\xea\\x4a\\xc5\\xa9\\xec\\x09\\xfa\\xd4\\xba\\x73\\xa7\\x78\\x38\\x3e\\x20\\x29\\xad\\x4b\\x79\\x06\\x00\\xd6\\xc1\\x38\\xcd\\x18\\x20\\xd0\\x56\\x14\\xd4\\xd4\\x08\\x28\\x60\\x48\\xfd\\x30\\x4b\\x88\\x0b\\xdc\\x50\\x83\\x44\\x23\\xf7\\x13\\xbe\\x3c\\xa8\\x71\\xa7\\x0e\\xce\\xe0\\xaa\\x8e\\x2e\\xae\\x23\\x1d\\x38\\xe8\\x27\\xd4\\x10\\x94\\x40\\x11\\xf7\\xe4\\x04\\xd0\\xd7\\x89\\xf5\\xa7\\xa8\\xf9\\x5f\\xd8\\x6f\\x9d\\x64\\x46\\x1b\\x41\\xf2\\x14\\x90\\x94\\x25\\x51\\x14\\x3c\\xcf\\x2b\\x6d\\xce\\xc1\\x88\\x9c\\x61\\xde\\x2d\\xe8\\x34\\x56\\x55\\x9e\\xd4\\x39\\x9f\\xac\\x54\\x3b\\xc7\\x3e\\x84\\x57\\x77\\xce\\x37\\xd2\\x9d\\x03\\x8e\\x34\\xb7\\xfa\\x22\\xdc\\xb4\\xb0\\x9a\\x9e\\x14\\x0c\\x63\\x98\\xcc\\xfe\\xba\\x18\\xa7\\xe8\\xe9\\x9d\\x4b\\x66\\xc5\\x57\\x87\\x47\\x0b\\xaf\\xee\\xd4\\x20\\xbc\\x3a\\xd1\\x62\\xf0\\xea\\xf2\\xec\\xe3\\xd5\\x95\\x5c\\x88\\xd7\\xa2\\x74\\x08\\x94\\x1d\\x2c\\x73\\x91\\x94\\x18\\x61\\x47\\x21\\xd3\\xd1\\x12\\x0a\\xe0\\x63\\xee\\x64\\x6a\\x03\\xea\\x62\\xfb\\x21\\xa6\\xd9\\x9f\\x99\\xe1\\xaf\\x5c\\xf0\\xaa\\xe7\\x42\\xf4\\x9a\\xf2\\x0c\\x32\\x26\\xb8\\x50\\x3c\\x65\\xd8\\x15\\xc8\\x52\\x8e\\xce\\xd6\\xdb\\xa9\\x40\\xda\\x08\\x76\\x37\\xc4\\x73\\x98\\xd3\\x62\\x78\\xc5\\xe6\\x1d\\x6d\\x77\\x67\\x98\\xb8\\x38\\x51\\x84\\x44\\x4e\\x8b\\xbd\\x47\\xc7\\x64\\x92\\xce\\x79\\xd2\\xe1\\x6b\\x4c\\x52\\xc1\\x9b\\x63\\x2b\\x1a\\xb9\\xbc\\x99\\x3a\\x67\\x27\\x91\\x79\\x51\\x69\\x16\\x88\\x50\\x56\\xd8\\xd9\\x5a\\xae\\x88\\x4a\\x35\\x3e\\xc9\\xa9\\xa0\\x53\\x36\\xf4\\xc3\\x0e\\x6b\\x76\\xb1\\x73\\xeb\\xf0\\xf0\\xea\\x98\\x0c\\x76\\x5b\\x53\\x30\\xbc\\x1e\\x5d\\x3a\\x4d\\x7c\\x75\\x96\\xd0\\x4b\\x6e\\x25\\xa9\\x97\\x74\\x9f\\xd8\\x4b\\x6e\\x3f\\xb9\\x97\\xf8\\x62\\x0b\\xdd\\x9f\\xfb\\x0b\\x57\\xfc\\xa1\\x71\\xf2\\xad\\xaa\\xb4\\xee\\xe4\\x47\\x55\\x86\\xfd\\x38\\x5c\\x11\\x99\\x73\\xad\\x99\\x0b\\xaa\\xf6\\x27\\x19\\x82\\x60\\xc2\\xe4\\x77\\x4b\\x73\\xc0\\x7b\\x85\\x91\\xd3\\xec\\xb3\\x6f\\xaf\\x1a\\x28\\xf4\\x60\\x6d\\xbb\\xe1\\x0a\\x55\\x70\\x41\\x78\\x5e\\x60\\xb3\\x07\\xa0\\x1d\\x43\\x27\\x29\\x5b\\xef\\x90\\x9f\\x49\\x02\\xd1\\x9b\\x84\\x7d\\x06\\x1f\\x19\\x7e\\xac\\x27\\x53\\x3d\\x99\\xea\\xc9\\xd4\\x6d\\x90\\x29\\xac\\x09\\xb0\\x7f\\x89\\x8d\\x88\\x3c\\xb9\\x41\\x6d\\x11\\x4a\\x3a\\x66\\x19\\xf9\\xb9\\x62\\xe5\\x9c\\xc8\\x6b\\x16\\x64\\x66\\x41\\xa3\\x5a\\x23\\xc8\\x62\\x6e\\x93\\xf5\\x94\\xef\\x2b\\xc9\\x3e\\x50\\xb3\\x04\\xe8\\x0b\\x2f\\x3f\\x17\\x25\\xc3\\xda\\x61\\x9d\\x33\\x85\\xe6\\x07\\xe2\\x12\\xa0\\xb8\\x0b\\x7e\\x67\\x42\\x83\\x16\\x86\\x55\\x47\\x26\\x2e\\x5a\\x32\\x72\\xf2\\xf6\\xb4\\x4b\\xcb\\xe3\\x43\\x57\\xfa\\x4f\\xd6\\x80\\x08\\x41\\xe9\\x7f\\x01\\xbe\\xe7\\x23\\xa3\\xbd\\x73\\x99\\x5c\\xb1\\xf9\\xc0\\x26\\x20\\xd8\\x2e\\xe5\\xee\\x61\\xcc\\xe5\\x89\\x5b\\x25\\xee\\x57\\x62\\x3b\\xbe\\x1e\\x81\\xbd\\x60\\xbf\\xd6\\x78\\xf1\\x58\\x0e\\xb8\\x0f\\xd4\\xfe\\xb0\\x77\\x0b\\xbd\\xf0\\x5a\\xd5\\x4e\\x0f\\xb1\\x15\\xba\\x6f\\xb9\\x3a\\x03\\x1e\\x41\\xa1\\xb6\\x02\\x50\\xd8\\x07\\x6b\\x16\\x20\\xd0\\xe5\\x09\\xb7\\xf1\\x96\\x80\\xe5\\x8f\\x60\\x94\\xc9\\x7e\\xc5\\xe6\\x87\\xca\\x56\\xa1\\x93\\x42\\xcd\\x78\\xe1\\xfa\\xab\\x03\\x9d\\xb4\\xa7\\x92\\xfc\\x00\\x29\\x23\\x6e\\x08\\xa4\\x88\\x67\\x62\\x40\\xde\\x4a\\x6d\\xfe\\x79\\x09\\x39\\x70\\x70\\x8e\\x4f\\x25\\x53\\x6f\\xa5\\x86\\x3b\\x0f\\x1a\\xdc\\xb8\\xb4\\x5b\\x02\\xb6\\x0d\\xcb\\xb1\\x66\\x6b\\xc8\\xf6\\x84\\xaa\\x2f\\x2e\\x33\\x0a\\x80\\x6a\\x83\\xc5\\xfd\\xc6\\x70\\x45\\xce\\x04\\x91\\xa5\\x83\\xaa\\x76\\x2d\\x63\\x95\\x1d\\xc2\\x39\\xf6\\x83\\x60\\xab\\x25\\x63\\xd8\\xcd\\x90\\x65\\xb4\\x17\\x6b\\x86\\xf3\\xe1\\x54\\xdc\\xfd\\x02\\xbe\\x44\\x08\\x8d\\xf3\\xe9\\x5c\\xd0\\xb6\\x94\\x6a\\x36\\xe5\\x09\\xc9\\x59\\x39\\x85\\x8a\\x85\\xc9\\xac\\xeb\\x2d\\xee\\x8a\\x2f\\xe2\\xd5\\x21\\x77\\xc4\\xab\\x53\\x3c\\x04\\x11\\xe5\\x35\\x24\\xea\\xdd\\x8e\\xf8\\x83\\x63\\x23\\xbb\\xce\\x69\\x61\\x50\\xf0\\x9f\\x86\\x2b\\x03\\x16\\xfc\\x0b\\xda\\x22\\xab\\x11\\x39\\x21\\x8a\\x8b\\x69\\xc6\\xa2\\xdf\\xac\\x0b\\x2e\\x1c\\xc6\\x8c\\x60\\xd4\\xdb\\x9f\\x2b\\x7e\\x4d\\x33\\x86\\x89\\xb5\\x54\\xf8\\xa6\\x85\\x72\\xb2\\x20\\x74\\x0d\\x6c\\x6f\\x64\\x43\\x97\\xbd\\x51\\xf7\\xe0\\x8a\\xcd\\x0f\\x06\\x0b\\x68\\x7b\\x70\\x26\\x0e\\xea\\xe2\\xa7\\x11\\xa2\\x7a\\xe1\\x02\\xfc\\x31\\x07\\xf0\\xdb\\xc1\\xdd\\xc8\\x69\\x8f\\x40\\x8d\\xed\\x0c\\x27\\xad\\x97\\xf4\\x45\\x46\\xd1\\x2f\\xdf\\xad\\x47\\xbb\\x39\\xfa\\xb2\\x96\\x6c\\x97\\xc1\\x33\\x75\\x34\\x83\\x4d\\xda\\xee\\xdc\\xf5\\x0b\\x45\\x43\\xba\\x4a\\xa1\\xeb\\x00\\xfe\\x38\\xaf\\x7d\\x1a\\x81\\xb8\\x6b\\x49\\x13\\x1d\\x28\\x5f\\xec\\x8a\\xca\\x44\\xb5\\xc8\\xea\\x88\\xf1\\x15\\x10\\xff\\x01\\x9c\\xf8\\x72\\x42\\x5e\\xd5\\xad\\xd6\\xc0\\x5d\\x6a\\xc4\\x2a\\x5b\\x66\\x46\\x48\\x4d\\xb8\\x48\\xb2\\xca\\xfa\\xef\\xe1\\x55\\x74\\xfa\\x3e\\x2c\\xf0\\x76\\x8e\\xd8\\xf5\\xb0\\x0e\\xa3\\x5d\\x8c\\xfb\\x42\\xed\\x80\\x66\\xc4\\x2f\\x04\\x80\\xfb\\x18\\x57\\x84\\xf6\\x7d\\x42\\x6b\\xb2\\x53\\x96\\x74\\xdc\\x22\\x30\\x89\\xe5\\xcb\\x57\\x7c\\x5c\\x32\\xf2\\x62\\x46\\x85\\x60\\x59\\x50\\x7f\\xd1\\xda\\x4a\\xa9\\xd6\\x34\\x99\\x61\\x98\\x09\\x25\\xe6\\x1c\\x67\\x4c\\x1f\\x2a\\x32\\x93\\xe0\\x53\\x4c\\x66\\x5c\\xf8\\x8a\\x64\\xc2\\xd7\\x21\\xad\\x4b\\x31\\xdc\\x43\\x53\\xcd\\x7d\\x15\\xa4\\x0e\\xfb\\x31\\x1e\\xda\\x86\\x8c\\x16\\xef\\xc2\\x4e\\x88\\x71\\x9f\\xc6\\xba\\xb5\\x4f\\xf3\\x99\\xba\\xc7\\x95\\x3d\\xf3\\x00\\x79\\xe4\\xcb\\xd0\\x34\\x10\\x9e\\x5d\\xdf\\xe9\\x31\\xf7\\xf6\\x6e\\x2e\\x26\\xac\\x2c\\x71\\x87\\xc6\\xcc\\xbe\\x40\\xf8\\x84\\x54\\x22\\x08\\x1e\\xc7\\xf6\\x6f\\x33\\x79\\x43\\x52\\x49\\x6e\\x18\\x44\\x0b\\x19\\x01\\x02\\xc2\\xcf\\x95\\x13\\x3d\\x82\\x99\\x42\\xa6\\x4a\\x22\\xf3\\xa2\\x94\\x39\\xf7\\xe1\\xdb\\x16\\x3d\\xee\\xad\\xd4\\x60\\x56\\xed\\xdc\\xad\\x21\\xde\\xc5\\xac\\x12\\x71\\x9b\\xf4\\x57\\x2f\\x88\\xa6\\xe5\\x94\\x69\\xf3\\x0d\\x22\\xaa\\x7c\\xcc\\xf6\\xac\\xa8\\x78\\xdf\\xfd\\x7c\\x3a\\xed\\x9f\\x77\\xe8\\x1b\\xe8\\x45\\x50\\xdb\\xd0\\x19\\x8f\\x5c\\xb8\\xb7\\x20\\xd0\\x00\\xb2\\x60\\x26\\xb2\\x4c\\x5c\\x58\\xa3\\xeb\\xc9\\x87\\x0d\\x9c\\x0c\\x16\\xfe\\x60\\x19\\x67\\x25\\xb4\\xda\\xb3\\x9f\\xd2\\x3e\\x9d\\xf5\\x10\\x15\\x7e\\xfc\\xf1\\x6d\\x37\\x0d\\x91\\x0e\\xeb\\xf1\\x56\\x61\\xdd\\x8d\\x2c\\xb3\\xf4\\x86\\xa7\\x2e\\xa8\\xeb\\xc8\\x3c\\x7c\\xbc\\x1f\\x04\\xee\\xb1\\x3f\\xd2\\xde\\x27\\xfd\\xe6\\x86\\xa7\\x1d\\x01\\x1f\\x86\\x8a\\x81\\xee\\x52\\xfa\\x0c\\xd0\\x09\\x40\\x9d\\xa7\\x4c\\x68\\x43\\x2c\\x4b\\x45\\x8e\\xe0\\x8d\\x63\\xf2\\x92\\x63\\xf1\\x2a\\x78\\x1f\\x42\\xd1\\xf2\\x31\\x17\\x75\\x61\\xb4\\x7a\\x53\\x0d\\xbb\\x34\\x74\\xc3\\xa9\\xf7\\x8a\\x69\\x2c\\x3b\\x04\\x59\\xe6\\x52\\xcf\\x88\\xe2\\x79\\x95\\x69\\x2a\\x98\\xac\\x54\\x36\\xdf\\x13\\xb5\\x1f\\xeb\\xc6\\x4e\\x32\\xf6\\x19\\x4f\\xf8\\xfe\\x42\\x8f\\x1f\\x2a\\x16\\x7e\\x20\\xb9\\xaa\\xae\\x35\\xb8\\x20\\xfd\\xd4\\xb9\\x89\\xe9\\x13\\x2f\\x09\\xf9\\xda\\x59\\xec\\x33\\x4b\\x6c\\x59\\x85\\x22\\xab\\xa6\\x7c\\xa7\\x3a\\x3a\\x7d\\x07\\xf1\\x9d\\xde\\x6e\\xd7\\x41\\xbc\\x6e\\x94\\x5c\\x29\\x56\\xd7\\xfc\\xb5\\x45\\xee\\xee\\x4b\\x2e\\xe9\\xbe\\xe1\\xf7\\xfd\\xca\\x97\\xef\\x97\\x37\\xfb\\x4e\\x59\\xc1\\x44\\x0a\\x4d\\x87\\x5e\\xd5\\xe7\\x0f\\x27\\x7f\\x6f\\xb0\\xb7\\xcd\\x7e\\xba\\xe1\\x15\\xae\\x73\\x50\\xc4\\xa5\\x83\\x00\\xc9\\x99\\xcc\\x52\\x45\\xd8\\x67\\x5d\\x52\\xc3\\x0e\\x72\\x43\\xf8\\xfd\\x3b\\x13\\x42\\xc5\\xbe\\xa4\\xfd\\x4b\\x69\\x59\\x4b\\xee\\x48\\x02\\x4d\\xbf\\x50\\x09\\x54\\x75\\xda\\xcb\\xfe\\x50\\x85\\x1d\\xec\\x6b\\xe8\\x45\\xb7\\x3b\\x6e\\x6b\\x8f\\x0c\\xd4\\x52\\x07\\x15\\x97\\x44\\x58\\xd2\\x7e\\xbe\\x4e\\xa9\\x5a\\xac\\xed\\xb3\\x63\\x1b\\x7a\\xb5\\xa4\\x29\\x75\\x63\\x56\\xf7\\x78\\x58\\xfb\\x9e\\xf4\\x8f\\xab\\x27\\xfd\\x04\\x2a\\xa4\\xee\\xdf\\x36\\xc4\\x8e\\xd3\\xb0\\xd9\\xd9\\x9b\\x56\\x6c\\x6d\\x63\\xa3\\xb3\\x27\\x2a\\xe0\\xc9\\x66\\xdf\\xdc\\x40\\xb6\\xd2\\x18\\x51\\x66\\x37\\xea\\xb4\\xc8\\x4a\\x88\\xdd\\xa8\\xf9\\x7d\\x77\\xec\\xa6\\x9a\\x2a\\xa6\\xf7\\xb1\\x24\\xc7\\x02\\x66\\x3d\\x9e\\x21\\x39\\x21\\xe6\\xdb\\x9f\\xb0\\xef\\x3d\\x54\\x1e\\x71\\x55\\x43\\xc9\\xf0\\xaf\\x56\\x16\\x15\\xd1\\x93\\x46\\x0a\\x75\\x70\\x77\\x6d\\x45\\x98\\x8f\\x2c\\xc3\\x31\\x52\\xb3\\xdb\\x09\\xd5\\x3b\\x67\\xec\\xee\\xcd\\x8d\\xed\\x6c\\xbf\\xff\\xfe\\xec\\xb4\\x4b\\x10\\x9a\\xf1\\x9c\\xb4\\x0a\\xff\\x8f\\xc1\\x38\\xf2\\xc9\\x64\\x95\\xe0\\x3f\\x57\\xa1\\xa2\\x0d\\xd5\\xce\\x3d\\xe0\\xec\\xf3\\xf7\\x01\\x9d\\x69\\xc2\\x6a\\x37\\xc1\\x29\\x57\\x57\\xfb\\xb7\\x06\\x5a\\x18\\x32\\x3e\\xee\\xdf\\xbe\\x78\\x49\\xec\\xdd\\x56\\xd6\\xf9\\x6d\\xcc\\xf3\\xfb\\x36\\xf6\\x98\\x26\\xac\\x76\\xdc\\xa5\\x5c\\x5d\\xdd\\x43\\x5b\\xa1\\x7d\\x75\\xe0\\x22\\x7d\\xbb\\x5b\\x4a\\xce\\xc3\\xf4\\x34\\x34\\x35\\x3c\\xd7\\x79\\x20\\x68\\x89\\x31\\x97\\x15\\xb9\\xb1\\x95\\xb7\\xad\\x86\\xf8\\x9e\\x17\\xcf\\xc9\\x4b\\xa1\\xaa\\x92\\xd5\\x11\\x5a\\xcd\\xa1\\x8c\\xbc\\xd5\\x5a\\x5f\\x84\\xe2\\xe6\\xea\\x79\\x67\\x5e\\x89\\xae\\x31\\xf5\\x4b\\x71\\x73\\x14\\xb4\\xd4\\xa0\\xc8\\x75\\x83\\x48\\x7e\\x38\\x47\\xa7\\x83\\x1b\\xa2\\x0d\\x26\\x9d\\x4d\\x5c\\x6e\\xc6\\xc0\\x96\\xe1\\xf5\\x2d\\x87\\xdc\\x43\\x06\\x77\\x82\\xba\\xfc\\x21\\xb6\\xbc\\xf2\\xbd\\x30\\xc8\\x93\\x94\\x5d\\x3f\\x51\\x29\\x7d\\x36\\x80\\xcf\\xb8\\x2c\\xf7\\x78\\x4e\\x54\\x91\\x83\\x67\\x07\\x23\\x72\\xc9\\x73\\x9e\\xd1\\x32\\x9b\\x47\\xad\\x81\\xeb\\xe7\\x0c\\xdb\\x75\\x03\\x42\\x34\\xcb\\xd3\\x03\\x72\\x24\\x4b\\x18\\x39\\xa1\\x82\\x64\\xcc\\x15\\x01\\xb3\\xa7\\x7a\\x8e\\x7a\\xc7\\xf1\\xc3\\x20\\x91\\xe4\\xc1\\x78\\x8a\\x90\\x5a\\x76\\x84\\x6b\\xa9\\x93\\xa9\\x2c\\xbf\\x8f\\xfa\\x3c\\x9c\\xd6\\x0c\\x8f\\x0b\\xc3\\x05\\x47\\xe4\\x7b\\xcb\\xbe\\xac\\x5c\\x80\\xc8\\x00\\x87\\xd9\\x3d\\xf1\\xb0\\x36\\xeb\\xe1\\xd9\\x43\\x76\\xb2\\x6c\\x2c\\xba\\xee\\x1e\\x1a\\xa0\\x77\\xb5\\x9e\\x4c\\xb9\\xbe\\x60\\x85\\xec\\x40\\x86\\xc3\\x81\\x1a\\xfe\\x05\\xae\\xcd\\x0d\\xa9\\x38\\x34\\x76\\xa4\\x9a\\x50\\x24\\x49\\x49\\x95\\x51\\xa3\\xd4\\xa1\\x77\\x61\\x44\\x4e\\x5f\\x9e\\x5f\\xbc\\x7c\\x71\\xf2\\xfe\\xe5\\xe9\\x73\\xf2\\xad\\x1d\\x89\\x87\\x7a\\xc0\\x88\\xbc\\x0f\\x5b\\xb5\\x04\\x09\\x6f\\xb6\\x1f\\x86\\xff\\xd6\\xc0\\x92\\x58\\x2a\\xea\\x96\\x73\\x50\\xba\\x9e\\x0a\\x72\\x26\\xb8\\xae\\x9b\\xed\\x62\\x5e\\x40\\x26\\x85\\x8d\\xf4\\x37\\x6f\\x5b\\xef\\xc6\\x94\\x6b\\x5b\\x0c\\x19\\x07\\x33\\x3f\\xc7\\xa3\\xd9\\xac\\x70\\x23\\x6c\\xd6\\x49\\xdd\\x8f\\x50\\xf8\\xab\\xb7\\xe7\\x3e\\x14\\x55\\xd7\\x45\\xb2\\x1b\\x1d\\xcb\\x77\\x10\\x75\\x15\\xb2\\xd0\\x5b\\x5c\\xdf\\x47\\x66\\xeb\\x1b\\xa6\\xbb\\x5e\\x14\\xb2\\x8c\\xfa\\x99\\x8f\\x46\\x87\\x23\\x62\\xd8\\xf8\\xe1\\xe8\\xd0\\x89\\x7c\\xd9\\x42\\xd3\\x7d\\x3f\\x68\\xd8\\xf2\\x27\\x46\\xf8\\x11\\x21\\xef\\x5c\\x56\\x25\\xd4\\x41\\x5d\\xde\\xbf\\x1f\\x4b\\x96\\x07\\xdd\\xda\\x1b\\xc7\\xc6\\x55\\x9b\\xa9\\xc6\\xe1\\x47\\x6d\\x8f\\xa0\\x29\\xbf\\xb6\\xd5\\x2c\\xef\\xcd\\xa7\\x50\\x4f\\xb5\\x93\\x6d\\x0c\\x57\\x6e\\x35\\xe5\\x8b\\xd7\\xf7\\xb7\\x36\\xa4\\x38\\x1d\\xad\\xcc\\x92\\x2f\\xbb\\xae\\x44\\xe6\\x39\\x36\\xb5\\x99\\xf9\\x3a\\x7b\\x75\\xa9\\x3c\\x4f\\x1d\\xef\\x45\\xcb\\xc7\\x56\\x3e\\x93\\x9d\\x0e\\x76\\x83\\x33\\xb8\\xa1\\x1a\\x5a\\xbd\\xbf\\x6d\\xb3\\x9f\\x45\\xad\\x4e\\x6d\\xdf\\x01\\xd8\\xf6\\x92\\x52\\xae\\x04\\x99\\x65\\xb3\\x4f\\xfc\\xc7\\x9f\\x5c\\xbc\\x3c\\x39\\x7d\\xf3\\x72\\x94\\xa7\\x8f\\x90\\x48\\x33\\x91\\x16\\x92\\x0b\\xad\\x76\\xd5\\xf0\\xa9\\x9e\\xdd\\x03\\x79\\xf7\\xd3\\xee\\x46\\x86\\xf3\\xc3\\xb9\\xf3\\xe3\\x6e\\x04\\x8d\\xc1\\x6c\\x71\\xb7\\x00\\xbb\\xb4\\x2c\\x64\\x26\\xa7\\xcb\\x5b\\x07\\x6f\\x81\\x36\\xff\\x86\\x4d\\x25\\x86\\x74\\x68\\xf0\\xf1\\xfe\\x94\\x5d\\x3d\\xeb\\x4a\\xcf\\xd5\\x33\\x07\\xc8\\x1a\\x5a\\x5e\\x6f\\xd4\\xb3\\x2f\\x03\\x60\\x77\\xa8\\x46\\x2c\\x40\\x11\\xcd\\x39\\x40\\xde\\x5c\\xdf\\xb6\\xba\\x11\\x5a\\xc1\\xca\\x9c\\x63\\x16\\x4a\\x5b\\xfd\\xe2\\x7e\\x80\\xbf\\xab\\x6a\\x61\\x28\\xf9\\xf9\\x8e\\xe8\\x1a\\x43\\xdd\\x8d\\x14\\x33\\x90\\xa2\\x64\\x43\\xdf\\x69\\x66\\xc2\\x33\\x06\\x55\\xd5\\xbd\\x84\\x14\\xf2\\x13\\x67\\x09\\x76\\x76\\x63\\x7c\\x2a\\x9b\\x37\\x2d\\xc2\\x41\\x61\\x37\\x67\\x88\\xc7\\xfa\\xd3\\x59\\x36\\xaf\\xbb\\x09\\x5a\\x6b\\x18\\x9d\\x62\\x07\\x99\\xd2\\x3a\\xe4\\x8a\\x92\\x5f\\xf3\\x8c\\x4d\\xa1\\x53\\x28\\x17\\xd3\\xa0\\xf2\\x60\\x58\\xab\\xd0\\x96\\xa9\\x8c\\x9d\\x53\\x6f\\xcc\\x5f\\x41\\xd3\\x6a\\xc0\\xac\\xb7\\xef\\xde\\x43\\xd3\\x59\\x08\\xa9\\xd8\\x5b\\xe1\\x34\\x1f\\x84\\x33\\x3f\\x1c\\x0e\\xc1\\xf4\\x77\\xf4\\x77\\xa3\\xf9\\xa4\\xd9\\x31\\xf9\\x91\\xd9\\xef\\x48\\xe8\\x8a\\x5b\\xf2\\x44\\x93\\x9b\\x99\\xf4\\x2d\\x4a\\x61\\xae\\x35\\x64\\x01\\xa1\\x31\\x8c\\xcf\\x3e\\xf5\\xc4\\x3c\\x69\\x24\\x6a\\x64\\xe5\\xd1\\xf3\\x9c\\x41\\xdf\\xaf\\x3a\\xce\\xe0\\x31\\x6a\\x49\\xf7\\xc4\\x40\\x3b\\xa6\\xf6\\xce\\xd9\\xb4\\xec\\x8c\\xf8\\xf0\\x01\\xc7\\x17\\x28\\x51\\xf3\\x3c\\xe3\\xe2\\xaa\\x6e\\xab\\x34\\x91\\xb6\\x32\\x2b\\x23\\xe6\\x07\\x77\\x6a\\x4a\\x46\\xb3\\xd5\\x1c\\x63\\x17\\x1c\\xbd\\x37\\x6e\\xa1\\x3b\\xf3\\x47\\x80\\xbf\\xc0\\x50\\x8b\\xff\\xeb\\x88\\x97\\x0d\\x00\\x0b\\x49\\xfd\\xc1\\xc1\\xa3\\x86\\x18\\x57\\x89\\xe2\\xfb\\x93\\x77\\x18\\x26\\xa2\\xed\\x82\\x9c\\x5d\\xbe\\xb8\\x3c\\xbb\\x53\\xaf\\xdf\\x2a\\xe6\\x0a\\xb3\\x7b\\xd4\\xda\\x03\\xff\\x79\\xb7\\xa8\\xaa\\x21\\xc9\\xaa\\x5d\\xdf\\x44\\xd3\\xcb\\xb9\\x2c\\x35\\xcd\\xee\\x81\\x70\\x26\\x33\\x5a\\x9c\\x54\\x7a\\x76\\xca\\x15\\x14\\x18\\xee\\x46\\xfc\\x5b\\x18\\x35\\xc8\\x57\\xc4\\xd6\\xcd\\xae\\x47\\x1d\\x77\\xe8\\x6b\\x9f\\x7b\\xf1\\x7f\\x4f\\xce\\x09\\xad\\x0c\\x3e\\x6a\\xdb\\x95\\xf3\\xde\\x82\\xe5\\xdc\\x2a\\x2e\\x31\\x07\\xba\\x53\\xc8\\xd8\\x31\\x37\\xc0\\xc5\\x3d\\xf5\\x90\\xa0\\x72\\x77\\x59\\x6f\\xbd\\x3f\\x1a\\x38\\x17\\x52\\xfd\\x2f\\xc4\\x07\\xcd\\x05\\xd7\\x9c\\x6a\\x59\\x76\\xe6\\x1b\\x8c\\x46\\xf4\\x06\\xc3\\x4a\\x69\\x99\\xdb\\x53\\x74\\xe6\\x9e\\x80\\x80\\x2c\\x90\\xdf\\x16\\x5e\\xaa\\xad\\x89\\xa0\\x7d\\x02\\xcc\\xcf\\x84\\xd1\\x15\\x69\\xc2\\x1a\\x69\\x36\\x03\\xe8\\x96\\x89\\x63\\x73\\xff\\xcc\\x5f\\xac\\x11\\x1d\\x3a\\x17\\x65\\x7f\\x7d\\x1e\\xf5\\x93\\xaf\\x5b\\x53\\xba\\x26\\xc0\\xd6\\x8a\\x99\\x48\\x21\\x58\\xb2\\x4f\\x6f\\xe5\\xfd\\xb7\\xe4\\xe7\\x6e\\x48\\x1b\\xff\\x59\\x34\\xfc\\x09\\x08\\xa2\\xff\\xaf\\xa2\\x19\\x82\\xf6\\xed\\x7d\\x1a\\xdf\\xe3\\x2d\\xed\\x66\\xc5\\x31\\x96\\xd8\\xc5\\xd7\\x28\\xf1\\xd6\\x5b\\xdb\\x2a\\x85\\x7d\\x99\\x10\\x22\\xba\\xa4\\x42\\x19\\x3c\\x89\\xed\\x19\\x87\\x36\\x00\\xe2\\x90\\x1c\\xe9\\xa4\\x38\\xbe\\x37\\x48\\x75\\x95\\x0e\\x9b\\x55\\x22\\x14\\x56\\x71\\xed\\xef\\x11\\x35\\x5e\\xfb\\x74\\xd8\\xfd\\x96\\x79\\xef\\x41\\x0e\\x70\\xda\\xbb\\xb1\\xdb\\xda\\xb1\\x3c\\x1e\\x85\\xf0\\x42\\x01\\x91\\xbc\\xe6\\x4a\\x63\\x1e\\x0d\\x3e\\x0c\\x65\\x5c\\x30\\x9f\\xd0\\xe8\\x02\\xe7\\x44\\x96\\x84\\x17\\xff\\x4b\\xd3\\xb4\\x7c\\x8e\\x72\\x84\\xd5\\x55\\xe1\\xff\\xca\\x77\\x0a\\xa2\\xc2\\x47\\xdb\\x1c\\xe9\\x79\\x61\\x7b\\xc4\\xbd\\x7f\\x71\\x0e\\x4f\\x2a\\xf2\\x1f\\x7f\\x7c\\x0a\\x7a\\xc1\\xef\\xbf\\xfe\\xe3\\xd3\\x3d\\x11\\xf1\\xb1\\x66\\x15\\x92\\xae\\x6d\\xa2\\x9d\\x47\\x56\\x7c\\x21\\x59\\x24\\x51\\xb6\\x08\\xb4\\x93\\x31\\xd2\\xee\\x25\\x26\\x67\\x18\\x3e\\x69\\x89\\x26\\x1e\\x04\\x83\\x95\\x9e\\x7b\\x77\\x29\\x13\\xf7\\x59\\x17\\xbf\\xa2\\xac\\x0b\\xe2\\xb3\\xf1\\x91\\xb0\\x76\\x82\\xc8\\xe1\\x80\\x50\\x56\\x67\\x91\\x80\\x23\\xed\\x3e\\x7f\\x2c\\xb4\\x7b\\x47\\xe8\\xee\\x8a\\xc9\\x31\\x06\\x87\\x21\\x7e\\x36\\x11\\x37\\x48\\x4f\\x3d\\x7d\\x7b\\xf9\\xbf\\xaf\\x4f\\xfe\\xf6\\xf2\\x35\\xac\\xd5\\x46\\x05\\x1a\\xf4\\xb4\\x9a\\xd0\\x2e\\x31\\xeb\\xed\\xd1\\x7d\\x77\\xe3\\xd6\\xae\\x20\\xed\\x22\\xc0\\x40\\x34\\x42\\x0b\\x04\\x79\\xfb\\xea\\x72\\xdb\\xa8\\x82\\x7d\\xd5\\x59\\x31\\xd9\\x03\\x7a\\x8f\\xcd\\xaf\\x61\\x5e\\x85\\x7e\\xad\\xf7\\x91\\x39\\xdf\\xb1\\x53\\x24\\xa8\\x8a\\x1f\\xd9\\x51\\x0c\\x0e\\xe1\\x1a\\xf7\\x36\\x75\\xec\\x88\\x1b\\xe4\\xc1\\xc9\\x7a\\xeb\\xfd\\xdf\\x06\\x62\\x08\\xc5\\xce\\x3d\\xdf\\x77\\x0a\\xed\\xfd\\x64\\xc8\\xb2\\xab\\xb2\\x0e\\x87\\x38\\x96\\x13\\x1f\\x0d\\x09\\x43\\xde\\x51\\x1a\\xae\\x6a\\xf8\\x29\\x53\\xbe\\x41\\xd1\\x17\\x80\\xad\\xc5\\xb2\\x76\\xd3\\xfb\\x73\\x87\\xa5\\xc3\\xe2\\x7f\\x2f\\x5d\\xb7\\xc0\\x20\\xaa\\x20\\xca\\xeb\\x5e\\xd5\\x51\\xde\\x45\\x64\\xd2\\x3c\\x68\\xac\\xd9\\x65\\xe5\\xc7\\xfa\\x16\\xde\\xc1\\x26\\x79\\x8f\\x90\\xc1\\xc0\\xc4\\xef\\x29\\xbd\\xcc\\x7f\\xbb\\x9b\\xe3\\xe8\\x87\\x6b\\x56\\x5a\\xd9\\x0a\\x4b\\x08\\x55\\x4e\\x90\\xb3\\xb1\\xe6\\x61\\x49\\x96\\x07\\x89\\x42\\xe4\\xc1\\xf1\\x21\\xcf\\x86\\x7e\\xdc\\xd1\\xdc\\x70\\x9f\\xa6\\x86\\x62\\x26\\xb5\\x14\\x1d\\xe7\\xd0\\x2e\\x1b\\x34\\x26\\x6c\\xe7\\xf0\\xc4\\x0b\\xcc\\x74\\xcf\\x58\\x19\\xd0\\x5b\\xcc\\x20\\xf2\\x6e\\x75\\xa3\\x79\\x38\\xd6\\x2d\\x85\\x73\\xb0\\xc7\\xee\\xf5\\xc7\\x47\\x89\\x8a\\xf4\\xec\\xf4\\x1e\\x88\\xd0\\x97\\x56\\xec\\x68\\x5b\\x37\\xe1\\xbd\\x05\\xca\\xa6\\x1d\\x65\\xee\\x9b\\x81\\x1c\\xcc\\xcf\\x4e\\xad\\xba\\xe0\\xd2\\xf2\\x95\\x3d\\x56\\x64\\xf5\\xb9\\xba\\x17\\x51\\x4a\\x96\\xfa\\x46\\x96\\x5d\\x95\\x8f\\x8b\\x87\\x6b\\x44\\x61\\xda\\xdf\\x16\\x8a\\x71\\x7c\\x99\\x54\\x04\\x57\\xf9\\xe8\\x29\\xc9\\x25\\x50\\x92\\x46\\xe7\\xee\\x55\\x14\\xe5\\x36\\x08\\xca\\xe3\\x21\\x24\\xb7\\x23\\xb8\\xdc\\x6e\\x25\\xae\\x7b\\x53\\x7f\\xdd\\xf1\\xe8\\x04\\x58\\x6e\\x30\\x6b\\x06\\x35\\x88\\x52\\xd3\\x5d\\x0a\\xe6\\xe6\\x80\\xf2\\xdc\\x0b\\x9d\\x2d\\xa5\\xa1\\x43\\xbb\\x91\\x93\\x98\\xc4\\xba\\x91\\xd0\\x39\\x88\\x5d\\x1d\\xb3\\xcc\\xec\\xac\\x14\\x61\\x3f\\x48\\x5b\\xac\\x6b\\x40\\xb0\\x67\\x62\\x4e\\x0b\\x85\\x4d\\x29\\x52\\x79\\x23\\x6e\\x68\\x99\\x92\\x93\\xf3\\xb3\\xbb\\xa7\\xab\\x7b\\x67\\x82\\xe2\\x79\\xd8\\xa7\\xb7\\x40\\x9c\\x0b\\x5a\\x8f\\x07\\x11\\xf8\\x10\\x24\\x64\\xfe\\x18\\x73\\x8d\\x6d\\x9b\\x31\\x18\\x5f\\x87\\xd6\\x28\\xc3\\xa7\\x7c\\x24\\x8b\\xa1\\x74\\x86\\xaa\\xd9\\x91\\x02\\xb1\\x4a\\x10\\x99\\x68\\x9a\\x61\\x0b\\x10\\x32\\x66\\xfa\\x86\\x31\\x41\\x9e\\x3e\\x7d\\x8a\\x0e\\x8a\\xa7\\x7f\\xfa\\xd3\\x9f\\x08\\x34\\xe5\\x4c\\x59\\xc2\\xf3\\xc5\\x07\\xe1\\xa9\\x7f\\x7f\\xf6\\x6c\\x44\\xfe\\xfb\\xe4\\xcd\\x6b\\x42\\x13\\xd0\\xe5\\xb0\\xf2\\x2d\\x8e\\x0c\\xfb\\x19\\xbe\\xac\\x06\\xe4\\xbf\\x2e\\xdf\\xbd\\xad\\x1b\\xca\\xc7\\xbf\\x02\\xba\\xf8\\xe5\\x8d\\xc8\\x69\\x10\\x7b\\x1f\\x3a\\x0f\\xa8\\x9e\\x01\\x34\\x84\\xd4\\x84\\x4e\\x26\\x88\\x70\\xae\\xab\\xbd\\x25\\x26\\xae\\xf6\\x1c\\x9f\\xce\\x60\\xb9\\x5c\\x00\\xaa\\x65\\x90\\x14\\xc0\\xcd\\x14\\xc1\\x61\\xe3\\xea\\x38\\x62\\x8e\\x03\\x8c\\xe5\\x99\\x08\\x4c\\x65\\x40\\x32\\x7e\\xc5\\xc8\\x44\\x7d\\x5b\\xca\\xaa\\xa8\\x1b\\xa7\\x94\\x4c\\x19\\x05\\x2c\\xa1\\xc2\\x8c\\x8e\\x83\\xd5\\x3b\\xa3\\xd8\\x9e\\xb5\\x31\\xef\\x3b\\x72\\xc2\\x9e\\xd3\\x6e\\x5c\\xc8\\xf6\\xcc\\xbb\\x16\\x62\\xb6\\x37\\xa0\\xcb\\xd1\\x42\\x92\\x61\\x76\\xe1\\xb1\\x46\\x32\\x44\\xab\\x3d\\xf7\\xeb\\x41\\xa4\\xb2\\xd5\\x0f\\x6b\\xca\\x48\\x33\\x29\\xa6\\x21\\x0e\\xd6\\xd2\\x87\\x0b\\xa6\\x9c\\x17\\x6c\\x57\\x60\\x74\\xd4\\x50\\xa7\\x9b\\xf6\\x74\\x48\\xdc\\xdf\\xd0\\x62\\xbf\\x4e\\x20\\x71\\x8c\\xae\\x1b\\x33\\xaa\\x43\\x49\\xc7\\xb2\\xd2\\x2e\\x66\\xcf\\xfe\\x0e\\xe5\\xdb\\xb4\\x74\\xa0\\xdf\\x6b\\x0a\\x9d\\x75\\x29\\xea\\xae\\xef\\x5f\\x47\\x4d\\xb7\\xe2\\x98\\x39\\xe0\\xda\\xb1\\xc8\\x3a\\x20\\x8c\\x26\\x33\\x72\\xc5\\xe6\\x43\\xe4\\x00\\x05\\x85\\xea\\x11\\x00\\xed\\x53\\x03\\x63\\x2c\\x93\\x1b\\x87\\x33\\x24\\x2c\\x35\\xda\\xa4\\xdd\\x0a\\x17\\x60\\x19\\xc8\\x07\\xae\\xfa\\x84\\x53\\xb8\\x94\\x95\\xcb\\x6d\\x2b\\x2b\\x11\\x58\\x28\\x5d\\xef\\xca\\x44\\x0a\\x6d\\xfb\\x62\\xfa\\xde\\x55\\x10\\x30\\xda\\x28\\x48\\x60\\x28\\x0c\\x4b\\xcd\\x6b\\x6a\\xdd\\x97\\xeb\\xa8\\x52\\xc3\\x51\\xac\\xfc\\x51\\x89\\x85\\xb7\\xa1\\x9e\\x3b\\xc4\\xf4\\x2a\\x66\\x2b\\x23\\x51\\xd7\\x13\\x31\\x88\\x4c\\x9d\\xf1\\x04\\x32\\x8e\\xcc\\xe3\\xf6\\x59\\x07\\x25\\x0f\\x88\\xa8\\x60\\x82\\x62\\xba\\xb2\\xa0\\x81\\x38\\x61\\xf3\\x6d\\xa6\\x14\\xe1\\xb0\\xc2\\x9c\\x96\\x57\\xcc\\x15\\x1a\\xa6\\xd9\\x88\\x9c\\x9b\\x49\\xfa\\x6a\\xf3\\xd8\\x4a\\xf0\\x1a\\x13\\x44\\x0c\\x8d\\x09\\x2b\\x41\\x98\\x8f\\x1c\\x8e\\x46\\x87\\xc8\\x2a\\x97\\xd4\\x85\\xd8\\x1b\\x6b\\xba\\xec\\x22\\xd7\\x59\\xf7\\xb8\\x08\\x95\\xdf\\xd0\\x42\\x61\\x37\\x3d\\xa3\\x5a\\x40\\xc7\\x4a\\x09\\x75\\x5b\\xf4\\xcc\\x09\\x13\\x74\\xcf\\x12\\xe2\\xe1\\xd5\\x71\\x1b\\xb3\\x6e\\x3b\\xa1\\x76\\xd7\\x07\\x75\\x0f\\x5f\\x7b\\x7c\\x75\\xdd\\xff\\xb4\\xc3\\xee\\xa7\\xab\\x7a\\x9f\\x5a\\x1c\\xb2\\x94\\xa4\\xab\\x8e\\x8c\\x9d\\xb7\\xdc\\xcc\\x3b\\x68\\x6c\\xe6\\xae\\xd8\\x75\\x04\\xf2\\x6d\\x54\\x4b\\xba\\x95\\x2e\\x62\\x4b\\xa9\\x67\\xec\\x51\\x29\\x1f\\x67\\x13\\x20\\xa9\\xcb\\x6b\\xdd\\x84\\x7a\\x99\\xe3\\x30\\x06\\x02\\xf7\\xaf\\x75\\xec\\xdb\\x65\\xcf\\x5d\\xb7\\xd1\\xa6\\x7e\\x7f\\xb5\\xa4\\x79\\xed\\x13\\x44\\xd3\\xbc\\x62\\x43\\x46\\x50\\x56\\xc2\\xb3\\xda\\x30\\xfb\\x18\\xb6\\x4a\\x4b\\xe8\\xd6\\x59\\x13\\x87\\x11\\x79\\x63\\x59\\x31\\x22\\x39\\x1d\\x2b\\x99\\x55\\xda\\x57\\xa2\\x58\\xc2\\xa7\\x61\\x50\\xd7\\xdb\\x13\\x8b\\x36\\xb9\\xc7\\x02\\xae\\x0d\\xf2\\x0a\\xb2\\xb2\\x6e\\x18\\x38\\x5e\\x1d\\x12\\x9f\\x7d\\x03\\x64\\xf1\\xfa\\x95\\x85\\xc9\\xe2\\xd5\\xe1\\x2e\\x38\\x71\\xb1\\xe3\\x9d\\x70\\xc3\\xfa\\xea\\x9d\\x2e\\x23\\x32\\x92\\x6e\\x21\\x46\\x56\\x2b\\x14\\x9d\\x9d\\xa0\\x8a\\x39\\x94\\xbb\\x56\\xc0\\xae\\xaf\\xfd\\xad\\xba\\x76\\x5d\\xd6\\xc0\\x78\\x72\\x7e\\xd6\\xa1\\x56\\x1a\\x8c\\xba\\x42\\x2f\\x0d\\x9f\\xe8\\x35\\xd3\\x36\\x57\\x04\\xe0\\x33\\xd4\\x4c\\x8d\\x48\\xef\\x0c\\x48\\xa7\\x35\\x44\\xad\\x4b\\xcf\\x10\\xe5\\x5f\\x81\\x6a\\xb3\\xb0\\xf0\\x57\\x86\\x19\\x85\\xc9\\x5c\\x71\\x87\\x0e\\x34\\x06\\xd7\\x6c\\x2b\\xe8\\xea\\xe1\\x62\\x78\\x80\\xc4\\x7d\\xf9\\x6a\\xd0\\x03\\x55\\x5e\\x00\\xfa\\x7b\\x64\\xec\\x34\\xaf\\x98\\x8b\\x5e\\x38\\x20\\x92\\x4b\\x96\\x19\\xa6\\x47\\x1a\\x26\\x9b\\x42\\xa6\\xcf\\xb1\\xe7\\x37\\x15\\x42\\x6a\\xc0\\x1b\\x35\\x20\\x19\\xf4\\x23\\x1f\\xa0\\x29\\xc6\\x48\\xa0\\x41\\xf4\\x57\\x19\\x38\\x4d\\x3b\\x96\\x39\\x3b\\x43\\x1e\\xd2\\x39\\x02\\x11\\x40\\x22\\x80\\xdd\\x79\\x37\\x98\\x44\\x6e\\x01\\x9b\\xcc\\x55\\x8b\\x2a\\x5d\\xb6\\xe5\\x8f\\xf0\\xca\\x8e\\xef\\x90\\x48\\x25\\x33\\x96\\x53\\xec\\x47\\xe2\\x00\\x64\\xe8\\xf5\\x4d\\xc9\\xb5\\x66\\x58\\x75\\x9c\\x95\\xb9\\x22\\x72\\x32\\x88\\xfc\\xc6\\x07\\xd7\\xcf\\x0e\\xba\\x92\\x67\\xc9\\x6d\\x28\\xd4\\xc4\\x9d\\xd0\\x5d\\xcb\\x80\\xad\\xba\\x62\\xbf\\x41\\xa4\\x5c\\x98\\xd3\\x09\\xda\\x74\\x06\\x0d\\x92\\x44\\xc3\\x60\\x69\\x84\\x88\\x6b\\x84\\xff\\x83\\x06\\xdd\\xed\\xd9\\x22\\x76\\xb5\\x41\\x0c\\xbc\\x60\\xda\\xdb\\x20\\x7a\\x1b\\x44\\x17\\x23\\xde\\x9a\\x0d\\x22\\x60\\xdc\\x8e\\x98\\x2e\\xb1\\x47\\x84\\x89\\x78\\xce\\x28\\x51\\x97\\xb2\\x08\\xca\\x44\\x1b\\x94\\x77\\xe6\\x08\\x59\\xc6\\xbe\\x82\\xc3\\xd1\\xe8\\xf0\\xd0\\x19\\x29\\xec\\xf9\\xa8\\xf4\\x64\\xf8\\x1f\\x84\\x89\\x44\\xa6\\x88\\x54\\x66\\xfc\\x52\\x69\\x10\\x6a\\x6b\\xad\\x3c\\x9c\\x4b\\xee\\xbe\\x15\\xfa\\x1b\\x60\\xec\\x6e\\x51\\xa2\\x43\\x0a\\xe5\\x42\\x52\\x5e\\xdd\\xaa\\x08\\x56\\x0b\\x5e\\xbe\\x0c\\x98\\x05\\xa0\\xaf\\x96\\x68\\x25\\xb0\\x3a\\x44\\x26\\xe3\\x39\\xb7\\xf5\\x09\\x0d\\xb9\\x60\\x4a\\x2b\\x72\\x84\\x37\\x47\\x49\\x51\\x0d\\xec\\x03\\xa3\\x9c\\xe5\\xb2\\x9c\\x0f\\xfc\\x43\\xe6\\xc7\\xe8\\x2d\\xfb\\xc4\\x31\\x48\\x6d\\x49\\x55\\x96\\x4c\\xe8\\x6c\\xfe\\xeb\\x95\\xdf\\x1c\\x88\\x1f\\xb0\\xf8\\xe6\\xb1\\x62\\x9f\\xbc\\x8f\\x65\\x57\\x8c\\x96\\x75\\x13\\x01\\xb0\\xde\\x79\\x68\\x03\\x1f\\xb2\\x19\\x18\\x83\\xda\\xf8\\x63\\xee\\x32\\x71\\x4d\\xae\\x69\\xb9\\x73\\x06\\xc6\\xb2\\xeb\\x56\\x24\\xb6\\x94\\x5f\\x73\\x25\\x77\\xce\\x61\\x5b\\x3a\\x64\\x08\\xbc\\x4b\\xcb\\x94\\xd1\\x46\\x2c\\x2b\\x5d\\x54\\xda\\x72\\x17\\x77\\xb6\\x5d\\xc9\\x3e\\x7f\\xa6\\x1b\\x82\\xef\\xb3\\x83\\x0e\\x27\\x57\\x50\\xad\\x59\\x29\\x9e\\x93\\xff\\x39\\xfa\\xf8\\xbb\\x5f\\x86\\xc7\\xdf\\x1c\\x1d\\x7d\\x78\\x3a\\xfc\\xf3\\xa7\\xdf\\x1d\\x7d\\x1c\\xc1\\x7f\\xbe\\x3a\\xfe\\xe6\\xf8\\x17\\xf7\\xc7\\xef\\x8e\\x8f\\x8f\\x8e\\x3e\\x7c\\xf7\\xe6\\xdb\\xf7\\xe7\\x2f\\x3f\\xf1\\xe3\\x5f\\x3e\\x88\\x2a\\xbf\\xc2\\xbf\\x7e\\x39\\xfa\\xc0\\x5e\\x7e\\x6a\\x39\\xc8\\xf1\\xf1\\x37\\xbf\\xed\\x70\\x11\\x54\\xcc\\xdf\\x75\\x46\\x82\\xf1\\x1a\\xde\\x8a\\x18\\x11\\x8f\\xdd\\x31\\xea\\x12\\xf2\\x79\\x58\\x5b\\xb4\\x87\\x5c\\xe8\\xa1\\x2c\\x87\\xf8\\x91\\xe7\\x44\\x97\\x55\\x57\\xa4\\xab\\x66\\x7f\\xb7\\x47\\x63\\x6a\\x21\\xa6\\xae\\x80\\xe9\\x14\\x9b\\x07\\x48\\x44\\x30\\x30\\xb5\\x43\\xcb\\xb0\\xed\\x63\\xbb\\xdc\\x28\\x6c\\x7f\\xec\\xed\\xc1\\x6d\\xae\\x5b\\x8c\\x54\\xb2\\xf5\\x6c\\x7e\\xe5\\x61\\x4a\\x97\\xb6\\x9b\\x72\\x1f\\xa3\\xb4\\x70\\xf5\\x31\\x4a\\x8b\\x57\\x1f\\xa3\\xb4\\xe5\\xd5\\xc7\\x28\\xb9\\xab\\x8f\\x51\\xea\\xed\\x83\\xfb\\x5f\\xbf\\x72\\xfb\\x60\\x1f\\xa3\\xb4\\xed\\xd5\\xc7\\x28\\xed\\x7c\\x3d\\xa2\\x18\\x25\\x14\\xf2\\x97\\x45\\x2a\\x59\\x31\\xbf\\x0e\\x53\\x7a\\xb0\\x51\\x4a\\xca\\xe0\\x43\\xc2\\x4e\\x92\\x44\\x56\\x42\\xbf\\x97\\x57\\x6c\\x4f\\x47\\x6e\\x43\\x27\\x5d\\x18\\x1d\\x4a\\x22\\xae\\xd0\\x51\\x17\\x1f\\x7e\\x90\\x0a\\x6b\\x57\\xf2\\x68\\x07\\xf2\\x63\\x77\\x92\\x23\\xad\\x52\\x6e\\x74\\xd4\\x8e\\x0f\\x8b\\x1b\\x36\\x2c\\x8b\\x2d\\x52\\x96\\xd6\\x3f\\x58\\x92\\xa6\\xcd\\x7e\\x8f\\xc8\\x09\\x29\\x59\\xc2\\x0b\\x6e\\x18\\x00\\xd4\\x0a\\x82\\xfb\\x78\\x7c\\x7c\\x17\\x67\\xae\\x15\\xcb\\x26\\xb6\\x93\\xad\\xa8\\xd3\\x9c\\xcb\\x40\\xff\\xb4\\x1c\\x65\\xe9\\x67\\x50\\x86\\x90\\xae\\xd7\\x28\\x51\\x33\\x59\\x65\\x29\\x29\\xd9\\xdf\\x9d\\xf0\\x61\\x67\\xf3\\x3e\\x1c\\x21\\x34\\xa9\\xc2\\x52\\xea\\xcf\\xda\\xc1\\x69\\xc1\\x6d\\x51\\xb1\\x87\\x44\\x06\\xd9\\xe7\\x82\\x97\\x70\\xd8\\x2e\\x59\\x22\\x45\\xda\\xb5\\x85\\x64\\x61\\xfc\\x5a\\x56\\x00\\xbf\\x10\\x4b\\x49\\x5a\\xe1\\x03\\x90\\x8e\\x49\\x33\\x9e\\x72\\x3d\\xf7\\xf1\\x1c\\x78\\xec\\x8d\\xd8\\x8a\\xbd\\x83\\x2d\\x22\\xa8\\x7a\\x23\\x08\\x2d\\x8a\\x52\\xd2\\x64\\xc6\\x54\\xf0\\x35\\x14\\x42\\x6d\\xa1\\x0c\\x9f\\xe5\\x99\\x55\\x53\\x2e\\x50\\x0e\\x85\\x77\\x8c\\xb0\\x92\\xcd\\x49\\x29\\xb5\\x0b\\x4d\\x5b\\xf1\\xc1\\xf7\\xc1\\x60\\xf0\\x3a\\x4a\\x1c\\xba\\x9c\\x43\\xfc\\x9a\\x0c\\x87\\xc0\\x59\\xf1\\x49\\xf8\\x87\\x22\\x32\\x4b\\x5d\\x69\\xd6\\xff\\x78\\x6a\\x04\\xff\\xc4\\x62\\xb1\\x61\\x02\\x50\\x34\\x53\\x4b\\x92\\x19\\xe1\\xc9\\x30\\x86\\xd5\\x2f\\x7f\\xfd\\x07\\x32\\x93\\x55\\xa9\\x46\\x61\\xb1\\xbf\\x67\\x70\\x0f\\x2d\\x1c\\x4e\\x71\\xd0\\x24\\x63\\x54\\x69\\xf2\\xec\\x29\\xc9\\xb9\\xa8\\x0c\\xc7\\xef\\x08\\xf1\\xba\\x92\\x75\\x03\\x29\\xf7\\x8f\\x7f\\xd8\\x73\\xb4\\x6e\\xe4\\xdb\\x95\\x92\\x6d\\x81\\x1d\\xf3\\xac\\x78\\x6b\\xcf\\x38\\x16\\xf4\\xc0\\xae\\x99\\x0d\\x61\\xd7\\xb2\\xa4\\x70\\x17\\x85\\x96\\xf7\\x7c\\xf2\\x7f\\xae\\xe4\\x78\\xae\\xf7\\x2f\\x61\\x63\\xc7\\x89\\x6b\\xd7\\xfc\\x7f\\xf6\\x66\\x9b\\x52\\xb1\\x75\\xa5\\xd8\\x1d\\xa6\\x72\\xef\\x3d\\xbe\\xa7\\x5c\\xe9\\x9d\\x3a\\x7c\\xd7\\x35\\x6f\\x76\\x78\\x79\\x5f\\x66\\x3e\\x35\\xfa\\x71\\x27\\x99\\xf4\\x30\\x92\\xd3\\xe8\\x9c\\x45\\x3a\\x49\\x98\\x02\\x52\\xe4\\x8a\\xc2\\x81\\x71\\x17\\x9f\\xdd\\xf1\\xa3\\x0f\\xb4\\xda\\xcc\\xb2\\x22\\x32\\x0e\\xf9\\x3b\\xe8\\x55\\xba\\x17\\xb0\\xf6\\x11\\xf9\\x1d\\x62\\x77\\x04\\x2d\\x1c\\x2c\\xa6\\x11\\x8a\\x8b\\x29\\xb6\\x16\\xcd\\xab\\x4c\\xf3\\x22\\xab\\x21\\x77\\xe1\\x5e\\xb0\\x0c\\x38\\xf4\\x16\\xd0\\xc0\\x3c\\x4d\\xb1\\xe8\\x15\\x56\\x3f\\x07\\xcf\\xca\\x91\\x1f\\x8b\\x09\\x8d\\x1d\\x32\\x4b\\xc3\\xc7\\x0b\\x5a\\x52\\x0f\\xfe\\x44\\xe6\\x39\\x55\\xc7\\xd6\\xf1\\x40\\x21\\x0a\\xc6\\xb6\\x01\\x32\\x6f\\xd1\\xac\\x9e\\x71\\x10\\x75\\x70\\x5f\\x88\\xab\\x99\\xa0\\x62\\x67\\xf7\\x5f\\x5c\\x70\\x1e\\x86\\x22\\xf2\\xc6\\x07\\xda\\x63\\x93\\xfb\\x06\\xc6\\x5a\\x81\\xf8\\x6f\\x34\\xb9\\x62\\x22\\x25\\xdf\\x2b\\x07\\xb8\\x74\\x2e\\x68\\x6e\\xeb\\xc7\\x17\\xa5\\xc4\\x2e\\xea\\x2c\\x6d\\xbc\\xaf\\x06\\xd6\\xec\\x88\\xa5\\x4f\\x5c\\x01\\x2b\\x94\\xb7\\xee\\x0b\\x8a\\x95\\xea\\xa8\\x78\\xb0\\x19\\x68\\x13\\xbd\\x53\\x68\\xd2\\x2d\\xf9\\x75\\xc2\\x9c\\xec\\x68\\xde\\xbb\\xaf\\xc5\\x5f\\xef\\x5c\\xad\\x8e\\x2c\\x2f\\x1d\\x65\\xdb\\x98\\xe2\\x29\\x04\\x96\\xee\\x3d\\x97\\x50\\x26\\x9e\\x66\\x86\\xc4\\xcd\\x7d\\xcd\\x9f\\x06\\x82\\x8d\\xe7\\x60\\xf7\\xba\\x97\\xca\\x63\\xe5\\x78\\xff\\x9a\\x52\\x87\\xe5\\x38\\x8d\\x89\\xd9\\x05\\x4d\\xa5\\x22\\x7f\\xcb\\x64\\x72\\x45\\x4e\\x19\\x28\\x0d\\xb7\\xd9\\x7c\\xbf\\x1c\\xa7\\x8f\\xbb\\x71\\x66\\x4e\\xa7\\xbb\\x45\\x8c\\x0c\\x49\\x2e\\x05\\xd7\\xb2\\xdc\\x85\\x1e\\x3f\\xa0\\x42\\x81\\x7d\\x2b\\xc3\\x36\\x15\\xd3\\xcd\\x39\\xfb\\x52\\x1a\\x19\\x1a\\x94\\xef\\x06\\x75\\x60\\x28\\x6f\\x3a\\x01\\xca\\x83\\xb7\\x80\\xa8\\xee\\x4c\\x47\\xfe\\x6d\\x26\\x6f\\x86\\x5a\\x0e\\x2b\\xc5\\x86\\x7c\\xe7\\x40\\xa8\\xbd\\x01\\x75\\xc5\\xe6\\x10\\x55\\xd6\\x09\\xa8\\xec\\x60\\x91\\xe6\\xae\\x25\\xd8\\xd9\\xe1\\xbe\\x91\\xef\\x2e\\xfe\\x76\\xfa\\xbd\\x62\\xe5\\x28\\xd4\\x56\\x9e\\x30\\x9d\\x3c\\x49\\x58\\x31\\x7b\\x62\\x47\\x78\\xf4\\x60\\x75\\x64\\xb3\\x1b\\xb8\\xba\\xd1\\x50\\x10\\x48\\x64\\x96\\xd9\\x02\\x63\\x72\\x42\\x5e\\xb0\\x62\\xe6\\x3f\\xf7\\x30\\xe0\\xf6\\x98\\x7b\\xca\\x15\\x52\\x76\\xd3\\x6e\\xea\\xd0\\x8c\\x14\\x93\\x0d\\xb8\\x83\\x54\\x23\\x40\\xfe\\x72\\xbc\\x5d\\x23\\xef\\x87\\x88\\xee\\x77\\xd8\\x9d\\x65\\x97\\x56\\x7c\\x0f\\x02\\xbc\\x0f\\xa7\\xa5\\xdf\\x61\\xd4\\xd3\\x2f\\xcc\\x1f\\x8a\\x1b\\xf6\\xb9\\xe8\\xd4\\x88\\x6c\\x9f\\x4d\\x50\\x19\\x4d\\x59\\x4a\\xe4\\x35\\x2b\\x4b\\x9e\\x32\\x45\\x3c\\xdd\\x0e\\x6d\\x50\\x3c\\x7b\\x18\\x90\\xef\\x7b\\x07\\x3e\\xae\\x80\\x83\\x87\\x63\\x7e\\x38\\x04\\xfb\\x43\\x44\\xc4\\xe1\\xce\\x02\\x11\\xa7\\x69\\xce\\xc5\\xc3\\xc0\\xf6\\x1d\\xe1\\xa6\\x12\\x9a\\xb1\\xb3\\x77\\x7b\\x6b\\xeb\\x76\\x9c\\x58\\x61\\xbf\\xb4\\x37\\x83\\x9e\\x02\\x1b\\xea\\xec\\x7f\\xe7\\x71\\x97\\x08\\x99\\xee\\xe6\\x40\\xbb\\x67\\xb5\\x7b\\x4a\\x35\\xbb\\xd9\\x51\\x10\\x1a\\xd6\\x24\\x7f\\xd7\\xf7\\x41\\x3d\\x7b\\xdc\\x6a\\xfb\\x83\\xe8\\x14\\x12\\x9c\\x72\\x2c\\xf9\\x7f\\x5f\\x42\\x96\\xc5\\xa7\\x6e\\x1c\\x49\\x38\\x56\\xd8\\x94\\xad\\xd9\\x8a\\xcd\\x9d\\xd9\\x93\\xf3\\x33\\xf2\\x2d\\x3e\\x7e\\x7f\\x5d\\x50\\x4a\\xa9\\x51\\xe5\\x39\\x95\\x39\\xe5\\xdd\\x34\\x40\\x6f\\x0e\\xda\\xec\\x87\\x15\\x02\\xe1\\xdc\\x3f\\x4b\\xec\\xc3\\x46\\x28\\xaa\\xcb\\x0d\\x57\\x25\\x4b\\x89\\xb5\\xa7\\x7c\\x61\\x2d\\x1e\\x16\\xc4\\xe9\\x2f\\xa3\\xc5\\xc3\\x6d\\x75\\xc9\\x0e\\x4c\\xf3\\x2e\\x7f\\xa7\\x96\\xa2\\x1d\\x3a\\x81\\x10\\xe1\\x63\\x9d\\x88\\x62\\x42\\x71\\x08\\x6f\\x08\\x22\\xf0\\x40\\xd4\\x86\\xb0\\x74\\x9f\\xac\\x83\\x62\\xf7\\x80\\xbc\\x96\\x53\\x2e\\x1c\\x15\\x93\\x36\\xaa\\x66\\x42\\x79\\xb6\\x1f\\x38\\x7b\\x39\\xf9\\x57\\x26\\x27\\x2b\\x95\\xbd\\x14\\x74\\x9c\\xed\\x1e\\x32\\x19\\x1f\\x02\\x3f\\x1c\\x79\\x95\\xd1\\x29\\x61\\xf0\\xc7\\x93\\x94\\x2b\\xf3\\x2f\\xb9\\xbc\\x7c\\x0d\\xce\\xe0\\x4a\\x38\\xfd\\x12\\xdc\\x9c\\x96\\xb7\\xf8\\xd4\\x68\\x24\\x32\\xf7\\x47\\x17\\x90\\x88\\x77\\xd6\\xc1\\x23\\x18\\x8f\\x70\\x91\\x9a\\xa5\\x33\\x15\\x05\\x25\\xdb\\x27\\xb0\\x57\\x8a\\xcf\\xbb\\xc3\\xd0\\xc7\\x31\\x23\\xef\\x67\\x3c\\xb9\\x3a\\x0f\\xfc\\xbf\\xb2\\x34\\xf7\\x44\\x70\\x2b\\x12\\x52\\x9a\\xbf\\xdd\\x17\\x37\\xb2\\xcb\\x3a\\xef\\xca\\xa0\\x16\\x8c\\xe7\\x38\\xb5\\x23\\xa7\\x97\\x16\\x82\\xf0\\x1b\\x55\\x4a\\x26\\xbc\\x8e\\x3f\\x00\\x4b\\x74\\xcd\\xbe\\x53\\x60\\xdf\\xf7\\x07\\x15\\x10\\x38\\xbb\\x01\\x08\\xca\\xb9\\x4b\\xa4\\x16\\x87\\x51\\xf6\\x09\\xaa\\x42\\x29\\x85\\x0b\\x07\\xb7\\x7b\\x03\\x02\\xe2\\x78\\x67\\x2d\\x4d\\xeb\\xe1\\x16\\x5b\\x9a\\x3a\\x35\\xb3\\xe1\\x22\\x77\\x09\\xaf\\x16\\x81\\x9c\\xca\\x60\\x7b\\x68\\x2f\\xa2\\x90\\x6f\\x6d\\x6a\\x9b\\x99\\xdc\\x0b\\xe8\\x76\\x4f\\x4d\\x5f\\x66\\xfe\\x6b\\xc4\\x07\\xe1\\x3d\\xeb\\x34\\x07\\xda\\x53\\xc8\\xa2\\xca\\x30\\xb2\\x76\\xff\\xce\\xae\\xce\\xc7\\x88\\xdf\\xb9\\x07\\x27\\xfa\\x43\\xeb\\xec\\x74\\x18\\xa6\\xe7\\x6d\\x9f\\xaf\\xf8\\x65\\xf4\\x77\\x0a\\x54\\x8b\\xa7\\x7f\\xfc\\xc3\\x1f\\x1e\\x7b\\xc7\\xa7\\xfd\\x0c\\x77\\xf7\\xdd\\xf2\\x69\\x2f\\xd7\\xdb\\x92\\xda\\x0c\\x67\\x7d\\x6d\\x86\\xbe\\x36\\x43\\x7c\\xdd\\xbb\\x7f\\xf8\\xee\\xab\\x2f\\x74\\x92\\xdd\\xd6\\x45\\x66\\xdb\\xbe\\xf5\\x15\\xf6\\xcc\\x8a\\xeb\\x26\\x23\\x6e\\xef\\x0a\\x0a\\x77\\x51\\x37\\xa1\\xa3\\x1c\\xb1\\xfd\\x6b\\x24\\xf4\\x95\\x11\\x7e\\x5d\\x95\\x11\\xba\\xcb\\x11\\xeb\\xaa\\x0a\\xc2\\xfe\\xb9\\x61\\xbf\\x9e\\x8a\\x07\\x7b\\x93\\x8d\\x7d\\xf3\\xea\\xf7\\xce\\xa6\\xef\\xaa\\xe9\\x47\\x57\\xd6\\xfd\\xce\\x2c\\x0c\\x87\\xf5\\x78\\x4b\\xed\\x2d\\xae\\xc4\\x9b\\xab\\xa6\\x7f\\x78\\xa8\\x82\\x62\\xf9\\x5a\\x1a\\xea\\x72\\x8f\\xaa\\x33\\xd9\\xdb\\xf2\\x80\\x53\\x91\\x3b\\xf1\\xee\\x65\\x56\\xbc\\x77\\x97\\x8d\\x00\\x01\\x7f\\xfb\\xe1\\xc7\\x05\\xf4\\x0e\\xf2\\xfd\\xc2\\xd4\\xbf\\x2c\\xf7\\xe8\\x17\\xda\\x01\\xff\\xb6\\xdc\\xa3\\x2a\\xaa\\x9a\\xeb\\xac\\x8e\\x40\\x20\\x41\\x84\\x93\\xe3\\xb0\\x33\\x4d\\x4d\\x16\\x4e\\xce\\xcf\\x48\\x52\\x32\\x28\\xed\\x40\\x33\\x35\\x22\\x4b\\x24\\x3c\\xe7\\x40\\xb2\\x12\\xa1\\x93\\xec\\xa8\\xd6\\x2c\\x2f\\xf4\\xbe\\x98\\xd7\\x7b\\x47\\x7f\\x65\\xde\\xd1\\x5b\\xf7\\x52\\xcc\\xaa\\x9c\\x8a\\xa1\\xa1\\x16\\xe0\\x1f\\x8d\\xe2\\x4e\\x1a\\xfc\\x70\\x44\\x2c\\x5d\\x40\\xb1\\x02\\x6c\\xa1\\x90\\xd2\\x5c\\x09\\xfe\\x73\\xc5\\x6a\\x73\\x85\\x97\\x3a\\x1e\\x80\\x73\\x07\\xe6\\xd1\\x31\\xec\\x50\\xa2\\x6a\\x50\\x91\\x44\\x2e\\x24\\x71\\x59\\x80\\x78\\x38\\x3a\\x82\\x11\\x88\\x65\\x91\\xe9\\x4d\\xcf\\x18\\x4a\\x6f\\xe7\\x50\\x24\\xa1\\x7e\\x2a\\xd6\\x0f\\x51\\x41\\xa4\\x59\\x26\\x6f\\xf0\\xdb\\xa1\\x3c\\x62\\xf6\\xcf\\xcc\\xc5\\xd6\\x25\\x19\\x33\\x92\\xf3\\xb2\\x94\\xa5\\x75\\x23\\x85\\xd3\\xc1\\xf0\\x21\\xa3\\x67\\xb2\\x12\\x15\\xb6\\xd2\\x06\\x7d\\x5c\\x32\\x6d\\xb7\\x1a\\x50\\x45\\x4b\\x42\\x05\\x26\\x70\\x9a\\xff\\xbb\\x88\\x6b\\xf8\\xb6\\xa3\\x77\\x63\\x36\\xa3\\xd7\\x5c\\x56\\x25\\xbe\\xad\\x25\\x39\\xb0\\x3f\\x01\\xef\\x9d\\xcb\\xca\\xdb\\xce\\x2b\\xc8\\xd0\\xf2\\xab\\x53\\x4b\\xe0\\xf4\\xb6\\xfe\\x11\\x14\\xdc\\x54\\x3a\\x73\\xe4\\x90\\x7d\\xe6\\x4a\\x2f\\xae\\xc5\\x81\\xc8\\xb5\\x9c\\xb8\\x0f\\xcc\\xbb\\x56\\x85\\x61\\xb0\\x3f\\xec\\x9c\\x7b\\x1b\\xe3\\x5b\\x38\\x5a\\x2c\\xa9\\x5e\\x5f\\xc2\\x4f\\x9b\\xe4\\x54\\x5b\\xb1\\x06\\x53\\xe6\\x5d\\x3a\\xdc\\xe3\\x8b\\x61\\xc5\\x55\\xee\\xd8\\xeb\\xea\\x41\\x0a\\xca\\xbd\\x90\\xbc\\xf6\\xf2\\x51\\x16\\x19\\x4f\\xe6\\x67\\xa7\\xdd\\x46\\x6e\\xe0\\x98\\x8e\\xfd\\x29\\x1f\\xb5\\x61\\xee\\x93\\xbf\\x51\\xc5\\x52\\xf2\\x86\\x0a\\x3a\\x45\\xab\\xcb\\xd1\\xe5\\xf9\\xdf\\xde\\x1c\\x1b\\x2c\\x02\\xab\\xce\\xd9\\xe9\\xd2\\xd0\\x8e\\xcb\\x70\\xf0\\xb7\\xf7\\x95\\xe7\\x4e\\x9a\\xa0\\xeb\\x4c\\x6c\\x58\\x18\\x75\\x47\\xf0\\xdd\\x5b\\x09\\x00\\xe2\\x65\\x82\\x7d\\xda\\xa7\\x2d\\x11\\x07\\xce\\x9b\\x45\\xa2\\x30\\x7c\\xc3\\x55\\x7f\\x53\\x4d\\x52\\x7d\\x9d\\xa7\\x57\\xb7\\x09\\x80\\xc0\\x6e\\xbe\\x6e\\x95\\xed\\x7c\\x60\\x2d\\xfc\\x5c\\x71\\x37\\x12\\x5d\\x52\\xcd\\xa6\\xf3\\x53\\x56\\x64\\x72\\x6e\\x10\\xe0\\x3c\\x30\\xe3\\xe3\\xa3\\x63\\x14\\x1b\\xca\\x31\\x4d\\x48\\x59\\x65\\x0c\\x7b\\x0b\\x35\\xcb\\xae\\x09\\xc6\\xd2\\x9a\\xd2\\x71\\xa1\\x34\\x85\\xa2\\x6b\\x38\\xfe\\xda\\x19\\xb5\\x66\\x56\\x6d\\xd9\\xd2\\x10\\xe7\\xb9\\xf1\\xa9\\xb8\\x44\\xa5\\x39\\x25\\x6b\\x5f\\x69\\xcf\\x98\\xe0\\xf3\\x9b\\x71\\x76\\x1b\\xbf\\x66\\x6b\\x0f\\x66\\xdc\\x1d\\x10\\x4e\\xf9\\x45\\x95\\x19\\xe6\\x93\\xa5\\x8d\\x16\\xaf\\x20\\xa7\\xd9\\x3d\\xc6\\x6a\\x17\\x40\\x13\\xcc\\xec\\x07\\x64\\x5c\\x19\\x21\\x8e\\xa9\\xc8\\xc6\\xbd\\x58\\xea\\xf3\\x66\\x86\\x2e\\x6d\\xf3\\x12\\xa1\\x45\\x91\\x71\\x0c\\x61\\x96\\xa5\\xf5\\x4b\\x07\\x06\\xcd\\xc5\\xc7\\xda\\x90\\x96\\x2d\\x65\\x99\\xed\\x64\\x97\\x21\\xb9\\x66\\xe5\\xb8\\x4d\\x9d\\x8a\\x6d\\xc5\\x12\\x5a\\x70\\xf0\\xe3\\xb4\\x96\\x62\\xa2\\x8d\\x3b\\x39\\x3f\\xc3\\xb7\\x97\\x19\\x8e\\xdd\\x8f\\xb8\\x83\\x76\\x6f\\x9c\\x7b\\xc3\\xf6\\x0c\\x42\\xcd\\xc5\\x57\\x5a\\x3a\\x39\\x3f\\xc3\\xd2\\x5e\\xb6\\xd8\\x52\\x6d\\xfe\\x30\\x7a\\x02\\xc5\\x20\\xc7\\xba\\xc2\\x23\\x9d\\x9a\\x11\\x35\\x91\\xc2\\x7f\\x94\\x89\\x2a\\x67\\x58\\xa0\\xa9\\x6e\\x36\\x66\\x94\\x47\\x31\\xaf\\x47\\xaf\\xad\\x27\\x46\\xd7\\x31\\xaa\\xcf\\xc1\\x41\\x28\\x08\\x63\\xea\\x43\\x19\\xcc\\x07\\x88\\xc9\\xc1\\x57\\xd1\\x53\\x86\\x72\\xd4\\x13\\x6e\\xcb\\x7e\\xb6\\x8f\\x12\\xd8\\x32\\x2a\\x60\\x6b\\x7e\\x26\\xa4\\xb8\\xb0\\xa0\\xfa\\xfe\\xe2\\xf5\\x6e\\x88\\xf0\\x36\\x1e\\xc3\\x16\\xf5\\x61\\x50\\xbf\\xb0\\xa0\\xa5\\xe6\\x34\\x23\\x55\\x99\\x39\\xb7\\x22\\xe6\\x08\\xd8\\x50\\xbc\\x19\\xbd\\x0e\\x0a\\x1f\\x8d\\x08\\xf9\\x0a\\x77\\xdf\\x6e\\x0e\\x9e\\x71\\x6c\\xe0\\x6b\\x4d\\xc1\\x55\\x96\\x0d\\xc8\\x84\\x43\\xcb\\x76\\xcd\\x0a\\x12\\xba\\xb5\\x2e\\xb9\\x48\\x8c\\x3a\\x28\\x86\\xbe\\x23\\x0f\\xcc\\xc8\\x29\\x89\\xfe\\xa0\\x83\\xd7\\x14\\x64\\x66\\x96\\xa5\\x50\\x0c\\x13\\x3e\\x61\\x0e\\x7d\\x02\\x26\\x0b\\xa3\\xc5\\xbe\\xc8\\x2a\\xa5\\x59\\x79\\x21\\x0d\\x43\\x09\\xc2\\x76\\xa0\\x30\\x08\\x0d\\x7f\\xfe\\x1b\\x17\\x29\\xc4\\x69\\x5d\\x00\\xf3\\x49\\xa8\\x20\\x8c\\x83\\x31\\xc8\\x0c\\x09\\xfe\\x77\\x83\\x2c\\x35\\x52\\x1e\\xa9\\x2a\\x99\\x99\\x25\\x1d\\x14\\x32\\x55\\x07\\x86\\x14\\x1d\\xa0\\xc9\\x50\\x1d\\x1c\\x9b\\xbf\\x9a\\x6b\\xc0\\x28\\x9c\\xe0\\xbd\\x27\\xb4\\xe0\\x07\\xc7\\x03\\x02\\x00\\x02\\x07\\xa0\\xd4\\xb3\\xc7\\x8b\\x87\\x6e\\xad\\xa0\\xa3\\xef\\x84\\x85\\x17\\xe1\\x08\\x80\\x83\\xa2\\x76\\xf5\\xdd\\xcc\\xb8\\x66\\xbe\\xbd\\x3a\\x5a\\x9a\\x7c\\xa5\\x9b\\x26\\xc1\\x27\\xe4\\x44\\x10\\x96\\x17\\x1a\\xac\\xd7\\x24\\x67\\xd4\\xb9\\xc4\\xd9\\x35\\x2b\\xe7\\x7a\\x66\\x2b\\x81\\x38\\x02\\xf2\\xe8\\x81\\xbe\\x1f\\xc0\\x1b\\xbd\\xeb\\x6b\\x24\\x87\\x13\\xb6\\x00\\xdc\\xc3\\xaf\\x0e\\x9b\\x84\\xb4\\xe6\\x08\\x8f\\x16\\x94\\xc0\\xa2\\x77\\x02\\xe3\\x0f\\xe6\\xcd\\x18\\x84\\x78\\x0b\\xa9\\xa5\\xa7\\x1f\\xaf\\x5f\\x5b\\xc7\\x0a\\xc2\\xea\\x3b\\x2e\\x52\\xe5\\xbb\\x29\\xda\\xb8\\x6f\\x0b\\xef\\xa5\\x40\\x86\\x19\\x3e\\x46\\x00\\x2f\\x8a\\xc0\\x6d\\xc5\\xd6\\x35\\xc3\\x3b\\xa9\\x7f\\xd5\\x50\\x6b\\x07\\xb0\\xaa\\xc3\\x1b\\x99\\x2e\\x3f\\x3a\\xd1\\xfe\\x9e\\x05\\x0f\\xfb\\x60\\x83\\xda\\xee\\x62\\xc7\\xb2\\xe2\\xee\\xbc\\x58\\xaa\\x13\\xac\\xdf\\x8e\\x35\\xa0\\x5f\\x35\\x93\\xda\\xe0\\x00\\x74\\x32\\xf8\\x05\\xac\\x49\\x58\\xe7\\x9c\\x4c\\x32\\x3a\\xad\\xd1\\x08\\xa8\\x1e\\x0a\\x5a\\x2f\\x2e\\x7f\\x70\\x4b\\x50\\x84\\x2f\\x17\\x79\\x37\\xca\\xc4\\x9b\\xa4\\xe0\\x61\\x0d\\xa5\\x95\\x4f\\x98\\x8f\\x2c\\xfd\\x71\\xb3\\x28\\xec\\x07\\x5f\\x8d\\x4d\\x6d\\x9c\\x8d\\x7a\\xad\\x21\\x6f\\x15\\xfc\\x9d\\xcd\\x8e\\x06\\x98\\xe0\\x0a\\xb6\\x39\\xc5\\x14\\xe2\\xa7\\x40\\x0e\\xb9\\xfc\\x21\\x42\\x93\\x0d\\xf3\\x5d\\x81\\xb4\\x57\\x6c\\x7e\\x23\\xcb\\xe5\\xb5\\xd8\\x63\\xb9\\xde\\xd3\\x21\\xf7\\x8a\\xd3\\xc0\\x9c\\xf3\\x12\\xed\\x83\\x72\\x69\\xd1\\xf9\\x9d\\x51\\x75\\xed\\xe4\\x33\\x3a\\x66\\xd9\\xe6\\xa9\\xbf\\xa1\\x85\\x99\\x77\\x1d\\xf7\\x8a\\x86\\x00\\xeb\\x36\\x45\\x55\\x04\\x43\\xd4\\x5c\\x58\\xa0\\x2c\\xa7\\x54\\xf0\\x7f\\x60\\xb0\\x70\\x62\\x48\\x82\\x2c\\xcd\\x9f\\x47\\xe8\\x7a\\x41\\x33\\x42\\xc6\\x12\\x7d\\x6c\\x51\\x79\\x29\\x09\\xdd\\x80\\xeb\\x34\\x4d\\x39\\x0a\\x22\\xe7\\x1b\\xd0\\x72\\x3d\\x10\\xb8\\xb8\\xda\\x66\\xfb\\xe0\\x79\\x8c\\x26\\xc3\\xc5\\xde\\xf2\\xde\\xad\\x39\\xeb\\x9b\\x8f\\xe3\\x7a\\x1f\\x70\\x0b\\x76\\x51\\x95\\x6b\\xc2\\xc3\\xd6\\xbe\\x9f\\x53\\x6e\\x9b\\x05\\x6f\\x03\\x5d\\x8b\\x39\\xd4\\x4a\\x98\\x86\\x40\\x9a\\xf5\\xf9\\xd1\\xee\\xe0\\xb0\\xec\\x05\\x70\\x96\\x53\\xbe\\x2b\\xc4\\xf0\\xda\\x63\\xcb\\x72\\xaa\\xab\\x92\\xeb\\xa5\\xec\\x77\\xfd\\x8b\\x5c\\x7c\\x57\\x8d\\x99\\xf5\\xa8\\x6f\\xfd\\xba\\x80\\xc0\\xca\\x93\\xf3\\xb3\\xa5\\x60\\xe9\\x86\\xcd\\x82\\xdd\\xc3\\x4e\\xd0\\x48\\x69\\xa4\\x12\\x34\\x1f\\xf3\\x69\\x25\\x2b\\x95\\xcd\\x43\\x33\\x2e\\x85\\x80\\x80\\x11\\x21\\x67\\x68\\xc7\\x12\\x87\\x9a\\x50\\x21\\xc5\\x3c\\xb7\\x8f\\x8a\\x24\\xab\\x52\\x16\\x8d\\x08\\x7e\\xd3\\x6b\\xc9\\x53\\x42\\x2b\\x2d\\x73\\xaa\\x79\\x42\\x12\\xc9\\xca\\x04\\x7c\\xac\\xe1\\x48\\x95\\x62\\x84\\xae\\x78\\x37\\xa9\\x94\\x96\\x39\\xc9\\x69\\xa9\\x66\\x34\\xcb\\x56\\xed\\x71\\x07\\x3c\\x7c\\x5d\\xb1\\xf6\\x21\\xac\\x7f\\xe5\\x8f\\xd7\\x38\\xeb\\x1d\\xf1\\x7b\\x43\\x6d\\xfa\\x16\\xf8\\x6d\\x26\\xb7\\xd7\\x00\\xd7\\xab\\xb1\\xb4\\xc5\\x18\\xb6\\x2a\\xc2\\xd2\\x7a\\x4f\\x11\\xc2\\xbd\\x9f\\x31\\x52\\x54\\xe3\\x8c\\x2b\\xd0\\x4c\\x81\\x12\\xcd\\xc9\\x98\\xcd\\xb8\\x8d\\xce\\xde\\x4c\\x82\\x56\\x6e\\xf1\\x26\\x38\\xaf\\xa3\\x01\\x1b\\x21\\xb4\\x86\\x64\\xaf\\x7d\\xd7\\xb2\\xb4\\xb3\\x9c\\x4e\\x5b\\x08\\xe0\\xaf\\x0d\\xc1\\xa6\\x62\\xee\\x39\\x21\\x14\\x39\\x55\\x03\\x22\\x4b\\x1b\\xb1\\xe3\\x7b\\xd2\\xdb\\x9f\\x7c\\xa1\\xdc\\x92\\xbc\\xb3\\xa0\\xb3\\xa1\\xf3\\x16\\xdf\\x21\\xa1\\x82\\x95\\x13\\x59\\xe6\\x06\\xc0\\xbc\\x24\\x93\\x4a\\x80\\x81\\x52\\xd9\\x48\\x7b\\xe0\\x12\\xd6\\xc6\\x45\\x33\\x25\\xfd\\x59\\x86\\xbd\\x10\\x6e\\x12\\x84\\x2a\\x72\\xc3\\xb2\\x6c\\x44\\x4e\\xb2\\xcc\\x56\\x5f\\x0d\\xea\\x6c\\xd4\\xb9\\xf2\\x75\\x3c\\xc7\\x78\\x4e\\x52\\x3e\\x65\\x4a\\x93\\xa3\\xcb\\xff\\x7b\\x72\\x0c\\x22\\x0a\\xd8\\x7f\\xe6\\x44\\x53\\x97\\x2a\\x18\\xdb\\xb5\\x40\\xd8\\x49\\x2b\\x10\\x8a\\x12\\xaa\\x69\\x26\\xa7\\x18\\xd2\\x00\\x36\\x72\\x91\\x92\\x22\\xa3\\x73\\x68\\xad\\x50\\xd0\\x12\\xa2\\x7d\\x13\\xb4\\x6d\\x91\\xb2\\x12\\x50\\x54\\xfa\\x4e\\x79\\xd7\\x66\\xa2\\xb2\\xae\\xee\\xf3\\x10\\x70\\x72\\x47\\xa2\\xb1\\xa1\\xba\\xee\\xed\\x32\\xc5\\x92\\x15\\x19\\x5d\\x61\\x8d\\x59\\x38\\xf0\\x75\\x22\\xb8\\x51\\x0f\\x40\\xf5\\x97\\x82\\xf9\\x31\\x46\\xe4\\x12\\x71\\x27\\xa7\\x3a\\x41\\x7f\\xf2\\x4f\\x39\\xd3\\x34\\xa5\\x9a\\x8e\\x8c\\x0e\\xfd\\x53\\x9c\\x95\\x28\\xb3\\xd4\\x0c\\xb4\\x7a\\xa3\\x57\\xcc\\x19\\x85\\x63\\xb9\\x99\\x48\\xbd\\x36\\x12\\xbc\\x7f\\x1c\\xf4\\x1a\\x77\\x1e\\xd7\\x9a\\x7f\\xf6\\xa4\\x4f\\xb0\\xfc\\x97\\x9f\\x8d\\x0a\\xbb\\xd6\\x7f\\x19\\xcd\\xb5\\xf9\\x52\\x6c\\x9d\\xc9\\xe2\\x95\\x58\\x6c\\xcd\\x19\\x94\\xe8\\x7c\\x6f\\xbb\\x50\\xb9\\x3b\\x60\\x7a\\x3e\\x79\\x7b\\xba\\xda\\x4c\\xb8\\xd9\\xd4\\xb2\\xc1\\xb4\\xd2\\x94\\x4f\\x57\\x4e\\xcf\\x19\\xe6\\xed\\x2f\\xb1\\x67\\xc6\\xa5\\x22\\x41\\xf2\\x26\\x26\\xf6\\x50\\xe1\\x39\\x87\\x2b\\xce\\x9f\\x81\\xc5\\x20\\x4c\\x3b\\xc5\\xf7\\x56\\xdb\\x95\\x5a\\xb9\\xc6\\xda\\x38\\xc4\\x36\\x65\\xf9\\x0d\\xfd\\x64\\x57\\x3e\\xd4\\xce\\x3f\\xb6\\x31\\x13\\x6f\\x55\\xa6\\x1d\\x42\\x1e\\x12\\x73\\x9c\\x69\\xd9\\x03\\xbb\\xad\\x3f\\xb1\\xa5\\x5d\\xcc\\x2d\\x75\\x8b\\x89\\xfa\\xad\\x8c\\x82\\xbe\\xae\\xd8\\xfc\\xd0\\xea\\x88\\x06\\xd3\\x67\\xbc\\xc0\\x54\\x51\\xeb\\xbe\\xb1\\xbb\\x4b\\x7e\\xa0\\x19\\x4f\\xfd\\x10\\x88\\xd5\\x67\\x62\\x40\\xde\\x4a\\x6d\\xfe\\x79\\xf9\\x99\\x2b\\x8d\\xba\\xf6\\xa9\\x64\\xea\\xad\\xd4\\x70\\xa7\\x93\\xa5\\xe2\\x14\\xb6\\x58\\xa8\\xd5\\xf6\\xd1\\x03\\x00\\xe7\\x2a\\xb0\\x09\\xb8\\x05\\x9d\\x4d\\x22\\xc9\\xc8\\x3c\\x7d\\x26\\x8c\\x44\\x60\\x57\\xe4\\x53\\xa8\\x95\\x1d\\xc2\\xe5\\xff\\x08\\x29\\x86\\xe0\\x1b\\x58\\x3a\\x86\\x05\\x84\\x2c\\x23\\x38\\xac\\x19\\xce\\x0e\\x85\\xc1\\x97\\xf0\\x0b\\x57\\x8e\\x88\\x7b\\x9e\\x4d\\x9d\\xb9\\x92\\x27\\x24\\x67\\xe5\\x14\\xbc\\x5d\\xc9\\x06\\x6f\\x4f\\x5b\\x13\\x6e\\x2b\\xc3\\xed\\xc6\\xbd\\x02\\x92\\xf9\\x7a\\xa5\\x95\\x66\\x61\\x93\\x82\\xe7\\x91\\x2c\\xe5\\x68\\xba\\xf9\\xa7\\xa1\\x3e\\x00\\xa9\\x7f\\x41\\x1e\\xbd\\x1a\\x91\\x13\\xd7\\xe2\\x27\\xfc\\xcd\\x7a\\xfd\\xc2\\x61\\xcc\\x08\\x5c\\x11\\x43\\x4a\\xae\\x69\\xc6\\xb0\\xc3\\x01\\x15\\x3e\\xd7\\x4d\\x4e\\x16\\x08\\xfb\\xc0\\xe6\\xd3\\x9b\\x33\\xeb\\x45\\xa6\\x83\\x2b\\x36\\x3f\\x18\\x2c\\x6c\\xed\\xc1\\x99\\x38\\xa8\\x13\\x1e\\xa3\\xcd\\xf4\\x44\\x14\\xa4\\xad\\x03\\xf8\\xed\\x60\\x77\\x5e\\xb0\\x96\\x58\\xb6\\xb7\\x25\\x6d\\xdc\\x37\\x75\\xc5\\x97\\xbb\\xfe\\x97\\x0a\\x1b\\x47\\xea\\x18\\xcc\\x1e\\x02\\x7b\\x2d\\xc9\\x12\\xcc\\xc0\\xe6\\x6e\\x58\\x5a\\xc5\\x88\\xaa\\x57\\xbc\\x28\\xea\\x4a\\x34\\x55\\x31\\x2d\\x69\\xca\\xc8\\xb4\\xa4\\xc5\\x6c\\x5b\\xb1\\x04\\x65\\x9b\\x65\\xc3\\x3f\\x1a\\x41\\x77\\x05\\xf0\\xd7\\xe8\\x86\\x6b\\xdf\\xbb\\x61\\xe3\\x99\\x94\\x57\\x90\\x86\\x08\\x88\\x70\\x8b\\x96\\x8c\\x1f\\xf1\\x5b\\xa7\\xf5\\x3d\\xa7\\x94\\x2a\\x92\\x32\\x4d\\x79\\x06\\x71\\x34\\xef\\x5e\\xbf\\xb1\\x91\\x36\\x8e\\x8f\\xbb\\x59\\x2e\\x0f\\x5a\\xe9\\x40\\x01\\xa0\\xa9\\x8d\\x00\\xbb\\x60\\xd7\\x9c\\xdd\\x58\\xfb\\xc6\\xaa\\x18\\x99\\x21\\x99\\x32\\x01\\x81\\x21\\x6b\\x02\\xa8\\x86\\x44\\xf1\\x94\\xbd\\x84\\xa4\\xe7\\xd5\\x03\\xed\\xe1\\x70\\x58\\x31\\xe7\\x4d\\x87\\x77\\x3d\\x05\\xdf\\x48\\xbd\\x5b\\x70\\x59\\xaf\\xfe\\x9e\\xcb\\x72\\x4d\\x11\\xa6\\x76\\x39\\xd8\\xed\\xf2\\xab\\x6d\\x14\\xff\\x73\\xf2\\x87\\x3f\\xfc\\x7e\\xe5\\x43\\x39\\xfd\\xcc\\xf3\\x2a\\x7f\\x4e\\xfe\\xf8\\xef\\xff\\xfe\\xfb\\x7f\\x5f\\xfd\\x18\\x17\\xf8\\xd8\\xb3\\xd5\\xeb\\xb3\\xa7\\xed\\xc5\\xc5\\xe9\\x03\\x80\\x77\\xea\\x23\\x19\\xd7\\x3b\\x33\\x5b\\x0c\\x35\\xa1\\x3c\\xab\\x4a\\x1b\\x43\\xdb\\x52\\x45\\x78\\x15\\xbe\\x03\\x8e\\xa8\\x3a\\xe9\\x84\\xba\\x11\\x5d\\xa0\\x9d\\x0d\\xc0\\x9b\\x70\\xc1\\x14\\x34\\xcf\\xa9\\x44\\xc9\\x12\\x39\\x15\\xfc\\x1f\\x2c\\x75\\xbd\\x73\\x20\\x20\\x06\\xaa\\xec\\x3b\\x14\\x27\\x4c\\xa4\\xd8\\xc3\\xd4\\xf0\\xbc\\x19\\x15\\x69\\xb6\\x2e\\x50\\xa2\\xc5\\x4a\\xc3\\x13\\xbc\\x17\\xc8\\x80\\xf3\\x6c\\x05\\xb0\\x37\\xf5\\x1b\\x0d\\x70\\x41\\x27\\x56\\xeb\\xb6\\x43\\x8e\\x86\\x60\\xdb\\x6b\\xa5\\x48\\x18\\x2f\\xd7\\x28\\xd6\\x4b\\xe6\\xb8\\xa0\\xf7\\xa1\\xca\\x0a\\xf7\\x7e\\xae\\x58\\x39\\x87\\x04\\x9b\\x5a\\xb0\\x0f\\x82\\xf0\\xde\\xd7\\xf5\\x1b\\xdc\\x32\\xac\\x44\\x85\\x05\\x74\\x1a\\xba\\x70\\x2d\\xc4\\xd4\\x61\\x32\\x8d\\x6f\\xc3\\x3b\\x0c\\xc3\\x0e\\x9c\\xd7\\x8c\\x9c\\x10\\x51\\x65\\xd9\\xaa\\x47\\x85\\x5c\\xe7\\x5f\\x0b\\x61\\xb7\\x41\\x95\\x6c\\xa7\\xe3\\xb5\\x35\\x0b\\x2c\\x81\\xf4\\x9d\\x1a\\x07\\xc2\\x85\\x77\\x24\\xca\\x3f\\x6c\\x73\\x41\\xb8\\xe0\\x56\\xf1\\xb4\\xed\\x63\\x69\\xdb\\x95\\x09\\x6a\\x61\\x46\\xc0\\x6b\\x9b\\x60\\xdb\\x96\\xc5\\x7d\\x6e\\xd3\\xb0\\x80\\xd7\\x56\\x71\\x4d\\xed\\x8c\\x0c\\x4b\\xa6\\xfe\\xe0\\x4c\\x0d\\x3b\\x2c\\xbe\\x8d\\xd9\\x61\\xc9\\xd2\\x7b\\xe3\\xc3\\x02\\xc0\\xdb\\x46\\x91\\x6d\\x11\\x41\\xd6\\x72\\x27\\x5b\\x18\\x25\\xf0\\xea\\x4d\\x13\\x5b\\x71\\xa2\\x16\\x84\\x79\\x3b\\x33\\x45\\xeb\\x5d\\x2d\\x19\\x17\\xd7\\x12\\x8b\\x6c\\x6f\\x25\\xc3\\x5d\\x2c\\xbc\\xd8\\x10\\xe5\\x6e\\x80\\xb2\\x5a\\x59\\xce\\x0b\\xbf\\xa1\\x48\\x6b\\x14\\x5a\\x52\\xa9\\xcd\\xc6\\xee\\xf5\\x2b\\x58\\x9f\\x77\\xd3\\x89\\x0e\\x12\\xaf\\xbc\\xca\\xd8\\x8f\\x5c\\xcf\\xde\\xb9\\xa2\\xfa\\x16\\xab\\x75\\x55\\x64\\xb0\\xd8\\xe0\\x07\\x83\\x42\\x17\\xb5\\x64\\x78\\x86\\x6d\\xdc\\x58\\x22\\xf3\\x9c\\x89\\x14\\x83\\x88\\x72\\x7a\\xc5\\x48\\xdd\\x2a\\xd4\\xc8\\x78\\x20\\x06\\xc3\\x70\\xec\\x73\\x41\\x45\\x2d\\x27\\x5e\\x1b\\x5a\\xbe\\x0e\\xa3\\x5a\\xe2\\x53\\x5b\\x5e\\xdb\\x3a\\xa1\\x65\\x7d\\x22\\x4b\\x90\\x89\\x12\\x25\\xac\\x90\\x31\\xcb\\x24\\xa4\\xc0\\x63\\x84\\x2d\\xc6\\x80\\xbb\\x1c\\x10\\x43\\x92\\xed\\x5d\\xcb\\xf5\\x6c\\xc1\\x4d\\x26\\xa6\\x75\\x1d\\x2f\\x95\\x41\\x53\\x5f\\x4b\\x81\\xa5\\x60\\x23\\x72\\x61\\x45\\x98\\x76\\x52\\x51\\x1b\\x72\\xda\\x92\\x94\\x6e\\xc1\\x10\\x3f\\x0f\\xeb\\x6a\\x19\\x43\\x23\\xec\\x0e\\xed\\x6c\\xb4\\xcc\\x79\\xb2\\x69\\x53\\x36\\xdb\\x3a\\xf0\\x6a\\x6e\\x8b\\x7b\\x2f\\xdc\\x98\\x6b\\x77\\xaf\\xcd\\xd6\\xb8\\x87\\xfb\\xcd\\x59\\x71\\xf9\\x56\\x1b\\xdb\\xed\\x4d\\x4c\\x4c\\x6a\\x7e\\xe4\\x37\\xa6\\x41\\x36\\x13\\x6c\\x56\\x0d\\x46\\xc2\\x21\\x79\\x71\\xf1\\xf2\\xe4\\xfd\\xcb\\x01\\xf9\\xfe\\xfc\\x14\\xfe\\x3d\\x7d\\xf9\\xfa\\xa5\\xf9\\xf7\\xc5\\xbb\\xb7\\x6f\\x5f\\xbe\\x78\\x6f\\x24\\x98\\xaf\\xb0\\x69\\x80\\x51\\x20\\xcd\\xd6\\x18\\x4e\\x28\\x63\\x3a\\x45\\xc5\\x9c\\x4c\\x2a\\x6d\\x08\\x51\\xfd\\xb1\\x68\\x16\\x14\\xad\\x0f\\x34\\x4d\\x8d\\xb2\\xfa\\xe8\\x10\\x60\\x39\\xc0\\x9b\\x06\\x9b\\xb0\\x5b\\x0a\\xf6\\x59\\xb0\\x29\\x72\\x9b\\x05\\xb4\\xbb\\xc1\\xb0\\xd6\\x49\\x26\\xd1\\x7a\\x0f\\x76\\xcc\\x2e\\xf9\\x28\\xc8\\x2b\\x59\\x12\\xdb\\x9b\\x0e\\x9a\\x95\\xa6\\xea\\xd0\\xe6\\xf0\\x98\\xff\\x8f\\xf0\\xd6\\x93\\x4c\\x4e\\x0f\\x7d\\x6a\\x0f\\x23\\x99\\x9c\\x12\\x55\\x8d\\x7d\\xca\\x15\\x08\\x01\\xf0\\xf4\\x57\\xee\\xb1\\x28\\x53\\x65\\xe0\\xf3\\xae\\x82\\xb7\\xfc\\xe0\\xd1\\x3b\\xe1\\x03\\xe1\\xb8\\x4f\\xa0\\xa1\\x5c\\xf4\\xa4\\xb9\\xd1\\x1c\\xf0\\xab\\x27\\xcb\\x67\\xe0\\xe4\\x3d\\x5e\\x36\\xde\\xf8\\x28\\x0c\\xae\\xdf\\xf0\\x2c\\x4d\\x68\\x99\\x2e\\x20\\x3c\\xf0\\x64\\xc4\\x17\\x80\\x1e\\x56\\x59\\xc6\\xe6\\xdf\\xf5\\xe0\\xb6\\x36\\x8a\\xbc\\x66\\x65\\x46\\x0b\\x4c\\x08\\x80\\x32\\xd7\\x10\\x31\\x05\\x1f\\x39\\x65\\x05\\x83\\xb4\\x37\\xd7\\x9c\\x9e\\x89\\x24\\x93\\x50\\x86\\x05\\x19\\xfa\\x20\\x5e\\x3a\\x46\\x50\\xb9\\x5a\\x95\\x2e\\xf9\\xd2\\x1f\\xaf\\x83\\x2f\\x93\\xc0\\x42\\x1c\\xf9\\x56\\xa8\\x8f\\x91\\xe7\\x2b\\x0b\\x01\\xf9\\x1c\\x1f\\x54\\x94\\xbd\\xb4\\xcf\\xc8\\x81\\xcd\\x48\\x3c\\x18\\x90\\x03\\x5f\\xeb\\x26\\xb5\\x9a\\xc1\\xc1\\x57\\x07\\xf5\\x03\\x61\\x4e\\x1b\\x28\\x06\\xd6\\x0d\\x36\\x84\\xef\\x84\\xd9\\xb3\\x80\\x1d\\xce\\x59\\xe7\\x3f\\x5d\\xd7\\x2b\\x32\\x1c\\xd9\\x1a\\xee\\x60\\x0e\\xf1\\x40\\xa3\\x68\\x22\\x0b\\x5f\\xad\\xd3\\x31\\x37\\x7e\\xd1\\x4c\\x3f\\x78\\x5d\\x43\\xf9\\x03\\x4c\\xeb\\xb4\\xc0\\x29\\x99\\xd9\\x4a\\x17\\x84\\x77\\x19\\x61\\x9e\\x77\\x36\\x86\\x05\\x95\\x78\\x49\\x0a\\x5a\\x1a\\xf5\\xcb\\x3d\\x19\\xb7\\xc4\\xfb\\x6a\\x63\\x43\\xbc\\x16\\x18\\x14\\xf8\\x94\\x5a\\x6a\\x2a\\x97\\xfe\\x8d\\x17\\x19\\x55\\x6a\\x89\\xb5\\x19\\xa8\\x88\\x19\\x98\\x30\\x1c\\x99\\x50\\xe7\\x70\\x83\\x7a\\xe7\\x33\\x7a\\xbd\\xa6\\x20\\x46\\x8b\\x49\\x6b\\x5a\\x4e\\x99\\x5e\\xef\\x0d\\xa2\\x62\\xfe\\x6e\\x6d\\x09\\xbd\\x61\\xeb\\xa2\\xbd\\xc3\\x76\\x47\\x31\\x3a\\x84\\x5c\\xe8\\xa1\\x2c\\x87\\xf8\\xca\\x73\\xa2\\xcb\\x6a\\x95\\x5f\\x4f\\xf3\\x9c\\xc9\\x4a\\x5f\\xb2\\x44\\x8a\\xe5\\xd9\\x2f\\xf6\\xb9\\xce\\xdc\\x5b\\x5b\\xa4\\x04\\x59\\x0f\\xeb\\x89\\x13\\x60\\xc2\\xa2\\x97\\x4e\\x19\\xad\\xa5\\x1b\\xe7\\x55\\x8d\\xcb\\xf6\\xbc\\x7b\\xfd\\x66\\x9f\\xcd\\x26\\x90\\x36\\xbf\\x7e\\x27\\x7f\\xb0\\x3c\\x43\\x4c\\xfd\\x4c\\xed\\xcc\\xd7\\xbe\\xf6\\xa6\\xd2\\xdb\\xbf\\xf4\\xc2\\x7b\\xeb\\xd6\\x3f\\x6d\\x81\\xb1\\xbe\\xf4\\xca\\xca\\xf5\\x2b\\x4d\\x75\\xb5\\x80\\x0d\\xd1\\xde\\x58\\x62\\x79\\x89\\xe9\\x87\\x56\\x15\\xb9\\x84\\xf7\\x42\\xc3\\xe6\\x62\\xbd\\x09\\xac\\x61\\x03\\xcf\\xb9\\x00\\xcd\\x11\\xb1\\x2f\\x9a\\xf3\\xa9\\x4b\\xca\\x51\\x69\\xa6\\x89\\xae\\x20\\x8f\\x9d\\x6a\\x1b\\xcc\\x69\\x0b\\x2e\\xfd\\x66\\xd9\\x32\\x96\\xaa\\xc9\\xeb\\x54\\xe3\\x84\\x95\\x5a\\xbd\\xa6\\x4a\\x7f\\x5f\\xa4\\x74\\x45\\xa6\\x5b\\x23\\x48\\x53\\x69\\x38\\x30\\x28\\xd2\\xdf\\x08\\x96\\x1a\\x0a\\x6f\\x41\\x80\\xe3\\x91\\x1b\\x43\\x7a\\x2b\\x1c\\x71\\x65\\xe8\\xc1\\x4a\\x94\\x73\\x07\\xc8\\xbc\\x3e\\x34\\x9f\\x5a\\x3e\\xeb\\x0b\\x69\\x60\\x72\\xb2\\x94\\x00\\xc5\\xe1\\x29\\x9b\\x66\\x6b\\xd8\\x49\\x09\\xa3\\x11\\xc1\\x3e\\x2f\\xb3\\x32\\xec\\x3f\\xe3\\x8c\\x51\\xb1\\x3c\\xd9\\xa0\\x81\\x51\\xf0\\xdc\\xf6\\x38\\x64\\x3f\\x40\\x6e\\x66\\xdc\\xc8\\xbb\\x98\\x11\\xa8\\x88\\x93\\xbf\\x52\\x96\\xb1\\x15\\x89\\x81\\x7b\\x86\\xcf\\xda\\x2f\\x9c\\xda\\x0f\\xb4\\x0a\\xed\\x3a\\x8f\\xdf\\xf1\\x4e\\x0c\\x2b\\xc1\\xdb\\xd4\\x93\\x5a\\xd2\\xb6\\xd2\\x83\\xd7\\xd7\\x9a\\xab\\x02\\xf1\\x65\\x9c\\xc9\\xe4\\x0a\\x0b\\xd0\\x41\\xed\\x07\\xfe\\x0f\\x56\\xba\\x58\\xfb\\xba\\xf9\\x9c\\xed\\x88\\x36\\x75\\xdd\\x5e\\x1d\\xdc\\x5c\\xfb\\x2b\\x18\\xc5\\x8c\\x6d\\x00\\xe8\\xc7\\x97\\x65\\x6d\\x4d\\xad\\x84\\xcd\\xb4\\xbc\\x9b\\x70\\x5d\\xa7\\xe5\\x40\\x8e\\x42\\xe4\\x2d\\x59\\x54\\x78\\xb0\\x56\\x0d\\xd4\\xc7\\xb4\\xca\\x2a\\xcd\\x6d\\x6e\\xd0\\x93\\xef\\x56\\xe7\\xd1\\x74\\x1a\\x82\\xbb\\x2e\\x9b\\x07\\x9f\\x00\\xf0\\x89\\x64\\x6d\\x69\\xa3\\xb5\\x79\\x3f\\x6d\\xad\\x7d\\x1b\\xf2\\x7b\\x48\\x7b\\x09\\xdf\\x4f\\xb9\\xcd\\x68\\x9d\\x06\\x54\\x76\\xee\\xe1\\x5c\\x99\\xfa\\x50\\x5f\\xdb\\xf8\\x2d\\xdb\\x16\\xe6\\xdd\\xca\\xb3\\x26\\xb6\\x29\\xa0\\x1a\\x17\\x9a\\xf1\\x6a\\x87\\xcd\\xe2\\xc5\\xe8\\x83\\x89\\x2c\\x57\\x2a\\x30\\xdd\\x4d\\x7e\\x7d\\x36\\xd8\\xc6\\x81\\x8c\\xf4\\xb9\\x3a\\x5e\\x6f\\x31\\x61\\xc9\\x50\\x2f\\xff\\xca\\x80\\x50\\x32\\xe3\\x4a\\xcb\\xd2\\xba\\x13\\xa1\\x79\\x5d\\x49\\xa1\\xb9\\xee\\xf2\\xb8\\xb7\\x6e\\x22\\x00\\x5f\\xf8\\x29\\x10\\x5a\\x14\\x8c\\xfa\\xbe\\x56\\x96\\x37\\x41\\x63\\xaa\\x92\\x25\\xb2\\x4c\\x97\\x4e\\xcc\\x99\\x06\\x96\\xca\\x52\\x4b\\x3f\\xdf\\x41\\x66\\x6b\\x46\\x95\\x7e\\xef\\xe7\\x60\\x04\\x84\\x96\\xd4\\x38\\x16\\x7f\\xec\\x12\\xeb\\xd5\\xb8\\xd2\\x3f\\x52\\xd4\\x3f\\x4a\\x42\\x05\\x9a\\x44\\xf6\\x93\\xc1\\x37\\x0b\\x19\\xf5\\xda\\x50\\x9a\\xdb\\x69\\x5d\\x37\\x5e\\x72\\x0b\\x96\\x78\\x37\\x33\\xcf\\x99\\x52\\x6b\\x93\\xab\\x1a\\x81\\x29\\x50\\x43\\x9a\\xf8\\x1a\\xd2\\xf6\\x75\\xc7\\xec\\x51\\x40\\xc0\\x10\\x54\\x57\\xe5\\x6d\\xbe\\x1a\\xd5\\x08\\x88\\x09\\x68\\x50\\xf0\\xc7\\x6a\\xaf\\x2d\\x2b\\x66\\x54\\xb5\\x5d\\x8c\\x3f\\x45\\x3e\\xac\\xb9\\xf5\\x71\\x68\\x39\\x9b\\x92\\x51\\xb5\\x2e\\xd1\\xb4\\x01\\xdb\\x71\\xc9\\xd9\\x84\\xbc\\xa0\\x39\\xcb\\x5e\\x50\\xd5\\x25\\x70\\x81\\x02\\x8c\\x08\\x1b\\x4d\\x47\\xe4\\xf0\\x22\\xf0\\x30\\xbf\\x95\\xfa\\xcd\\xba\\x1e\\x1f\\x1b\\xca\\x3f\\xb4\\x39\\xd1\\xb7\\x7a\\x96\\xf7\\x56\\x12\\x36\\x9f\\xdc\\x3d\\xcf\\xec\\xde\\x33\\x5c\\x73\\x42\\x1f\\xc4\\xd9\\x5c\\x9f\\x2d\\xbd\\xea\\x3c\\xc6\\x27\\xb1\\x2a\\xc1\\xe2\\x97\\xec\\x7a\\x22\\x37\\x24\\x70\\xae\\x3a\\x85\\x0f\\xf9\\xfc\\x6d\\x58\\x92\\x1f\\xe2\\x72\\xa9\\xc9\\x64\\x61\\x75\\xef\\x23\\xcd\\x15\\x7c\\x06\\x61\\x50\\x21\\x94\\x87\\x37\\x33\\x7d\\x71\\xf9\\x43\\x97\\x62\\xcb\\xfd\\x96\\x2a\\xb0\\x1b\\xb8\\xf2\\xf7\\x35\\x72\\xf9\\x70\\x3d\\x17\\xde\\xb7\\x0c\\x42\\x0a\\x5e\\x1a\\x83\\x01\\x77\\x19\\x74\\x72\\xea\\xbe\\x6a\\x6d\\x1d\\xbe\\xb2\\x33\\xfc\\x35\\xb1\\x1d\\xf4\\xec\\x33\\x11\\x7e\\x1c\\x41\\xaf\\x42\\x76\\x8d\\x0d\\x42\\x21\\xc9\\x85\\x11\\xc1\\x94\\x39\\x14\\xc7\\x6b\\x3e\\xdf\\x52\\xa1\\x6a\\xa7\\x4c\\x6d\\x56\\x74\\x37\\x2a\\xb1\\x64\\xf3\\xd6\\xba\\x87\\xd6\\x6d\\x30\\x5e\\x6d\\x75\\xb6\\x16\\x3a\\xf1\\x16\\xca\\xda\\x66\\x8d\\x67\\x8b\\xc1\\x36\\x8a\\x7f\\x5b\\x8e\\xb7\\xdc\\x80\\xdb\\xbc\\x1a\\x95\\xa4\\xcd\\x2b\\x17\\x40\\xa4\\xd1\\xab\\x9c\\x18\\x0a\\x9c\\x40\\x7d\\x71\\xa4\\xdd\\x96\\x3c\\xc5\\xf6\\xdb\\x8b\\x26\\x0d\\x84\\x10\\xcb\\x18\\xc3\\xbb\\x5a\\x56\\x55\\xf1\\xee\\x60\\xbe\\xb1\\xfe\\x48\\xeb\\xf1\\x1e\\x40\\x31\\x95\\x8d\\x08\\x74\\xbb\\xc5\\x19\\xf0\\xda\\x84\\x75\\xf7\\x8f\\x6f\\x6d\\x2a\\x65\\xad\\xc5\\xb1\\x5b\\xaa\\x6b\\xa3\\x58\\x79\\xcd\\xd2\\xc8\\x53\\x67\\xeb\\xfc\\xc7\\xf7\\x02\\xbf\\x6d\\x3d\\xbe\\x05\\x3b\\xf9\\xe7\\xbf\\x7e\\xf3\\x9b\\xe1\\x70\\xf8\\x9b\\x3a\\xa4\\xec\\x39\\xa1\\x05\\x67\\x9f\\x35\\xc3\\xa8\\xc3\\xd1\\xd5\\x7f\\x40\\x33\\xa7\\xeb\\x67\\xbf\\x01\\x84\\x23\\x2f\\xc0\\xda\\xec\\xcc\\xac\\xa7\\x3e\\x6b\\xf2\\x37\\x2e\\xeb\\xd4\\x7c\\x84\\x0a\\x21\\x75\\x18\\x05\\x95\\x48\\xa1\\x4b\\x99\\x65\\xac\\x1c\\x4e\\x99\\x18\\x5d\\x55\\x63\\x36\\xae\\x78\\x96\\xb2\\x12\\x06\\x77\\x9f\\xbe\\x7e\\x3a\\xfa\\xf3\\xe8\\xe9\\x6f\\x88\\xcf\\x31\\x35\\x92\\xbd\\xd2\\x34\\x2f\\x9e\\x43\\xb2\\xcb\\x6f\\x2c\\xc6\\xb9\\xea\\x7d\\x45\\x46\\x85\\x1a\\xf9\\xd0\\xf6\\x51\\x22\\x4b\\x26\\xcd\\x3f\\xf9\\x6f\\x54\\xc1\\x12\\xf3\\x6d\\x3c\\x68\\x64\\xe9\\x33\\xd6\\x74\\x66\\xa7\\x68\\x6b\\xd5\\xd5\\x60\\x1a\\x12\\x99\\xe5\\xf0\\x7f\\x5c\\xba\\x2d\\x37\\x78\\x9e\\xd9\\xda\\x85\\x19\\x57\\xfa\\xbb\\xe6\\x2f\\xaf\\xb9\\x42\\x76\\x59\\x64\\x55\\x49\\xb3\\x78\\xaa\\xf0\\x83\\x9a\\xc9\\x52\\x47\\x65\\x79\\x87\\x84\\x23\\x6b\\x54\\x5c\\x4c\\xab\\x8c\\x96\\xd1\\x5b\\xbf\\x71\\x31\\x0f\\xb5\\xb9\\xce\\x70\\xc9\\xeb\\x28\\x04\\x70\\x18\\x05\\x08\\x73\\xa1\\x59\\xf9\\x42\\x66\\x55\\x1e\\x5a\\xc7\\x86\\x8b\\x72\\xe5\\x84\\x97\\x4a\\xdb\\x7a\\x88\\xb1\\x53\\x61\\x99\\x5c\\x0c\\xdf\\x0f\\x70\\xf4\\xef\\x4a\\x0a\\x70\\x17\\x92\\x91\\x01\\xf7\\x68\\xf5\\x4b\\x1f\\x9e\\x7e\\x0a\\xde\\xc3\\x3d\\x8c\\xe5\\xd5\\xa5\\xa7\\x64\\xc9\\x8c\\x69\\x51\\x94\\xf2\\x9a\\x62\\x35\\xc7\\x35\\x73\\x71\\xcf\\x2d\\x7c\\xf6\\x64\\xf1\\x87\\x15\\xdf\\x5e\\x3e\\x64\\xe4\\xa3\\x0b\\x87\\x8c\\x7e\\xd0\\x4b\\x2a\\x5d\\xe2\\xc3\\xd7\\xcf\\x68\\x56\\xcc\\xa8\\xcb\\xad\\x54\\xc9\\x8c\\xe5\\xb4\\xde\\x24\\x59\\x30\\x71\\x72\\x7e\\xf6\\xc3\\xef\\x2f\\x1b\\x3f\\x2c\\xaf\\x7d\\x69\\x50\\xce\\xa7\\x13\\x06\\x5d\\x18\\xa8\\xd3\\xc5\\x7c\\x3a\\x48\\x7d\\x02\\x16\\xa6\\xb9\\x20\\xe4\\x2d\\x17\\xea\\x8c\\x54\\x8e\\x67\\xbc\\x71\\xdb\\x40\\x27\\xb8\\xb5\\x4a\\xb8\\x0a\\x88\\x4c\\x83\\xd0\\xc5\\xfd\\xe6\\xea\\x38\\xd5\\x68\\x65\\x16\\xe1\\x59\\x6a\\x61\\x56\\x47\\xef\\x38\\x37\\x4f\\xbd\\x68\\x61\\xd7\\x34\\x22\\x06\\x19\\x59\\xe9\\x2b\\x3f\\x61\\xea\\xaa\\x26\\x41\\xce\\x25\\x8e\\xa6\\x5c\\x3d\\x47\\x48\\xb1\\xd2\\x10\\xb7\\x50\\x0a\\xd7\\x34\\x7a\\xe0\\x7b\\xdf\\x97\\xcc\\x8c\\x1b\\x67\\x6d\\xba\\x34\\x94\\x25\\x2d\\xf1\\xa6\\x5c\\x3b\\x12\\x9a\\xc8\\x3c\\xaf\\x04\\xd7\\xf3\\x27\\x40\\x0d\\xf9\\xb8\\x32\\xbb\\xf1\\x24\\x65\\xd7\\x2c\\x7b\\xa2\\xf8\\x74\\x48\\xcb\\x64\\xc6\\x35\\x4b\\x74\\x55\\xb2\\x27\\xb4\\xe0\\x43\\x98\\xac\\xc0\\x00\\x9c\\x3c\\xfd\\x37\\x4f\\xc7\\x9b\\x4a\\xe7\\x4a\\x0e\\xb3\\x4c\\x46\\x88\\x61\\x0d\\xf5\\xf4\\x78\\xd0\\xdb\\x1e\\xdb\\x6f\\x47\\x35\\x6a\\xa1\\x4a\\xf2\\xcb\\xcb\\xf7\\xb5\\x8b\\x11\\xab\\x23\\x01\\x84\\x03\\x27\\x5b\\x0d\\x6c\\x03\\x28\\xe8\\x5d\\x64\\x8b\\xc2\\xbb\\x74\\x56\\x9f\\xc4\\x0a\\x3d\\x01\\x32\\x6e\\x74\\x12\\x55\\x8d\\x73\\xae\\x95\\x8b\\xb2\\xc4\\xa8\\xc3\\x17\\xc0\\x41\\xa0\\xae\\x28\\x5a\\x6a\\x46\\xe4\\x4c\\xd4\\xfa\\xfd\\xad\\x83\\x1a\\xa2\\x82\\x86\\x06\\x7c\\xed\\x81\\x1d\\x32\\xc0\\xc5\\x17\\x96\\x28\\x52\\x8e\\x45\\xad\\xdc\\x9d\\xe0\\x8c\\x5f\\x16\\x2c\\xf1\\xa7\\xc1\\x9f\\xe9\\x13\\xac\\xaf\\x6f\\x1b\\x39\\xf8\\x40\\x4e\\x89\\x1d\\xc9\\xe1\\xe5\\x85\\x90\\x82\\x35\\x7a\\xdd\\x6a\\x5d\\x6e\\x48\\x96\\xd0\\xd3\\xf8\\xa7\\x25\\xb1\\x0b\\xc3\\x76\\x6c\\x84\\x6c\\x50\\xc8\\xdc\\xa7\\x37\\xdb\\x81\\x1c\\x6f\\xb0\\xda\\x31\\xf4\\x45\\xf0\\x0c\\xc3\\xe6\\xa0\\x80\\xae\\x2c\\x42\\xd8\\x42\\x5e\\x46\\x10\\xa2\\x6c\\x20\\x7b\\x70\\xe2\\x8a\\x41\\x62\\x2f\\x81\\x37\\x54\\x54\\x34\\x5b\\x1a\\xc0\\xb6\\x56\\xbe\\x73\\xb0\\x59\\x5d\\x53\\x62\\x55\\x35\\xe4\\xd5\\xa0\\xeb\\xb4\\x3e\\xc5\\xda\\xd9\\xdb\\x1c\\xf1\\xb5\\x65\\x35\\x56\\x05\\x78\\x21\\x36\\x6e\\x5d\\x8e\\x23\\xe8\\x39\\xb0\\xca\\xa5\\xb9\\x4f\\x0c\\xd2\\x41\\x78\\xa6\\x16\\xc2\\x46\\x90\\x81\\xae\\x0f\\x1d\\x51\\x9a\\x15\\xaa\\x2e\\xcc\\xa1\\x25\\x49\\x64\\x5e\\x64\\x4c\\xc7\\xbc\\x17\\x22\\x7a\\xb7\\x8b\\x51\\x6a\\x06\\xec\\xee\\x78\\x52\\x6d\\x9d\\x96\\xcb\\x15\\xfe\\xda\\x21\\x5a\\x76\\xb7\\x39\\x7f\\x5a\\x33\\x51\\x19\\x2a\\x7c\\x19\\x55\\x8e\\x5f\\xd1\\xf2\\x37\\x3e\\x92\\xab\\xdf\\x0d\\xeb\\x32\\x62\\x06\\x6e\\xdc\\x5d\\xca\\xc5\\x98\\xb8\\xca\\xd2\\xa9\\x0d\\x4c\\x4d\\x83\\x54\\xbd\\xd5\\xa1\\x25\\x7b\\xc6\\xe9\\xac\\x96\\x55\\x96\\x2f\\xb3\\xce\\xa3\\x59\\xe8\\x94\\xbb\\xe2\\xfd\\x8d\\x6a\\x21\\x24\\x29\\xae\\x8b\\xc6\\x8b\\x39\\xf9\\x99\\x05\\x68\\x69\\x7b\\x8a\\x52\\x52\\x70\\x86\\x81\\xf7\\x5e\\x1c\\x02\\x80\\x31\\x9a\\xda\\x9b\\x86\\xe1\\x95\\xcc\\x07\\x97\\x5b\\x7b\\x37\\x0c\\x50\\x8b\\x4b\\xd0\\x03\\x8a\\x62\\x94\\x3b\\xf9\\xaf\\xcb\\x77\\x6f\\x9f\\x7c\\x2b\\x6d\\x02\\xa5\\x6d\\x33\\x03\\x98\\x9c\\x43\\x3c\\xbc\\xeb\\xa6\\x92\\x32\\x65\\xd0\\xf3\\x12\\x8c\\xe7\\x39\\x15\\x7c\\xc2\\x94\\x1e\\xf9\\xba\\x28\\xea\\xc3\\xd7\\x9f\\x46\\x61\\x5e\\xc1\\xc0\\x15\\xc2\\xf7\\x42\\x85\\x45\\x0d\\x20\\xe5\\x66\\x31\\x75\\x49\\x51\\xdf\\xc0\\xb6\\x90\\xae\\xeb\\xcc\\x0d\\x4c\\x56\\xd3\\x2b\\x43\\xbf\\x71\\xb2\\x95\\xd1\\x65\\xae\\xd8\\x73\\x72\\x80\\xaa\\x89\\xff\\xf4\\x3f\\x8d\\x18\\xfe\\xaf\\x03\\x72\\x74\\x03\\x21\\xcf\\x07\\xe6\\xcf\\x03\\xfc\\xa0\\x97\\x01\\xc3\\xc6\\x4b\\xf5\\x87\\x31\\x50\\xba\\xe4\\xd3\\x29\\x2b\\xad\\xef\\x08\\xcc\\xaa\\xd0\\x5f\\x86\\x43\\xcb\\xd8\\xfa\\x61\\x61\\xfb\\xef\\xd5\\x75\\x46\\x9b\\x13\\xf9\\xf0\\xf5\\xa7\\x03\\x72\\x14\\xaf\\x8b\\x70\\x91\\xb2\\xcf\\xe4\\x6b\\xef\\x7e\\x28\\x64\\x7a\\x6c\\xa3\\xb2\\xd4\\x5c\\x68\\xfa\\xd9\\x8c\\x99\\xcc\\xa4\\x62\\x02\\x43\\xbe\\xb5\\xc4\\x96\\x3f\\x4a\\x82\\x67\\x2b\\xcb\\x86\\x28\\x25\\xa4\\xe4\\x06\\x53\\xa5\\x1d\\x28\\x31\\xf5\\x18\\xca\\x34\\xc5\\x12\\x32\\xb6\\x5b\\x86\\xaf\\x99\\x6d\\x9b\\x82\\x69\\xc5\\x48\\x5f\\xd8\\x13\\x08\\xb3\\x22\\xc2\\xca\\x50\\xaa\\xc2\\x4d\\x32\\xa4\\x6f\\x46\\x05\\xb8\\x59\\x6c\\x2b\\x21\\x23\\x4f\\x8d\\x56\\xf9\\x24\\x37\\x62\\xfc\\x3a\\x93\\xd6\\x12\\xb1\\xb5\\x4d\\x4b\\xea\\x3b\\x12\\x0a\\x5b\\x2f\\x71\\x9d\\xc1\\xec\\x5e\\xbb\\x6e\\xef\\xb5\\xa2\\xb5\\xd1\\x47\\x8b\\xcb\\xc2\\x90\\xa3\\x3b\\x58\\x1b\\xf4\\x26\\x7e\\xb2\\xf3\\xd2\\x9c\\x48\\xbd\\x0d\\x27\\x38\\xbc\\xc4\\x03\\x9f\\x34\\xdf\\x36\\xc7\\x05\\x23\\x0e\\xad\\xd2\\x1a\\x50\\xb8\\x9c\\xa6\\x48\\x02\\xa9\\x98\\xdf\\x3a\\x1a\\x1b\\x00\\x82\\xd7\\x36\\x99\\x0f\\xad\\x5d\\x6e\\x48\\x45\\x6a\\xfe\\xaf\\xb8\\xd2\\xe6\\xfe\\xce\\x10\\x5b\\x63\\x08\\x8d\\xa1\\xf4\\xfd\\xd9\\xe9\\xdd\\x20\\x77\\xc5\\x77\\x3c\\xad\\xe3\\x4a\\xa4\\x19\\x7b\\x2d\\xe5\\xd5\\x8a\\xf4\\xe7\\x68\\x41\\x7f\\x0b\\x9f\\xf6\\xde\\x39\\xd4\\xd2\\xb8\\x18\\xfa\\x18\\xda\\x40\\xcb\\x25\\x45\\x95\\x21\\x79\\xad\\x44\\x41\\x93\\x2b\\x3a\\x65\\xf6\\xa3\\xc0\\x46\\x6c\\x51\\x03\\xd4\\x94\\x41\\x15\\xe8\\xb4\\x96\\xde\\xca\\xd9\\xa3\\x35\\xc0\\xce\\x73\\xc5\\x34\\x1d\\x5f\\xb4\\xa5\\x16\\xa8\\x9b\\xf7\\xe6\\xf9\\x76\\xe2\\x57\\x8e\\x24\\xdc\\x0b\\x36\\x59\\xf9\\xa0\\x6f\\x0d\\xb0\\x2a\\xff\\x64\\x08\\x6d\\xe0\\x56\\xfe\\xe8\\x8a\\x3f\\x2f\\x7d\\x60\\xb3\\x0f\\xb1\\x39\\xcf\\xb6\\xd1\\x4d\\x8d\\xd7\\xdc\\x8e\\x38\\x82\\x61\\xa1\\x1c\\x3d\\x06\\x77\\xec\\x2e\\x40\\xe7\\xbe\\x1b\\xaa\\x80\\x02\\x65\\xd7\\x36\\x32\\xe7\\x4e\\xca\\x40\\x6d\\x16\\x9b\\x97\\xac\\x77\\x07\\xe1\\x39\\x9c\\xf8\\x46\\xbf\\xdd\\x46\\x41\\x7a\\xc9\\x9c\\x7a\\x71\\xba\\x17\\xa7\\x1f\\xb8\\x38\\xbd\\xd5\\x19\\xd8\\x1c\\x7a\\xf0\\x38\\x04\\xec\\xad\\x16\\xbd\\x39\\xda\\xfe\\x41\\x8a\\xdc\\x5b\\xaf\\xb1\\x45\\xf0\\xff\\x83\\x15\\xc2\\xb7\\x5a\\x6c\\x4b\\x81\\x7c\\xd9\\x92\\xbf\\x64\\xb1\\x7c\\x2b\\x18\\x6e\\x8c\\x87\\x79\\x80\\x82\\x7a\\xeb\\x05\\xae\\x4f\\x0a\\x59\\xb2\\xbe\\x20\\x1f\\xa3\\x61\\x07\\x36\\x93\\xc6\\x76\\xf6\\xde\\x4e\\x1b\\x8a\\xc9\\x9b\\xc4\\xa9\\x4e\\xaa\\xde\\x76\\x16\\x7d\\xd7\\x2a\\x6c\\x6e\\x65\\x29\\x66\\xbc\\xda\\xc6\\xcc\\x6d\\x93\\x2d\\x82\\xd7\\x9a\\x38\\xf3\\x3a\\xae\\x78\\xef\\xb4\\x11\\xbc\\xb6\\xc8\\xac\\x6a\\x9b\\x88\\x51\\x2f\\xbb\\x4d\\x22\\xc9\\x16\\x4b\\x36\\x32\\x7c\\x51\\xca\\x71\\xdb\\x5a\\x39\\xb7\\xb0\\xaa\\x96\\x51\\x86\\x7b\\x86\\xb3\\x43\\x76\\xbe\\xdf\\xdf\\xce\\x16\\xbb\\x29\\x89\\x63\\xc9\\xdc\\xb1\\x8e\\x5f\\x14\\x49\\xe6\\xf7\\xe3\\x50\\xc1\\x26\\xdf\\xc6\\x4c\\x77\\x0e\\xbe\\x0c\\xc4\\x6a\\x9c\\xe4\\xc0\\x79\\x30\\xdf\\x97\\x15\\x1b\\x90\\x57\\x34\\x53\\x6c\\x40\\xbe\\x17\\x57\\x42\\xde\\x74\\x37\\xdf\\xf5\\x15\\x19\\x96\\xcc\\xf6\\xbd\\xad\\xbd\\xd0\\x22\\x57\\xa8\\xf5\\x54\\x6a\\xed\\xbe\\x25\\xb1\\x3f\\xf3\\x2f\\x38\\x0b\\x8d\\xd5\\xd0\\x87\\x95\\xe0\\x3f\\x57\\xb1\\xa2\\xe2\\x9d\\x4c\\x47\\x4d\\x15\\xe6\\xc5\\xe5\\x0f\\x80\\x1c\\xa8\\x6e\\xab\\xa8\\x90\\xaf\\xf9\\x51\\xad\\x0e\\xab\\x6e\\x93\\x07\\xb5\\x56\\x51\\x8d\\x13\\xc3\\x8d\\xa2\\x1f\\xab\\x5a\\x99\\x2d\\xc9\\xd8\\x34\\xcb\\x14\\x55\\x96\\x8d\\xc8\\x99\\x3e\\x54\\x66\\x0e\\x3c\\xa1\\x59\\x36\\x37\\x5a\\x4b\\xa3\\x43\\xda\\x7e\\x19\\x5c\\x2d\\x18\\xc4\\xc2\\x61\\xc3\\x8a\\x2b\\xfc\\x9a\\x05\\xaf\\x3b\\x40\\xa3\\xc1\\x89\\xa5\\x76\\x1d\\xfb\\x95\\x89\\x5c\\xd3\\x0b\\x6c\\xc9\\xd4\\x2e\\xec\\xe3\\x0e\\x51\\xc2\\xfd\\xaf\\xa1\\x6a\\x07\\x45\\x5d\\x13\\x90\\x46\\x30\\x32\\x91\\x95\\x48\\x09\\xd5\\xb0\\x3d\\x3b\\xce\\x39\\xf6\\xe1\\xde\\x9d\\xc3\\x7f\\xbd\\xfc\\xd4\\x8d\\xb1\\x31\\xf0\\xc0\\xd7\\x79\\x7c\\x6b\\x84\\xaf\\x9a\\xc8\\xb1\\xcf\\x2c\\xa9\\x82\\x18\\xaf\\x30\\x86\\x63\\x37\\x5b\\x63\\xb7\\xb9\\xaf\\xf7\\x92\\x98\\x7a\\xb7\\x39\\xa5\\x5d\\xa7\\x4e\\x7a\\x0c\\x68\\x1f\\xd5\\xdd\\x4e\\x54\\xe8\\x20\\xf6\\xbc\\x4d\\x61\\xa7\\xf6\\x95\\x89\\x96\\xa1\\x3d\\x70\\x45\\xdb\\x0b\\x9c\\xa9\\x60\\x85\\x0b\\xf8\\x6d\\xe8\\x09\\x85\\x0a\\x2c\\x86\\xc9\\xd8\\x4e\\x10\\x50\\xa7\\x6a\\x26\\x77\\xa6\\x8c\\x6d\\xf3\\x13\\xdf\\x38\\xf9\\xcd\\x7c\\x10\\x64\\xbb\\xe1\\x82\\x6c\\x67\\xf9\\x5f\\x2d\\xdb\\x41\\xc3\\xa2\\x3a\\x94\\x06\\x98\\x64\\x4e\\xe7\\x10\\x9a\\x96\\x17\\xb2\\xd4\\x14\\x1d\\x1c\\x95\\x48\\x59\\xa9\\x34\\xc5\\x1a\\x25\\x2e\\x2f\\xaf\\x30\\x6b\\x9e\\x51\\x45\\xb8\\x56\\x24\\xb1\\x49\\x86\\xb8\\x61\\xb7\\x94\\xc9\\x18\\x00\\xfb\\xdc\\xbc\\xe0\\x45\\x84\\xe8\\xe3\\xc8\\x57\\xa3\\x8d\\x59\\xbb\\x0b\\xeb\\x27\\x96\\xd1\\x35\\x81\\x55\\xfb\\xd2\\xd9\\x4b\\xcd\\x8a\\x26\\x5d\\x0d\\x16\\x21\\x40\\x1c\\xbf\\xe6\\x29\\x06\\x23\\xb1\\x82\\x70\\xd1\\x0d\\x51\\xdd\\xec\\xc0\\x41\\xc7\\xc4\\xea\\x63\\x35\\xf4\\x56\\x9a\\x95\\x0f\\xac\\xd1\\x68\\x37\\x13\\x75\\x59\\x60\\xa4\\xfc\\xa6\\xb3\\xbf\\x2a\\x36\\x0f\\x2f\\xbf\\x8a\\x3d\\xc9\\xe5\\xea\\x48\\x39\\xbc\\x16\\x76\\xd5\\x65\\x5f\\xac\\xd9\\xdd\\x20\\x56\\x17\\xa2\\x41\\x75\\x69\\x25\\xa9\\x79\\xab\\x3d\\x26\\x77\\x5d\\xe5\\x66\\x43\\xea\\xdf\\xc6\\x42\\x2c\\xc3\\x20\\x70\\xb0\\xe5\\x63\\x60\\x98\\x5c\\xfb\\xec\\xa6\\x3c\\xc2\\xbb\\xae\\xab\\xb3\\x67\\xc5\\x94\\xfa\\x72\\x2e\\xa4\\x4e\\x06\\xdb\\x6c\\x65\\x6f\\x39\\x50\\xbd\\x35\\x1d\\x0f\\xd7\\xc2\\x3e\\xde\\x72\\xcc\\x56\\x09\\x80\\xdd\\xa7\\xbd\\xb1\\x22\\x4e\\xfb\\x5d\\xc6\\x93\\x0a\\x5a\\x6a\\x9e\\x54\\x19\\x2d\\xeb\\xb3\\x0f\\x44\\x7e\\x21\\x6f\\x69\\xeb\\x39\\x2b\\x4d\\x4b\\xdd\\xaa\\xc8\\xc2\\xa5\\x7b\\xd2\\xd7\\x5c\\x84\\x82\\x0b\\x33\\x26\\xbc\\xf3\\x0f\\xd3\\xc0\\xc8\\x98\\x4d\\x0d\\xf3\\x2c\\x8a\\x6c\\xee\\x72\\x0c\\xea\\x08\\xf6\\x8c\\x2b\\x5d\\x37\\x3c\\x04\\x59\\xa0\\x6d\\x28\\xc4\\xd6\\xe5\\x1a\\x7e\\xd5\\x79\\x74\\x32\\xcb\\x13\\x29\\x26\\x7c\\x7a\\x77\\x59\\x74\\xef\\x5e\\xbf\\x79\\x01\\x9f\\x84\\x7b\\x75\\x0e\\x9d\\xbf\\xbf\\x90\\x41\\x57\\x4f\\x12\\x6e\\xd7\\x49\\x72\\xfe\\x87\\x3a\\x45\\xce\\xd6\\x73\\x58\\x92\\x1f\\xe7\\xb2\\xaf\\xdc\\x7e\\xee\\x98\\x77\\xe5\\xa7\\xe9\\xa2\\x32\\x3c\\x2b\\x56\\x85\\x14\\x8a\\x1b\\x99\\x18\\xea\\x67\\xc1\\x43\\xd8\\xf1\\xe5\\xdd\\xeb\\x37\\xdd\\x26\\x5d\\xf5\\x19\\x56\\x7d\\x86\\x55\\x9f\\x61\\xb5\\xe9\\x40\\xb5\\xc8\\xb0\\xf2\\xa7\\x19\\xf2\\xab\\x5c\\xd8\\x9e\\xf9\\xbf\\x4d\\x13\\xaa\\x8f\\xbb\\xaf\\x69\\xdd\\xf6\\xe3\\xeb\\xe5\\xc3\\x09\\xa3\\x06\\x34\\x9b\\x23\\x0b\\x5f\\xd9\\x07\\xeb\\xce\\x43\\x51\\x9e\\xae\\x25\\x33\\xa0\\x8b\\xbf\\x7b\\xfd\\xc6\\x8f\\x7b\\x0b\\x39\\x11\\x29\\x57\\xe6\\x33\\x2f\\x64\\xc1\\x59\\xfa\\xe2\\xf2\\x87\\x76\\x8d\\xa9\\x4f\\x9b\\x6f\\x45\\x39\\x1d\\xf8\\xa3\\x99\\xf9\\xa1\\x22\\x07\\xf8\\x10\\x79\\x71\\xf9\\xc3\\x81\\x5b\\x08\\x6c\\x44\\xdd\\xbc\\xcc\\x67\\xb5\\x11\\xaa\\x43\\x81\\x00\\xe9\\xff\\x80\\x60\\x14\\x12\\x8d\\x6f\\xa7\\x51\\x73\\x27\\x29\\x6c\\xa7\\x9d\\x19\\x55\\x64\\xcc\\x98\\x08\\x06\\x45\\x15\\xf8\\x9d\\x7d\\x1a\\x4a\\x81\\xda\\x38\\x25\\xa8\\xe0\\x8d\\x1d\\x03\\xea\\xa8\\x86\\x11\\xf9\\xd1\\x88\\x36\\x25\\x63\\xc2\\x2c\\x23\\x1d\\xc0\\x16\\x60\\x85\\x5c\\x06\\xbc\\x17\\x5d\\x7a\\xc1\\xc2\\xd4\\x01\\xac\\x08\\xca\\xf8\\xac\\x98\\xe4\\xfa\\x8c\\x91\\x75\\x3a\\xa9\\x8d\\xcf\\x44\\x22\\x71\\x39\\x17\\xc9\\x99\\xa1\\xb1\\x2b\\x52\\xe7\\x16\\x76\\xea\\x7c\\xd5\\xdb\\xd1\\x8e\\x01\\xbf\\xc0\\x73\\x32\\x17\\x09\\x52\\x71\\xf3\\x8c\\x59\\x95\\xfd\\x7e\\x09\\x32\\x55\\x69\\x1b\\x33\\xd8\\x61\\x83\\x7b\\xa4\\x60\\x25\\x97\\xa9\\xf5\\x42\\x24\\x33\\x96\\x5c\\x35\\xf4\\xd7\\x28\\xb6\\x51\\xfd\\x1f\\x1b\\x4b\\x17\\x15\\x6e\\xc7\\x31\\x48\\x05\\xfd\\x11\\xd2\\xaa\\xee\\xd8\\x91\\x53\\x4d\\x8e\\xa0\\x5e\\xd3\\xc1\\x1f\\x9f\\xe6\\x07\\xc7\\x18\\x19\\x87\\xe1\\x5f\\xb4\\xa4\\x39\\xd3\\xac\\x1c\\x60\\xb4\\xd7\\x4c\\x56\\xa5\\x22\\x47\\x07\\xb3\\x83\\xe3\\x01\\xc9\\xb9\\xa8\\x34\\x33\\x7f\\xe6\\xe6\\x4f\\xc3\\x8e\\x14\\xd6\\x38\\x27\\x47\\x07\\xea\\xe0\\xd8\\x59\\xaf\\x7c\\x08\\x9a\\xdd\\x7d\\xe8\\x59\\xe1\\xee\\x0d\\xc2\\xb9\\xd9\\xa6\\xbc\\x9e\\xf1\\x21\\xe5\\xaf\\x43\\xd8\\x6c\\xe8\\x1d\\xbc\\x11\\x02\\x69\\xe7\\x94\\x21\\xf0\\x1e\\x19\\xae\\xfa\\x9c\\xfc\\xcf\\xd1\\x87\\xa7\\xc3\\x3f\\x7f\\xfa\\xdd\\xd1\\xc7\\x11\\xfe\\xe7\\xf8\\x9b\\x23\\xf5\\x4b\\xfe\\xcb\\xec\\xf8\\xf8\\x77\\xbf\\x8d\\x89\\xe4\\xe6\\xac\\xb9\\x9a\\x4c\\xae\\xac\\x3e\\x74\\x8b\\xa4\\xf2\\x2e\\x9c\\x12\\x07\\xb5\\x2b\\xc2\\xd3\\x59\\xe7\\xa3\\x06\\x0a\\x24\\x18\\xa1\\x66\\xe7\\xb4\\xf7\\xb8\\x06\\x3a\\x58\\xdd\\x49\\xe2\\xe4\\xfc\\xcc\\xd7\\x20\\x1e\\x91\\xe1\\x70\\x68\\x83\\x0d\\x75\\x59\\x25\\x1a\\xeb\\x8a\\x69\\xec\\xfc\\x65\\x46\\x4d\\x79\\x09\\xa2\\x8e\\x62\\x60\\x46\\x74\\x0d\\x0e\\x2d\\x69\\xc3\\x08\\x41\\x88\\xe6\\x1d\\x59\\xd3\\x67\\x0d\\x8a\\x11\\x89\\x03\\x3e\\x3f\\x0a\\x80\\x04\\x79\\x25\\xa5\\xdd\\x24\\xfc\\xe6\\x3f\\xc9\\x93\\x27\\xe4\\xa2\\xe1\\x5d\\x19\\x1b\\x3c\\xb3\\x6d\\x7d\\x40\\x79\\x9c\\x48\\x79\\x18\\xdb\\x59\\xd9\\xc8\\xbc\\xf8\\x9d\\x90\\x37\\x62\\xd9\\xd7\\xe1\\x5b\\xb4\\x64\\xcf\\xc9\\xc7\\x83\\x93\\x6b\\xca\\x33\\x43\\xff\\x3e\\x1e\\x0c\\xc8\\xc7\\x83\\x73\\x1b\\xeb\\xce\\xc5\\xf4\\xa3\\xed\\x95\\xf1\\xf1\\xe0\\x94\\x41\\xd3\\xfa\\xf4\\xe3\\x81\\x19\\xf6\\x77\\xd0\\xf1\\xf0\\x0d\\x2b\\xa7\\xec\\x3b\\x36\\xff\\x4f\\x18\\xcc\\xdf\\xbe\\xc4\\xee\\x88\\xf3\\xff\\xc4\\xe6\\x88\\xe6\\xbe\\xe1\\x76\\xef\\xe7\\x05\\xfb\\xcf\\x9c\\x16\\xfe\\xc6\\x1b\\x5a\\xf8\\x97\\x83\\x30\\x9e\\x0f\\x9f\\x8c\\x98\\x70\\xfd\\x6c\\x54\\xef\\xe8\\x4f\\x7f\\x57\\x52\\x3c\\xff\\x78\\x10\\xd4\\x7f\\x95\\xb9\\xc1\\x8c\\x42\\xcf\\x3f\\x1e\\x90\\xe8\\xab\\xcf\\x3f\\x1e\\xc0\\x77\\xdd\\x7d\\x37\\xc9\\xe7\\x1f\\x0f\\xcc\\x97\\xcc\\xed\\x52\\x6a\\x39\\xae\\x26\\xcf\\x3f\\x1e\\x8c\\xe7\\x9a\\xa9\\xc1\\xb3\\x41\\xc9\\x8a\\x81\\xe1\\x0a\\xff\\x59\\x7f\\xe1\\xe3\\xc1\\x4f\\x66\\x4f\\x9e\\x3c\\xc1\\x06\\x2f\\xb8\\x99\\x8a\\xfc\\x6b\\x79\\x57\\x96\\x0e\\x6c\\xaa\\x8b\\x8e\\xaa\\x95\\x8f\\x6e\\x2a\\xae\\x86\\x4e\\x97\\x5d\\x4c\\xaf\\x7b\\x76\\x74\\xdf\\xb9\\xd0\\xec\\xe2\\x8b\\x75\\xab\\xd7\\xfd\\xc2\\x89\\xec\\xf9\\x45\\xdd\\x66\\x1c\\xd8\\x32\\xc0\\x6f\\x81\\xc6\\x8b\\x7a\\x54\\x0c\\xe0\\x4d\\x47\\x04\\xdb\\x89\\x62\\x02\\xab\\x61\\x10\\x10\\x7e\\x01\\xcc\\x41\\x58\\x96\\xb5\\x68\\x1d\\x31\\xb4\\x03\\xcf\\xbc\\x1d\\x06\\xd4\\x86\\x24\\x61\\x85\\x36\\xa7\\xeb\\x8e\\x0a\\xe2\\x6e\\x57\\x56\\x36\\x5f\\x70\\x0d\\xed\\x1e\\xf6\\x83\\xa0\\xb6\\x5c\\x96\\xba\\x56\\xd8\\xb8\\xac\\x3d\\x17\\x9f\\xd3\\xcf\\xaf\\xa1\\x2f\\xd9\\x73\\xf2\\xfb\\xaf\\xff\\xf4\\xc7\\xff\\x58\\xe5\\x17\\x18\\xa3\\x35\\xe8\\xdb\\xb5\\x79\\xef\\x4b\\xc0\\xb0\\xf8\\x62\\xd3\\x36\\x3f\\x72\\xca\\xcb\\xa8\\x4e\\xaa\\xaf\\xbb\\x0f\\xc7\\x31\\x5f\\x8a\\x69\\x32\\x06\\xf7\\x67\\x55\\x18\\xb8\\xbc\\x72\\xa9\\xce\\x22\\xc1\\x78\\xd4\\xa5\\x83\\x71\\x4f\\xc0\\xb3\\x39\\x79\\xf6\\x35\\x36\\xd4\\x82\\x4f\\x2f\\x90\\xef\\x0f\\x9f\\x3f\\x8d\\x96\\x4c\\x99\\x2b\\xf2\\xe7\\x41\\x63\\x3e\\x46\\x60\\xae\\x80\\xe9\\x19\\xc4\\xc1\\x48\\x87\\x92\\x21\\x27\\x74\\x36\\xb9\\x45\\x4e\\xc8\\xfc\\x7c\\x37\\x6d\\xdc\\x16\\xfd\\x61\\xfe\\xf8\\x87\\xd5\\xfb\\xcb\\x05\\xcf\\xab\\xfc\\x39\\x79\\xba\\xd2\\xcb\\xb2\\x85\\x53\\xda\\x3a\\x9d\\xbd\\x20\\x40\\xb1\\x07\\x02\\xcd\\xa1\\x20\\x44\\x10\\x77\\x14\\xa2\\xb6\\xde\\x2e\\x72\\x8c\\x9c\\x97\\x32\\xad\\x12\\xa3\\xcb\\xcb\\x89\\x93\\x09\\x93\\x90\\x40\\x41\\x63\\x22\\x73\\x1a\\xac\\xc8\\xcd\\x3e\\x1b\\xa0\\xb3\\xba\\x43\\x95\\x48\\xa1\\x83\\x13\\x17\\x53\\x55\\x57\\x01\\x05\\x02\\x82\\x5c\\xf7\\x66\\xc6\\x80\\xf5\\xe8\\xb0\\x87\\x2d\\xcc\\x4a\\xf1\\x14\\x72\\x2e\\x28\\x99\\x56\\xb4\\xa4\\x42\\x33\\xec\\xf4\\x81\\x7d\\x6c\\xad\\x98\\xea\\x49\\x1e\\x0d\\x0a\\xab\\xda\\xd3\\x88\\x47\\x15\\x89\\x95\\x99\\xa2\\x35\\x25\\x60\\xff\\xe3\\xce\\x8e\\xea\\xb3\\xa7\\x5f\\xaf\\xdd\\x72\\xff\\xdc\\x6a\\x0f\\x8d\\x17\\x87\\x3f\\x9c\\x0c\\xff\\x1f\\x1d\\xfe\\xe3\\xd3\\x91\\xfd\\xcf\\xd3\\xe1\\x9f\\xff\\x77\\xf0\\xfc\\xd3\\x57\\xc1\\x9f\\x9f\\x8e\\xbf\\xf9\\x6d\\x17\\xf6\\x7a\\xd5\\x69\\x64\\x5e\\x2b\\xa0\\x6d\\xee\\x38\\x74\\x60\\xbe\\xba\\xae\\x25\\xdc\\x90\\x1c\\xc0\\x94\\xd6\\x3f\\x63\\xa7\\xbb\\x4e\\x41\\x69\\x07\\x24\\xdd\\x0c\\x08\\x34\\xba\\x77\\x8d\\x67\\x40\\xf1\\x8c\\x58\\x3a\\xb2\\x12\\xee\\x28\\x91\\xf9\\x93\\xc0\\x3c\\x65\\x44\\xeb\\x37\\x54\\xcc\\x49\\x4d\\xd6\\x50\\x28\\x6d\\x62\\xba\\x82\\x2c\\x45\\x9a\\x94\\x52\\xa9\\xc8\\xc5\\x70\\xc5\\x88\\x97\\x5c\\x91\\x58\\x8e\\x59\\x42\\x41\\x16\\x2f\\xc7\\x5c\\x97\\xb4\\x9c\\x07\\xaa\\x87\\xeb\\x90\\x50\\x29\\x36\\xa9\\x32\\x72\\xa4\\x18\\x23\\x23\\x21\\x53\\xb6\\x48\\x5d\\x8f\\x91\\x86\\xd2\\x31\\xcf\\xb8\\x9e\\xa3\\xd2\\x9c\\x48\\x31\\xc9\\xb8\\x55\\x01\\x5c\\xf8\\x83\\x6b\\x1b\\x3d\\x65\\x9f\\x09\\xd7\\xd8\\x55\\x0d\\x43\\xce\\x8e\\x52\\xa1\\x9e\\x3d\\xfb\\xfa\\xf7\\x97\\xd5\\x38\\x95\\x39\\xe5\\xe2\\x55\\xae\\x9f\\x1c\\x7f\\x73\\xf4\\x73\\x45\\x33\\xd0\\x1d\\xdf\\xd2\\x9c\\xbd\\xca\\xf5\\x5e\\x91\\x86\\x31\\x5b\\x7c\\xf6\\xc7\\x16\\xa7\\xe8\\xe8\\x03\\x9e\\x95\\x4f\\x47\\x1f\\x86\\xf6\\x7f\\x5f\\xb9\\x5b\\xc7\\xdf\\x18\\x5d\\x73\\xdd\\xef\\xc7\\x5f\\x99\\x35\\x04\\x27\\xf0\\xd3\\x87\\x61\\x7d\\xfc\\x46\\x9f\\xbe\\x3a\\xfe\\x26\\xf8\\xed\\xf8\\xb7\\xbd\\x87\\xa6\\x76\\xb9\\x04\\xba\\xd7\\x9d\\x79\\x6a\\xec\\x18\\x5e\\x91\\x6a\\x7a\\x6c\\x9a\\xbf\\x2f\\x7a\\x6e\\x16\\x26\\x8f\\x1e\\x9c\\x25\\x15\\x10\\x93\\xe8\\x23\\x81\\x8f\\xa7\\x39\\x44\\xcb\\x72\\x88\\x5d\\xb9\\x7b\\x9a\\x6b\\x44\\x49\\x17\\x71\\xc3\\x6b\\xfa\\x40\\xeb\\x0d\\xf1\\xf9\\x69\\xe1\\xf9\\x9f\\x6c\\x76\\x51\\x60\\x42\\x03\\x4b\\xf8\\x3c\\x8e\\x8e\\x92\\x60\\x39\\x8c\\xeb\\x0d\\xf9\\x64\\xd3\\x25\\x76\\xc1\\xde\\x87\\xd4\\xfb\\x90\\x7a\\x1f\\xd2\\xc3\\xf0\\x21\\x35\\x8f\\x3c\\xf8\\x92\\xa0\\x1f\\xaf\\x0a\\x3c\\x11\\x34\\xcd\\xb9\\x58\\x71\\xfc\\xd7\\x9f\\x7b\\x4b\\x1d\\x06\\xa4\\x90\\x46\\x96\\xe1\\x60\\x35\\x97\\xd7\\xac\\x2c\\x39\\xc4\\x4c\\xe2\\x3b\\x25\\xab\\x3b\\x58\\x86\\xf9\\x0b\\x1d\\x19\\x61\\x53\\x56\\x64\\x72\\x9e\\xaf\\xaa\\x7b\\x7f\\x3b\\xe1\\xe8\\x76\\x91\\x1d\\x47\\xc0\\xf7\\x86\\xdf\\xde\\xf0\\xfb\\x05\\x19\\x7e\\x7b\\x6b\\x6e\\x6f\\xcd\\xed\\xad\\xb9\\x4b\\xae\\xde\\x9a\\xdb\\x5b\\x73\\x7b\\x6b\\x6e\\x6f\\xcd\\x5d\\xb8\\x7a\\x6b\\xae\\x7d\\xa6\\xb7\\xe6\\xf6\\xd6\\xdc\\xbb\\xb6\\xe6\\xd6\\x97\\x8a\\x2a\\x42\\xdf\\x91\\x5a\\xd9\\x26\\xda\\x69\\x41\\xa1\\xb7\\xbd\\x79\\xad\\x4a\\x1f\\x6b\\xe6\\x4b\\xd4\\x79\\xae\\x95\\xcb\\x54\\x05\\xcd\\x7d\\x14\\xf6\\xf0\\x6b\\x59\\x0c\\xbc\\x1b\\xad\\xbd\\x0f\\x9d\\xea\\x35\\xe8\\x5e\\x83\\xee\\x43\\xa7\\xe2\\xab\\x57\\xb6\\xfd\\xd5\\x2b\\xdb\\xbd\\xb2\\xdd\\x2b\\xdb\\xbd\\xb2\\xdd\\x2b\\xdb\\xcd\\xab\\x57\\xb6\\xf1\\xea\\x95\\xed\\x5e\\xd9\\x5e\\x72\\x3d\\x0e\\x65\\x7b\\x5d\\xe8\\xd4\\xc4\\xa0\\xac\\xbb\\xb9\\x29\\x76\\x8a\\x84\\x41\\x35\\x5f\\xf7\\x41\\x35\\x7d\\x50\\x4d\\x1f\\x54\\xd3\\x07\\xd5\\xb8\\xeb\\xae\\x83\\x6a\\x62\\x0b\\x1c\\x46\\xbe\\x44\\x16\\x37\\xc0\\xd9\\xa2\\x94\\xd7\\x3c\\x65\\xaa\\x11\\x82\\xe3\\x8b\\x35\\x06\\x5c\\x26\\x87\\xf6\\x8e\\x75\\x58\\x0d\\xbb\\x9b\\xa0\\x9a\\xde\\x3c\\xd7\\x9b\\xe7\\x7a\\xf3\\x5c\\x6f\\x9e\\x8b\\xaf\\xde\\x3c\\xe7\\xaf\\xde\\x3c\\xd7\\x9b\\xe7\\x7a\\xf3\\x5c\\x6f\\x9e\\xeb\\xcd\\x73\\xcd\\xab\\x37\\xcf\\xe1\\xd5\\x9b\\xe7\\x7a\\xf3\\xdc\\x92\\xeb\\x71\\x98\\xe7\\x42\\x0c\\xea\\xd3\\x2b\\x7a\\xed\\xb3\\xd7\\x3e\\x1f\\x9e\\xf6\\xd9\\xab\\x94\\xbd\\x4a\\xd9\\xab\\x94\\x4b\\xae\\x5e\\xa5\\xec\\x55\\xca\\x5e\\xa5\\xec\\x55\\xca\\x85\\xab\\x57\\x29\\xed\\x33\\xbd\\x4a\\xd9\\xab\\x94\\x7d\\x7a\\xc5\\x96\\xe9\\x15\\xef\\x5e\\xbf\\x09\\xe2\\x39\\x30\\xce\\x23\\xc0\\x2c\\xe8\\xce\\x0e\\x55\\x9b\\x1d\\x4f\\xee\\x7d\\xb1\\xbd\\x36\\xdc\\x6b\\xc3\\xbd\\x2f\\xd6\\x5e\\xbd\\xe2\\xdc\\x2b\\xce\\xbd\\xe2\\xdc\\x2b\\xce\\xd1\\xc6\\xf5\\x8a\\x73\\xaf\\x38\\xc7\\x5b\\xd9\\x2b\\xce\\xdb\\x03\\xad\\x57\\x9c\\x7b\\xc5\\x79\\xc9\\x56\\x7c\\x19\\x8a\\x73\\x5f\\x65\\x56\\xcb\\x12\\xaa\\xc7\\xde\\x7d\\x85\\xd9\\x6f\\x7d\\x7f\\xd8\\xc5\\xea\\xb2\\xf0\\xdb\\xca\\xca\\xb2\\x38\\x61\\xf8\\x69\\x59\\x55\\x59\\x89\\x58\\xb9\\x58\\x4e\\xd6\\x75\\xa4\\xbd\\x87\\x52\\xb2\\xd8\\x55\\xca\\x2a\\x0e\\x95\\xe0\\x20\\xf6\\xe4\\x55\\xa6\\xb9\\x66\\x82\\x8a\\x64\\x0e\\x6c\\xf6\\xdd\\xeb\\x37\\x24\\xa7\\x82\\x4e\\x83\\xc6\\x50\\x6a\\x44\\xce\\x34\\xd0\\x1b\\x5d\\xfa\\x4e\\x60\\xb6\\x79\\x95\\x4f\\x00\\x09\\x7b\\x65\\x41\\x25\\x0a\\xdf\\xae\\x0a\\x14\\x8e\\xa0\\xfd\\x90\\x11\\x00\\x0d\\xfb\\x80\\xd6\\x56\\x61\\x57\\xab\\xdf\\x34\\x0f\\x78\\x9f\\x12\\xd3\\xa7\\xc4\\xf4\\x29\\x31\\x0f\\x24\\x25\\x06\\xe8\\xc7\\xca\\x7e\\x85\\x11\\x91\\xd9\\xa1\\x11\\x97\\xed\\x59\\xb6\\x28\\x5f\\x55\\x05\\xd8\\xd6\\xbc\\x05\\x8b\\x9c\\xe2\\x93\\x5b\\x98\\x58\\x15\\xcb\\x58\\xa2\\x65\\xb9\\x4c\\x78\\x8b\\xdb\\x08\\xdb\\x07\\xed\\x1b\\xb8\\xcc\\x68\\x69\\x87\\x6a\\x3d\\xdd\\x6a\\xb1\\xd2\\x4d\\xb3\\x25\\x20\\xba\\xe8\\x64\\xf6\\xf2\\x73\\x01\\x96\\xc6\\x15\\xa6\\xe1\\x85\\xd9\\x37\\x5f\\xc2\\x13\\xe5\\x3a\\x36\\x66\\x74\\xcc\\x32\\x0f\\x0a\\x47\\x49\\x73\\x3c\\x32\\x28\\xa9\\xd5\\x77\\x40\\xc0\\x3c\\x79\\x7b\\xba\\x68\\xe5\\x8e\\x17\\xb8\\xca\\x30\\x4d\\xd6\\x1b\\xa7\\x17\\xa6\\x7e\\xb2\\x66\\x7a\\x96\\x30\\xb8\\x5f\\xc0\\xaa\\xe0\\x95\\x57\\x24\\x7a\\x03\\x42\\xc9\\x15\\x9b\\x23\\x7d\\x8c\\xb2\\xb4\\xcc\\xc3\\x25\\x03\\x6a\\x0a\\x9b\\x79\\xc5\\xe6\\xf0\\x90\\x25\\x96\\x1b\\x04\\xcc\\x4e\\x9a\\xd0\\x5f\\xb1\\x55\\x10\\xc2\\xdf\\xdd\\x64\\x57\\x0b\\xa8\\xad\\xda\\xbd\\x5f\\xb1\\xf9\\xba\\x9f\\x1b\\x00\\x37\\x70\\xf0\\x36\\x44\\x03\\x79\\x73\\xc3\\x1b\\x6c\\x3c\\xb0\\x69\\x51\\x64\\xd0\\xf8\\x50\\xae\\x06\\x15\\x69\\xdf\\xc6\\xdc\\x2d\\x75\\x8b\\x89\\xfa\\xad\\x0c\\x2c\\x4e\\xb0\\xd9\\x87\\x0a\\x37\\xd6\\x60\\xfa\\x8c\\x17\\x56\\xc8\\x40\\xd1\\xc2\\xb1\\xc2\\x1f\\x68\\xc6\\x03\\x31\\x06\\xb0\\xfa\\x4c\\x0c\\xc8\\x5b\\xa9\\xcd\\x3f\\x2f\\x3f\\x73\\x43\\xea\\x0d\\x3e\\x9c\\x4a\\xa6\\xde\\x4a\\x0d\\x77\\x3a\\x59\\x2a\\x4e\\x61\\x8b\\x85\\x5a\\xcd\\x8e\\x07\\x9e\\x12\\x39\\x89\\xf8\\xa1\\x11\\xc3\\x26\\x51\\x3a\\xa0\\x79\\xfa\\x4c\\x18\\x75\\xd2\\xae\\x28\\x32\\x86\\x98\\x21\\xf2\\x4a\\x01\\x03\\x13\\x52\\x0c\\xd1\\x7e\\xb1\\x6c\\x0c\\x0b\\x08\\x59\\x46\\x70\\x58\\x33\\x9c\\x1d\\x0a\\xec\\x24\\xf8\\x0b\\x4a\\x40\\x99\\x11\\x65\\x49\\x8a\\xed\\xa7\\x81\\x9b\\x1b\\xa2\\xcd\\x13\\x82\\xde\\x0e\\xf0\\x39\\xb4\\x01\\xef\\x3a\\xba\\x82\\xd7\\x06\\xea\\xd2\\x72\\xaf\\x80\\x64\\xbe\\x36\\x07\\x60\\x0b\\x12\\x8b\\xcf\\x23\\x59\\xca\\x69\\x61\\xb6\\xe9\\x9f\\x86\\xfa\\x00\\xa4\\xfe\\x45\\x0a\\xca\\x8d\\xc4\\x7c\\x02\\xd2\\x7f\\xc6\\xa2\\xdf\\x6c\\xd7\\xcd\\x70\\x18\\x33\\x02\\x57\\xc4\\x90\\x92\\x6b\\x9a\\x19\\x7a\\x07\\xf6\\x79\\xc2\\x32\\xa4\\x7e\\x46\\x48\\x6f\\x10\\xf6\\x01\\xb9\\x99\\x49\\x85\\xc4\\x0c\\xad\\x54\\x5c\\x91\\x83\\x2b\\x36\\x3f\\x18\\x2c\\x6c\\xed\\xc1\\x99\\xb0\\x6e\\xaa\\x85\\xcd\\xf4\\x44\\x14\\x7a\\x92\\x1e\\xc0\\x6f\\x07\\xbb\\xf3\\x82\\xb5\\xc4\\x92\\xa6\\x68\\x3e\\xa0\\xd9\\x79\\x0b\\x6a\\xb6\\x76\\xdf\\x62\\xff\\xb2\\xd1\\xa0\\x5a\\xf0\\xf5\\xe6\\x2b\\x8e\\xf8\\x61\\x6a\\x6e\\xa8\\x9b\\xc0\\x93\\x84\\xe2\\xa3\\xd6\\x0f\\x0c\\x9d\\x75\\xd1\\x3c\\x62\\x9b\\xd1\\x16\\x99\\x9c\\x7b\\x38\\x1f\\xa9\\x63\\xdc\\x59\\x23\\x8f\\x3a\\xd8\\x83\\xa6\\xb7\\x5a\\x34\\x58\\xb5\\x38\\xa3\\x3e\\x24\\xe7\\x98\\x41\\x9c\\x9e\\x9c\\x9f\\x6d\\x6e\\xd4\\x7c\\x09\\xaf\\x10\\xcd\\xb2\\x0c\\xbd\\xd8\\x46\\x66\\xd5\\xd2\\xca\\xac\\x4b\\x45\\x98\\x22\\x18\\x3f\\x50\\xf2\\x57\\x4e\\x76\\x55\\xef\\x5f\\x14\\x85\\xbc\\x12\\xbb\\x79\\xae\\xef\\x1b\\x2f\\x58\\x72\\xc7\\x3e\\x17\\x19\\x4f\\xb8\\x76\\xf4\\xbb\\x96\\xad\\x40\\x1f\\x82\\x97\\x80\\x70\\x71\\x90\\x06\\x14\\xd3\\x83\\x5a\\x56\\xe3\\x8a\\xf0\\xa9\\x90\\xe5\\x72\\xfc\\xbc\\x9d\\x08\\x76\\x42\\x3e\\x0f\\xaf\\xaa\\x31\\x2b\\x05\\xd3\\x4c\\x0d\\x8d\\x8c\\x35\\xb4\\x2f\\xb0\\xc5\\x23\\xd0\\x14\\x61\\x37\\x41\\xe9\\xe0\\xfb\\xf8\\x85\\x48\\x01\\xb5\\x83\\x39\\xda\\x3a\\x5f\\x68\\x54\\x0d\\x4f\\x79\\x08\\xc2\\x79\\x2e\\x19\\x5a\\x0c\\xbd\\x03\\x45\\xdf\\x48\\xa2\\xaa\\xc2\\x26\\x99\\x37\\x86\\x34\\x47\\x93\\x7c\\x14\\x4e\\xd0\\x7e\\x5e\\x37\\x97\\x06\\x42\\x01\\xf1\\x12\\x2e\\xb7\\xdd\\x9e\\x2c\\xab\\x29\\xc3\\x76\\xe5\\xf2\\x9a\\x39\\x35\\x16\\x59\\x82\\x61\\x06\\xc5\\x8c\\x2a\\x56\\xeb\\x60\\xaa\\x4a\\x12\\xc6\\x52\\x96\\xe2\\x0f\\x96\\x95\\xb0\\xc9\\x84\\x25\\x9a\\x5f\\xb3\\x6c\\x0e\\xc6\\x7f\\x85\\x22\\x89\\xff\\xbe\\xc1\\x6c\\xfc\\x7c\\xbd\\xe0\\xc6\\x17\\x05\\xfb\\xac\\x9d\\x92\\x4e\\x38\\x28\\xe1\\xb1\\xa5\\xa2\\xf4\\xcb\\x9d\\x51\\x45\\x26\\x94\\x67\\x46\\xaf\\xfb\\x28\\xc8\\x7b\\x96\\xcc\\xce\\x4b\\x76\\xcd\\xd9\\xcd\\xf7\\x42\\xd1\\x09\\x7b\\x45\\x79\\xf6\\x4a\\x96\\x37\\xb4\\x4c\\x03\\x18\\xdc\\xc6\\xf2\\xcd\\xac\\xfc\\x6f\\x38\\x25\\x07\\x97\\x13\\x4f\\x38\\xb3\\x79\\xd0\\xe6\\xdb\\x7a\\xc6\\xcc\\x7a\\x6f\\xdc\\x02\\xcf\\x33\\x03\\x31\\x70\\xb8\\x52\\xa3\\xd0\\x7a\\x8c\\x22\\x25\\x9b\\xb0\\x92\\x09\\x73\\x9e\\xa8\\x1b\\x3f\\x78\\xc9\\xb3\\x87\\x04\\xdb\\x5f\\xd7\\x1d\\xca\\xad\\xde\\x8b\\x8e\\x31\\x0a\\x1f\\x73\\xd0\\x73\\x6e\\x20\\x66\\x44\\x05\\x68\\x07\\x82\\x67\\x37\\x30\\x1a\\x7d\\x14\\xe4\\xc7\\x93\\x8b\\xb7\\x67\\x6f\\xbf\\x7d\\x0e\\x5c\\x65\\x1d\\x84\\x17\\xf1\\x9a\\x2b\\x52\\xc1\\x53\\x81\\xd5\\x43\\x55\\x99\\x36\\x28\\x5e\\x09\\xef\\x2f\\x1a\\xb3\\x19\\xbd\\xe6\\xe6\\x0c\\x94\\xd6\\x1e\\x72\\xcd\\xb0\\x2d\\xbd\\x51\\x83\\x49\\x26\\x95\\x19\\x27\\x63\\x4a\\x91\\xb9\\xac\\x30\\x8e\\x27\\x65\\xac\\x40\\x17\\xb7\\xd2\\x54\\x40\\x33\\x13\\xeb\\xcf\\x68\\x2e\\x82\\x8c\\x99\\xf9\\xd5\\x59\\xc4\\x16\\x4e\\xd7\\x32\\x7f\\xc2\\x06\\xca\\xe1\\x34\\xdd\\x15\\x8a\\x2c\\x59\\xeb\\xf0\\x18\\xae\\x79\\xcb\\xfc\\xba\\x0e\\xc4\\xb1\\xda\\xdf\\x3e\\x60\\x0a\\x15\\xff\\x75\\x1d\\xb8\\xc3\\x07\\x2f\\xb6\\xd7\\xfd\\x57\\xeb\\x51\\x18\\xf8\\xf1\\x3d\\x62\\xe1\\x16\\x1a\\xff\\xfa\\xa0\\xaa\\x68\\x95\\x41\\x70\\x4d\\x43\\xf6\\x5e\\xc6\\x39\\x83\\x20\\xa1\\x2e\\x99\\x4d\\x1f\\xad\\xd5\\x47\\x6b\\xf5\\xd1\\x5a\\xcb\\x7e\\xef\\xa3\\xb5\\xfa\\x68\\xad\\x3e\\x5a\\xab\\x8f\\xd6\\xea\\xa3\\xb5\\xfa\\x68\\xad\\x3e\\x5a\\x8b\\xf4\\xd1\\x5a\\xf5\\x33\\x7d\\xb4\\x56\\x1f\\xad\\x75\\x7f\\x69\\x4e\\x81\\x62\\xba\\x51\\xc7\\x7c\\x5d\\x3f\\x8b\\xd2\\x89\\x76\\xf1\\x50\\xee\\x64\\xc6\\xa2\\x61\\x53\\xeb\\xb4\\xa7\\xd8\\xf0\\x63\\x3b\\xcc\\xd6\\x86\\xe5\\x36\\x42\\x97\\x68\\x6f\\xc8\\x8d\\x4d\\xb8\\x81\\xe5\\x64\\xc1\\x3b\\xee\\x39\\x50\\xb4\\xa8\\x87\\x6a\\xaa\\x8d\\x9d\\x0b\\x17\\x6c\\xb2\\xa5\\x6f\\xe1\\x82\\x4d\\x42\\x6b\\x1b\\x02\\x26\\x76\\x29\\xd8\\x88\\x15\\xef\\x73\\xb8\\x85\\xf0\\x81\\xd5\\x31\\x4e\\x4b\\x97\\x60\\x84\\x7d\\x67\\x32\\xb5\\xf8\\x68\\xd7\\xb0\\xd2\\x17\\xba\\xf1\\x48\\x03\\x3f\\x3e\\xa7\\x7a\\xd6\\x6a\\x06\\x87\\x67\\x16\\x6c\\xe0\\x38\\x04\\x57\\x6e\\xc1\\x59\\xc2\\xa2\\x30\\x2a\\x90\\xe3\\x18\\x4d\\xed\\x4d\\x23\\xf8\\x94\\xcc\\xfe\\x36\\x40\\x89\\xc3\\xba\\x4b\\xeb\\x30\\x2b\\x23\\x34\\x11\\x6a\\x08\\x31\\x4f\\xc9\\x7f\\x5d\\xbe\\x7b\\xfb\\xe4\\x5b\\x69\\x65\\x05\\xa3\\xcd\\x28\\xdb\\x30\\x29\\x67\\x42\\x0f\\x88\\xaa\\x92\\x19\\xa1\\xca\\x4c\\xcd\\xe8\\xb7\\x97\\x60\\x7a\\xc8\\xa9\\xe0\\x13\\xa6\\xf4\\xc8\\x8e\\xc6\\x4a\\xf5\\xe1\\xeb\\x4f\\xa3\\xd8\\xe2\\xc1\\xad\\x4f\\xd5\\x05\\x23\\x59\\x04\\x80\\xb3\\x61\\x16\\xe3\\xdf\\x05\\xa1\\x15\\xa6\\x54\\xc8\\xd4\\x4e\\xfa\\x06\\x26\\xab\\xe9\\x15\\x23\\xd2\\x4e\\xb6\\x62\\xc0\\x14\\x9e\\x93\\x03\\x83\\x26\\xc1\\xa7\\xff\\x69\\x0e\\xd6\\xbf\\x0e\\xc8\\xd1\\x0d\\x58\\xf5\\x0f\\xcc\\x9f\\x07\\xf8\\x41\\x1f\\x3b\\x66\\xee\\x05\\x1c\\xdf\\x7e\\x18\\xe5\\xfb\\x92\\x4f\\xa7\\x20\\x6e\\x81\\xe9\\xf6\\x9a\\x09\\x7d\\x0c\\xfc\\x6d\\x42\\x84\\x0c\\x1e\\x16\\xd6\\x45\\x56\\x3b\\xc6\\x9a\\x13\\xf9\\xf0\\xf5\\xa7\\x03\\x72\\x14\\xaf\\xcb\\x88\\xa0\\xec\\x33\\xf9\\xda\\x3b\\xc3\\x0a\\x99\\x1e\\x3b\\xad\\x75\\x2e\\x34\\xfd\\x0c\\x8a\\xc1\\x4c\\x2a\\x26\\xd0\\x97\\xa0\\x25\\x1a\\x64\\x95\\x34\\xca\\x27\\xcb\\xb2\\x21\\x0a\\x98\\x29\\xb9\\x41\\x1b\\x9c\\x03\\x25\\xfa\\x93\\x0b\\x5a\\xea\\x46\\x64\\xdd\\xfb\\x77\\xa7\\xef\\x9e\\xe3\\xd7\\xcc\\xb6\\x4d\\x85\\xd3\\x72\\x27\\x5c\\xd0\\xcc\\x5a\\xb6\\xbd\\x7c\\x68\\x26\\x52\\xe1\\x26\\x69\\x69\\x55\\x5b\\x67\\xd4\\x9d\\x54\\xba\\x2a\\xd9\\xa8\\x19\\x69\\xd5\\x1a\\xe3\\x97\\x85\\xb9\\x2d\\x47\\x76\\x08\\x77\\x6b\\x1e\\xb4\\x7b\\x0c\\x26\\x6b\\xbd\\x44\\xb1\\xc2\\xd9\\xba\\xb8\\xc4\\xb7\\x01\\x0e\\xae\\x5d\\x62\\x4d\\x9a\\xcd\\x2a\\x53\\x99\\x28\\xb3\\xc0\\x84\\x15\\x5a\\x3d\\x91\\xd7\\x86\\x74\\xb2\\x9b\\x27\\x37\\xb2\\xbc\\xe2\\x62\\x3a\\x34\\x48\\x36\\xc4\\x9d\\x57\\x4f\\x80\\xc5\\x3c\\xf9\\x37\\xf8\\x67\\xaf\\x15\\x01\\x9f\\x6a\\xbf\\x2c\\x8c\\x69\\xbd\\x83\\xb5\\x01\\xfb\\x7c\\xb2\\xf3\\xd2\\x9c\\x7c\\xb9\\x0d\\x27\\x38\\xbc\\x74\\xca\\x5f\\xe3\\x6d\\x73\\x5c\\xd0\\x17\\x6e\\x83\\x5d\\x03\\x0a\\x97\\xd3\\x14\\x49\\x20\\x15\\xf3\\x5b\\x47\\x63\\x03\\x40\\xd0\\xf1\\x93\\xf9\\xd0\\x46\\xa3\\x0f\\xa9\\x48\\x87\\x5e\\xbe\\x4e\\xe6\\x3b\\x43\\xac\\xe2\\x2d\\x0f\\xf0\\xf7\\x67\\xa7\\x77\\x83\\xdc\\x15\\xdf\\xea\\xb4\\x76\\x95\\x4b\\x40\\xa2\\xf8\\x73\\x9a\\x15\\x33\\xda\\x55\\xef\\x85\\x3e\\x0a\\x1d\\xae\\x3e\\x0a\\xbd\\x8f\\x42\\xef\\xa3\\xd0\\xeb\\xeb\\x81\\x44\\xa1\\xf7\\x51\\xe4\\x7d\\x14\\x79\\x1f\\x45\\xbe\\xfa\\xe7\\x3e\\x8a\\xbc\\x8f\\x22\\xef\\xa3\\xc8\\x9b\\x57\\x1f\\x45\\xde\\x47\\x91\\xf7\\x51\\xe4\\x7d\\x14\\xf9\\x92\\xab\\x8b\\x82\\x75\\x8f\\x30\\xfe\\xb2\\x77\\x8e\\x3d\\x0e\\xe7\\x58\\xef\\xee\\xea\\xdd\\x5d\\xbd\\xbb\\xab\\x77\\x77\\xed\\x80\\xf1\\xbd\\xbb\\xab\\x77\\x77\\xf5\\xee\\xae\\xde\\xdd\\xf5\\x40\\xdd\\x5d\\x5b\\x75\\x19\\x7f\\xd4\\xb5\\xb3\\xee\\xbe\\x6c\\x16\\xdc\\x5a\\xac\\x98\\xb5\\xb2\\x58\\x96\\xad\\x93\\xb5\\x50\\x0c\\xab\\xae\\x83\\xf5\\x02\\xd3\\x29\\x6f\\xbf\\x08\\x56\\x6c\\x00\\x74\\x0d\\x9a\\xb7\\x68\\xca\\xde\\x3b\\xf4\\x7a\\x87\\x5e\\xef\\xd0\\xdb\\x74\\x4a\\xb6\\x70\\xe8\\x81\\x2f\\x2f\\x3c\\x0a\\x56\\x1d\\xa9\\x53\\x38\\xde\\x2d\\x77\\x6d\\xac\\xfe\\x74\\x7b\\xd3\\x8a\\xb5\\xaa\\x84\\x9f\\x77\\xb9\\x28\\xf5\\xf7\\x03\\x0b\\x0b\\x9c\\x14\\xb3\\xa1\\x89\\xcc\\x0b\\x29\\x0c\\x62\\x74\\xe3\\x5c\\xac\\xc7\\x6b\\x91\\xb0\\xea\\x1e\\xb5\\xf7\\xc7\\x2c\\x0c\\x26\\xb7\\x9e\\xad\\xbc\\x90\\x8a\\x45\\x76\\xdc\\x1d\\x14\\xef\\xf5\\xae\\xa9\\x21\\x3a\\x7d\\x9c\\x09\\x6d\\x07\\xc5\\x3d\\x7a\\xbf\\x95\\x2c\\xf2\\x3a\\x7c\\xc3\\xba\\x26\\xc1\\xf3\\xf4\\x73\\xc5\\x4a\\x6c\\xa3\\x5f\\x3b\\x70\\x6a\\xa0\\x38\\x93\\x2b\\xba\\xa4\\x22\\xb0\\x1c\\xae\\xd9\\xcc\\x96\\x60\\x6a\\xb3\\x54\\xb2\\x85\\x3f\\x76\\x61\\xd5\\x77\\xea\\x93\\x25\\xad\\xfd\\x27\\x2d\\xbc\\x27\\x0f\\xdb\\x3f\\x4b\\xda\\xfa\\x68\\x49\\x4b\\x3f\\x2d\\x69\\xe1\\xab\\x25\\xed\\xfc\\xb5\\xa4\\xb5\\xcf\\x96\\xb4\\xf1\\xdb\\x92\\x5b\\xf6\\xdd\\x92\\xf6\\x4e\\x4d\\xd2\\xda\\x87\\xbb\\x30\\xe9\\x07\\xe7\\xc7\\xdd\\x72\\xd9\\x6d\\xfc\\xb9\\x0b\\x8b\\xee\\x7d\\xba\\x0d\\x50\\x6f\\xf6\\xeb\\x92\\xb6\\xbe\\x5d\\xd2\\x3e\\x3d\\x69\\xa3\\x8f\\x97\\xf4\\x7e\\xde\\xed\\xf8\\xcb\\x46\\xa2\\xbb\\x9d\\xbf\\xb7\\xd5\\x5e\\x96\\x6c\\xd2\\xce\\x49\\x7f\\xc1\\x26\\xb8\\x98\\x40\\x9c\\xa8\\x1d\\x1d\\x72\\xa5\\x0c\\x51\\x4b\\x1d\\x03\\x4b\\x45\\x5d\\xfd\\x9c\\x48\\x76\\xb9\\x9b\\x88\\xa8\\x0b\\x9e\\xcc\\x2e\\x42\\xe3\\x15\\x0d\\x6c\\x59\\x40\\x23\\xdd\\x6c\\x07\\x84\\x89\\x92\\x27\\x33\\x37\\x59\\x23\\xe4\\x5a\\xcf\\xda\\xfa\\x9a\\x27\\xe1\\xb4\\x37\\x6c\\x68\\x3b\\x76\\xb6\\xd9\\x9b\\xb3\\x64\\xa1\\x3b\\xf8\\x74\\xc2\\x89\\x6f\\x24\\xde\\xeb\\x0b\\xca\\xac\\x98\\x54\\x50\\x09\\xa4\\x91\\x81\\x6f\\xf5\\xf0\\x28\\x4b\\xdd\\x63\\xd0\\x1d\\x86\\xb6\\x2c\\x9f\\x6e\\x3d\\xdb\\x70\\xb2\\xd4\\x25\\xa8\\x2e\\xd6\\x6c\\x11\\xf5\\xe4\\xad\\x43\\x76\\x4d\\xae\\x7d\\xb8\\x8c\\x16\\x62\\x57\\x7b\\xc1\\x6b\\x63\\x3d\\x90\\xf0\\xc1\\x95\\x95\\x41\\xea\\xab\\xbd\\xf4\\xb5\\x5d\\xb5\\x90\\xfa\\x5a\\xf0\\x83\\xef\\x53\\x1d\\xa4\\x2b\\x4e\\x57\\x5f\\x6d\\xcb\\x74\\xc4\\x60\\x40\\x27\\x7c\\xa7\\x20\\xb8\\xa1\\x10\\x6d\\x32\\x5e\\x88\\x41\\xb8\\x97\\x45\\x6e\\xac\\x4a\\xb2\\x62\\x75\\x27\\xfb\\x16\\x25\\xe9\\x7a\\xf1\\x9b\\x0a\\x51\\xac\\x58\\xc7\\xfb\\xed\\xaa\\x4b\\x74\\x3d\\xeb\\x4d\\xf5\\x0f\\x56\\xcc\\xfa\\xb2\\xd3\\x4a\\x08\\x3b\\xce\\x7d\\x7d\\x51\\x82\\x15\\x33\\x7f\\xdf\\x2c\\x4f\\xd0\\xe1\\xb4\\x36\\xc6\\x2d\\x2c\\x99\\x4f\\x1f\\xbd\\xd0\\x47\\x2f\\x3c\\xf0\\xe8\\x85\\xad\\xce\\xc0\\xba\\x48\\x86\\x65\\xe8\\xff\\x50\\xe3\\x19\\xb6\\x5a\\xf4\\xba\\xd8\\x86\\x65\\x8b\\x7e\\x20\\x11\\x0e\\x5b\\xaf\\x71\\x6d\\xb4\\xc3\\xaa\\x85\\x3e\\x90\\x98\\x87\\xad\\x16\\xdb\\x32\\xfe\\x61\\xd9\\x92\\xbf\\xe4\\x28\\x88\\xad\\x60\\xb8\\x26\\x22\\x62\\x19\\xdc\\x1e\\x44\\x5c\\xc4\\xca\\x05\\xfe\\xaa\\x1b\\x8b\\x85\\xe5\\x8f\\xef\\x2e\\x40\\xe2\\x32\\xf8\\x6a\\x23\\x48\\x22\\xfc\\x69\\x21\\x50\\x22\\x9a\\x2d\\x06\\x4b\\x2c\\x69\\x2a\\xa6\\xaa\\x71\\xf8\\xff\\x66\\x54\\x85\\x8a\\x3f\\xde\\xa6\\xc3\\x58\\x68\\x5f\\x83\\x98\\x80\\x17\\x32\\xab\\xf2\\xd0\\xc6\\x31\\x5c\\x14\\xfd\\x0b\\x9a\\x5c\\x19\\xad\\xc5\\x7e\\x6f\\x0c\\x9e\\xb5\\x00\\x39\\xff\\xae\\xa4\\x00\\x89\\x92\\x8c\\x40\\x0c\\x31\\x10\\x0c\\x7e\\xc6\\xfd\\x39\\xc7\\x41\\x7e\\xb3\\x16\\x83\\x97\\x7e\\xde\\xd5\\xa8\\xb6\\xde\\x7a\\xa7\\x81\\xd4\\xc2\\x4f\\xb1\\x30\\x74\\x73\\x46\\xf8\\xea\\xc2\\x9c\\x2e\\x9b\\xb7\\x5b\\x4f\\x69\\x46\\x85\\x60\\x99\\xa1\\x05\\xe8\\xd1\\x07\\xe9\\xce\\xc3\\x67\\x3d\\x78\\xec\\xcb\\x0b\\xb3\\x79\\xb1\\x70\\x7f\\xc9\\x74\\xa2\\x14\\xfd\\x7d\\x63\\x64\\x42\\x14\\x25\\x57\\x8c\\x15\\x2a\\x70\\x96\\x54\\xe0\\x53\\x81\\x5c\\x90\\xf1\\xdc\\xa8\\x77\\xc9\\x15\\x94\\x1b\\x05\\xa9\\x0c\\xd6\\xfb\\x02\\x37\\xa6\\xe3\\x04\\x7a\\x40\\xf6\\x82\\x25\\xc1\\xad\\x3e\\x04\\xa7\\x0f\\xc1\\xe9\\x43\\x70\\x36\\x9d\\xb1\\x16\\x21\\x38\\xe1\\x81\\x8f\\xc2\\x70\\xa8\\x20\\x27\\x45\\x91\\x81\\x51\\xca\\x95\\x86\\xb5\\x35\\x07\\x6d\\xc1\\x8d\\x05\\x4b\\xdc\\x8e\\xe9\\x45\\x0d\\xe6\\xe0\\x6e\\x2f\\x50\\xe8\\xf8\\x07\\xcf\\xd4\\x1a\\x4f\\xac\\x8d\\xb0\\x41\\x7a\\xba\\x4c\\xbe\\x5b\\x2b\\x1d\\x26\\x52\\x4c\\xf8\\x74\\x73\\x5e\\x4c\\x00\\xcb\\x17\\xf0\\x4a\\xed\\x31\\xc3\\x21\\x2a\\x5b\\xd9\\xb6\\xe6\\x54\\x90\\xbe\\x15\\xf1\\xed\\xdb\\x48\\x8e\\x99\\x80\\x04\\xb6\\x32\\x3c\\x20\\x5a\\xc5\\xd9\\xa4\\x9e\\xde\\x00\\xa2\\x69\\x4a\\x9e\\x5a\\xfa\\x58\\xc8\\xf4\\x50\\x01\\x35\\x4b\\xab\\xcc\\x96\\x9a\\xc6\\x52\\x2c\\xe6\\x68\\x0a\\x9e\\x99\\x95\\x0c\\xa9\\xc6\\xf3\\xc0\\x14\\xe6\\x3b\\x7e\\x25\\xa4\\xfe\\xca\\x8f\\x84\\x86\\x97\\x92\\x4f\\xb9\\x27\\x7d\\xbe\\x65\\x49\\x21\\xd3\\x91\\x2f\\xe6\\xa0\\xc1\\x65\\x19\\x0f\\x38\\x22\\xdf\\x2b\\xeb\\x60\\x76\\xc4\\xe1\\xe8\\x9f\\xff\\x3a\\x36\\x84\\x95\\x95\\x58\\xa8\\xd3\\x0e\\x1c\\xbd\\xb7\\x21\\x0a\\xa4\\xa3\\xd8\\x1e\\x21\\x53\\x76\\xb2\\x01\\xd4\\x0b\\xe0\\x3e\\xf5\\xf1\\x5b\\xe6\\x75\\xbf\\x55\\x21\\x90\\xcb\\x2a\\x0b\\xd2\\xc4\\x0c\\x8c\\xf6\\x77\\xab\\xb6\\x75\\x6c\\x14\\x68\\xe5\\x63\\xe9\\x29\\xb8\\xed\\x2f\\xfd\\xac\\xce\\x30\\x53\\x12\\x6f\\xbf\\xfc\\xcc\\x92\\x4a\\x6f\\x54\\x39\\x97\\x18\\x91\\xed\\x32\\xc1\\x20\\x95\\x65\\xf6\\x73\\x20\\x3a\\xd9\\x1f\\xcc\\x7a\\x81\\x71\\x1a\\xf0\\xd8\\xd0\\x36\\x45\\x35\\x57\\x93\\x39\\xe6\\xdd\\x3a\\x80\\xb1\\x20\\x36\\xaa\\x3e\\x5f\\x46\\x50\\x09\\xea\\x10\\x8f\\x2b\\x8d\\xa5\\x4d\\xe7\\x24\\x99\\x49\\x83\\x5f\\x14\\xe1\\x0e\\xe3\\x5e\\x73\\x89\\x01\\x44\\x60\\x0f\\x2e\\x49\\x6e\\x38\\x80\\xd5\\xee\\x82\\xe1\\xd1\\xe3\\x5d\\xbf\\x66\\x54\\x61\\xa9\\x74\\x0d\\x2b\\x17\\x54\\x63\\x86\\x01\\x3b\\x9b\\xf9\\x63\\x6a\\xd4\\x15\\xf0\\xf8\\x55\\xb9\\x19\\xf4\\x86\\xf1\\xe9\\x4c\\xab\\x01\\xe1\\x23\\x36\\x82\\xdd\\x65\\x34\\x99\\x05\\xc3\\xe6\\x8c\\x69\\x45\\x68\\x96\\xf9\\xc6\\x24\\x01\\x4a\\x84\\xee\\xf6\\x23\\xcf\\x34\\x2d\\x83\\x1b\\x78\\x7a\\xdb\\xdc\\xb5\\xa5\\xe0\\x1a\\x10\\xa6\\x93\\xd1\\xf1\\x00\\x3c\\x78\\xe6\\xb4\\x50\\x98\\xe3\\x78\\x4e\\xb8\\x86\\x5a\\xdc\\xc0\\xa0\\x4b\\x59\\x4d\\x71\\x25\\x36\\xd0\\x40\\x79\\xe9\\xc8\\xda\\x67\\x45\\x0a\\xda\\x84\\x98\\x92\\x03\\x5c\\xdc\\x81\\x13\\x78\\xcc\\x70\\xd6\\xe4\\x0a\\xeb\\x73\\xa5\\x65\\xd1\\xe2\\x59\\x96\\x4c\\x15\\x12\\x7b\\xb0\\x34\\x23\\x17\\xfe\\x8f\\x7f\\xe9\\x48\\x1d\\xd7\\xc0\\x9c\\xf1\\xe9\\xcc\\xc1\\x92\\x96\\x48\\x53\\xe2\\x3d\\x68\\xe7\\x7c\\x6c\\x13\\x46\\xd2\\x32\\x88\\x24\\xf6\\xf3\\xb8\\x72\\xf1\\x35\\x4e\\x04\\xbb\\xa7\\x59\\x99\\x7b\\x18\\xc0\\x06\\xa3\\xae\\x6f\\x8d\\xb2\\xb9\\xcd\\x61\\x46\\x20\\x92\\xa7\\xe4\\x08\\x50\\x84\\xeb\\x43\\x05\\xe8\\x3a\\x94\\xc5\\xf1\\x88\\x9c\\x80\\xb6\\xdb\\xe2\\x03\\x42\\xfa\\xf1\\xed\\x40\\xe6\\xa3\\x4a\\xd6\\x63\\xb5\\xf3\\x59\\xb4\\xf3\\xd4\\x6e\\xe3\\xab\\x35\\xdc\\xbc\\xf0\\x26\\xa5\\x56\\x8f\\x23\\x4c\\x36\\x3e\\xba\\x8d\\xdf\\x96\\x04\\x73\\x68\\xf3\\xf4\\x82\\x4b\\x0f\\x50\\xba\\x0e\\x5b\\x64\\x65\\x3e\\x20\\x54\\x29\\x99\\xf0\\xba\\x71\\xd2\\x22\\xa6\\xe3\\x4a\\xda\\xf8\\x71\\xb6\\x84\\x3f\\xd9\\x7a\\xfd\\x64\\xcb\\xc0\\xd4\\xf8\\x6a\\xc6\\x77\\xda\\x90\\xd4\\x18\\x2a\\x11\\xc1\\x1a\\xcf\\xe1\\x57\\x70\\x14\\x8e\\x59\\xb6\\x21\\x3a\\x33\\xbc\\xb6\\x09\\xfe\\x72\\x57\\xeb\\x20\\xb0\\x15\\x0b\\x5a\\xb9\\x90\\x7b\\x8b\\x57\\x5d\\x06\\x93\\x2d\\x90\\x03\\xaf\\x6d\\x8e\\x69\\x7d\\xb5\\x89\\x6c\\x6d\\xbe\\xd1\\x2a\\xce\\x35\\xbe\\xb6\\xc7\\x5f\\xbc\\x5a\\xc5\\xc0\\xc6\\xd7\\x82\\x48\\xd2\\x55\\x28\\x6c\\x7c\\x6d\\x19\\x92\\x50\\x5f\\xed\\xc3\\x64\\xd7\\xac\\xeb\\xe2\\xb6\\x62\\x65\\x07\\x71\\xa0\\x2c\\xf9\\x56\\x23\\xae\\xbf\\x6e\\x49\\xd9\\x3a\\x00\\x50\\xdb\\x80\\xda\\x35\\xe0\\x39\\x79\\x34\\x41\\xb5\\x4b\\x86\\xfa\\x56\\x9b\\x61\\x5e\\xaf\\x7c\\x19\\x1c\\xb6\\xd4\\x05\\x97\\x5a\\xe1\\x6d\\xd0\\x28\\x48\\x03\\xb6\\xa8\\xa2\\x64\\x86\\x61\\x61\\xef\\x2f\\xdb\\x09\\xe5\\xd6\\xe2\\x78\\x97\\xed\\xfe\\x76\\x84\\x1d\\xaf\\xad\\xc9\\x7b\\xf8\\xc1\\xad\\xd0\\x0d\\x58\\xe4\\x2b\\x68\\x9c\\x75\\x37\\xdc\\x11\\x9b\\x74\\xf5\\xdc\\xb1\\xe7\\x8e\\xf1\\xd5\\x73\\x47\\x7f\\xf5\\xdc\\x71\\xc3\\xd5\\x73\\xc7\\x9e\\x3b\\xde\\x3a\\x77\\x44\\x5d\\x76\\x07\\xe5\\xf9\\x47\\x34\\x71\\x34\\xb5\\x65\\xe0\\xb4\\xce\\x2f\\x14\\xab\\xcd\\x86\\xdf\\xb8\\x04\\x8a\\xf7\\xa0\\x6a\\x5b\\xdb\\x71\\x09\\xb1\\x61\\xcf\\x86\\xcf\\x9e\\x3e\\xdd\\x46\\xa9\\xde\\xd4\\xf0\\x2d\\xbc\\x82\\xe6\\x6f\\xbf\\xff\\x7a\\xed\\x1b\\xab\\xec\\x6f\\x1d\\x58\\x4d\\x2d\\x8e\\x7b\\x43\\x5e\\x24\\x3b\\xac\\x30\\x7c\\x02\\x75\\x12\\x52\\x93\\x9c\\x69\\x42\\x75\\x64\\x2a\\xe2\\x39\\x1b\\x38\\xc3\\x72\\xdd\\x62\\x7b\\x5c\\x9b\\x66\\x53\\x22\\x85\\x8b\\x54\\x94\\x29\\x1b\\xed\\x36\\x83\\x84\\x51\\x05\\xf9\\x26\\x63\\xe6\\x67\\x21\\x73\\xf3\\x55\\x2e\\xb4\\x3b\\x2e\\x66\\x0a\\xcc\\x41\\x85\\x1c\\xb1\\xd1\\x74\\x44\\xd2\\x8a\\xd9\\x04\\x27\\xf4\\xd3\\xd9\\x76\\x56\\x6a\\xae\\x34\\xcb\\xc1\\x92\\x2b\\x4b\\xdf\\xf4\\x4d\\x97\\x10\\xa3\\x08\\x81\\x92\\x15\\xcd\\xb2\\x39\\x61\\xd7\\xdc\\x66\\xfb\\x9a\\xc1\\xc1\\x4d\\x08\\x35\\xe1\\xcd\\x4a\\x5a\\x99\\x08\\x3b\\xcf\\x4f\\x68\\x62\\xf0\\xa6\\x54\\x85\\x6d\\xb8\\xfd\\xc2\\xd8\\x5b\\x47\\x1a\\x5f\\xd8\\x95\\x8c\\x56\\x0a\\xab\\xda\\x8c\\x8b\\x36\\x70\\xf8\\x2f\\x20\\xd7\\xbb\\x8b\\xcd\\x26\\x57\\xb2\\x35\\x25\\xdb\\x82\\x7a\\x35\\xc5\\xd2\\x2a\\xcb\\x0c\\x62\\xa0\\x15\\x76\\x71\\x01\\x4b\\xac\\xa3\\x4b\\x12\\xd9\\xd0\\xf0\\x9e\\x07\\x09\\x6d\\xd8\\xc4\\x5c\\x16\\x32\\x93\\xd3\\x79\\x08\\x69\\xec\\x20\\xc7\\xf3\\xc2\\x19\\xc7\\xd1\\xab\\xc7\\x7c\\x83\\xe6\\xb7\\x8d\\xad\\xe9\\x2d\\x7f\\xbd\\xe5\\xaf\\xd7\\x6d\\x16\\xae\\x5e\\xb7\\xf1\\x57\\xaf\\xdb\\x6c\\xb8\\x7a\\xdd\\xa6\\xd7\\x6d\\x7a\\xcb\\x1f\\xe9\\xb9\\xe3\\x1a\\x98\\xf4\\xdc\\x91\\xf4\\xdc\\x71\\xe5\\xba\\x7a\\xee\\xb8\\x16\\x3c\\x3d\\x77\\xec\\xb9\\xe3\\xb2\\xab\\x90\\xe9\\x1e\\x81\\x8e\\x85\\x4c\\xd7\\xc4\\x39\\xa2\\xd5\\x27\\x91\\xc3\\x4c\\x26\\xd8\\x76\\x02\\x13\\x53\\x9d\\x9d\\x4f\\xd1\\x1c\\x0d\\x51\\x03\\xf2\\x0f\\x29\\x18\\x06\\xaf\\x99\\xbd\\x01\\x73\\x12\\xd4\\x41\\x30\\x8f\\x1f\\xa9\\xe3\\xb5\\x81\\x4d\\x7d\\x9c\\x64\\x1f\\x27\\xf9\\xe0\\xe3\\x24\\x67\\x54\\xe1\\xbe\\x22\\x51\\x5a\\x1d\\x36\\x19\\x1c\\xc8\\xf7\\xac\\xcc\\x1f\\x69\\xd4\\xa4\\x41\\x17\\xbb\\xdd\\x90\\x62\\x53\\x6f\\x29\\xae\\x3c\\xb5\\xfe\\x02\\x96\\x9e\\xc7\\xeb\\xb5\\xf2\\x32\\xd6\\x6a\\x4a\\x53\\x96\\x92\\x82\\x95\\x43\\x44\\x11\\x49\\x26\\xdc\\x16\\xb3\\x6a\\x60\\x9f\\x85\\xcf\\xbd\\x46\\x3f\\xc6\\xeb\\xb8\\xc7\\x10\\xc8\\x78\\x22\\x3b\\xd8\\x5c\\x43\\xc3\\x71\\x44\\xe1\\x1f\\x44\\x40\\xe4\\xb6\\x52\\xfd\\x90\\x68\\x6b\\xe4\\xfd\\xae\\xa5\\x5c\\xbf\\xbd\\x68\\xde\\xaa\\xf4\\xe9\\xe2\\xb5\\xb4\\x9e\\xe6\\xda\\xda\\xa7\\x03\\x5f\\xe0\\x21\\xa1\\x0a\\x39\\xc5\\xb6\\xaa\\xe5\\x96\\x6a\\xd4\\x6e\\x7a\\xca\\xee\\x96\\x68\\x72\\xef\\xe5\\x52\\x17\\xaf\\x5d\\x45\\xb7\\x9d\\x04\\xb7\\x87\\x5f\\x64\\x75\\x15\\x80\\xb6\\x56\\xd0\\xc9\\xce\\x4a\\x3a\\xd9\\x49\\x51\\x27\\xbb\\x2a\\xeb\\x64\\x0f\\x85\\x9d\\xec\\xa6\\xb4\\x93\\x3b\\x28\\xf1\\xba\\x78\\xed\\xac\\xa2\\x92\\x3d\\xf4\\x78\\xf2\\x28\\x0a\\xc3\\x2e\\x5e\\x7b\\x01\\x6b\\x37\\x9d\\x9e\\xf4\\xe5\\x64\\xb7\\xb8\\x76\\x57\\xb9\\xc9\\xee\\x6a\\x37\\xd9\\x1d\\x33\\x5a\\x96\\xa5\\x5d\\xbc\\xfa\\x42\\xb5\\x7b\\x71\\xf6\\x1d\\x18\\xd7\\xf6\\xc5\\x6c\\x57\\x7d\\x7c\\x2b\\x2c\\xf1\\x75\\x86\\xba\\x17\\x36\\x75\\xdd\\xd9\\x30\\xec\\xb5\\xe9\\x18\\x0c\\x84\\x5a\\x04\\xcc\\xc5\\x47\\x8d\\x00\\x8e\\xc1\\xfd\\xd4\\x29\\xbf\\x95\\x08\\x2a\\xb7\\x06\\x83\\xf9\\x0a\\xba\\x8d\\x90\\x26\\xbb\\xf1\\x52\\x30\\x05\\x82\\x1d\\xf3\\x26\\xa2\\xb0\\xb9\\xa2\\x79\\x76\\x84\\xe1\\x20\\x35\\xb7\\x13\\x69\\x33\\x40\\xa4\\x7e\\x03\\x64\\xc4\\x9c\\x51\\xa1\\xc8\\x81\\xb3\\x3d\\x1d\\xaa\\xfa\\x89\\x83\\x51\\x9d\\xdd\\xe7\\x47\\x84\\x24\\xe4\\x30\\xa3\\x6f\\x7d\\x53\\xf7\\x75\\x3b\\xdb\\x4b\\xda\\xbd\\xa4\\xdd\\x4b\\xda\\xbd\\xa4\\xbd\\xf4\\xea\\x25\\xed\\x2d\\xae\\x5e\\xd2\\xee\\x25\\xed\\x75\\x1f\\xee\\x25\\xed\\x5e\\xd2\\xde\\xfc\\xf1\\xdd\\x24\\xed\\x5d\\xe3\\x84\\x42\\xb9\\xd7\\x3a\\xe7\\xb0\\x72\\x16\\xb4\\xe6\\xf7\\x31\\x44\\xbe\\x40\\x29\\xfc\\xaf\\x5b\\x79\\x3b\\x94\\xa5\\x97\\x4b\\xdb\\xa1\\x44\\xbe\\xa0\\x5b\\x8c\\x36\\x88\\xd6\\x5e\\xf8\\x5e\\x78\\x73\\xbd\\xd4\\xfd\\xb0\\x62\\xa1\\x76\\xc0\\x8d\\xc0\\xa1\\xb0\\x23\\x72\\xbc\\x77\\xae\\x70\\x5b\\x69\\x6e\\xcc\\x6a\\x3f\\x79\\x4a\\x8e\\x9c\\xc7\\x05\\x2a\\x44\\x0b\\xa9\\xe3\\x1f\\x85\\xe6\\xc3\\xfa\\x09\\xef\\x83\\x01\\xf7\\x62\\x94\\x6f\\x93\\xc5\\xfd\\xd5\\x44\\xa3\\xb6\\x62\\xbd\\x9f\\x86\\x84\\xb0\\x32\\x9a\\x03\\x77\\x8d\\xf4\\x20\\x5a\\xa2\\xac\\x84\\x30\\xa3\\x42\\x95\\x6c\\xf0\\xc6\\x21\\xcd\\xc1\\x02\\x70\\xbe\\xb3\\xbf\\x11\\x96\\x60\\x3e\\x20\\x31\\xd5\\x50\\x0a\\xfc\\x9d\\xd4\\x96\\x91\\xb6\\xa1\\xfc\\x52\\x58\\x8f\\xa8\\xb9\\xe3\\xbc\\xbe\\x0e\\x29\\x61\\x45\\xdc\\x7f\\x7d\\x44\\x5e\\x02\\x1e\\x86\\x03\\xdb\\x92\\xd3\\x34\\xcb\\xe4\\xcd\\x36\\x24\\xe9\\xae\\xd2\\xa2\\x6e\\xb6\\x4e\\x8b\\x6a\\xf8\\xef\\xfa\\xac\\xa8\\x5f\\x49\\x56\\x14\\xfc\\x88\\x47\\xa8\\xf3\\xf4\\x28\\xf2\\xe3\\x8c\\x01\\x16\\x95\\x0c\\x40\\x95\\x57\\x99\\xe6\\x45\\x1d\\x2b\\xa5\\xf0\\x53\\x19\\x4a\\x99\\x13\\x1b\\x79\\x12\\xe3\\xa5\\xf9\\x1a\\x4d\\x66\\x4d\\xfc\\x84\\xf1\\x20\\xb6\\x4a\\xc1\\xa1\\xb5\\xd1\\x1d\\x34\\xcb\\x6c\\x4e\\x91\\x13\\x49\\x31\\x84\\x85\\xdf\\x77\\x64\\xc2\\xa9\\xab\\x8a\\xe8\\xb4\\x19\\x20\\x32\\x47\\x86\\x16\\x66\\x73\\x5b\\xa9\\x6e\\x0d\\x11\\x45\\xa5\\xe8\\x9a\\x39\\xd6\\x3b\\xe5\\xd7\\x4c\\xd4\\x94\\xf4\\x48\\x1d\\x1f\\x3b\\x1e\\xde\\x29\\x85\\xbf\\x15\\x0a\\xfd\\x97\\x80\\x92\\xfe\\xb5\\x0d\\x8d\\x86\\x05\\x79\\x2a\\x5d\\x83\\xaf\\xa6\\xd1\\xf7\\x19\\x82\\xb1\\x8d\\x9f\\x7f\\x3b\\x1b\\xc3\\x0e\\xfe\\xfd\\x3b\\xf4\\xed\\x3f\\x9e\\xcc\\xb2\\x7b\\xb6\\x30\\xde\\x47\\x6c\\xfd\\x83\\xb7\\x2a\\xf6\\xc1\\xf5\\xf5\\xb5\\x6f\\x70\\xfd\\xad\\x5b\\x0e\\xef\\x37\\xc6\\xfe\\x11\\x58\\x0b\\xef\\x33\\xc6\\xbe\\xb7\\x10\\xae\\xdd\\x94\\x87\\x16\\xfa\\x1e\\x5f\\x3b\\x59\\x04\\x7b\\x6b\\xe0\\xce\\x5c\\x78\\x4b\\x86\\xb3\\xaf\\x15\\x70\\x4b\\x8c\\xd8\\xd1\\xcf\\xde\\xfb\\xd8\\xef\\xc6\\xc7\\xde\\x4b\\xbc\\x2d\\xaf\\x5e\\xe2\\x5d\\x09\\x94\\x5e\\xe2\\x25\\xbd\\xc4\\xbb\\x69\\x79\\xbd\\xc4\\xbb\\x16\\x3c\\xbd\\xc4\\xbb\\x76\\x53\\x7a\\x89\\xb7\\x97\\x78\\xc9\\x63\\x93\\x78\\x77\\xa9\\xd2\\xd5\\xfb\\xba\\xf7\\xf2\\x75\\x6f\\x4b\\x2d\\xb6\\xa2\\x11\\x5b\\xe2\\xc1\\xd6\\xbe\\xed\\xde\\xaf\\xfd\\x50\\xfc\\xda\\xad\\x13\\xfe\\x85\\xe6\\xfb\\x26\\xfd\\x87\\x7b\\xb5\\x2a\\xf3\\x9f\\x5e\\x4b\\x9e\\x92\\xa2\\xd2\\x36\\x9f\\xba\\xcf\\xfe\\xef\\x22\\xfb\\x3f\\x82\\x7c\\x5f\\x02\\xa0\\x55\\x09\\x80\\x55\\x30\\xeb\\xeb\\x00\\xf4\\x75\\x00\\x3a\\x76\\x42\\xf7\\x75\\x00\\xfa\\x3a\\x00\\x7d\\x1d\\x00\\x77\\xf5\\xd9\\x49\\xa4\\xcf\\x4e\\x6a\\x75\\xf5\\xd9\\x49\\xab\\xaf\\x3e\\x3b\\xe9\\xc1\\x5a\\x5f\\x49\\x9f\\x9d\\xf4\\xb0\\x2d\\xb1\\xa4\\xcf\\x4e\\xea\\xad\\xb3\\x2d\\x37\\xea\\x11\\x66\\x27\\xf5\\x75\\x00\\x1e\\x6a\\x8c\\x02\\xe9\\x25\\xed\\x5e\\xd2\\xee\\x25\\xed\\x5e\\xd2\\x5e\\x7f\\xf5\\x92\\xf6\\x16\\x57\\x2f\\x69\\xf7\\x92\\xf6\\xba\\x0f\\xf7\\x92\\x76\\x2f\\x69\\x6f\\xfe\\x78\\x5f\\x07\\xe0\\x11\\xc5\\x46\\x90\\xbe\\x0e\\x40\\x1f\\x2f\\xd1\\xd7\\x01\\xf8\\xf5\\xd6\\x01\\x88\\x7c\\xf7\\xf7\\x57\\x0c\\x60\\xfb\\x69\\xf4\\x15\\x01\\xfa\\x8a\\x00\\x7d\\x45\\x80\\xbe\\x22\\x80\\xbb\\xfa\\x8a\\x00\\x78\\x3d\\x24\\x5b\\x63\\x9f\\x1f\\xb5\\x12\\x28\\x7d\\x7e\\x14\\xe9\\xf3\\xa3\\x36\\x2d\\xef\\x11\\xd8\\x0d\\xfb\\xfc\\xa8\\x07\\x68\\x2b\\xec\\xf3\\xa3\\x7a\\xbb\\x60\\x73\\x73\\x1e\\x49\\x7e\\x54\\x5f\\x11\\xe0\\x21\\x7a\\xdb\\x7b\\x89\\xb7\\xe5\\xd5\\x4b\\xbc\\x2b\\x81\\xd2\\x4b\\xbc\\xa4\\x97\\x78\\x37\\x2d\\xaf\\x97\\x78\\xd7\\x82\\xa7\\x97\\x78\\xd7\\x6e\\x4a\\x2f\\xf1\\xf6\\x12\\x2f\\x79\\x6c\\x12\\x6f\\x5f\\x11\\xa0\\xaf\\x08\\xd0\\x57\\x04\\x78\\x8c\\x1e\\xee\\x8d\\x3b\\xcd\\xc4\\xf5\\xaa\\x3d\\x8d\\x76\\xf1\\xa5\\xb8\\x8e\\xf5\\x14\\x26\\xae\\x79\\x29\\x05\\x50\\xe0\\x6b\\x5a\\x72\\x3a\\xce\\xe0\\xa4\\x82\\xc4\\x63\\xe1\\x6f\\xe9\\x27\\x2b\\x47\\xe4\\x05\\x15\\xd6\\xd1\\x8a\\x9e\\xcc\\x95\\xf3\\xdf\\x8c\\xf8\\x1b\\x50\\xbd\\x39\\xed\\x1f\\x68\\x2c\\xaa\\x89\\xa5\\x53\\x27\\xf6\\x01\\x33\\x75\\x4a\\x5e\\xf8\\x89\\xaf\\xfc\\x4c\\x2b\\x02\\xde\\x46\\x3f\\x18\\x02\\x72\\xae\\x7c\\xa0\\x9d\\x14\\x6f\\x86\\x58\\x7f\\x36\\x23\\xb0\\xbc\\xa5\\x79\\x9d\\xe2\\xbf\\x04\\x1a\\x23\\xf2\\xc6\\x4a\\x48\\x94\\xbc\\xf8\\xdf\\xb3\\xd3\\x97\\x6f\\xdf\\x9f\\xbd\\x3a\\x7b\\x79\\xb1\\x1e\\xe9\\x5a\\x92\\x15\\x38\\x48\\x5b\\x4c\\xf6\\xf0\\x07\\xb7\\x47\\x90\\xe6\\xcd\\x84\\xa1\\xc0\\xbf\\x3d\\xfa\\xe1\\xe4\\xe2\\x7f\\xdf\\x9e\\xbc\\x79\\x79\\x0c\\xec\\x97\\x7d\\x2e\\xa8\\x48\\x59\\x4a\\x2a\\xe5\\x48\\x42\\x51\\xb2\\x6b\\x2e\\x2b\\x95\\xcd\\xfd\\xf1\\x5e\\x8e\\xb4\\x4d\\x6c\\xb5\\x8a\\xe6\\x9c\\x28\\x56\\x5e\\xf3\\x64\\x39\\x88\\x50\\x8a\\xa5\\x35\\x02\\x25\\x1e\\xc3\\x4b\\xa6\\x64\\x76\\xcd\\x52\\x94\\x35\\xfc\\xa4\\xdd\\x77\\xb8\\x28\\x2a\\xed\\x24\\x62\\x08\\x41\\x30\\xa7\\x42\\x24\\x33\\x2a\\xa6\\x2c\\x1d\\x91\\x53\\x59\\x99\\xf1\\x7e\\xfb\\x5b\\x58\\x58\\xc9\\xd2\\x2a\\x41\\x5e\\x47\\x9d\\xc0\\xf4\\xdb\\x81\\xa3\\x24\\x86\\x16\\x28\\x2c\\xa3\\xa0\\x12\\x5a\\xb8\\xa5\\x87\\xd0\\x51\\x73\\xa1\\xe9\\xe7\\xe7\\xe8\\x83\\x3f\\xf8\\x6d\\xf0\\xd3\\x81\\x2b\\x41\\x21\\xcd\\x27\\x90\\x1e\\xe1\\xac\\x32\\xa8\\x7e\\x90\\x91\\x83\\xf0\\xe9\\x11\\x79\\x69\\xbe\\xc1\\xd2\\x70\\x1f\\x30\\x84\\x82\\x5d\\xb3\\x12\\xe4\\x69\\xbb\\x0b\\x03\\x52\\xb2\\x29\\x2d\\xd3\\x8c\\x29\\x08\\x1e\\xb8\\x99\\x31\\x28\\xe7\\x81\\x12\\x96\\x05\\x18\\xf3\\xd2\\xba\\x90\\x7a\\x44\\x4e\\xd9\\x84\\x56\\x99\\x06\\x1a\\x72\\x70\\x30\\x3a\\xec\\x0c\\xd5\\x5e\\x95\\x72\\x43\\xf2\\x7b\\x84\\x6e\\x97\\x58\\x54\\x62\\x22\\xcb\\x95\\xc7\\xe3\\xd0\\x9a\\x26\\x22\\xb2\\xa6\\x0c\\x27\\xb1\\x9a\\x9e\\xa3\\xd5\\xa8\\x5f\\xb4\\x58\\x49\\x0b\\x41\\xb0\\xbd\\x3a\\x9f\\x48\\x31\\xe1\\xd3\\x37\\xb4\\xf8\\x8e\\xcd\\x2f\\xd8\\x64\\xcb\\x68\\x08\\x64\\xa2\\x56\\xa7\\x05\\x06\\x66\\xc8\\x21\\x0e\\xb8\\x99\\xe9\\xdc\\xa2\\x2f\\xbf\\x8d\\xd1\\x64\\x3b\\x9b\\x47\\x6b\\x4b\\xc7\\x42\\x49\\x0b\\x64\\xfa\\x96\\x7d\\x77\\x58\\x9c\\xa7\\xbe\\x36\\x53\\xf4\\xa5\\x93\\x3b\\x0c\\x49\\xbb\\x3d\\xa7\\x7a\\x44\\xde\\x48\\x08\\xc9\\x99\\xc8\\xe7\\x64\\xa6\\x75\\xa1\\x9e\\x3f\\x79\\x72\\x55\\x8d\\x59\\x29\\x98\\x66\\x6a\\xc4\\xe5\\x93\\x54\\x26\\xea\\x49\\x22\\x45\\xc2\\x0a\\xad\\x9e\\xc8\\x6b\\x43\\xf9\\xd8\\xcd\\x93\\x1b\\x59\\x5e\\x71\\x31\\x1d\\x1a\\x49\\x67\\x88\\xbb\\xaa\\x9e\\x80\\x30\\xf5\\xe4\\xdf\\x50\\x62\\x7f\\xff\\xee\\xf4\\xdd\\x73\\x72\\x92\\xa6\\xb6\\x62\\x4f\\xa5\\xd8\\xa4\\xca\\x6c\\xf5\\x8e\\x11\\xa1\\x05\\xff\\x81\\x95\\x46\\x29\\x1b\\x90\\x2b\\x2e\\xd2\\x01\\xa9\\x78\\xfa\\xcd\\xfa\\xc3\\xbd\\x23\\xc4\\x64\\x81\\xba\\xd1\\x0e\\x50\\xbb\\x04\\x41\\x71\\x1e\\xd1\\x29\\x8f\\xf4\\x86\\x42\\x71\\xad\\x60\\xcf\\x9d\\xe1\\xc0\\x32\\x94\\x2d\\x96\\x31\\x96\\x32\\x63\\x54\\x6c\\x78\\x03\\xc0\\xb6\\xfd\\x99\\x3d\\xac\\x0f\\x2d\\x6a\\x39\\x16\\x01\\x0a\\x99\\x3e\\x27\\xaa\\x2a\\x0a\\x59\\x6a\\x45\\x72\\xa6\\x69\\x4a\\x35\\x1d\\x99\\x9d\\x1b\\xc4\\x7f\\x82\\x70\\x3c\\x20\\x3f\\xf9\\x9b\\x20\\xe1\\xaa\\x0f\\x87\\x87\\x7f\\xf9\\xee\\xe5\\x7f\\xff\\xf5\\xf0\\xf0\\xd3\\x4f\\xe1\\xaf\\x40\\xf6\\xd0\\xd4\\x15\\x3f\\x62\\x44\\xee\\x91\\x11\\x77\\xdf\\xc2\\x37\\xe0\\x4f\\xcb\\x46\\x4f\\x92\\x44\\x56\\x42\\xdb\\x1f\\x34\\xd5\\x95\\x1a\\xcd\\xa4\\xd2\\x67\\xe7\\xfe\\xcf\\x42\\xa6\\xcd\\xbf\\xd4\\x06\\x4e\\x40\\x6e\\x97\\xe8\\x00\\x38\\xcf\\xa9\\x9e\\x75\\x4c\\x7a\\xea\\x73\\xb1\\x03\\xba\\xda\\x37\\xc3\\x0a\\x49\\x39\\x85\\xff\\xbe\\x72\\xd3\\x35\\x1c\\xe8\\xa6\\xe4\\x5a\\x33\\x01\\x72\\x07\\xc4\\xdd\\xc9\\xc9\\xc0\\x60\\x6e\\xcd\\x66\\xaf\\x9f\\x6d\\xa5\\x8e\\xb6\\x3e\\x8a\\x1e\\x6a\\x3b\\x2c\\x0e\\x66\\x6f\\x57\\x86\\xc8\\xec\\x09\\xed\\xa2\\x5e\\x77\\x72\\x7e\\x46\\xae\\x11\\x1a\\x9d\\x2f\\xc4\\x45\\x61\\xbd\\xda\\xfb\\x4c\\xfa\\x4a\\x55\\x76\\x59\\x5e\\xd2\\x7c\\x8e\\x96\\x25\\x1f\\xef\\x45\\x32\\x9e\\x73\\x6b\\x00\\xb6\\x55\\xad\\x14\\x39\\xc2\\x9b\\xa3\\xa4\\xa8\\x06\\xf6\\x81\\x51\\xce\\x72\\x59\\xce\\xfd\\x9f\\xac\\x98\\xb1\\xdc\\x48\\x6c\\x43\\xa5\\x65\\x49\\xa7\\x6c\\xe0\\x5f\\xc7\\xd7\\xfc\\x5f\\xf8\\x62\\xf4\\x81\\xc5\\xb7\\x51\\xa4\\x4e\\xaa\\xd2\\x30\\x8f\\x6c\\xee\\x28\\x08\\x4b\\xef\\xf7\\x2c\\x3a\\x30\\x75\\x7c\\x14\\xfd\\x6e\\xbc\\xdd\\x91\\xe5\\x7a\\x6d\\x11\\x99\\xb6\\x5f\\x15\\xc8\\x90\\xd7\\x32\\xab\\x72\\xa6\\x06\\x9e\\x3d\\xa1\\xb4\\x2e\\xae\\x8d\\x34\\xa9\\x6e\\x85\\x11\\xa6\\xfc\\x9a\\xab\\x9d\\xfc\\xd3\\x97\\xde\\x52\\x07\\x26\\xb2\\x4a\\x1b\\x4d\\x05\\x83\\xc1\\x83\\x8a\\x70\\x52\\x81\\x0e\\xe0\\x63\\x14\\x23\\x92\\xf2\\xec\\xa0\\x9d\\xf7\\x95\\x6a\\xcd\\x4a\\xf1\\x9c\\xfc\\xcf\\xd1\\xc7\\xdf\\xfd\\x32\\x3c\\xfe\\xe6\\xe8\\xe8\\xc3\\xd3\\xe1\\x9f\\x3f\\xfd\\xee\\xe8\\xe3\\x08\\xfe\\xf3\\xd5\\xf1\\x37\\xc7\\xbf\\xb8\\x3f\\x7e\\x77\\x7c\\x7c\\x74\\xf4\\xe1\\xbb\\x37\\xdf\\xbe\\x3f\\x7f\\xf9\\x89\\x1f\\xff\\xf2\\x41\\x54\\xf9\\x15\\xfe\\xf5\\xcb\\xd1\\x07\\xf6\\xf2\\x53\\xcb\\x41\\x8e\\x8f\\xbf\\xf9\\x6d\\xab\\xe9\\x51\\x31\\x7f\\xd7\\xe2\\xc0\\xe3\\x35\\xdc\\x21\\xc2\\xbe\\x7e\\x6b\\x0b\\x03\\xfd\\xe7\\x61\\x2d\\xb4\\x0d\\xb9\\xd0\\x43\\x59\\x0e\\xf1\\xf5\\xe7\\x44\\x97\\xd5\\xe6\\x83\\x51\\x13\\xb5\\x5d\\xf0\\xdc\\x95\\x03\\x7b\\x5e\\x13\\x34\\x4f\\x9a\\x3b\\x47\\x64\\xc5\\x92\\x92\\xe9\\xae\\x34\\x18\\x1c\\xcd\\xf1\\x8f\\x86\\x49\\xb6\\x57\\x6a\\x6a\\xa5\\xc6\\xdb\\x25\\x01\\x5e\\x35\\xe7\\x9d\\x94\\x32\\x1f\\x91\\xc0\\x2c\\x74\\x0d\\x9e\\x4c\\xfb\\xdc\\x15\\xdb\\xa0\\xe5\\xba\\xab\\x57\\x82\\x1e\\x97\\x12\\x74\\x89\\xfb\\x7b\\xeb\\x1a\\x10\\x13\\xd7\\xeb\\xcc\\x34\\x4d\\x9b\\xee\\x2b\\x48\\x65\\x09\\xcd\\xd1\\x4e\\x80\\xd2\\x92\\x14\\xb2\\xa8\\x32\\xaa\\x57\\x98\\xed\\x96\\xd8\\xa6\\x2d\\xee\\xd7\\x5e\\x00\\xb3\\xd1\\x60\\x07\\xb6\\x54\\x2e\\x5f\\x6e\\x0c\\x25\\x27\\x59\\x46\\xb8\\xc0\\x93\\x00\\x03\\x38\\x6b\\x5e\\xc9\\x50\\x5e\\x22\\x14\\x0d\\xce\\xd7\\x66\\x0a\\x37\\x36\\xe1\\x26\\x30\\x34\\x72\\x65\\x74\\x9d\\x52\\x83\\xc5\\x1f\\x12\\x72\\x90\\x66\\x59\\xd3\\x18\\x17\\x75\\x5a\\x8e\\xe7\\xb6\\xde\\x4b\\xb9\\xb4\\xfe\\x62\\x46\\x95\\x76\\xd3\\x86\\xd9\\x68\\x7a\\x05\\xa6\\xd0\\x84\\xa5\\x4c\\x24\\x0c\\x42\\x10\\x2a\\x56\\xaf\\x75\\x6c\\x84\\x41\\x30\\xef\\xc3\\x18\\x94\\xa4\\x55\\x91\\xf1\\xc4\\xc0\\xcf\\xcc\\x64\\xf9\\x18\\x67\\x79\\x5e\\x69\\x30\\x14\\xdf\\x95\\x15\\xdf\\xec\\xf8\\xa5\\x2b\\xf7\\xea\\x8d\\xf9\\x40\\xaa\\xbc\\x68\\xed\\xa3\\x2d\\xbc\\xea\\xae\\xf6\\x33\\xdf\\xb7\\x23\\xbc\\xde\\xdc\\xb6\\x91\\x53\\x2d\\x50\\xdc\\xda\\xc6\\x10\\x53\\xda\\xbb\\xb6\\x18\\xb6\\xa3\\xb3\\x5f\\x24\\x8d\\xdd\\x82\\xbe\\xb6\\xa7\\xad\\x5b\\x18\\x97\\xb6\\xa5\\xa7\\x6d\\xad\\x49\\x45\\xc9\\x26\\xfc\\xf3\\x16\\xf8\\x78\\x22\\x6a\\x15\\x85\\xa7\\x4c\\x68\\xa3\\x08\\x40\\x65\\xea\\xa2\\x64\\x05\\x13\\xa9\\x4f\\xf7\\x83\\x00\\x2f\\x11\\xaf\\xe3\\x56\\x3d\\x46\\x28\\x65\\x6c\\x7f\\xbc\\x2e\\x97\\x49\\x31\\xfd\\xd9\\xfa\\xc2\\xcf\\x96\\xdd\\xf5\\xee\\x0f\\x96\\x90\\xe9\\xc6\\xe0\\xef\\xc6\\x3e\\x06\\x6f\\x34\\x22\\x5d\\x6d\\xf9\\x6f\\x3b\\x49\\xa3\\xbd\\x79\\x97\\x53\\x21\\x53\\xac\\x71\\xad\\xeb\\x20\\x84\\x11\\xb9\\x5c\\xf2\\x26\\xc4\\x1a\\xd8\\x27\\x0e\\x0f\\x15\\x86\\x25\\xa8\\xe6\\x40\\x8d\\xec\\x66\\x8c\\x4c\\xc0\\x41\\xb7\\x44\\x29\\x64\\x75\\x55\\x09\\x96\\xdf\\x27\\x54\\x29\\x3e\\x15\\xc3\\x42\\xa6\\x50\\x97\\xfb\\xc9\\x2a\\x84\\x68\\x71\\xa8\\xb6\\x8b\\x6c\\xda\\x88\\x57\\xde\\x38\\xd1\\x6e\\x9b\\x2e\\xbc\\xfd\\x2d\\x90\\x2d\\x5c\\x45\\xf8\\x32\\xf8\\xd1\\xda\\x75\\x5c\\x1c\\x7d\\x20\\x43\\xd6\\x12\\xd1\\x7e\\x30\\xcd\\xa9\\xa0\\x53\\x36\\xb4\\x1f\\x1f\\xfa\\x8f\\x0f\\xfd\\xb7\\xf6\\x01\\x73\\x1b\\xaa\\x95\\x64\\x94\\xaf\\x0f\\x25\\x8a\\x80\\x77\\xf0\\x02\\x9e\\xb7\\x89\\xe2\\x3e\\x02\\xab\\x91\\xc6\\xea\\xa4\\x4d\\x2e\\xd0\\x25\\xe0\\x7e\\xc2\\x97\\x07\\x88\\x92\\xb4\\xb4\\x6e\\xd4\\x25\\xf0\\xfd\\x28\\x30\\x90\\xc8\\xc6\\x95\\x66\\xc5\\x8c\\x06\\x01\\x5d\\x76\\x67\\x14\\x61\\x82\\x8e\\x33\\xe7\\x05\\x3f\\x9d\\x0b\\x9a\\xf3\\xc4\\xed\\xee\\x49\\x06\\x01\\x3f\\x5c\\x0a\\x32\\x61\\x54\\x57\\x25\\x23\\x53\\xaa\\x59\\x3d\\xb6\\x8f\\x14\\xe4\\xf5\\x66\\x9e\\x69\\x92\\x50\\x81\\x66\\xda\\x31\\x66\\x6a\\x98\\xd3\\xe5\\x67\\xa6\\x46\\xeb\\xec\\x5d\\xed\\xa2\\xb8\\x5a\\xc4\\x6e\\x35\\xca\\xb2\\x07\\xc0\\x0b\\x9d\\xf1\\x52\\x18\\xa5\\x47\\x97\\xc0\\x9e\\xcf\\x65\\x6a\\xa8\\xe3\\x28\\x7a\\x7a\\x43\\x50\\x7c\\x6b\\xf6\\xd7\\xd6\\xc8\\xb1\\x21\\xb8\\x85\\xdc\\x36\\x27\\x05\\x46\\x1a\\x90\\x4a\\x87\\x9f\\x06\\x3d\\x23\\x68\\x15\\x32\\x1d\\x2d\\xc1\\x4c\\xc7\\x84\\xcf\\x65\\x6a\\xe3\\xc6\\x74\\x84\\x29\\x06\\x5d\\x01\\x49\\x72\\x7a\\xe5\\x62\\xbe\\xbc\\x71\\x8c\\x5e\\x53\\x9e\\x41\\xa8\\x03\\x17\\x8a\\xa7\\x46\\x34\\x4a\\x36\\x07\\x16\\xb9\\xab\\x25\\xf3\\x8c\\x6c\\x82\\xe6\\x10\\x0e\\x73\\x5a\\x0c\\x8d\\x36\\xba\\x1e\\x54\\x1b\\x77\\x66\\x71\\x60\\x9c\\x51\\x4e\\x8b\\x95\\x6f\\xa1\\x3b\\xa2\\x35\\xed\\x38\\x7c\\x8d\\xee\\x8e\\xd4\\xb7\\x96\\xc1\\xd8\\xdf\\xcf\\x3c\\xaf\\x72\\x42\\x73\\x59\\x61\\x78\\xef\\x22\\x29\\x76\\x41\\x70\\x9d\\x10\\xdb\\x25\\x44\\x56\\xad\\xa4\\xb2\\xa4\\xfd\\x31\\xd9\\x3e\\x5c\\xf7\\x81\\x5a\\xc5\\x5b\\x59\\xc3\\xb7\\xb3\\x82\\x6f\\x61\\xfd\\xde\\xd9\\xea\\xed\\x1c\\x5c\\xed\\xf1\\xf1\\xc2\\xf9\\xdc\\x1a\\x18\\xc9\\xc5\\x46\\x8c\\x2c\\x7d\\xaf\\x8c\\xb3\\x09\\xf1\\xe3\\x70\\x45\\x64\\xce\\xb5\\xb6\\xce\\xa0\\x80\\x00\\x0c\\x08\\xd7\\x91\\xe7\\xc4\\x9e\\x05\\xe8\\x15\\x83\\xed\\x75\\xd8\\xe7\\x22\\xe3\\x09\\x07\\x0f\\x9c\\xf3\\x78\\x0e\\x50\\x42\\xbf\\xe1\\x58\\x59\\x86\\x0a\\xc2\\xf3\\x02\\x03\\xe1\\x01\\xa7\\x87\\x8e\\xd3\\xda\\x00\\x25\\x3f\\x13\\x1b\\x9e\\xc6\\x3e\\x27\\x8c\\xa5\\xf6\\x63\\xfd\\xf1\\xe9\\x8f\\xcf\\xf2\\xe3\\xa3\\xb6\\x51\\x73\\x42\\x0d\\xa7\\x0e\\x8e\\xf6\\x9a\\x8e\\x41\\x7c\\xd7\\xd3\\x0a\\x82\\xbf\\x11\\x87\\xcc\\x51\\x81\\xfc\\x1c\\x23\\xae\\x5d\\x30\\x30\\x3a\\x5e\\x32\\xad\\x6c\\xb8\\x35\\xbc\\x61\\x24\\xc2\\x85\\xec\\x55\\x67\\x64\\xf5\\x51\\xfc\\x74\\x32\\x89\\x9f\\x48\\x59\\x91\\xc9\\x79\\x0e\\x4a\\xf3\\x99\\x6e\\xf2\\x7f\\xd0\\x8a\\x58\\x5e\\x64\\x54\\x33\\xaf\\x33\\xad\\x37\\x64\\xee\\x2d\\x54\\x6f\\x93\\x3a\\x7a\\xbf\\xc9\\xa2\\xb7\\x23\\xb2\\x3e\\xc8\\x14\\xd0\\x5b\\x90\\x76\\x37\\xbb\\xf3\\x5a\\xa6\\x72\\xb6\\x97\\x8a\\x5b\\xf9\\xfb\\x6e\\x3b\\x41\\x73\\x2b\\x4b\\x4f\\xdb\\x24\\xcc\\x87\\x9f\\x76\\xb9\\xc5\\xb2\\xdb\\xa6\\x56\\xf6\\xc9\\x94\\xeb\\x40\\xdd\\x2e\\x21\\xaa\\x75\\x32\\x54\\xab\\xfd\\x6b\\x99\\x14\\xd9\\xa7\\x41\\x6e\\xc1\\x5f\\x6e\\x41\\xf8\\xdb\\xb8\\x97\\x5a\\x66\\x0c\\x25\\xd7\\x76\\x66\\xc1\\xf7\\xf5\\xf3\\xbe\\xb5\\x22\\x46\\x8e\\x04\\x23\\xdd\\x8d\\x03\\xf4\\xbd\\x13\\x5b\\xcc\\xd9\\xaa\\xe7\\x05\\xa8\\xa5\\x35\\x85\\x3e\\x8a\\x5a\\xba\\x79\\x99\\x8d\\x13\\x73\\x62\\xf6\\x4c\\xdb\\xa6\\x9a\\x41\\x97\\x49\\x5d\\x82\\x3f\\xf9\\x2f\\x1e\\xdb\\x06\\x0c\\xe4\\xa7\\xbf\\x06\\xa9\\x33\\x3e\\xb5\\xce\\x63\\xc8\\x5f\\xdc\\xff\\xfe\\xba\\x67\\x4a\\x54\\x3b\\xc6\\x86\\x53\\xda\\x42\\xc0\\x78\\x09\\x2f\\x10\\x2e\\x52\\xf0\\x5d\\xdb\\xa5\\x02\\x04\\x70\\x2c\\x03\\x1f\\x58\\x96\\x4b\\xad\\xc3\\x1c\\x4d\\x6b\\x41\\x07\\x27\\x77\\xfd\\xb0\\xb2\\xde\\xf8\\x40\\xed\\xb2\\x16\\x87\\xfa\\x64\\x30\\xf2\\x56\\xda\\x7a\\xa7\\x6c\\x40\\xce\\xc1\\x0c\\x57\\xdf\\x81\\x93\\xf4\\x56\\x62\\xe5\\xd3\\x95\\x6e\\xf2\\x10\\x6e\\x1b\\xb9\\xc8\\x46\\x46\\x1f\\x01\\xe4\\xbb\\x9a\\xc9\\xe3\\xca\\x22\\x26\\x5f\\x63\\x70\\x94\\x64\\xbb\\x0e\\x32\\x57\\x6c\\x5e\\x33\\x1b\\x2b\\x42\\x00\\xc9\\x1f\\xd4\\x58\\xe2\\x58\\x01\\xf2\\x8e\\xff\\xe3\\xac\\xb8\\xf9\\x98\\x0b\\xfc\\x18\\x0e\\xed\\xb6\\x02\\x46\\x77\\x00\\x35\\x92\\x5d\\x96\\xe1\\x67\\xba\\x00\\x57\\x3b\\x39\\x23\\x82\\xd9\\xbb\\x2d\\x64\\x0c\\x4f\\x25\\x97\\x4b\\x17\\x81\\x48\\xf1\\xf2\\xe7\\x8a\\x66\\x71\\x7e\\x93\\xbd\\x65\\x1f\\x5a\\xa0\\xea\\x37\\x3c\\x4b\\x13\\x5a\\xda\\x00\\x52\\x38\\xa3\\x44\\x49\\x6b\\x24\\x07\\x42\\x90\\x50\\xe1\\x4f\\x7b\\xbd\\x47\\xd8\\x62\\x95\\x14\\xb4\\xd4\\x3c\\xa9\\x32\\x5a\\x12\\x73\\x16\\xa6\\xb2\\x6c\\x95\\x83\\xb4\\x11\\xa2\\x35\\xd2\\x5c\\xb2\\x44\\x8a\\x74\\x1b\\x05\\xe0\\x7d\\xf3\\xdd\\x66\\x18\\x47\\xc1\\x4a\\x6e\\x2b\\x89\\xf2\\x9c\\x35\\x91\\xf4\\x28\\x76\\x97\\xc9\\x89\\x3b\\xd5\\xfe\\x88\\x45\\x86\\x91\\xd8\\x9a\\x8f\\xa5\\x88\\x8f\\x03\\xf2\\xe8\\x4f\\xc5\\x88\\xfc\\x6d\\xee\\xac\\x30\\x60\\x91\\xb1\\x89\\x5b\\x8a\\x69\\x97\\x63\\xe7\\x50\\xd6\\x02\\xbb\\x3e\\x50\\x13\\x59\\x42\\xde\\xdb\\x51\\x2a\\x31\\xd9\\xeb\\x9a\\x27\\xfa\\x78\\x44\\xfe\\x1f\\x2b\\x25\\x26\\x87\\xb3\\x29\\x16\\x86\\xb5\\x28\\xee\\x15\\x57\\xe8\\x89\\x0c\\xc1\\x41\\x4f\\xc9\\x11\\x16\\xe9\\xe5\\x79\\xce\\x52\\x4e\\x35\\xcb\\xe6\\xc7\\xa8\\xc7\\xba\\x32\\xbf\\x6d\\xb6\\xae\\x8d\\xd1\\x20\\xa8\\xe9\\xfc\\xc7\\x3f\\xac\\x79\\x72\\xdb\\xf4\\xcc\\x1f\\x5c\\xc2\\x5b\\x0d\\x19\\x0c\\x4f\\x6a\\x6c\\xa1\\xe7\\x41\\x72\\x8d\\xb8\\x19\\x86\\x37\\xd5\\xf9\\xe2\\x8e\\xcc\\xf8\\x0d\\xfe\\xbb\\xc1\\x03\\x4a\\x4a\\x36\\x05\\x2c\\x47\\xcc\\xdd\\x13\\xc7\\x31\\x50\\xfb\\x8d\\xac\\xc4\\x6a\\x8b\\x61\\xb4\\xf0\\xd7\\x56\\x09\\xff\\x21\\x78\\x71\\x65\\x02\\xf4\\x9d\\x88\\x09\\xc1\\x4c\\x02\\x0b\\x26\\x25\\x60\\xb6\\x04\\x76\\x6e\\xc8\\x03\\x3e\\x55\\x07\\xb9\\xb5\\xf0\\x49\\x74\\x98\\xec\\x0c\\x73\\xd9\\x90\\x50\\xd3\\x49\\x4a\\xb4\\xff\\xd0\\x16\\xb8\\x0c\\xb9\\x27\\x16\\x30\\x8d\\x94\\x60\\x6d\\xc9\\x01\\xe0\\x27\\x42\\xb0\\x46\\x50\\xf8\\x16\\x4b\\x5d\\x80\\x2c\\x96\\x31\\x80\\x57\\xc9\\xe1\\xf3\\xc3\\x4e\\x88\\x2f\\x2e\\xa7\\x94\\x05\\x9d\\xd2\\xcd\\xa5\\xd4\\x63\\x65\\xa4\\xf1\\x2a\\x49\\x99\\x66\\x65\\x0e\\x35\\xaf\\x67\\xf2\\x06\\x7f\\x47\\xb6\\x55\\xd8\\xa7\\x98\\x2d\\x17\\x6e\\x56\\x3b\\x93\\x0a\\xb8\\x52\\x9c\\x1f\\x0d\\xe7\\x17\\x62\\x2e\\x6e\\xe8\\x9c\\xd0\\x52\\x56\\x22\\xb5\\x52\\x93\\x27\\xa0\\x6f\\x1a\\x1f\\x7e\\x2b\\x05\\xab\\xbd\\x66\\xb1\\xcf\\x75\\xcc\\x34\\x35\\xc7\\xe6\\xd9\\xe8\\xd9\\x86\\xb2\\xf6\\x2d\\x01\\xb6\\x65\\x4a\\x3c\\xcc\\xa6\\x61\\x29\\x74\\x61\\x38\\xee\\xcc\\x74\\x32\\xaf\\x92\\xd1\\xf4\\x9d\\xc8\\xb6\\x91\\xe5\\xde\\x20\\x7a\\xc1\\xab\\x43\\x50\\xc2\\xf8\\x04\\x6c\\xb7\\x03\\xbc\\x75\\x53\\x72\\xcd\\x02\\xf2\\x78\\x34\\xa1\\x99\\x82\\x5e\\xfe\\x95\\xf0\\x22\\xec\\x71\\x2c\\x82\\xc0\\x23\\x6d\\x16\\xb4\\x39\\xd4\\x4c\\x55\\xe3\\x3d\\xcf\\x99\\x3d\\x50\\x80\\x72\\xf5\\x31\\xf3\\x08\\xf7\\xff\\xb3\\xf7\\xae\\xcd\\x6d\\xe4\\xd8\\xfd\\xf0\\xfb\\x7c\\x0a\\x94\\xf6\\x85\\xa4\\x14\\x49\\xd9\\xfb\\x4c\\x76\\xb7\\xe6\\x49\\x6d\\x95\\x2c\\xd9\\xb3\\xcc\\xda\\x1e\\xc5\\xb2\\x67\\x2a\\x95\\xa4\\xb2\\x60\\x37\\x28\\x62\\xd5\\x04\\x38\\x0d\\xb4\\x64\\x26\\xb5\\xdf\\xfd\\x5f\\x38\\xe7\\xe0\\xd6\\x24\\xc5\\x6e\\x8a\\xba\\x78\\x46\\x7c\\x31\\x63\\x91\\x0d\\x34\\xae\\xe7\\x7e\\x7e\\xe7\\xd0\\xdc\\x71\\xe5\\xf2\\xbc\\x71\\x76\\x84\\x4f\\x3a\\x89\\x4d\\x6b\\x7b\\xbc\\x9f\\xf8\\x33\\x9c\\xa0\\xd3\\xac\\xfb\\xa8\\x24\\x1e\\x92\\x60\\xb1\\xc7\\xd9\\xbe\\x11\\x33\\x7e\\x23\\x0c\\x33\\x72\\x2e\\x2b\\x5e\\x57\\x90\\x86\\x7c\\x89\\xe3\\x63\\x93\\xc6\\xae\\x07\\xb7\\xe8\\x07\\x9c\\x90\\x8e\\x24\\xe9\\x6e\\xeb\\x52\\xfb\\x71\\xb8\\x75\\x02\\x1a\\xe1\\xc7\\x85\\xf5\\x05\\x7c\\x51\\x82\\xaf\\x45\\xd5\\x18\\x79\\x73\\xdf\\xdb\\x44\\x89\\x55\\x3b\\xb0\\xea\\x36\\x97\\x5e\\x50\\xa4\\xc4\\x23\\xf2\\xe8\\x5c\\xc3\\x70\\xa4\\xaa\\xf4\\x9b\\x0e\\x3c\\x19\\x95\\x7d\\xd0\\xdc\\x21\\xee\\x84\\x17\\x85\\x30\\xc6\\x87\\x6b\\x2f\\xd3\\x10\\xf2\\x30\\x87\\x6f\\x05\\xab\\x84\\xdf\\x9a\\xb7\\x15\\x37\\x56\\x16\\x6f\\x2a\\x5d\\x5c\\x5f\\x5a\\x5d\\xf7\\x82\\x03\\x59\\xd7\\xbe\\x85\\xf0\\x72\\xfa\\xf3\\x25\\x3b\\x97\\xe6\\x3a\\x49\\x54\\x22\\x9f\\x6a\\x6a\\x2e\\xe1\\xec\\xba\\x99\\x88\\x4a\\xd8\\xc3\\x43\\x83\\x5c\\x6e\\xce\\x8b\\x99\\x54\\xc2\\x33\\x38\\x15\\xb2\\xdd\\x48\\xe1\\x73\\xab\\xdc\\xd7\\x67\\x4a\\x39\\x95\\x27\\x74\\x5e\\x7f\\xc7\\x6f\\x8d\\xc0\\xe1\\x4f\\xdc\\xf0\\xdd\\xcf\\xa2\\x0b\\xd8\\xc5\\x5e\\xfd\\x14\\x38\\x98\\xf1\\xf9\\x9e\\x7c\\x10\\x53\\xf3\\xd9\\x8d\\xb1\\x9f\\x71\\xfb\\x10\\x5b\\x79\\xd5\\x61\\x2a\\x2b\\x41\\x85\\x4d\\xdc\\x84\\x7d\\xe4\\x0d\\xdd\\x0a\\xd8\\xbf\\xa5\\x6e\\xd8\\x2d\\x47\\x1d\\x19\\x28\\xe2\\x88\\x7d\\x96\\x8b\\xef\\xd9\\x5b\\x65\\x9a\\x5a\\x44\\xeb\\x46\\xbb\\x2b\\x69\\x62\\x0a\\xab\\x57\\xae\\x60\\xbf\\x51\\x01\\x71\\x74\\x8f\\x74\\x2d\\xf6\\xf6\\x2b\\x9f\\x2f\\x2a\\x61\\xbe\\x67\\x07\\xe2\\xab\\xfd\\xee\\x60\\xc0\\x0e\\xbe\\x4e\\x8d\\xfb\\x9f\\xb2\\x53\\x73\\x30\\x62\\xe3\\x79\\x70\\xca\\x4b\\x35\\x15\\x75\\x2d\\x7c\\x8c\\x25\\x36\\x70\\xac\\x39\\xe1\\xba\\x0f\\x72\\x5c\\x28\\x5e\\xd7\\xc9\\x6e\\xa5\\x66\\xb7\\x08\\x75\\xe3\\x08\\xbe\\xa8\\x6b\\x5d\\x87\\x14\\x97\\x64\\x19\\x80\\xd7\\x14\\x7a\\xbe\\xa8\\xf5\\x5c\\x26\\x66\\x3e\\x38\\xee\\x7b\\x0d\\xe4\\x05\\xe3\\x43\\x97\\x5a\\x3f\\xed\\xd3\\x10\\x1a\\xfa\\x03\\x91\\x7c\\xa1\\xba\\x1c\\x85\\xf1\\xd4\\xc7\\x5a\\xa0\\x16\\x49\\x6a\\x3d\\x74\\x47\\x0f\\xb9\\xcd\\xa7\\x5e\\x1c\\x21\\x4b\\xb7\\xfb\\x5d\\xc8\\xd5\\x65\\x27\\xa5\\xb8\\x39\\x31\\x25\\x7f\\x3d\\x80\\xd7\\x18\\x8a\\x31\\xce\\xc7\\xc4\\x0d\\x3b\\x78\\x7d\\x30\\x62\\x97\\x9e\\x11\\x0f\\xd2\\x31\\xc6\\xe7\\xa6\\xba\\x0e\\x1d\\x82\\x9d\\xfd\\xd5\\x01\\x3b\\xd2\\x35\\xf4\\x5c\\x70\\xc5\\x2a\\xc1\\x6f\\xc8\\xb6\\x8c\\xd7\\x6d\\x89\\xea\\xee\\x71\\xe7\\x5c\\xeb\\xae\\x69\\xa7\\xdd\\x8b\\x3a\\x75\\x15\\x52\\x57\\x37\\xd1\\xb7\\xf3\\x26\\x80\\xba\\xa1\\x34\\xa4\\xa9\\xae\\x09\\x62\\x28\\x3c\\x62\\x84\\x85\\xab\\x27\\x55\\xa6\\x42\\x3f\\x01\\x81\\x65\\x3d\\x51\\x3a\\x3c\\xf5\\xec\\xbb\\x3a\\xbe\\x1d\\xe8\\x40\\x4a\\xfe\\xd2\\x08\\x36\\x3e\\x0f\\x58\\x1d\\xa2\\x36\\xd2\\x58\\x77\\x8d\\xcb\\x8c\\x75\\x49\\xe4\\x67\\x47\\xa7\\x73\\xfe\\xbf\\x5a\\xb1\\xb7\\x6f\\x2e\\x69\\x00\\xc7\\x4f\\xba\\x54\\x5b\\xa9\\x01\\xff\\xdf\\xa6\\x16\\x8e\\x0b\\xf7\\x60\\xee\\xa1\\x4d\\x9b\\xa1\\xbb\\xef\\xd9\\x39\\xb7\\x1c\\xf9\\x3a\\x05\\x62\\xa9\\x48\\xca\\x1d\\xcb\\x9e\\x48\\x55\\xd2\\x4f\\x09\\xc3\\x7e\\x6c\\xde\\xea\\x76\\xef\\xe3\\xb6\\xa8\\x57\\xff\\xe0\\x97\\x4f\\xe3\\x3d\\xf1\\xe0\\x02\\x88\\xf9\\xd5\\x07\\x5d\\xf6\\x66\\xc4\\x49\\x53\\x4f\\x7c\\xff\\xe2\\xd6\\xf4\\x0c\\xbf\\x67\\x73\\xd7\\x27\\x73\\xda\\xfb\\x80\\x7d\\x12\\xbc\\x64\\xee\\xfe\\xd2\\x3f\\x7f\\x76\\xba\\x67\\x67\\x5a\\xd5\\x89\\x85\\xf8\\x05\\xec\\x39\\x0d\\xdf\\xcc\\x4f\\x21\\x4d\\xa2\\x29\\xdd\\xc9\\x81\\x6b\\x45\\xbc\\x64\\x52\\xe9\\x09\\xa3\\xeb\\xb0\\xef\\xb1\\x7f\\xf9\\x34\\xde\\x61\\xe8\\x5f\\x3e\\x8d\\xfd\\xc8\\xdd\\x3f\\xf5\\xf4\\xf1\\x06\\xbd\\x93\\xf8\\x16\\xa5\\xb7\\x77\\x2d\\x71\\x2b\\xb2\\xe4\\x98\\x13\\xd6\\x16\\xc9\\xba\\xcb\\x63\\xa3\\x7d\\x49\\x62\\xfb\\x5c\\xb1\\x6b\\xa9\\x3a\\x24\\xf8\\xe7\\xb7\\xcc\\xb5\\x71\\x0a\\x05\\xc6\\xaa\\x25\\x7e\\xc4\\xcb\\x19\\x07\\x54\\x85\\x90\\xeb\\x0b\\xfb\\xec\\x36\\xde\\x38\\xae\\xe0\\x77\\xdc\\x29\\x81\\x40\\xdb\\xd8\\xb9\\x40\\x2f\\x67\\xf9\\xbd\\x8f\\x1d\\x08\\x2d\\xd6\\x37\\xf8\\x00\\x91\\x9a\\x25\\xd1\\x57\\x86\\x81\\x9b\\x65\\x72\\xc0\\x8e\\xd0\\xaa\\xa4\\xc2\\x4f\\x14\\xbb\\x2e\\x2b\\x09\\x55\\x1a\\x9c\\x76\\x9f\\x06\\xab\\x1a\\x18\\xf2\\x5e\\x6f\\xfd\\x8e\\x22\\x47\\x10\\x27\\x56\\x8c\\x5b\\xec\\xc8\\xfd\\x76\\x02\\xc6\\xb1\\xe3\\x11\\x50\\x2b\\x78\\x10\\xc2\\xf8\\x5b\\x42\\xc9\\xa7\\x6d\\x42\\xc9\\xde\\xe4\\x07\\xd8\\x01\\x77\\x63\\xfa\\x72\\x45\\xd7\\x66\\x2d\\x57\\x84\\x1f\\x2e\\x09\\xaa\\xf2\\x39\\x33\\x46\\x4c\\xe3\\xec\\xc4\\x1a\\xe1\\x7c\\x6d\\x7d\\xb2\\x3b\\x73\\xbc\\xef\\xe1\\x2a\\xbf\\x8d\\xc3\\xc5\\x42\\xb2\\xec\\x0e\\xfc\\x33\\x36\\xf4\\x7c\\x28\\xa4\\xca\\x78\\x38\\x90\\x2c\\x34\\x13\\x4f\\xdf\\x25\\xd1\\x1a\\x42\\x77\\x43\\xae\\xeb\\xce\\x5c\\x97\\x92\\x8b\\x7d\\xf0\\x60\\xfc\\x89\\xe8\\x3b\\x2b\\xdf\\xce\\x4f\\x0a\\x49\\x20\\x7c\\xcd\\x3a\\x9c\\xc5\\xce\\x83\\x2c\\xc4\\x62\\x36\\xed\\xe3\\x12\\x77\\x0d\\xde\\x5d\\xe6\\x96\\xc0\\x33\\xb1\\x98\\xb1\\x77\\x97\\x6b\\xae\\x31\\xac\\x3d\\x8c\\xda\\xa0\\x7d\\xf0\\xd0\\xb0\\x4a\\x4e\\x85\\x95\\x5b\\xa6\\xf0\\x00\\x17\\x79\\xae\\x95\\xb4\\xba\\xde\\x8c\\xae\\xc0\\x7a\\x5d\\x4e\\xdf\\x5d\\x5f\\x86\\xea\\xdb\\xb9\\x9d\\x8d\\xd8\\x44\\x1f\\x92\\x6f\\x39\\x2b\\x74\\x55\\x89\\xc2\\x12\\x5a\\x1e\\x2c\\x6f\\x68\\xb6\\x46\\x79\\x12\\x64\\x0f\\x18\\x5d\\xff\\x09\\xd4\\x27\\x52\\x94\\x4e\\x70\\x73\\x4f\\x3e\\xbd\\x3d\\x3d\\xff\\xf0\\x76\\x34\\x2f\\x7f\\x37\\xd3\\xb7\\x43\\xab\\x87\\x8d\\x11\\x43\\xd9\\x01\\xfc\\xe8\\xe9\\xa2\\x17\\xf1\\xb3\\xe8\\x84\\xc5\\xd7\\x36\\xc8\\x20\\x8c\\xe0\\x8f\\x3e\\x35\\x9b\\x7d\\x31\\x18\\xb5\\x00\\xb6\\x23\\xef\\x93\\xd2\\xda\\x0e\\x58\\xcd\\x29\\xfd\\x9a\\x93\\xe9\\xa9\\xa9\\x2a\\x5c\\x6d\\x5b\\x0b\\x31\\x48\\x6d\\x31\\x77\\xa6\\x86\\xf4\\x9e\\xd8\\xbd\\x0d\\x15\\xd9\\x04\\x1f\\x56\\x86\\x78\\xfc\\x03\\xd7\\x87\\x63\\x6c\\x97\\x49\\x56\\x57\\x31\\xb6\\xcc\\xd7\\xf1\\x32\\xfb\\x1e\\x0d\\x67\\x76\\xe6\\x56\\xf5\\x5a\\x2c\\x19\\x04\\x02\\x4f\\x75\\xed\\xce\\x53\\x9d\\x9f\\x0d\\x61\\x0b\\x98\\xfa\\x49\\x63\\x44\\x3d\\x22\\xb6\\xf3\\xe8\\xcb\\xd6\\x03\\xa0\\x6c\\x07\\x5c\\xc8\\xd0\\x70\\xdd\\x9a\\xd1\\xd7\\x11\\x34\\x9c\\xe4\\x35\\xde\\xd8\\x99\\x50\\x56\\x52\\x02\\x33\\xad\\xcc\\xda\\x45\\xa4\\x38\\xec\\x47\\x5f\\xb5\\x8e\\xf8\\x68\\xfd\\xd0\\xcc\\x5e\\x10\\xc0\\xfa\\x9c\\x49\\x77\\x6b\\xfa\\x1e\\x47\\xd7\\x06\\xf2\\x14\\x53\\x32\\x1f\\x72\\xb9\\x6a\\x5e\\x6a\\x08\\xd8\\x40\\x70\\xcb\\xec\\xa0\\xf1\\x72\\x2e\\xd5\\x33\\xbc\\x9d\\x85\\x54\\xe5\\xb6\\x75\\x68\\x19\\xc0\\xa0\\x45\\x2e\\x8a\\xd1\\x77\\x64\\xd0\\x0f\\x7e\\x43\\xee\\x35\\x29\\xc4\\xd2\\x20\\x0f\\x62\\xee\\x3f\\xec\\x74\\xf9\\xe6\\x4b\\xf3\\x4b\\x35\\xc4\\xb7\\x0c\\x17\\x65\\x5c\\x95\\x17\\x67\\xe0\\xaa\\x07\\x6f\\xbf\\x26\\xa5\\x47\\x70\\xf1\\xed\\x69\\xb7\\xd9\\x23\\x4b\\x43\\x0f\\xab\\xe7\\x3e\\xca\\x42\\xf5\\x91\\x79\\xee\\xcb\\xbd\\x23\\xcd\\x5c\\x68\\x49\\xe1\\x9f\\x01\\x6c\\x14\\xef\\xa8\\xd7\\x97\\xdd\\x7a\\x2c\\x78\\xcd\\xe7\\xc2\\x8a\\x1a\\x43\\xe0\\x28\\xa8\\x4e\\x51\\x76\\xc2\\x8f\\x0b\\xa1\\x2e\\x2d\\x2f\\xae\\xf7\\x8d\\xb2\\xfc\\xc2\\x71\\x1f\\x8e\\xe3\\xde\\xdb\\x15\\xe8\\x0f\\x02\\x41\\xae\\x2d\\x53\\x2f\\xb2\\x54\\xc4\\x85\\x9e\\x09\\x89\\x09\\x48\\x87\\x7d\\xac\\x1c\\x01\\xe9\\x2e\\xe7\\xae\\x11\\xf9\\x10\\x0d\\x1b\\x10\\xe9\\x16\\xa0\\x3b\\x21\\x82\\x1f\\x57\\x61\\x3f\\xdc\\xb0\\xfb\\x1d\\x20\\x12\\xb8\\x8b\\x1f\\x2d\\x69\\x9a\\x53\\x87\\xb9\\xfb\\x66\\x22\\x6d\\xbc\\xf7\\x46\\x58\\xb6\\x10\\xf5\\x5c\\x52\\x5a\\xb7\\x56\\xac\\xa0\\xb4\\x00\\xe0\\x6b\\x8e\\x87\\x51\\x77\\x09\\xcf\\x53\\x4c\\x17\\x96\\x53\\xce\\x0c\\x9b\\x08\\x7b\\x2b\\x84\\x62\\xaf\\x5e\\xbd\\x7a\\x05\\x72\\xc9\\xab\\x3f\\xfe\\xf1\\x8f\\x0c\\x60\\x26\\x4a\\x51\\xc8\\xf9\\xea\\x83\\xf0\\xd4\\xbf\\xbc\\x7e\\x3d\\x62\\xff\\x71\\xfa\\xe1\\x3d\\x44\\x95\\x2d\\xac\\x61\\x13\\x6d\\x67\\xd4\\xb3\\x7b\\x20\\x6b\\x6c\\x06\\xec\\xdf\\x2e\\x7f\\xfc\\x18\\x21\\x96\\xf2\\x5f\\x41\\x05\\x09\\xd3\\xcb\\x43\\x04\\x5f\\xfd\\xe1\\xbb\\xef\\x46\\xec\\x5c\\xd6\\x90\\x4f\\x2c\\x21\\x03\\x22\\x04\\x41\\x2e\\x7c\\x60\\x20\\xd4\\x34\\x6b\\x67\\xf0\\x13\\x07\\xa1\\x20\\xe1\\xb9\\xbc\\x9a\\xc1\\x02\\xb8\\x0b\\xa1\\xd5\\xb4\\x92\\x85\\x45\\xb8\\x52\\xbc\\xfa\\xb8\\xd0\\x04\\xbf\\xc3\\x29\\xdd\\x8b\\xa4\\x08\\x18\\xdc\\x80\\x55\\xf2\\x5a\\xb0\\xa9\\xf9\\xa1\\xd6\\xcd\\x22\\xa6\\x39\\xd6\\xc2\\x38\\x59\\xb6\\xe0\\x0a\\xb2\\x4a\\xa0\\xb3\\xb8\\x57\\x46\\xd8\\x27\\x0d\\xc2\\xe8\\x68\\x08\\xca\\xce\\x20\\xb4\\x69\\x09\\x28\\x83\\x00\\xdb\\x38\\xc4\\xf3\\xb0\\xe0\\x32\\x04\\x0e\\x82\\x4f\\x3d\\x2b\\x1a\\x12\\x74\\xcf\\x32\\x81\\xa9\\xf4\\xb9\\x2b\\x8b\\x5a\\xff\\x1d\\xb7\\x4a\\x2a\\x9f\\x05\\x45\\x12\\xb2\\x21\\x99\\x8c\\x92\\x4e\\x55\\x62\\x73\\xf5\\x59\\xf9\\x8e\\x17\\x52\\xc6\\x7f\\x92\\x3f\\x35\\x9e\\xa6\\x89\\x76\\x90\\x96\\x8e\\x95\\x1b\\x33\\x4c\\xdd\\x35\\x6f\\x8e\\x75\\x20\\xdc\\x69\\x32\\xb8\\xaf\\x8d\\x5a\\x69\\x4d\\x25\\x9a\\x88\\xfc\\x50\\xe1\\x2e\\x4a\\x61\\x8b\\x7d\\x60\\x28\\x2e\\x25\\x00\\x25\\xe5\\xe0\\x32\\x9c\\xcb\\x2c\\xca\\xc7\\x08\\xdb\\xd0\\xd2\\x40\\xe4\\x95\\x7b\\xb7\\x30\\x86\\xf2\\x88\\xe6\\xbc\\xbe\\x76\\x4a\\x02\\x51\\x81\\x11\\x44\\x3d\\x9b\\x90\\xc3\\x84\\x09\\x65\\x37\\x68\\x2c\\x9f\\xf3\\x65\\x96\\x35\\xe0\\x5e\\x72\\x38\\x1a\\x1d\\xe2\\x35\\xd1\\x35\\xc2\\x04\\xe3\\x99\\x77\\xdf\\x3f\\x51\\xbe\\x74\\x1e\\x95\\xce\\x17\\x58\\xd1\\x13\\xec\\x39\\x54\\x11\\x89\\x67\\xd1\\xce\\x9c\\x56\\xaa\\x0b\\x38\\x78\\xcf\\x8a\\xa8\\xfd\\x4a\\x6f\\x77\\x2f\\xb9\\x3d\\x84\\x09\\x74\\x78\\xb4\\x6f\\x79\\xed\\x1e\\x65\\xb5\\x37\\xa1\\x35\\xd0\\x1a\\xd3\\x4d\\xe8\\x5a\\x6c\\xb6\\x77\\x99\\x81\\x79\\x27\\xd6\\xb7\\x66\\xa8\\x87\\x73\\xe2\\x7c\\x3f\\xf6\\xe3\\x7c\\x94\\xaf\\x97\\xd5\\x1d\\x7c\\xfe\\xac\\x6e\\x3c\\xc5\\x4c\\x97\\x9c\\x74\\x11\\x69\\x48\\x45\\x81\\x50\\xe3\\x2f\\xa6\\xbd\\x3c\\x6b\\x8e\\x96\\x1e\\x9b\\x7e\\x35\\x2d\\xfa\\x70\\x37\\xfc\\x74\\x73\\x4c\\xe0\\x27\\x3b\\x6b\\xde\\x3b\\x81\\x93\\x26\\x52\\xba\\xc8\\x6a\\x07\\x55\\x68\\x37\\x00\\x19\\xd3\\x5f\\x9e\\x11\\xfb\\x40\\xa4\\x16\\x0f\\x19\\x9f\\x18\\x5d\\x35\\x16\\x9b\\xc6\\x1f\\x53\\x3a\\x0c\\x9d\\x7a\\x94\\x05\\x20\\xbe\\xe1\\xb1\\x84\\x2a\\xdb\\x58\\x3d\\xb1\\x1b\\x81\\xc6\\x4f\\x8f\\xcb\\xf9\\x02\\x24\\xfc\\x80\\x40\\xc2\\x01\\xfa\\xda\\x74\\x2c\\x05\\x67\\x1e\\x0c\\xb9\\xbb\\x30\\xb2\\x8f\\x7e\\x65\\x24\\x3b\\x8a\\x15\\x88\\xbc\\x3b\\x7e\\xac\\xac\\xa8\\xa7\\xbc\\x10\\xc7\\xa9\\xde\\x15\\x2a\\x3d\\x85\\x10\\x21\\x9f\\x17\\x31\\xe3\\xaa\\xac\\x50\\x00\\x2f\\x44\\x0d\\x67\\x5f\\x7c\\xb5\\xa2\\x76\\x4b\\x72\\x76\\x39\\x66\\x65\\x2d\\x6f\\x44\\x6d\\xd8\\xd1\\x1b\\xe1\\xe4\\x45\\xc4\\x4f\\xed\\x94\\x5d\\xb5\\xdf\\xd8\\x4a\\x18\\xc6\\xbe\\x34\\x3d\\xe8\\xac\\x6f\\xa8\\x1e\\x34\\xf2\\x94\\x47\\x25\\xf7\\x2b\\x2e\\x13\\xae\\x2a\\x2e\\xa9\\x49\\x75\\xd9\\x91\\x3b\\x4a\\x40\\xa0\\x81\\x66\\x2c\\x75\\x53\\x93\\x15\\xdd\\x43\\x36\\x17\\xba\\x76\\xea\\x12\\x76\\xcc\\x0d\\xab\\xc5\\x95\\x93\\x66\\x6b\\x5f\\xc7\\x5c\\xb0\\xa2\\x6a\\xdc\\x17\\x7b\\x0d\\x67\\xbb\\x4f\\x00\\x60\\x34\\xcd\\xde\\x15\\xab\\x37\\x25\\xa9\\x5a\\xdf\\xc8\\xd2\\xb3\\x4a\\x2c\\xab\\x1e\\x0a\\xa6\\x2e\\xb8\\x49\\x52\\x6d\\x92\\xe2\\x16\\xc9\\xc2\\xa2\\x8c\\x0e\\x0c\\x35\\x24\\xb1\\x66\\xc1\\xfe\\xa9\\x51\\x58\\x03\\xb6\\x45\\x87\\xca\\x34\\x7d\\x88\\xb0\\x2e\\xc5\\x45\\x33\\xa9\\xa4\\x99\\x5d\\xee\\x68\\x42\\x5c\\xd7\\x05\\x06\\x2b\\xac\\x78\\xfd\\x36\\x5a\\x12\\x8d\\x50\\x46\\x02\\xcb\\x73\\x64\\xdc\\x31\\x5d\\xe9\\xe4\\x28\\x0d\\x8b\\xe8\\x5b\\xa7\\x07\\x52\\x43\\xf6\\x47\\x25\\x08\\xc1\\xc0\\xfd\\xf4\\x31\\x8e\\x83\\x92\\xd2\\x10\\xb3\\xa4\\x14\\x5f\\xd4\\x22\\xfb\\xbe\\xe0\\x55\\x65\\xda\\x09\\xbb\\x9e\\x62\\xa2\\xec\\xe1\\x13\\xd5\\x70\\x4f\\xa5\\xdb\\xee\\x50\\x74\\xa9\\x05\\x8e\\xb9\\x71\\x62\\x86\\xcd\\x35\\xa6\\xf1\\x28\\x00\\xe7\\xc5\\x87\\x00\\x7a\\xc5\\x37\\x48\\x12\\x19\\x21\\x5d\\x19\\x8e\\xcc\\x9e\\xab\\xd2\\xbe\\x98\\x4b\\x1f\\xce\\x5c\\x7a\\xdf\\x38\\x3c\\x13\\x0a\\xd4\\xf1\\x24\\x1b\\x3a\\x83\\x25\\x0d\\xa4\\xd4\\x93\\xdc\\x2d\\x41\\x1d\\x7b\\x75\\x2b\\xe0\\x3b\\x4f\\xad\\xad\\xe5\\xa4\\xb1\\xfd\\xf1\\xde\\x5a\\xcd\\x81\\x4d\\x3b\\x45\\x04\\x6e\\xf1\\x90\\x66\\x5f\\x24\\x47\\x34\\x22\\xa7\\xe7\\xe4\\x33\\xde\\xfd\\xc8\\x73\\x80\\xdd\\xe0\\x97\\x87\\x86\\x95\\xba\\x68\\x02\\x6c\\x2c\\x2c\\x5a\\x74\\xa0\\x75\\x41\\x4f\\x64\\x7d\\xef\\x55\\x7f\\x48\\xaf\\xf4\\x25\\x5b\\x8f\\x57\\xa9\\x6f\\xd5\\x2d\\xaf\\xcb\\xd3\\x8b\\x2d\\xd1\\xf7\\x39\\x3b\\x8f\\xad\\x52\\x41\\xc9\\x7f\\x0d\\x05\\x46\\xf9\\x44\\x37\\x36\\x42\\x87\\xfe\\x7a\\xec\\xd5\\xeb\\xd4\\x74\\xab\\x1d\\x69\\xe8\\x68\\x8f\\xee\\xab\\xe8\\xbf\\x98\\xb8\\x5f\\x4c\\xdc\\xd9\\x67\\x17\\x13\\xf7\\x18\\x4d\\xdc\\x29\\x0e\\x6e\\x76\\x5d\\x3d\\xbc\\x82\\xac\\xba\\xc6\\xf6\\x3e\\xa4\\x95\\xf4\\x3c\\x12\\x18\\x94\\xa6\\xda\\x71\\xfc\\x2d\\x01\\x0e\\xaf\\x48\\xdc\\xdb\\x44\\xe8\\xf3\\x14\\x08\\x78\\xf6\\xd3\\x5b\\x54\\x1f\\xc8\\x4e\\xda\\xbd\\x04\\x3a\\x7e\\x36\\xd5\\x28\\xbd\\xab\\x24\\x3a\\x48\\x0d\\x49\\x0d\\xf3\\x01\\xa1\\x40\\x0f\\x48\\xef\\x52\\x65\\xac\\x0e\\x8a\\x20\\xd4\\x3d\\x2a\\x20\\xe3\\xa7\\xe7\\xe2\\xb3\\xde\\x1b\\xc0\\x7a\\xd6\\x27\\xc7\\x4f\\xdf\\xdd\\x60\\x3b\\xd4\\x2a\\xc7\\xcf\\x13\\x57\\x2c\\xc7\\x4f\\x6f\\xdb\\x37\\xeb\\x5f\\xbd\\x7c\\xcd\\x74\\x1f\\xb6\\x86\\xf9\\x8e\\x53\\xdb\\xdd\\xac\\xbf\\xab\\x39\\x7f\\x10\\x2b\\x67\\x3e\\x7f\\xb6\\xfe\\x62\\xce\\x5f\\xf9\\x3c\\xa2\\x39\\x3f\\x21\\xdc\\x9e\\x18\\xac\\x31\\xed\\xa7\\xe6\\x36\\x6f\\xdf\\x9f\\x08\\x2f\\x56\\x8e\\x22\\xfa\\x9a\\x3b\\x72\\xde\\xb2\\x1f\\xcb\\x35\\xa1\\x5b\\xf5\\x70\\x34\\x3a\\x3c\\xf4\\xf6\\x7e\\x3a\\x9f\\x8d\\x9d\\x0e\\xff\\xc4\\x84\\x2a\\x74\\x89\\x9b\\xea\\xfa\\xaf\\x8d\\x05\\xa6\\x1f\\xd5\\xf4\\x74\\x2c\\x73\\xff\\xae\\xd4\\x35\\x0b\\x7d\\xf7\\xdb\\x92\\x1e\\x37\\xd8\\x43\\x02\\xbc\\xbb\\x17\\x8b\\x8c\\x8c\\x31\\x40\\x0c\\xd0\\x04\\x03\\xaa\\x10\\x71\\xc8\\x58\\xdd\\x04\\x0b\\xfb\\x84\\x5a\\x5b\\x50\\x51\\xe4\\x08\\xbf\\x1c\\x15\\x8b\\x66\\x40\\x0f\\x8c\\xe6\\x62\\xae\\xeb\\xe5\\x20\\x3c\\xe4\\x7e\\xcc\\x5a\\xd1\\x13\\x88\\x3d\\x55\\x34\\x75\\x2d\\x14\\xd4\\x37\\x79\\xae\\xfc\\xd5\\x2f\\xc1\\x03\\xb2\\xd7\\xb0\\xea\\xdd\\xb2\\xdb\\xe2\\x27\\xdf\\xd6\\xe8\\x03\\x00\\x93\\x54\\xac\\x56\\x37\\x0d\\xc8\\x26\\x66\\x10\\xfd\\x1c\\xee\\x5b\\xa1\\x6e\\xd8\\x0d\\xaf\\x4d\\xd7\\x35\\x67\\xbb\\x72\\xd4\\x52\\xde\\x48\\xd3\\x05\\xf2\\x7f\\xc3\\xe4\\x2e\\x83\\xd9\\x07\\x60\\x07\\x1b\\xbb\\x68\\x2c\\x51\\x27\\x7f\\x76\\x3d\\x52\\x53\\x5e\\x74\\x2e\\x0a\\x0e\\xaf\\xef\\xaa\\xd3\\xd6\\xfe\\x3c\\xd3\\x42\\x32\\xf9\\xa7\\x53\\x59\\x99\\xfc\\xd3\\xaf\\xc8\\xcc\\xfa\\xb6\\x3d\\xb7\\xfe\\x1e\\xf5\\x9b\\xda\\x1f\\xbf\\xb5\\xbb\\xdf\\x91\\xc8\\x64\\x22\\x30\\x98\\x17\\xcc\\x1e\\xe0\\x12\\x80\\x31\\xfc\\x5c\\xf6\\x4a\\x45\\xf0\\x6d\\xf2\\x70\\x49\\x2b\\xe6\\x0b\\x5d\\xf3\\x7a\\xc9\\x4a\\xb2\\x35\\x2c\\xd7\\x64\\x84\\x26\\x29\\xa1\\xf7\\x86\\x86\\x81\\x71\\x94\\xb2\\xde\\x53\\x36\\x42\\x8f\\x6c\\x50\\x51\\xca\\x66\\x63\\x25\\xf8\\x4d\\xcb\\x86\\xad\\xd2\\x45\\xbb\\x05\\x34\\x30\\x42\\x12\\xf3\\xee\\x4e\\x7a\\xcc\\x03\\x2b\\xf2\\xe2\\x9a\\x2a\\x06\\xf9\\x55\\x45\\xde\\x9f\\x24\\xb9\\x1c\\x1c\\xb4\\x70\\xa0\\xc1\\x3c\\x06\\xbe\\x3f\\x2a\\xba\\xea\\x1f\\xc6\\xbe\\x33\\x53\\x16\\x7a\\x43\\x28\\x2c\\xe0\\x88\\x1e\\x3c\\x76\\x12\\xc9\\x07\\x60\\x83\\x8f\\xb4\\x4b\\xac\\x67\\x66\\x9b\\xfc\\x5f\\x01\\x05\\xc2\\x7a\\xc7\\xc6\\xfb\\x86\\x01\\x0e\\x5a\\x83\\x64\\x1e\\xca\\xa6\\x55\\xba\\x48\\x7c\\xcf\\x19\\x87\\x82\\x6d\\x78\\xeb\\x0f\\xbf\\xb7\\xdd\\xbb\\xcd\\x70\\xbd\\xa2\\x7c\\x01\\x46\\x9f\\xca\\xa0\\x5f\\x4f\\x16\\x00\\x6d\\x09\\x52\\x3c\\x2c\\x66\\xd8\\x80\\xcf\\x49\\x11\\xc1\\xc6\\xb8\\x37\\x01\\xf2\\x7c\\xf2\\x4c\\x7c\\xd1\\xad\\x47\\xd8\\xb4\\x49\\x9d\\xb7\\x5c\\xf7\\x70\\xbf\\x5c\\x86\\x99\\x45\\xbd\\x0d\\x52\\x20\\xbc\\xa0\\x6e\\x1a\\x10\\x13\\xe9\\x2d\\x24\\x2e\\xe9\\x29\\xf8\\xae\\x62\\x59\\xb4\\x00\\xee\\xb8\\x72\\xcc\\x94\\xac\\xf2\\x73\\xe6\\xb1\\xec\\xc2\\xc4\\x1b\\x45\\x81\\x06\\x8f\\x78\\x68\\x9e\\x31\\x1f\\xec\\xcc\\xfd\\xfa\\xf3\\xbc\\x9e\\x9c\\xee\\x1e\\xfc\\x2d\\xc4\\x63\\xf4\\xe0\\x10\\x07\\x31\\x88\\x23\\x63\\x11\\x29\\x3a\\x5e\\x1e\\xd0\\xc1\\x7d\\xcc\\x40\\xb8\\x79\\xde\\x33\\xf4\\x39\\x68\\xb8\\xc4\\x3a\\x8a\\x65\\x41\\x39\\xbb\\x32\\x43\\xbd\\xc4\\x6e\\xf1\\x00\\x42\\x7c\\xeb\\xd0\\xfd\\xc7\\x6b\\xc2\\xde\\xac\\x3f\\x11\\x53\\x1d\\x0b\\xa5\\xa0\\x62\\x44\\x51\\xb9\\xa5\\xa8\\x84\\x85\\x20\\x5b\\x11\\x00\\x4b\\xd1\\x33\\x3c\\xd7\\x37\\xee\\x4c\\xff\\x97\\x62\\x5f\\x3c\\x74\\xbf\\x9c\\x7e\\xcf\\xf8\\x71\\x96\\x09\\x41\\xc5\\x67\\x94\\x10\\x25\\x86\\xea\\x56\\xf1\\x3d\\x75\\xa3\\xcc\\x80\\x4d\\x8e\\x7d\\x58\\x0a\\x5c\\x3c\\xe5\\xa4\\xc3\\xca\\x0b\\xbe\\xa8\\x5e\\xd7\\xc2\\x2d\\x00\\x64\\x1f\\xd7\\x7a\\xce\\x8c\\xe2\\x0b\\x33\\xd3\\x16\\x34\\x44\\xbe\\xe0\\x85\\xb4\\x4b\\x66\\x6b\\x5e\\x5c\\x43\\xa5\\xa2\\x5a\\xd0\\xeb\\x06\\xac\\x38\\xa6\\xf8\\xae\\x74\\xf9\\xf2\\xe8\\x61\\x3b\\xab\\x75\\x73\\x35\\x83\\x80\\x58\\x7c\\xaa\\xa8\\xb8\\xf1\\xb3\\x5f\\xdb\\x9e\\x94\\x1e\\xc3\\x4a\\x2c\\x54\\x1c\\xc0\\x03\\x6b\\x7d\\x23\\x8d\\xd4\\x64\\xf4\\xf5\\xfd\\x5e\\x04\\x80\\x38\\x34\\x24\\x63\\xf9\\xdf\\x23\\x23\\x04\\x7b\\xeb\\x8f\\x04\\xfe\\x72\\x89\\xa2\\x0d\\x1a\\x38\\xea\\x3c\\x46\\x40\\x07\\x64\\x73\\x45\\xb8\\x08\\x91\\xce\\x05\\x1f\\x16\\xf2\\x4d\\x37\\xf2\\xb5\\x2f\\x3d\\x0e\\xdb\\xb5\\x7e\\x4c\\xba\\x06\\xff\\xbd\\x47\\xf0\\x14\\xaa\\xd4\\x89\\xf3\\xf2\\xf4\\x62\\x6c\\x52\\xa5\\x04\\xcf\\x16\\xc1\\xdf\\xc1\\x0f\\x95\\x56\\x57\\x29\\x9a\\x40\\x3c\\x99\\x8e\\xa2\\x2a\\xa8\\xf2\\x72\\x23\\xcb\\x86\\x57\\x48\\x4b\\x69\\x30\\x67\\x97\\x63\\x6c\\x2e\\xaf\\x66\\x76\\x78\\x2b\\xc0\\x28\\x83\\x2c\\x27\\xde\\x19\\xff\\x52\\xb9\\x12\\xb4\\x23\\x0d\\xd0\\x5e\\x4b\\x46\\x05\\x34\\x70\\xb9\\xa1\\xdd\\xf2\\x25\\xa0\\xd7\\x50\\xa4\\x49\\xe6\\x37\\xf5\\xf8\\x62\\xd8\\xc5\\xba\\x15\\x87\\xe1\\x9d\\x86\\xaa\\x1d\\x4e\\x7a\\x00\\xab\\x95\\x5b\\x62\\x38\\xa9\\xab\\x63\\x73\\x0b\\x9f\\xc0\\x01\\x86\\xaf\\xa9\\x40\\x1b\\x77\\x1b\\xe4\\x64\\xbc\\xbb\\x55\\x9a\\x07\\x90\\xcd\\x6e\\xe2\\x26\\x7f\\xa6\\x0a\\x8a\\x3d\\x65\\x84\\x83\\x9f\\x13\\xeb\\x59\\xe2\\xef\\x70\\xd7\\x86\\xab\\x72\\xc8\\x2b\\x77\\x72\\x2e\\x7e\\x3a\\xa3\\x40\\x67\\xbc\\x08\\x99\\x3f\\xdf\\x17\\x43\\x92\\x2a\\xa0\\x67\\x3b\\xd1\\x61\\xed\\x15\\x80\\x74\\xf8\\x89\\x28\\x81\\x68\\xa4\\x75\\x23\\x6f\\x9d\\xa2\\xec\\x8b\\x3b\\xff\\x74\\x36\\x60\\x72\\x24\\x46\\xfe\\xaf\\xf0\\xa8\\xa7\\x5a\\x56\\x5f\\x61\\x34\\x60\\x08\\xf5\\x84\\x73\\x07\\x43\\x49\\x6d\\x52\\x69\\xdb\\xbf\\xfd\\xab\\x1b\\xa4\\xfb\\xf5\\xcf\\xc3\\x7f\\x4d\\x40\\x47\\xff\\xfc\\x37\\xaa\\x24\\xfd\\xb7\\xd6\\xb7\\x69\\x48\\x59\\x00\\xdf\\xff\\x9b\\x2f\\xe3\\x4d\\xd0\\xd5\\x7f\\xa3\\x9a\\x5c\\x50\\xb8\\x7a\\x04\\x75\\xa9\\x6f\\x78\\x25\\x4b\\x3c\\x8d\\xf0\\xee\\x5a\\xfc\\xdd\\xdb\\x17\\x61\\x99\\x82\\x6d\\xa7\\xe0\\x56\\x28\\x20\\xd4\\x3e\\x37\\x43\\x69\\x8b\\xcd\\xa9\\x3a\\xad\\x1b\\xff\\x11\\x58\\x06\\x30\\xb7\\x6c\\xc0\\xac\\xd6\\x70\\x1d\\xf1\\xca\\x9f\\x2a\\x26\\x7c\\xc9\\x4e\\x9c\\x2b\\x2c\\x07\\xa7\\x78\\x35\\xcf\\x7b\\x5c\\xb7\\x6e\\x85\\x43\\x26\\xae\\x1b\\x07\\x8c\\xed\\x9f\\x95\\xb6\\xff\\x1c\\xb6\\xdf\\x47\\x6a\\x00\\x83\\xd1\\x8c\\xdf\\x68\\xe9\\x71\\xc8\\xdd\\x4d\\x51\\x58\\xd8\\x31\\x20\\x63\\x4f\\x96\\x6c\\x2e\\x8d\\xe5\\xd7\\x62\\xc4\\x2e\\x1d\\x6f\\x49\\x9d\\x62\\xb8\\x7a\\x8a\\x01\\x90\\xa5\\x28\\x59\\xa3\\xac\\xac\\xe0\\xd7\\xd8\\x8f\\x1b\\x72\\xca\\x73\\xc6\\x53\\x66\\x9a\\xc2\\xd1\\xd6\\x45\\x2d\\x86\\x9e\\x8b\\xd1\\x53\\x2b\\xb4\\x20\\xce\\x65\\x10\\x36\\x7b\\xc6\\x51\\x25\\x58\\x94\\xd0\\x14\\xd6\\x83\\x2b\\x3a\\x5e\\x2b\\xe1\\x5c\\x6e\\x9c\\x5a\\x15\\x91\\x73\\xc1\\x62\\x9a\\x11\\xfb\\x08\\xcc\\xaa\\xf2\\x9e\\x61\\xd4\\x4e\\xc8\\x8e\\xa9\\x44\\x21\\x8c\\xe1\\xf5\\x72\\x00\\xf8\\xee\\x32\\x60\\x82\\x53\\x04\\x0f\\x70\\xd4\\x39\\x57\\x88\\xae\\x5e\\x8b\\x42\\x2b\\x63\\xeb\\xa6\\xb0\\x58\\x6e\\x6f\\x52\\xeb\\x6b\\xa1\\x42\\xd4\\xe0\\x6a\\xb1\\xfb\\x18\\x46\\x03\\x6e\\x2f\\xcd\\x8a\\x19\\x57\\x57\\x49\\xb9\\x9a\\x39\\x2f\\x61\\xed\\xff\\x1a\\xa4\\x1c\\x3f\\x1f\\xb7\\x02\\x7c\\xea\\x04\\x0b\\x69\\x61\\x29\\x26\\x8e\\x8f\\x04\\x6b\\xec\\x7f\\xa9\\x00\\xcb\\x33\\x88\\xe6\\x52\\x37\\x25\\x59\\x6d\\xa1\\x5d\\xbd\\xe8\\x17\\xeb\\x69\\xdb\\x1b\\x02\\xdb\\xde\\x73\\x1c\\xd8\\x5c\\x58\\x5e\\x72\\xcb\\x77\\x88\\x05\\xfb\\x10\\x6b\\xec\\x91\\x1f\\x92\\xea\\x9c\\x06\\xff\\x24\\xf1\\x21\\x2f\\x6e\\xe9\\x85\\x4c\\xd3\\xa0\\xe0\\x26\\xce\\xfc\\xca\\x43\\xe2\\xb5\\x75\\x67\\x8a\\xfc\\x05\\x18\\xe2\\x05\\xf2\\x8c\\x2f\\x62\\xe6\\xba\\xf7\\xbd\\x21\\xb9\\x88\\x15\\x1a\\x23\\x39\\xe9\\xe6\\x8d\\xea\\x69\\x88\\x75\\x4b\\xbf\\xc3\\x1a\\x7d\\x8e\\x2e\\xb3\\x22\\x0f\\xf3\\x5a\\x2b\\x82\\x20\\x97\\x10\\xca\\xca\\x5a\\xa4\\x59\\x67\\xb4\\x74\\x8d\\xc2\\x43\\xde\\x5a\\x44\\x58\\xe5\\x2b\\x61\\x4d\\x0c\\x54\\x41\\x3a\\xec\\x88\\x0b\\xf1\\x3b\\xd2\\x49\\x81\\x48\\xd3\\xc2\\x92\\x5a\\xb7\\x5e\\x16\\xc2\\x65\\x37\\x9a\\xe8\\xac\\xa3\\xfc\\x0f\\xb2\\xae\\xbb\\xd8\\x9e\\xb1\\xaa\\xc0\\x07\\x5d\\xf6\\x31\\x57\\xb7\\xc0\\xf8\\x63\\x17\\x31\\x8c\\x13\\x03\\x72\\x0d\\xe8\\xf6\\xf8\\x00\\x38\\xad\\x4c\\x96\\x3b\\x87\\x44\\x6e\\xc6\\x6f\\x76\\xb7\\x55\\x45\\x19\\x69\\x18\\x10\\x8d\\xe1\\x75\\x43\\x78\\xdd\\xf0\\x75\\x77\\x9b\\x5e\\x9f\\x40\\x10\\xff\\xe9\\x1c\\x10\\x92\\xbf\\xa4\\x97\\x01\\xd5\\x91\\x94\\xcb\\x9e\\x56\\xcf\\x56\\x52\\x72\\xe8\\x81\\x68\\x3e\\x39\\x13\\x83\\x03\\x97\\x12\\x1e\\x84\\x74\\xd4\\xe2\\x7b\\xf6\\xcf\\x19\\x97\\x27\\x69\\x2a\\x68\\x4a\\x18\\xb0\\x7b\\xe4\\x55\\xa7\\x11\\x6d\\x85\\xcf\\x41\\xcf\\x1f\\x3f\\x6e\\x75\\x06\\xe2\\xc5\\x7a\\x8d\\xc2\\x07\\x06\\x07\\x91\\xcf\\x89\\x67\\x35\\xd8\\xd0\\x7c\\x1a\\x82\\x3b\\x5e\\xb5\\xae\\x2a\\x51\\xc3\\x14\\x48\\x7b\\x6a\\x39\\xd3\\x01\\xd2\\x14\\x4d\\xbb\\x83\\xa0\\xa2\\x06\\x19\\x53\\x89\\xdb\\x20\\x4c\\x70\\x83\\x08\\x2e\\xde\\xf1\\x25\\xa8\\x7e\\xde\\xc6\\xfe\\xa8\\xba\\x91\\xfb\\xfd\\x54\\x2d\\x71\\xf0\\xe7\\xc9\\xe2\\xa2\\xf2\\xc9\\xae\\xdc\\xab\\x9c\\xdc\\xa9\\xf8\\xa4\\x72\\x9c\\x2f\\xd9\\x80\\xf0\\x9e\\x16\\x29\\xb7\\x3a\\x79\\xea\\x93\\x98\\x92\\xd6\\x98\\x7e\\xd5\\xad\\x2d\\xf2\\x81\\xac\\xe1\\x28\\x46\\xb2\\xf8\\xe2\\x76\\x11\\xb9\\x84\\x56\\x3d\\x7b\\x24\\xf7\\x80\\xb7\\x7a\\xcb\\x12\\x6a\\xd7\\x8d\\xa0\\xb3\\x03\\x6f\\x27\\x17\\xde\\x2e\\x4e\\x3c\\xc8\\xfe\\x94\\xaa\\x4b\\xc4\\x54\\x6c\\x70\\x67\\x9d\\x93\\xf6\\x67\\x17\\xaf\\x1f\\x84\\xd5\\x80\\xb7\\xbf\\x9f\\x0b\\x27\\x2f\\xab\\x7e\\x31\\x86\\x2e\\xbc\\xee\\x70\\x05\\x7f\\x78\\xce\\x18\\x7c\\x1c\\x13\\xe1\\x6e\\x5f\\xcc\\xeb\\x86\\x7d\\x4f\\xdb\\xae\\x09\\x7c\\x88\\x57\\xe0\\xaf\\x00\\x1e\\x4b\\x46\\xed\\x50\\x18\\xad\\x16\\x10\\xb8\\x02\\x6f\\x1c\\x41\\xf5\\x04\\xae\\x96\\x24\\x71\\xd8\\x99\\xac\\xcb\\xe1\\x82\\xd7\\x76\\x89\\x6a\\xee\\x20\\x7b\\x5b\\xc8\\x06\\xe8\\x35\\xf1\\x1d\\xbd\\x4f\\xdd\\x90\\x9a\\x37\\xae\\x30\\x4c\\xde\\x5b\\xb3\\xc9\\x99\\xb0\\x71\\x5d\\x1f\\x63\\x3e\\xdd\\xf3\\x0d\\xd6\\xce\\x27\\x45\\x42\\xf5\\x9a\\xeb\\x93\\xcd\\x27\\xa3\\x2c\\xf7\\xe7\\x6f\\x8e\\x3c\\x99\\xdc\\x53\\x8c\\xec\\x2a\\xad\\xb4\\xa5\\xd3\\xa0\\xed\\x20\\x8d\\x80\\xe2\\xe6\\x7a\\x1a\\x38\\x7d\\x99\\xc7\\xd2\\xe8\\x89\\x01\\x92\\x24\\x1a\\x1f\\xf2\\x43\\x85\\x99\\xdc\\xa1\\x4f\\xde\\x92\\x36\\x0d\\xf7\\x83\\x1d\\x29\\xad\\xf0\\xce\\xe0\\xb3\\xc7\\x18\\xeb\\xb4\\xc1\\x7a\\x06\\x8f\\x04\\x6e\\x93\\xea\\x6a\\xc9\\x1d\\xf5\\x6c\\x4c\\xaa\\xd2\\x6d\\x1a\\x90\\x65\\xd0\\xe2\\x4c\\x53\\x14\\x42\\x04\\xbd\\x3f\\xad\\xa5\\x13\\xef\\x34\\x0d\\xd9\\xd7\\xe4\\x34\\x1a\\xd0\\x66\\x8c\\xe5\\x55\\x15\\xf5\\x6d\\x5a\\x28\\x0d\\x9c\\xd8\\xdb\\x28\\x13\\x06\\x9d\\x65\\x04\\x91\\xe9\\x01\\xaa\\xbd\\x63\\x7c\\x4e\\xa3\\x0a\\x8c\\x35\\x90\\x76\\x99\\xe2\\xf0\\x67\\xc2\\x08\\x28\\x3a\\x06\\xd5\\x70\\x39\\x45\\xcb\\x58\\xa2\\xb0\\x84\\xc5\\x04\\xa2\\x44\\xb5\\xe6\\x67\\xbe\\x62\\x0a\\x48\\xe1\\x04\\x22\\xe1\\x28\\xd0\\x84\\x17\\xd7\\xb7\\xbc\\x2e\\xa1\\xe6\\xf0\\x82\\x5b\\x89\\xf8\\xe5\\x03\\xe4\\x8a\\x29\\x93\\x53\\x87\\x87\\xa9\\x2b\\x47\\xaa\\x36\\xff\\x4d\\x07\\x72\\x94\\x8c\\x7a\\x85\\x2f\\x1f\\x07\\x7e\\x6c\\x44\\x40\\xd7\\x8e\\x03\\x63\\xbc\\xb1\\x7a\\xce\\xad\\x2c\\x40\\x3d\\x97\\xd3\\xc4\\x32\\x3a\\x0f\\x68\\x8d\\xad\\x8a\\x8a\\x40\\x91\\x43\\x6d\\xfe\\x9f\\xdb\\x83\\xbf\\x73\\xe0\\xc9\\x58\\xfd\\x34\\xd7\\x8f\\x2b\\x21\\xea\\xa1\\x72\\x3f\\x78\\xb4\\xc0\\x82\\x5f\\x0b\\xc1\\xe4\\xdc\\x09\\x58\\x1c\\x0a\\x92\\x4c\\x43\\xde\\x95\\x37\\x17\\xdf\\xb5\\x28\\x4e\\x8a\\xfc\\x19\\x6c\\xf4\\xc9\\x53\\x68\\x63\\x70\\x1a\\xa8\\x61\\xf6\\x56\\x07\\x75\\x2e\\x5a\\x42\\x29\\x71\\x69\\xd0\\x12\\x39\\xa8\\x8d\\xbb\\x6a\\x6e\\x59\\x92\\x7b\\x34\\x70\\x67\\xe7\\x56\\x54\\x95\\xfb\\xff\\x5d\\xb7\\xc9\\x8c\\xd6\\x8d\\x08\\x2b\\x03\\x1b\\x56\\x4a\\xd3\\x2a\\xef\\x7d\\x54\\xd6\\x7a\\xb1\\x20\\xfb\\xd2\\xfc\\xb8\\x3d\\x22\\x70\\xbb\\xd4\\x37\\xc2\\x24\\x15\\xac\\x51\\x66\\xbb\\x12\\x2a\\x94\\x60\\x27\\x50\\x10\\x20\\x28\\xed\\x57\\x64\\xdb\\xb8\\x76\\x70\\xe9\\x72\\xa1\\x11\\xfb\\xee\\xe5\\xa1\\x5f\\x41\\x17\\x75\\x2b\\xe5\\x0f\\x8c\\x19\\x61\\xd2\\xee\\x31\\xfb\\x42\\x85\\x9f\\xc2\\x9d\\x0d\\x91\\x91\\x9d\\x64\\x5a\\x34\\x85\\x91\\x58\\x3b\\x62\\x47\\xa7\\xd5\\x62\\x96\\xf4\\x9a\\x4a\\x91\\x21\\xe2\\x3a\\x1f\\x69\\xf6\\xbe\\xb3\\x5a\\x1b\\xf3\\xd1\\x37\\xe9\\xf3\\xea\\x17\\x09\\xb3\\xe3\\xe7\\x45\\xc2\\x7c\\x91\\x30\\x7f\\xdb\\x12\\xa6\\x9f\\x0f\\xd0\\x98\\x7b\\x4e\\x2a\\xb0\\xdf\\x9c\\xd6\\xdd\\x35\\x3d\\xf6\\x51\\x5b\\x72\\x8b\\x80\\x08\\xc2\\x37\\x6a\\xda\\x1c\\x08\\xdd\\x2d\\x5f\\x8e\\x94\\xb0\\x94\\xcd\\xeb\\x8d\\x2a\\x9f\\x7c\\x7f\\x3f\\xd4\\x8e\\x19\\x93\\xec\\x96\\x1c\\x73\\x7f\\x67\\x7c\\x1e\\x71\\xf2\\x16\\xab\\x91\\x3f\\x44\\x2f\\x0d\\x7c\\x7f\\x68\\xc8\\x47\\xe1\\x7e\\x87\\x58\\xfa\\xb4\\x83\\x42\\x8c\\xd8\\xa5\\xf0\\xa0\\x9e\\xd9\\xcb\\x57\\xb3\\x46\\x4b\\x61\\xb9\\xac\\x4c\\x64\\x08\\x9f\\x37\\x30\\x98\\xdd\\x09\\xfe\\x43\\x9f\\x92\\x10\\x33\\xba\\xab\\x0e\\x12\\x03\\xa5\\x93\\x90\\x8c\\x34\\xa2\\x28\\x3e\\xb0\\xc9\\x04\\x3a\\x9e\\xb2\\x4f\\xa2\\xd0\\x37\\xa2\\xc6\\x95\\x81\\xea\\xc1\\x4e\\xce\\x7e\\xc7\\x65\\xe5\\xd6\\xc5\\xaf\\x4f\\x34\\x2d\\x01\\x2c\\x73\\x6e\\xd8\\x4f\\xec\\x79\\xe1\\x50\\xd2\\x26\\xcc\\x69\\x50\\x94\\x2e\\xec\\x9e\\x27\\x17\\xfb\\xa2\\x16\\x37\\x52\\x37\\xc6\\xc7\\x3d\\x35\\x16\\x89\\xb1\\xb1\\x24\\xd9\\xce\\xe4\\x55\\x40\\xf7\\x0f\\x81\\x12\\xb5\\x28\\x74\\x5d\\xc6\\xc3\\x67\\x2c\\xb7\\x8d\\xc9\\x93\\xad\\x0a\\xb4\\xc5\\xef\\xcf\\xbc\\x1b\\xd6\\xf1\\x81\\x65\\x80\\xdd\\xf8\\x2d\\x4c\\xb7\\x57\\x8b\\xb6\\x77\\x1c\\x64\\x56\\x03\\x79\\x8d\\x09\\x9d\\x49\\x69\\x0c\\xc6\\x35\\x4b\\x85\\x0b\\xef\\x36\\x7b\\xe4\\x7f\\xc2\\xc6\\x83\\xb8\\xc7\\xd1\\x6d\\x29\\x4d\\x52\\xe6\\x3f\\xf8\\x00\\x25\\x48\\xa9\\xdc\\x5d\\xdb\\x44\\x1d\\x0b\\x97\\x16\\x8e\\x99\\x17\\xee\\xce\\x51\\xff\\xfb\\x44\\xef\\x3a\\xad\\x9c\\x4c\\x8a\\x44\\x20\\xb9\\xb8\\x6b\\xfc\\x8b\\x72\\x3e\\x6f\\xac\\x3b\\xaf\\x23\\x36\\xc6\\x4c\\x16\\x90\\x6c\\x49\\x61\\x9a\\xc6\\xec\\x0c\\x51\\x9b\\x0e\\x5e\\xc1\\xf4\\xb3\\x8b\\xd1\\x9e\\xed\\x62\\xb8\\x5f\\xd9\\xa8\\x4f\\xe9\\x92\\xa7\\xa8\\x14\\x4e\\xbb\\x03\\xdf\\xbc\\xdb\\x1d\\xef\\xbb\\xcf\\x9e\\xee\\x90\\x56\\xbf\\x6e\\x96\\x3d\\x0f\\x30\\x7e\\x76\\x11\\x65\\xf1\\xd3\\x53\\x3e\\xc5\\xcf\\x6e\\xb7\\x06\\x3f\\xfd\\xa5\\x0e\\xfc\\xac\\xca\\x1e\\xad\\x22\\xfe\\x5e\\x06\\xc9\\x76\\x66\\xa1\\xcb\\xd1\\x9a\\xbb\\x13\\xe2\\x38\\x74\\x49\\x41\\x1a\\xb9\\xfd\\x05\\x53\\xbe\\xc6\\xae\\xfb\\x6b\\x1f\\xb8\\x14\\xe8\\x2c\\x95\\x4c\\xab\\xc0\\x92\\x22\\x4b\\x81\\x28\\xb7\\x74\\xe7\\x76\\x98\\xd9\\x8e\\xe2\\x4e\\x2b\\x20\\xd1\\x91\\x92\\xe1\\x9c\\x2f\\x86\\xd7\\x62\\xd9\\x7b\\x5b\\x76\\x38\\x05\\xab\\x2f\\xc7\\x79\\xcc\\xf9\\xa2\\x47\\x3f\\x18\\x40\\x7b\\x0f\\x4a\\x7a\\xf8\\x1e\\x43\\x70\\xf1\\xcb\\x09\\x31\\x5e\\x1f\\x15\\x1c\\x23\\x92\\x0b\\x3d\\x5f\\x34\\x56\\x24\\x0c\\x9a\\x58\\x69\\x6f\\xae\\x95\\x81\\x90\\x9c\\x60\\x1d\\xbd\\x61\\xe8\\x76\\x18\\x89\\x5c\\x87\\x02\\x38\\xe9\\x67\\xe7\\xeb\\xbf\\x2b\\xde\\x46\\xfa\\x79\\xc6\\x01\\xc0\\xad\\xc9\\xf6\\x4f\\x86\\x61\\xf7\\x4c\\x88\\x61\\xf7\\x49\\x8a\\x61\\xfb\\x4c\\x8c\\x61\\x21\\xbd\\xee\\x3e\\x37\\xe6\\x93\\x4f\\xec\\x6b\\xdd\\x19\\x12\\x61\\xef\\xba\\x33\\x19\\xbe\\x53\\xe8\\x47\\x1a\\x5f\\x90\\x9b\\xc2\\xcb\\xc2\\x1d\\x00\\xd7\\x6c\\x9a\\x9e\\x45\\xb7\\x15\\x6c\\xd6\\x18\\x43\\x26\\xbe\\x86\\x22\\x0c\\x89\\x9a\\x04\\xda\\xff\\xad\\x34\\xa8\\xd8\\x28\\x26\\xe7\\x0b\\x04\\x66\\x84\\x5b\\x37\\xf4\\x92\\x11\\xd9\\x84\\xc3\\x48\\x0a\\x88\\xa5\\x61\\xe2\\x2b\\x58\\xc6\\xf1\\x65\\x2f\\x17\\x9c\\xbd\\x5c\\xf0\\xce\\xed\\x9f\\xf2\\x82\\x63\\x7e\\x5a\\x9f\\xf4\\xc9\\x56\\x5d\\x47\\x6c\\x4e\\x90\\x29\\x7c\\x22\\x2a\\xf6\\x4b\\x23\\xea\\x25\\x73\\xda\\x66\\x8c\\xc2\\x86\\x62\\x14\\x4e\\x70\\xc1\\x38\\x66\\xf2\\x2c\\x75\\x97\\x5c\\x1e\\x51\\xd1\\x02\\xe9\\xee\\xed\\x57\\xa7\\x6a\\x03\\xea\\xc0\\x3d\\xc8\\x5e\\xbb\\xab\\x1c\\x58\\x06\\x57\\x2b\\xac\\x60\\xaa\\x4a\\x63\\x20\\x58\\xa6\\x5c\\x3b\\x9d\\xeb\\xf4\\xe3\\xf9\\x6e\\x16\\x8b\\xa7\\x50\\x63\\x4e\\xef\\x98\\x20\\x2e\\x44\\xf8\\x25\\xaf\\xfd\\x19\\x5c\\x1e\\xec\\x5a\\x2c\\x07\\x14\\xae\\x48\\xb5\\x76\\xfc\\xc3\\x18\\x75\\x9b\\x03\\xc0\\x77\\x05\\x16\\x5b\\xb7\\x40\\x8f\\xae\\x01\\x75\\x85\\x0c\\xcf\\x5b\\xf9\\x45\\x78\\x44\\xdd\\xa9\\x07\\xb4\\x78\\xfa\\xd9\\x04\\x33\\x8e\\x67\\x02\\xf0\\x92\\x7d\\x16\\x5a\\x38\\x06\\x90\\x79\\x07\\xd4\\xe2\\x51\\x55\\x1a\\x06\\xc8\\xbe\\xb8\\xb0\\xf7\\x9e\\x6a\\x38\\xa6\\x59\\xfe\\xd4\\xb5\\x58\\x1e\\x1a\\xc2\\x78\\xd0\\xca\\xcc\\xe4\\xc2\\x57\\xf3\\x01\\x4a\\x40\\x27\\x97\\xfd\\x04\\x61\\x9c\\xbe\\x0b\\xbc\\xf3\\x63\\x35\\x60\\x1f\\xb5\\x75\\xff\\x7b\\x0b\\x11\\xdd\\x70\\xd6\\xcf\\xb5\\x30\\x1f\\xb5\\x85\\x6f\\x1e\\x7d\\xb1\\x70\\xb8\\xf7\\x5e\\x2a\\x72\\x87\\x92\\xa1\\x08\\x32\\x0f\\x20\\x9b\\xd6\\x47\\x0a\\xc3\\x92\\x50\\x10\\x59\\x58\\x56\\x69\\xd8\\x58\\x31\\x5d\\xfb\\x35\\xb1\\xbe\\xd4\\x83\\xa1\\x2e\\xbc\\xab\\x27\\x71\\x72\\xaf\\xe9\\x83\\x96\\x52\\xd7\\xd9\\x4a\\xde\\xd1\\x5d\\x70\\x63\\x4b\\xff\\x0b\\xd8\\xc8\\x21\\x24\\x21\\x84\\x37\\x43\\xc1\\x02\\x6e\\xc5\\x95\\x2c\\xd8\\x5c\\xd4\\x57\\x80\\xe6\\x51\\xcc\\x76\\xdf\\xa0\\xfe\\x74\\x1b\\x3f\\x3b\\x51\\xef\\xf4\\xc5\\xbd\\x4f\\x06\\xb0\\xba\\xf7\\x10\\x60\\x7e\\x5f\\x86\\x89\\xbd\\x20\\x8b\\x98\\xf3\\x85\\x3b\\x14\\xff\\xe7\\x38\\x01\\xec\\xcb\\x3f\\xa0\\xc0\\x88\\x19\\xb1\\x53\\x5f\\x9e\\x3e\\xfd\\x8d\\xcc\\xc5\\x69\\x37\\xae\\x07\\x27\\xf2\\xff\\xd2\\xc8\\x1b\\x5e\\x09\\x4c\\xbb\\xe0\\x2a\\x80\\xae\\xeb\\xe9\\x0a\\x9b\\x1e\\x50\\x95\\x11\\x47\\xa5\\x82\\x79\\xe6\\xe0\\x5a\\x2c\\x0f\\x06\\x2b\\x07\\xe9\\x60\\xac\\x0e\\x22\\xa4\\x4e\\x76\\x74\\x02\\x43\\x03\\x9b\\xe4\\x01\\xfc\\x76\\xb0\\x6f\\xce\\xfe\\x44\\xa2\\xfd\\x0e\\xa7\\x84\\x2c\\xef\\x67\\x15\\x47\\x4f\\xcd\\xae\\xfe\\x90\\x76\\x3f\\xeb\\xe0\\xb2\\x2f\\x93\\x67\\xa2\\x27\\x8b\\x92\\x6c\\xf6\\xee\\x38\\x80\\x64\\xcc\\xfe\\x01\\xe1\\xbd\\x56\\xef\\x86\\x6a\\xdd\\x75\\x87\\xd9\\x5a\\x0b\\xff\\x0a\\x20\\x53\\x3e\\xd5\\x36\\x43\\x31\\x88\\xb1\\x68\\x1b\\xd6\\xeb\\x27\\x70\\xe0\\xe8\\x29\\x7b\\x17\\x61\\xb0\\xc1\\x04\\xef\\x98\\x36\\x25\\xdf\\x3a\\x45\\x58\\xaa\\xa2\\x6a\\xc8\\x77\\x03\\x4d\\xd1\\x91\\xf0\\xf0\\x8b\\x73\\x8f\\x43\\x15\\x3b\\xf0\\xa7\\xc9\\xc7\\xbe\\xad\\xe4\\x59\\xb5\\x23\\x81\\x20\\x30\\x2c\\xc4\\xbe\\xe0\\x5a\\xed\\x7b\\xae\\xd3\\x2d\\x59\\x2d\\x39\\x74\\x7a\\x91\\xcb\\x1e\\xef\\xe4\\xa4\\x16\\xec\\x6c\\xc6\\x95\\x12\\x55\\x82\\x4d\\x42\\xb6\\x90\\x50\\x7c\\x14\\x04\\x12\\x2a\\x39\\x7a\\x98\\xd7\\x1c\\xf5\\xf4\\x4d\\x05\\x24\\x9c\\x98\\x74\\xb6\\x27\\x98\\xfe\\x5f\\x53\\x09\\xd0\\xcd\\x48\\xf5\\x7d\\x8b\\x7f\\x22\\xb0\\xf6\\x4c\\xdf\\xb2\\x52\\xb3\\x5b\\xa8\\x32\\x75\\xe3\\x98\\x16\\x04\\x7f\\x19\\xcf\\xee\\x92\\x91\\x42\\x9c\\x68\\xa1\\xe7\\x8b\\x5a\\xcf\\x65\\x08\\x9e\\xa2\\x6d\\xdc\\x2b\\x90\\x47\\xd5\\x74\\x40\\x6c\\xcc\\xf7\\xa0\\x6a\\x54\\x5e\\xc0\\xe7\\xdd\\x19\\xb3\\xbc\\xbe\\x12\\xd6\\xf5\\xc6\\x54\\x33\\x9f\\x88\\xce\\x68\\x23\\x0f\\x81\\x18\\xfb\\x2d\\x15\\x7c\\xdf\\x6f\\xc9\\x52\\xdc\\x86\\x9f\\x7f\\xfe\\xd8\\x17\\x30\\xf7\\x30\\xb6\\xdc\\xb4\\xb7\\xb7\\xba\\xae\\xca\\x5b\\x59\\x7a\\x87\\xf3\\x91\\x7b\\xf8\\xb8\\xeb\\xf8\\xf7\\x8c\\x9f\\xdb\\xe3\\x84\\xdf\\xde\\xca\\xb2\\xf7\\x72\\x40\\xa3\\x7c\\x19\\x7c\\x18\\xb8\\x5b\\x06\\x06\\xeb\\x40\\xf5\\x38\\x25\\x14\\x3d\\x81\\x16\\xc7\\xec\\xad\\xc4\\x24\\x70\\x68\\x0f\\x8e\\xeb\\xf9\\x44\\xaa\\x08\\x04\\x10\\x97\\xd9\\x11\\x63\\x77\\x5f\\xbc\\x6a\\x62\\x84\\xc5\\xf4\\x5d\\xc8\\x9c\\xd1\\x76\\xc6\\x8c\\x9c\\x37\\x95\\xe5\\x4a\\xe8\\xc6\\x54\\xcb\\xce\\x47\\xe5\\x69\\x96\\x7a\\x5a\\x89\\xaf\\x78\\xb2\\xfb\\x30\\xb9\\xd0\\x28\\x67\\x76\\x10\\x22\\x1b\\xd1\\x2e\\x56\\xb8\\x5d\\x8c\\x30\\x2f\\x4f\\x02\\xe7\\x0b\\x59\\xe1\\xe2\\xab\\x28\\x28\\x79\\x6b\\x51\\x35\\x57\\x72\\x4b\\x96\\xea\\x6f\\xac\\x06\\x4d\\x2c\\xf7\\xd1\\x18\\x11\\x71\\x95\\xba\\x56\\xe1\\x7b\\xa4\\x92\\x31\\x4f\\xcb\\xe1\\x3f\\xaf\\x2f\\x17\\x53\\x8a\\x85\\x50\\x25\\x00\\xd8\\xbe\\x8b\\x27\\x17\\x07\\xbf\\xd7\\x95\\x23\\x30\\xd8\\xbe\\x54\\xcb\\x63\\xc8\\x66\\x14\\x3c\\x09\\x4f\\x98\\xe9\\xaa\\x34\\x4c\\x7c\\xb5\\x35\\x77\\x84\\x69\\xee\\x48\\x50\\x68\\x33\\x65\\x5c\\x75\\x27\\x32\\xcf\\xa3\\xa0\\x03\\xdb\\x3b\\xb7\\x7f\\xd8\\xea\\xe6\\xcf\\xb1\\x40\\x79\\x9c\\x7b\\xf6\\xf5\\x9e\\x0b\\x0d\\x21\\x21\\xa6\\xbb\\x62\\xf2\\x04\\xa9\\x35\\x05\\x81\\x62\\x00\\xeb\\x6a\\x26\\xea\\x8e\\x85\\x81\\xcc\\x9a\\x12\\x28\\xad\\x51\\xbd\\x14\\x55\\xff\\x26\\xaa\\x04\\x4d\\x01\\xbf\\xa5\\x0f\\x64\\x26\\xb5\\x68\\x69\\xd4\\xf4\\xa5\\x2f\\x4e\\xdc\\x41\\x83\\xa6\\x73\\x9b\\xf0\\x01\\xb7\\xea\\xbe\\x23\\xca\\x3e\\x67\\xc6\\xad\\x65\\x0c\\xf5\\x6e\\x94\\xda\\x46\\xc5\\x1e\\xa2\\xe6\\x0b\\xb7\\xdc\\x08\\xdb\\xcd\\x9a\\x92\\x8b\\x0e\\xb1\\xa5\\xbb\\x80\\xe9\\xf9\\xa2\\x9f\\xb0\\xe6\\x10\\x64\\xe5\\x79\\x4c\\x13\\x36\\xfc\\x33\\x49\\x19\\x2a\\x7b\\xd2\\xc9\\x17\\x7e\\x7d\\x3c\\xa4\\xa6\\x08\\x5e\\x64\\xec\\xa3\\x74\\xbb\\x52\\x70\\xdb\\xb9\\x40\\x62\\x27\\xbe\\x40\\x23\\xf8\\xf2\\xa5\\x77\\xe5\\xfd\\xa4\\xa5\\x97\\x43\\xe0\\xdf\\xf9\\x22\\x8c\\x42\\x80\\x6c\\xa3\\xe4\\x2f\\x4d\\xaa\\x0e\\x00\\x06\\x59\\x98\\x36\\x3d\\xbf\\xaf\\xb9\\x5d\\x15\\x22\\x1a\\xaf\\xce\\xa5\\xb9\\xee\\x03\\x1d\\xbb\\xd2\\x38\\xbf\\x12\\x3f\\x9c\\xbd\\x65\\xf4\\x6d\\x27\\xfb\\x52\\x1f\\x03\\xd3\\x7d\\x21\\x29\\xaf\\x0a\\x11\\x8d\\xb6\\xa5\\x34\\xd7\\x7b\\x82\\x9d\\xed\\x2e\\xd5\\x2f\\xca\\x8f\\xdb\\x42\\x1d\\x1f\\xcf\\xfe\\xd5\\x96\\x7a\\x3d\\x92\\x5e\\x02\\xf1\\xb8\\xd4\\x0d\\xbb\\x25\\x84\\x2a\\x92\\x9a\\x3f\\xcb\\xc5\\xf7\\xec\\xad\\x32\\x4d\\x2d\\xa2\\xe7\\xb6\\xdd\\x95\\xe3\\xba\\x9d\\x65\\x68\\x00\\x01\\x33\\xdf\\xef\\xcd\\x56\\xb6\\xef\\x53\\xf2\\x9c\\x8d\\x6f\\x0b\\x5e\\x5b\\x10\\x8f\\xfb\\x1e\\x83\\xd0\\xd0\\xd3\\xa7\\xe4\\x0b\\xd5\\xe5\\x1c\\x8c\\xa7\\x3e\\xee\\x6e\\x40\\x50\\x3c\\x01\\x66\\xd6\\x3f\\xe4\\x76\\x3e\\x41\\x9f\\x4b\\xf7\\xfa\\x5d\\x40\\x66\\x64\\x27\\xa5\\xb8\\x39\\x31\\x25\\x7f\\x3d\\x80\\xd7\\xf8\\xcc\\x92\\x7c\\x4c\\xdc\\xb0\\x83\\xd7\\x07\\x23\\x76\\x29\\xe7\\xb2\\xe2\\x75\\xb5\\xcc\\x0a\\x67\\xc4\\xe7\\x1c\\xb3\\xf0\\x1d\\x82\\x57\\xee\\xd5\\x01\\x3b\\xd2\\x35\\xf4\\x5c\\x70\\xc5\\x2a\\xe1\\xd3\\xba\\xe9\\x9e\\x2d\\x51\\x76\\x3c\\x7e\\x6c\\xe2\\xc2\\x1e\\xd4\\x7e\\x89\\x74\\xa6\\xf7\\x99\\x28\\x3d\\xc7\\x26\\x7e\\x94\\xa1\\x0e\\x9e\\x47\\x92\\x2e\\x95\\xa3\\xf3\\x23\\xf6\\x85\\x08\\x34\\xf1\\x2d\\xdc\\x34\\xb8\\x32\\xfe\\x89\\xa7\\x5a\\xd4\\xc7\\xd1\\xfb\\x76\\xd2\\xe0\\x56\\xcd\\xc1\\x4f\\xb7\\x4c\\xdb\\xb5\\xc4\\x2b\\x69\\x3f\\x89\\x85\\xee\\x25\\x21\\x60\\x93\\x96\\x3d\\x4e\\x5a\\xf7\\x85\\x36\\x12\\x60\\xe5\\xb9\\x65\\x1c\\xaf\\x6d\\xd1\\x54\\xdc\\x89\\xd5\\x68\\x8d\\x1b\\xb1\\xf3\\xb7\\x17\\x9f\\xde\\x9e\\x9d\\x7e\\x7e\\x7b\\xfe\\x3d\\xfb\\x81\\x7a\\x92\\xa9\\x84\\x37\\x62\\x9f\\x53\\xd0\\xce\\x24\\xe0\\x97\\x90\\x11\\xc3\\xbb\\x06\\x44\\x86\\xb8\\x8a\\x50\\xdc\\x00\\xc5\\xc6\\x15\\x1b\\x2b\\x69\\x63\\x31\\x0b\\x8c\\x3b\\xab\\xb4\\x12\\xbe\\xd6\\xfb\\x42\\x93\\x35\\xf0\\x4a\\x5a\\x82\\x28\\xc2\\xce\\xdc\\xcf\\x79\\x6f\\x94\\xcb\\xe1\\x44\\x99\\x98\\x8a\\xf1\\xe8\\xa2\\x45\\x5c\\xdc\\x7d\\x89\\xff\\x1e\\xad\\xbe\\xaf\\xec\\x1b\\x6a\\x07\\xf8\\x7c\\x63\\xb4\\xfe\\xc7\\xef\\x91\\x19\\x84\\x32\\x3a\\x1e\\x95\\x50\\xd7\\x59\\x95\\x1b\\xa8\\x81\\xef\\xd8\\xcc\\xe1\\xe8\\xd0\\x0b\\x14\\xd5\\x4a\\xc9\\xa4\\xd0\\x69\\x0a\\xbc\\x9a\\x1f\\xb6\\x11\\x63\\x3f\\xfa\\x88\\x6e\\x40\\x5e\\x59\\x5f\\x7d\\x09\\x41\\xbc\\x92\\x1a\\x3e\\xad\\x23\\xeb\\x33\\x10\\x9b\\x49\\xfa\\x52\\x42\\x6a\\xbd\\x92\\x37\\x84\\x9f\\xb1\\x57\\x2b\\x5e\\x7c\\x7d\\xef\\x5a\\xb6\\x71\\xdc\\xa4\\x7f\\x7c\\x7a\\xbf\\xdf\\x91\\xe1\\xfd\\xeb\\x3d\\x2e\\xba\\xb6\\x34\\xaa\\x42\\xcf\\xe7\\x08\\xeb\\x39\\x0b\\xf9\\xfe\\x31\\x65\\x3f\\x50\\x85\\xbd\\x69\\x3e\\x08\\x50\\x3a\\xdd\\x72\\xf8\\x5b\\xf4\\xcc\\x37\\x6a\\x69\\x3a\\xe1\\x6b\\xca\\x59\\x50\\x51\\xcc\\xed\\x5f\\x35\\x83\\xb0\\x70\\x8d\\x4f\\xc7\\x26\\xd2\\x7e\\x12\\x5e\\x7e\\xf2\\xe9\\xed\\xe9\\xf9\\x87\\xb7\\xa3\\x79\\xf9\\xe8\\xa4\\x45\\xa8\\x72\\xa1\\xa5\\xb2\\x66\\xbb\\x7e\\xb3\\xad\\x46\\x60\\x77\\xf2\\x13\\x5e\\xda\\x97\\x3b\\x87\\x86\\xfe\\x8c\\xf9\\x2f\\x12\\xf8\\x60\\x4a\\x27\\x4f\\xf6\\xd0\\xea\\x85\\xae\\xf4\\xd5\\xfa\\x62\\x19\\x3d\\x36\\xe7\\x77\\x08\\x03\\x38\\xe4\\x43\\xb7\\xeb\\xfb\\x15\\xf5\\xbb\\x54\\x3d\\x6b\\x4b\\xf9\\x58\\xe5\\xcc\\x2d\\x43\\x9c\\x6b\\x90\\x9a\\xa1\\x38\\xd9\\x33\\x9d\\xee\\x83\\x08\\x67\\x2b\\x6b\\x80\\x8a\\x24\\x5c\\x60\\x8f\\xac\\x1c\\xa1\\x8a\\x93\\x8a\\x83\\x5d\\xa5\\xb6\\x87\\x5e\\xba\\xed\\x02\\x9b\\xa3\\x3f\\xdb\\xcb\\x4a\\xe6\\x6b\\xe6\\xdb\\xe4\\x04\\x6e\\x51\\x8b\\x61\\x40\\xd5\\x84\\x42\\x78\\xba\\x4e\\x18\\x6e\\x4a\\xef\\xbc\\xf5\\xc6\\xdb\\x7a\\xf0\\xa9\\x6a\\xd9\\xb6\\xe2\\x24\\xe9\\xe1\\xde\\xf4\\x85\\x58\\x46\\x55\\xb5\\x8c\\x68\\xdd\\xa4\\x45\\xf3\\x2b\\x44\\xcb\\xac\\xc9\\x4c\\xbc\\xa8\\xe5\\x8d\\xac\\xc4\\x15\\x20\\xe6\\x4b\\x75\\x95\\xe0\\x0c\\xa4\\xc8\\x04\\x04\\x29\\x91\\x1b\\x5d\\x3f\\xb8\\xbf\\x92\\x12\\x29\\x70\\x2e\\x3e\\xfe\\xf8\\x19\\x8a\\x2f\\x80\\x83\\xeb\\xde\\x42\\xb8\\x7b\\x21\\xdc\\xb7\\xe1\\x70\\x08\\x26\\x83\\xa3\\xbf\\x3b\\x79\\xb2\\xac\\x8e\\xd9\\xcf\\x82\\xde\\xa3\\xa1\\x3a\\x44\\x0d\\x85\\x1b\\x67\\x3a\\x40\\xf5\\xc3\\x58\\xe3\\xca\\xc2\\x71\\x44\\xf7\\x3e\\x3d\\x75\\xe2\\x9e\\x74\\xb2\\x12\\xb2\\x9a\\xec\\x79\\xa8\\x53\\x8f\\x08\\xdb\\xe8\\x63\\x7a\\x7c\\xd9\\x73\\x8f\\x64\\x7f\\x67\\x2a\\xe7\\x4d\\xab\\xeb\\xce\\x67\\x70\\xfc\\x78\\x7a\\xc8\\x99\\x59\\xce\\x2b\\xa9\\xae\\x23\\x7c\\xeb\\x54\\x13\\x82\\x89\\x60\\xee\\x07\\x7f\\x62\\x6b\\xc1\\xab\\xcd\\x94\\x72\\x97\\xf3\\xb1\\x57\\x2a\\x69\\x77\\xb0\\x00\\x82\\x85\\xce\\xdd\\xb3\\xbf\\xf8\\x6b\\x4f\\x6e\\xe8\\x94\\xc4\\x1d\\x1c\\x3c\\xbb\\xf9\\x4a\\x53\\x18\\xd9\\x87\\xac\\x41\\x83\\x8c\\xa6\\x29\\x36\\xbe\\x3c\\xbb\\x1c\\x3f\\xaa\\x85\\x7a\\x13\\x4b\\x80\\xd1\\x3d\\xa1\\x54\\x27\\x7f\\xd9\\xe6\\x1d\\x1e\\xb2\\xaa\\xd9\\xfe\\x0c\\xaa\\x77\\x17\\xba\\xb6\\xbc\\xda\\x13\\x11\\x28\\x66\\x7c\\x71\\xda\\xd8\\xd9\\xb9\\x34\\x00\\x56\\xd3\\x57\\x08\\x58\\x69\\x9f\\x44\\x3a\\x63\\x89\\x0d\\x8f\\xeb\\x2c\\xfd\\x71\\xa0\\xe7\\xce\\xfe\\x72\\x7a\\xc1\\x78\\xe3\\xf6\\xd7\\x12\\x06\\xfc\\x5e\\x1d\\xee\\x7e\\x64\\x97\\x98\\x61\\xb0\\xe3\\xbc\\xa8\\xf5\\x96\\x59\\xf9\\xa7\\x1e\\x7a\\x4e\\x0f\\x11\\x87\\xfb\\xe2\\x8b\\x00\\x1a\\x8a\\x14\\xec\\x19\\xfb\\x1f\\xa4\\x92\\x56\\x72\\xab\\x3b\\x96\\x95\\xcd\\x8e\\x40\\xd6\\x36\\x18\\x04\\x1a\\x63\\xf5\\x9c\\x4e\\xf0\\xd8\\x3f\\x01\\x2e\\x64\\xe0\\xe2\\x2b\\x8d\\xa2\\xb5\\x00\\xa4\\x77\\x58\\xb1\\xb1\\x72\\xb2\\x36\\x2f\\x44\\x2b\\x00\\x72\\x00\\xd8\\xec\\xd8\\xb7\\x0c\\xcf\\xfc\\x2b\\x19\\xa8\\x00\\x87\\xb4\\xfa\\xf3\\xf7\\x59\\xc5\\x9c\\x95\\xf2\\x63\\xde\\x4a\\x11\\x6b\\x5b\\xed\\xd5\\xe2\\x23\\x7f\\xe9\\x4b\\x14\\xe4\\x2f\\xaa\\x65\\x69\\xc3\\x09\\xfe\\x7b\\xc3\\x2b\\x5c\\x98\\x8f\\xfb\\x36\\x4b\\xe5\\x8b\\xdc\\x77\\xbc\\xf9\\x0e\\xd1\\xd0\\xe3\\x76\\x7c\\x0c\\x5a\\x7a\\x63\\x10\\xe1\\x14\\xe7\\x63\\x6b\\xae\\x8c\\xdb\\xa3\\x5c\\x17\\x3b\\x24\\xc7\\xd3\\x21\\x3b\\xb2\\xc5\\xe2\\x78\\xaf\\xf3\\xec\\x1f\\xda\\x5e\\x35\\x2a\\x15\\x38\\x70\\xe4\\x9f\\x71\\x5b\\xde\\x87\\xd0\\xf6\\xae\\x83\\x7c\\x10\\xd7\\x10\\x9c\\xf2\\xbe\\x56\\x15\\x6a\\x15\\x76\\x2b\\x9d\\x17\\xb2\\x7e\\xf6\\x5e\\x1a\\xeb\\xeb\\x66\\xc1\\x17\\xd2\\x50\\xb9\\x07\\x90\\xbb\\x2e\\x9c\\x22\\x27\\x17\\xff\\xc3\\xcb\\xb2\\xfe\\x1e\\xb9\\x14\\xc9\\xe4\\xf0\\x6f\\x13\\x30\\x37\\xb9\\x0a\\xbe\\xc4\\x23\\xbb\\x5c\\x10\\xa6\\xf1\\xe7\\xb3\\x0b\\x86\\x75\\xec\\xfe\\xf4\\x07\\xac\\xd3\\xff\\xff\\xfd\\xfe\\x0f\\xaf\\x3a\\x6f\\xf7\\xd3\\x05\\x8f\\xef\\x68\\xc7\\xd8\\xbb\\x8f\\xe9\\x59\\xc4\\x0d\\x66\\xf1\\x81\\x00\\xd7\\xe8\\x64\\x93\\x4b\\x0c\\xc7\\x73\\x94\\x95\\xae\\x3a\\x1e\\x2c\\xb7\\xcb\\x81\\xde\\xef\\x26\\xc1\\xbc\\xc4\\xd9\\x3d\\x69\\x9c\\x1d\\x0b\\x19\\x25\\x48\\x24\\x7a\\x1e\\x97\\xb4\\x29\\xa4\\x18\\xae\\x92\\x1d\\xa4\\x38\\x17\\xcf\\x8f\\xe2\\x6c\\x5d\\x9b\\xed\\xa7\\x28\\x3f\\x3d\\xa9\\x33\\xde\\x57\\x29\\x8c\\x21\\xec\\xe7\\x1f\\x2f\\xff\\xe7\\xfd\\xe9\\x9b\\xb7\\xef\\x61\\xa4\\xe4\\xbf\\x77\\x47\\x43\\xaa\\x9d\\xe3\\xa7\\xba\\x1f\\xb5\\x2e\\xca\\xeb\\xf6\\x05\\xe9\\xe7\\x96\\x51\\x2d\\x87\\x8c\\x62\\x1f\\xdf\\x5d\\xf6\\xf5\\xc5\\xdc\\x57\\x40\\x57\\xd3\\x4e\\x73\\x7f\\x5c\\x6b\\x1b\\x14\\x9f\\x13\\xf5\\xfe\\xf2\\x47\\x76\\x36\\xca\\x25\\x38\\x5b\\x99\\xfe\\xe5\\x76\\x0a\\x47\\x78\\x6f\\x15\\x69\\xeb\\x0e\\xb0\\x67\\xe0\\x77\\x70\\xf3\\xc5\\x35\\xd8\\xbb\\xc7\\xe1\\x81\\xd6\\xaa\\xab\\x1c\\x50\\xf7\\x4f\\x2c\\x3a\\xc4\\x56\\x5e\\x04\\x70\\x97\\x14\\x69\\x5b\\xed\\x68\\xb6\\xa3\\xd6\\xc2\\x04\\x90\\xcc\\x67\\x7a\\x52\\x16\\xeb\\xca\\x40\\xf4\\xa1\\x5e\\x6b\\x3b\\xc8\\xaa\\xca\\x66\\xbe\\x98\\x2c\\x97\\x62\\x53\\x4d\\x17\\x1f\\xa1\\xc0\\xe7\\x09\\x74\\xf8\\x3e\\xf1\\x0d\\xe2\\x57\\xf8\\x0d\\x42\\x11\\x3f\\x3a\\x01\\x84\\xd7\\xee\\x31\\x90\\x36\\xf4\\xd7\\xf7\\x20\\x87\\x86\\xed\\x2c\\xb9\\x5e\\x3b\\xc4\\xb8\\xf1\\x2c\\x9a\\x62\\x8e\\xd2\\x74\\xba\\x27\\xde\\x3e\\xf6\\xb8\\xda\\xce\\xcf\\x3b\\x2a\\x3a\\xfb\\x56\\x72\\x16\\x33\\x6d\\xb5\\xda\\x39\\x4a\\x7e\\x5d\\xf3\\xfc\\x42\\x5f\\xc0\\x13\\x67\\xb1\\xda\\x60\\x52\\x8a\\x1b\\x22\\x28\\x83\\x33\\x02\\x6a\\xe8\\x10\\xbb\\xd0\\xca\\xbb\\x25\\x72\\xa7\\xc4\\xa3\\x8b\\x20\\xe5\\xf8\\x7c\\x4f\\x97\\xef\\xdb\\x4d\\xf1\\xec\\x6b\\x0c\\xde\\x6b\\x30\\x48\\xd9\\x3b\\x27\\xc5\\x35\\xf1\\x2b\\x36\\x3e\\x27\\xd1\\xcc\\x27\\x9c\\x18\\x3a\\x90\\x6c\\xf3\\x89\\xdc\\x1b\\xeb\\xd4\\xb5\\xbd\\xd5\\x75\\xff\\x54\\xef\\xbc\\x61\\x2b\\x56\\x81\\x7e\\x5b\\x49\\xc5\\x7a\\x8e\\xb7\\x07\\xc7\\xf8\\xc4\\x37\\xe8\\x12\\x6e\\x50\\xab\\x92\\xc4\\xa6\\x9b\\xf4\\x10\\x17\\xe9\\x69\\x2f\\xd0\\x7d\\x19\\xd5\\xc3\\x66\\xf9\\xee\\x55\\x48\\xf7\\xc7\\xad\\xe7\\x54\\x7d\\x33\\x32\\x26\\xb8\\x4d\\x8a\\xd4\\x82\\x83\\xc9\\x25\\xb9\\x71\\x7b\\xa3\\x0e\\xb5\\xc6\\x4a\\xe1\\x7d\\x08\\x83\\x6f\\x83\\x06\\x5c\\xc4\\x81\\xae\\x2a\\xb7\\xaa\\x5a\\xa5\\x08\\xd2\\x94\\xc6\\x3b\\x60\\x88\\xb2\\x3c\\xe7\\x0b\\x2a\\xa8\\x56\\xea\\x5b\\x75\\xcb\\xeb\\x92\\x9d\\x5e\\x8c\\xf7\\x43\\x0d\\x7a\\xc4\\x59\\xe3\\x49\\xea\\x86\\xe8\\x95\\x47\\x5a\\xc7\\x96\\x54\\x50\\x4f\\x40\\x09\\x6c\\x36\\x91\\xd6\\xc4\\xd2\\xcb\\xc2\\xa6\\x7a\\xa5\\xa3\\x82\\xc1\\x97\\xe5\\xee\\xb2\\xbb\\xb7\\xd4\\x53\\xc2\\x30\\x15\\xd3\\x85\\xe5\\x95\\xaf\\xd6\\x42\\xe5\\xf8\\x5e\\xbd\\x7a\\x85\\xa6\\xb0\\x57\\x7f\\xfc\\xe3\\x1f\\xb1\\xbc\\x64\\x29\\x0a\\x39\\x5f\\x7d\\x10\\x9e\\xfa\\x97\\xd7\\xaf\\x47\\xec\\x3f\\x4e\\x3f\\xbc\\xa7\\xf2\\x3f\\x06\\x51\\x49\\xb0\\x67\\x58\\xf7\\xb4\\xb1\\x19\\xb0\\x7f\\xbb\\xfc\\xf1\\x63\\x2c\\x0d\\x92\\xff\\x0a\\xdb\\x1a\\xa6\\x37\\x62\\xe7\\x49\\xfc\\x53\\x6a\\xe8\\xe2\\x76\\x46\\x55\\x1d\\x2d\\xe3\\xd3\\x29\\x1e\\x0c\\x5f\\x9f\\x84\\x2e\\x9c\\xcf\\x1e\\x97\\x57\\x33\\x5f\\x0e\\xcc\\x1d\\x89\\x0a\\x02\\xb3\\x9c\\x4a\\x8e\\xa6\\x41\\x8f\\x6c\\x80\\x71\\x66\\xd0\\x57\\x20\\x93\\x30\\x94\\x01\\xab\\xe4\\xb5\\x60\\x53\\x03\\x45\\xc1\\x22\\xfc\\x5f\\x2d\\x8c\\x13\\x4a\\xa9\\x08\\x36\\x76\\x16\\x77\\xc6\\x88\\xce\\x58\\x0f\\x0f\\xe1\\x01\\xea\\x5c\\x86\\x28\\x37\\xdd\\xd3\\x1d\\xf2\\xf0\\xad\\x84\\x5d\\xec\\x63\\x49\\xf1\\x0a\\xba\\xd5\\x7a\\x1a\\x8f\\x4c\\x36\\xd6\\x8b\\x30\\x1a\\xdc\\x3a\\x42\\x09\\x88\\x74\\x82\\x57\\x1a\\xca\\x99\\x86\\x9d\\x8e\\x5c\\xcc\\x87\\x1c\\x2c\\x17\\x62\\xfb\\x54\\x7a\\x83\\x2f\\xf6\\x05\\xe0\\x45\\x42\\xf5\\x81\\x77\\xae\\xae\\x97\\xc7\\x8b\\xf8\\xd6\\x19\\xae\\x02\\x9f\\xe8\\xc6\\x7a\\x1f\\x36\\xfd\\x0e\\x09\\xd8\\x56\\xfb\\x25\\xea\\xf8\\xb2\\x1d\\x90\\x27\\x77\\x41\\x20\\xee\\x0d\\x62\\x9a\\xfb\\x9b\\x81\\x27\\xe4\\xa2\\xc4\\x80\\x09\\x5e\\xcc\\xd8\\xb5\\x58\\x0e\\x91\\x6e\\x2d\\x38\\x64\\xf3\\x60\\x11\\x22\\xb7\\x16\\x59\\x85\\xa9\\xa4\\xd6\\xda\\x59\\x58\\x32\\x1f\\x18\\x90\\x70\\x1f\\x9f\\x0d\\xe4\\x85\\x50\\x43\\xf2\\x12\\xc1\\x88\\xaa\\xc4\\x52\\xe0\\xb1\\xaa\\xa9\\xe0\\xba\\xff\\x9a\\x6a\\x0a\\x8c\\x57\\x92\\x54\\xdc\\x7d\\x13\\xa5\\x6b\\x66\\xee\\x7a\\x73\\x8c\\x86\\x70\\x74\\x90\\xb8\\x5b\\xa3\\x56\\x5a\\x53\\x6d\\x75\\x12\\xfe\\xe0\\x85\\xdc\\xa3\\x33\\x27\\x11\\x15\\x50\\xcd\\x98\\x0a\\x2b\\xd2\\xb3\\x7e\\x95\\xc2\\x42\\x64\\x49\\x34\\x46\\xd8\\x86\\x96\\x06\\xeb\\x92\\x36\\xaa\\x12\\xc6\\x30\\x09\\x33\\x9c\\xf3\\xfa\\x5a\\x78\\xc0\\x18\\x5e\\x8d\\xd8\\x85\\x1b\\x64\\xc0\\xaf\\x42\\x58\\xe4\\x1b\\x2a\\x1b\\xcb\\x97\\x59\\x76\\x90\\x7b\\xc9\\xe1\\x68\\x74\\x88\\x04\\x7e\\x4d\\xae\\x50\\x8f\\xf3\\xb1\\x1b\\xa6\\xee\\x0e\\x58\\xba\\xd9\\x41\\xfc\\xc0\\x17\\x06\\x91\\x81\\x9d\\xc8\\x07\\xc8\\xd7\\x1a\\xb2\\xe0\\xec\\xcc\\x33\\x30\\xde\\x19\\x44\\x69\\x75\\x3a\\x3b\\x00\\xc0\\xee\\x8a\\x5b\\xbe\\x0b\\x6a\\x79\\x27\\xbf\\x45\\xfe\\xd9\\x1d\\xad\\x7c\\x27\\xac\\xf2\\x4d\\x48\\xe5\\xb4\\x53\\x74\\xdb\\xfa\\x63\\x38\\xdf\\x03\\x62\\x7b\\xde\\x0b\\xe6\\xd5\\x7f\\x72\\x23\\x25\\xc8\\x1d\\x19\\x4a\\x4f\\x27\\x19\\x91\\x40\\x9f\\x2a\\xf1\\x4d\\x09\\x85\\xe3\\xe9\\xba\\x22\\xb0\\x3e\\x59\\x30\\x91\\x97\\x3d\\x0d\\xc5\\x62\\x5b\\x4f\\x2d\\x0d\\xf6\\xab\\xe5\\xc2\\x7a\\x8b\\x87\\xed\\x4f\\x1f\\x71\\xb1\\xfd\\xe9\\xe6\\x0c\\x6c\\x7f\\x72\\x85\\x2d\\x49\\x4b\\x0a\\x44\\x3f\\x8d\\xe2\\x87\\x25\\xb5\\x1a\\x30\\xbb\\xe3\\x15\\x1c\\xb1\\x0f\\xc4\\x14\\xf0\\x30\\xf2\\x89\\xd1\\x55\\x63\\x43\\x26\\xd3\\x1a\\x8e\\x01\\x9d\\x7a\\x84\\x6f\\x4c\\x29\\xf5\\x8f\\x25\\xfc\\x03\\x38\\x27\\x92\\xe5\\xbe\\xac\\x04\\x3f\\x3b\\x5d\\xf1\\xbe\\xc5\\xe8\\x7e\\xb5\\xc1\\x24\\xf7\\x58\\x43\\x2f\\x4a\\xec\\xbc\\x8e\\xbe\\x83\\x80\\x3b\\xe1\\x63\\xa9\\x33\\x19\\x07\\x22\\x49\\xac\\x41\\x01\\xca\\x8b\\x2b\\x54\\x07\\xaa\\xf7\\x14\\xbb\\x59\\x6d\\x68\\xac\\x64\\x98\\x38\\xbd\\x18\\xef\\xa4\\x01\\x24\\xed\\x37\\xe8\\x00\\xe9\\x13\\xbf\\x62\\x2d\\x60\\x8c\\x5a\\x40\\x5a\\x76\\xe7\\x3c\\xce\\x9c\\x4c\\xca\\x8e\\xec\\x3c\\x7b\\x31\\x72\\x65\\xd8\\xef\\x1c\\xb1\\x4c\\x83\\x4e\\x73\\x0c\\x3d\\x34\\xf6\\x44\\xb2\\x9a\\xe0\\xee\\x79\\xaf\\x23\\x5c\\xe2\\xe7\\x2e\\x72\\x3e\\xa2\\xf8\\x08\\xeb\\xd1\\x29\\xba\\xb1\\xfd\\x59\\x2d\\x76\\x07\\x93\\x65\\x97\\x50\\xda\\x06\\xf5\\xc1\\x44\\xb1\\x5c\\xe8\\xf2\\x7b\\xac\\x0a\\x01\\xb5\\xe3\\xb0\\x28\\xcc\\x00\\x6b\\xe3\\x98\\x01\\x2a\\x8c\\x4e\\x8a\\x48\\x7c\\xc5\\x75\\x62\\x72\\xdf\\x59\\x6e\\xd8\\xa9\\xca\\xd1\\x7d\\xea\\x1c\\xb9\\x0d\\x84\\x99\\x5f\\xf4\\xdd\\x45\\x76\\xcf\\xb2\\x45\\x2c\\x61\\x4d\\xbb\\x15\\x42\\xc9\\xf6\\x94\\x7a\\xf2\\x1b\\x68\\x8a\\x99\\x98\\x73\\xc4\\xf0\\xf3\\xd3\\x73\\x54\\xe6\\xb6\\x96\\xd6\\x0a\\xc4\\x52\\x12\\x35\\xd4\\x7c\\x1d\\x64\\x3e\\x83\\x83\\x9b\\xd7\\x07\\xbb\\x94\\x83\\xb9\\x67\\xc5\\x1e\\x16\\x77\\x61\\x0f\\x8b\\x71\\x91\\x89\\x6c\\xee\\x5c\\x83\\x2e\\x51\\x01\\xf0\\xa6\\x6a\\x19\\x24\\x1c\\x83\\xb9\\xc1\\xd5\\x7b\\xf4\\x89\\xef\\x43\\x8f\\xda\\x55\\x7f\\x1a\\x04\\x81\\xe1\\x45\\x7f\\x7a\\xd1\\x9f\\xf6\\xa2\\x3f\\x25\\x8c\\xc5\\x13\\x9c\\x35\\xba\\x54\\x1a\\x30\\xec\\x15\\xaa\\x98\\xc8\\x94\\x00\\xf0\\xb8\\xa3\\xe9\\x55\\xa9\\x58\\x29\\x1d\\x2d\\x6e\\x4e\\x1f\\x3a\\xf4\\x0a\\x16\\x9d\\xe3\\xc6\\x4e\\x87\\x7f\\x62\\x42\\x15\\xba\\xc4\\xcd\\x77\\xfd\\xd7\\xc6\\x82\\x68\\x13\\x75\\x92\\x74\\x2c\\x73\\xff\\xae\\xd4\\x6a\\x07\\x7d\\xef\\xba\\x75\\x3b\\xd1\\x01\\xef\\x0a\\x7c\\xb7\\x27\\x06\\x1f\\xd9\\x7a\\x48\\x26\\xa6\\xe9\\x07\\xac\\x01\\xe2\\xef\\xd1\\x09\\x89\\x55\\xa7\\x43\\x11\\x7c\\x28\\x1d\\x7b\\x84\\x5f\\x8e\\x8a\\x45\\x33\\xa0\\x07\\x46\\x73\\x31\\xd7\\xf5\\x72\\x10\\x1e\\x72\\x3f\\x66\\xad\\xe8\\x89\\x63\\x90\\x09\\x8a\\xa6\\x76\\x1a\\x60\\xb5\\xfc\\x56\\xa5\\x03\\xbf\\x40\\x8f\\x2c\\x1c\\x84\\x7d\\xea\\x57\\x34\\x28\\xfd\\xe4\\x47\\x22\\x82\\x8a\\x81\\x7e\\x1f\\x8b\\x28\\x4d\\x03\\xe4\\xa1\\x19\\x44\\xb5\\xd3\\x7d\\x2b\\xd4\\x0d\\xbb\\xe1\\x75\\x87\\x48\\xbc\\x75\\x9f\\x7b\\xca\\x03\\xa5\\xbc\\x91\\x66\\xb7\\x7a\\x87\\xad\\xa9\\x5f\\x12\\xd3\\x40\\xbb\\x8e\\x6e\\xec\\xa2\\xb1\\x44\\x29\\xfd\\xad\\xf0\\x29\\xf3\\xe1\\x36\\xb4\\x84\\xa2\\xd7\\x07\\x3b\\x0d\\xe3\\x9b\\xa9\\x2f\\x8c\\x9f\\x1d\\xab\\x0c\\xe3\\xe7\\xbe\\xb5\\x86\\xf3\\x5e\\x76\\x3e\\x36\\x7b\\x2d\\x2c\\xee\\x3f\\xfe\\x58\\xec\\xe3\\x1e\\x46\\x16\\x19\\x71\\x1e\\xbc\\x70\\xfa\\x48\\x17\\x0d\\xc3\\x4d\\x76\\xb2\\xdb\\x10\\x42\\xfd\\x7a\\x93\\x0d\\xfd\\xf8\\x2b\\xb6\\xd6\\xec\\xd7\\x67\\x4b\\xf9\\x85\\xbf\\x71\\x87\\xed\\x25\\xd5\\x33\\x78\\xf1\\xd6\\x76\\x3a\\x82\\x2f\\xde\\xda\\x17\\x6f\\xed\\x8b\\xb7\\xf6\\xc5\\xda\\xf0\\x62\\x6d\\x78\\xf1\\xd6\\xb2\\x17\\x6f\\xed\\x5e\\xd6\\x70\\x7f\\xde\\x5a\\x14\\xf5\\xd6\\xf9\\x6c\\x49\\xd8\\x8b\\x0e\\xdb\\x47\\xf5\\xd7\\x52\\xe1\\x9e\\xd3\\xa2\\xd0\\x8d\\xb2\\x9f\\xf5\\xb5\\xe8\\xec\\x74\\x68\\xc9\\xff\\x2b\\xfd\\x00\\x00\\xc2\\x06\\x7d\\x60\\xf5\\xe1\\x47\\x53\\x0e\\xfa\\x4b\\x25\\xbd\\x64\\x8b\\x5d\\xa4\\x0a\\xde\\x94\\xd2\\x49\\xfe\\x3b\\x1f\\x33\\xdf\\x41\\x0a\\x4e\\xa4\\x4a\\x51\\xc6\\x1f\\xe8\\x2a\\x5b\\xb7\\xd6\\x23\\x76\\xca\\x6a\\x51\\xc8\\x85\\xa4\\x32\\xf2\\x1c\\xbf\\xc7\\x83\\x17\\x6a\\x23\\x48\\x6b\\x44\\x35\\x25\\x8c\\x7a\\x95\\xd6\\xfa\\x89\\xf2\\x3b\\xd1\\xc1\\xb5\\xaf\\x41\\x0e\\xa5\\x3d\\x92\\xb9\\xaf\\x85\\x54\\x8b\\xbf\\x7b\\xd6\\x46\\xa3\\xf9\\x9c\\xf6\\x90\\x9a\\x57\\x60\\x2a\\x59\\x89\\x21\\x78\\xd9\\x42\\x52\\x82\\xf5\\x43\\x5f\\x7f\\xf1\\x75\\x21\\x6b\\x38\\xbc\\x97\\xa2\\xd0\\xaa\\x4b\\x4d\\xd5\\x0d\\x1b\\xb4\\xd2\\x53\\xe4\\x4f\\x60\\x1b\\x15\\x25\\x2b\\x9b\\x3a\\xd4\\x4c\\xbd\\xe1\\x95\\x2c\\xa5\\x5d\\x06\\xaf\\x1d\\x95\\xd7\\xe2\\x78\\x63\\xc2\\x36\\x9a\\xb8\\x8c\\x8c\\x2f\\x16\\xb5\\xe6\\xc5\\x4c\\x98\\xe4\\x6d\\x28\\xa0\\x50\\x12\\x59\\x88\\x7d\\xc7\\x12\\x70\\x20\\xa3\\x40\\x1b\\xc7\\x20\\xab\\x25\\xab\\xb5\\xf5\\x8e\\xf7\\x0d\\x2f\\xfc\\x9c\\x74\\x06\\xcd\\x91\\xcb\\xd9\\x7a\\x09\\xde\\x79\\x9d\\x76\\x81\\xa3\\x92\\xd3\\xf4\\x0f\\xc3\\x74\\x55\\x7a\\x08\\x93\\x3f\\xbd\\x72\\x42\\x61\\x41\\x67\\xd0\\x11\\x3f\\x00\\xb8\\xb0\\x9a\\x55\\x8e\\x61\\x3b\\x82\\xb8\\xb9\\xf1\\xef\\xbf\\x63\\x33\\xdd\\xd4\\x66\\x94\\x82\\x0e\\xbc\\x86\\xef\\x50\\xbf\\xf3\\x42\\xa5\\x65\\x95\\xe0\\xc6\\xb2\\xd7\\xaf\\xd8\\x5c\\xaa\\xc6\\xf1\\xa9\\xde\\xc7\\xa6\\xbf\\x1c\\x94\\x48\\x40\\x7f\\xf8\\xae\\x73\\xbb\\xbe\\xb2\\xcf\\x46\\xa9\\x67\\x81\\xd8\\xc8\\x24\\xfa\\xd0\\x4d\\xc2\\xc4\\x38\\x44\\x16\\x6f\\x09\\x42\\x44\\x74\\xd3\\xd5\\x56\\x56\\x3f\\xc0\\xfd\\xfa\\xa5\\xd1\\x93\\xa5\\xed\\x93\\x44\\x49\\x2d\\xf2\\xec\\xc9\\x7f\\xa7\\x2f\\xbb\\x80\\xa7\\x44\\xec\\x94\\x3b\\x5f\\xfa\\x20\\x15\\x2e\\xae\\xa4\\xb1\\x5b\\xea\\x5b\\xc4\\xfc\\xca\\x3b\\x1f\\xeb\\xce\\x56\\xae\\x9c\\x76\\xd0\\x33\\x57\\x06\\xda\\x78\\x89\\xd8\\xdb\\x96\\x8a\\x42\\x60\\x31\\xcb\\xf3\\x58\\x29\\x49\\x69\\x7c\\x76\\x6b\\xf7\\x4f\\x0c\\x38\\xe6\\x0f\\xc8\\x1e\\x50\\xd3\\x3b\\x4e\\xb5\\x9b\\xd0\\xe5\\x8f\\x44\\xef\\xb9\\x62\\xb3\\xfc\\x16\\x18\\xa9\\xae\\x10\\xe4\\x7c\\xde\\x54\\x56\\x2e\\xaa\\x38\\xef\\x4f\\xbe\\x01\\x11\\xf2\\xd4\\xe6\\xc6\\x13\\x33\\x11\\xc7\\xc4\\x62\\x44\\x9b\\x02\\xfb\\xe4\\x51\\xe8\\x4b\\x28\\x8b\\x58\\xdd\\xb5\\xe3\\x07\\x0b\\x5e\\xf3\\xb0\\x78\\x50\\x49\\xd7\\x1c\\x93\\xf9\\x8e\\x83\\x47\\x91\\xe0\\x30\\x5d\\x2b\\x5e\\xc5\\x11\\x27\\x5e\\xa4\\x7d\\x1e\\x1a\\x2b\\x14\\x57\\x1d\\x4c\\xd5\\x39\\x3c\\x17\\x34\\x62\\xfa\\x36\\x04\\x93\\x61\\x19\\x94\\xd6\\x69\\x21\\xa1\\xe6\\x0d\\x2f\\xae\\x85\\x2a\\xb1\\x68\\x14\\x4c\\xbb\\x5c\\x2a\\x3e\\x27\\xb4\\xad\\xa4\\x1e\\x77\\xab\\xbd\\x19\\x90\\x61\\x02\\xd3\\xf7\\x7c\\x9a\\x31\\x72\\xdd\\x7d\\xae\\x41\\x63\\x7a\\x43\\xd9\\xb8\\x26\\xdb\\xee\\xb9\\x41\\x93\\x4d\\x2d\\x6f\\x0a\\xe1\\xf9\\xbf\\x6b\\xb7\\xcf\\xa1\\xdf\\x74\\xc8\\xa5\\x5f\\x19\\xbc\\xdf\\x9e\\xe4\\xfc\\x02\\xb9\\x0f\\x96\\x73\\x00\\xd5\\xe2\\x95\\xbb\\xda\\xcb\\x90\\x33\\xda\\xda\\xdc\\xc9\\x72\\xbf\\x55\\x6f\\xea\\x49\\x9f\\xcc\\xdf\\xc3\\x7a\\x52\\xe6\\x97\\xf8\\x13\\x2f\\xb5\\x61\\x6f\\x2a\\x5d\\x5c\\xb3\\x73\\x01\\x42\\xd7\\x43\\x96\\x67\\xa9\\x27\\xe5\\x53\\x42\\x78\\xcf\\xf9\\xd5\\x36\\x3f\\xdb\\x90\\xcd\\xb5\\x92\\x56\\xd7\\x77\\xd3\\x8b\\xc7\\x2b\\x3b\\xf9\\x02\\xf7\\xbc\\x11\\xa1\\xca\\x9d\\xe6\\xe7\\x0c\\xf6\\xec\\x8e\\x5b\\xdf\\x8d\\x87\\x46\\x41\\x3d\\x83\\xdb\\x89\\x5f\\x51\\x15\\xb0\\x1d\\xef\\xda\\xef\\x66\\xfa\\x76\\x68\\xf5\\xb0\\x31\\x62\\x28\\x3b\\x38\\x74\\x7b\\x4c\\xf3\\x5a\\x2c\\xc1\\x8b\\xdd\\x73\\xa2\\xd4\\x2c\\xd3\\x19\\xac\\x06\\x0b\\x14\\x7c\\xef\\x38\\xf7\\xa7\\x37\\xe7\\x5f\\x8c\\xa8\\x47\\xa9\\x0c\\x78\\x22\\x6c\\x71\\x52\\x88\\xc5\\xec\\x84\\x7a\\x78\\x96\\x8b\\xe2\\x89\\x48\\xdf\\x55\\xf1\\xed\\x90\\xcd\\x14\\xba\\xaa\\x28\\x31\\x5b\\x4f\\xd9\\x99\\x58\\xcc\\x42\\xc7\\x8f\\x3d\\xeb\\xa7\\x43\\x04\\x5e\\x68\\xdd\\x17\\x08\\xf5\\xd0\\xb5\\xc9\\x2f\\x11\\x7c\\x83\\x77\\x28\\x39\\x4c\\xf5\\xa4\\x5f\\x11\\x8a\\xc7\\x3a\\x3e\\xcf\\xba\\xd4\\xe6\\x03\\x2e\\xce\\xc3\\xc2\\x29\\x1f\\x66\\x78\\xca\\x69\\xbc\\x67\\x0e\\x96\\xec\\x23\\x46\\x32\\x12\\x34\\x9e\\xa2\\xd0\\x5d\\x8a\\x92\\xe9\\x1b\\x51\\xd7\\xb2\\x14\\x86\\x05\\x1a\\x94\\x6a\\xa9\\xb2\\x7a\\xec\\x75\\x7b\\xc1\\x6d\\x7e\\x72\\xdc\\xe6\\x1d\\xd4\\xa1\\x43\\xd0\\x87\\x32\\x32\\x05\\xdf\\xac\\x90\\x29\\x5e\\xce\\xa5\\x7a\\x76\\x84\\xca\\x14\\xbc\\x12\\xe3\\x1f\\x7b\\xe8\\x1f\\xd4\\x22\\x57\\x41\\x2e\\xe9\\xcb\\x04\\x3f\\x6d\\x0b\\x2a\\xd9\\x5f\\xc3\\xb9\\x61\\x4a\\x97\\xdb\\x4c\\xaa\\x0f\\xa0\\x48\\x5c\\x71\\x2b\\x6e\\xb7\\xb2\\xc3\\x61\\x24\\x54\\xdb\\x9f\\x04\\xe1\\xf4\\x29\\x55\\x8e\\x67\\x81\\x11\\x98\\x9c\\x79\\x04\\x3d\\xdb\\x27\\x53\\xa5\\x5d\\xeb\\x6b\\x9c\\xc4\\x56\\x29\\xfc\\x6e\\x1b\\x74\\xd7\\x9f\\xe0\\xd3\\x8b\\x31\\xfb\\x01\\x1f\\xdf\\x2f\\x7a\\x61\\xad\\x2d\\x8a\\x81\\xe7\\x7a\\xce\\x65\\xdf\\x22\\x1b\\xed\\xe6\\x6d\\xf4\\xd5\\x74\\x0a\\x17\\xe1\\x59\\x46\\x0f\\x27\\x05\\x5c\\xa6\\xf2\\xaa\\x71\\x3a\\x1d\\xe9\\x61\\xcf\\x0a\\x60\\x6e\\x45\\x74\\x79\\xbe\\x00\\x73\\xf7\\xaf\\x06\\x91\\x98\\x9c\\x7c\\x5c\\x64\\x94\\x58\\xfc\\x56\\x02\\x2b\\x09\\x3e\\x50\\x66\\x84\\x32\\x12\\x1c\\x32\\x89\\x57\\x9c\\x2a\\xfd\\x61\\x69\\x49\\x0c\\x82\\x44\\x11\\x67\\xc0\\xde\\xeb\\x2b\\xa9\\xfc\\xed\\xd5\\xe4\\xaf\\x9b\\x72\\x59\\x75\\x5d\\x8c\\x17\\x99\\xe4\\xc9\\x65\\x12\\x63\\xaa\\xb7\\x8a\\x4f\\xaa\\x2e\\xe1\\x06\\xf9\\x51\\x0b\\x0d\\xd9\\xbb\\x8a\\x5f\\x31\\x01\\x7f\\x9c\\x94\\xd2\\xb8\\xff\\xb3\\xcb\\xcb\\xf7\\x60\\x84\\x6f\\x94\\x97\\x98\\xc1\\x40\\x4d\\xb4\\x2f\\x24\\x29\\xe0\\x45\\xdc\\xef\\xdd\\x41\\xd2\\xb3\\x03\\xfa\\x5f\\xd2\\x92\\x49\\x55\\xba\\x81\\x27\\xa5\\xe0\\x30\\x48\\x0a\\x9e\\x40\\x3c\\xc4\\x10\\xf3\\x8b\\x61\\x03\\x13\\xc1\\x3e\\xcf\\x64\\x71\\x7d\\x91\\xd8\\xdd\\x75\\xed\\xbe\\x53\\xc9\\x57\\x19\\x03\\x6b\\xff\\xb6\\x4f\\x6a\\x49\\x43\\xbd\\xe8\\xaf\\x1a\\x27\\x2d\\x3d\\x1f\\xf0\\x04\\xe3\\x92\\xe6\\x0f\\xbf\\x71\\x63\\x74\\x21\\xa3\\xcf\\x05\\x6c\\x34\\x91\\x39\\x94\\xc0\\x1c\\xf6\\x3b\\x27\\x10\\x0f\\xfa\\x4e\\x07\\xe5\\x8f\\x35\\x1c\\xcd\\xef\\xa6\\xaf\\x8e\\x6b\\x52\\x0e\\x26\\x95\\x9f\\xf5\\x5e\\xa7\\x80\\x67\\x66\\x07\\x68\\xf4\\xd8\\x70\\x15\\x1a\\xdd\\x0b\\xc3\\x2d\\xc7\\x82\\x0f\\x53\\xa7\\xcd\\xf3\\x82\\x98\\xaf\\xcd\\xb9\\xb2\\x7d\\x01\\x22\\x9d\\xa0\\x09\\xf7\\x36\\xf1\\x2e\\x69\\x1b\\xeb\\xd4\\xf0\\x96\\x37\\x11\\xbf\\x23\\x57\\x03\\xdc\\xb9\\x85\\x5e\\x34\\x15\\xc6\\x73\\xdc\\x1f\\xdf\\xdd\\xdb\\x8c\\xf1\\x3d\\x7b\\x72\\x3d\\x3c\\x06\\x6a\\xe9\\x61\\x1a\\xd8\\xdb\\x3f\\xd2\\xf9\\xd7\\x81\\x5d\\x9a\\x08\\x77\\xaf\\xfe\\xf0\\xdd\\x77\\xdf\\x3a\\x9a\\x69\\x57\\x15\\xfc\\x21\\xe0\\x4c\\x3b\\x9a\\x68\\xd7\\xe4\\x17\\x8d\\x5f\\xf2\\x8b\\x7e\\xbb\\xf9\\x45\\x0f\\x8f\\x42\\xbb\\xe7\\x0c\\xa2\\x9e\\xb1\\xb9\\xfd\\xe2\\x72\\xbb\\xe7\\x08\\x75\\x8e\\xde\\xed\\x1b\\xb9\\xdb\\x23\\x0b\\x68\\xbf\\xb9\\x3f\\xbd\\x63\\x59\\xfb\\xe4\\xf9\\xbc\\x64\\xf7\\xfc\\x5a\\xb3\\x7b\\x76\\x89\\x65\\xed\\x9f\\xc9\\xd3\\x27\\x86\\xf5\\xd7\\x98\\xb5\\xd3\\xe3\\x72\\x76\\xcf\\x2e\\xb9\\x77\\x4e\\x49\\x7f\\x10\\xc0\\xfe\\xf6\\xb4\\x5d\\x0a\\x52\\xc5\\x96\\x6b\\x35\\x48\\x9f\\x54\\xee\\xb1\\xc7\\x0e\\x0f\\x4d\\x02\\x2d\\x66\\xb5\\xbb\\x81\\x8f\\xa2\\x90\\xb0\\x1e\\xda\\x18\\x76\\xaf\\xfb\\xd4\\x86\\xa4\\x36\\x3f\\x5e\\xb6\\x1c\\x33\\xe1\\xeb\\xa7\\xf1\\xc7\\xfc\\x16\\x1c\\x1e\\x2f\\x35\\x5d\\xbe\\x11\\x93\\xbb\\xc9\\xd0\\x5a\\xbc\\xb5\\x02\\x48\\x00\\x30\\x72\\x3d\\x49\\x51\\x22\\xe3\\xd5\\x39\\xbd\\x18\\x3b\\x1d\\x1c\\xd2\\x88\\x78\\x65\\x46\\x6c\\x0d\\x9f\\xf7\\xe6\\x52\\x92\\x0b\\x3c\\x7f\\xe7\\xd6\\x8a\\xf9\\xc2\\x76\\xdf\\xf5\\x17\\x8b\\xfb\\x93\\x5b\\xdc\\xf7\\x68\\x01\\x9c\\x35\\x73\\xae\\x86\\xee\\x46\\x81\\xcd\\x3d\\xf3\\xd6\\xb5\\x28\\xf3\\x88\\xd1\\xdd\\x41\\xf6\\x04\\x16\\x10\\x48\\x2e\\xc8\\x0b\\x1b\\xf3\\xa4\\xcc\\xe5\\xc3\\x98\\x3d\\xa1\\xef\\x9d\\x67\\x8e\\x7c\\xb5\\x75\\xd3\\x0a\\xbd\\x12\\xf0\\x4a\\xd3\\x09\\xab\\xe0\\x2f\\x55\\xc2\\x9c\\x33\\x35\\xdc\\xce\\x04\\xf2\\xf0\\x0b\\x48\\xc8\\x89\\x4f\\xe5\\x92\\x34\\x8a\\xd2\\xbc\\xaa\\xf4\\x2d\\xbe\\x3b\\xe5\\x6b\\x6e\\xf5\\xdd\\x58\\x28\\xd3\\x6c\\x22\\xd8\\x5c\\x3a\\x1d\\x9d\\x0c\\xac\\xe9\\x70\\xd0\\x65\\xea\\x24\\x72\\x51\\xa3\\xc0\\x5b\\x93\\xb3\\xed\\x52\\x58\\xda\\x28\\xd8\\x68\\xa7\\xdf\\x2a\\x0c\\x08\\x77\\xff\\xf6\\x51\\x45\\xf0\\x6e\\x4f\\x13\\x26\\x62\\xc6\\x6f\\xa4\\x6e\\x6a\\x6c\\x6d\\x35\\x3b\\xa0\\x9f\\x80\\x37\\x2c\\x75\\x13\\xec\\x5d\\x58\\x0c\\x33\\xcc\\xce\\xac\\x59\\xa7\\x8f\\xf1\\x47\\x50\\x05\\x4a\\xed\\x4d\\x13\\x43\\xf1\\x55\\x1a\\xbb\\x3a\\x17\\xbf\\x44\\x1e\\x06\\x6f\\x5f\\xe7\\xe6\\xc6\\x2c\\x1c\\x5b\\xe8\\x5d\\xd5\\x2e\\x6b\\x97\\xcb\\x2b\\x37\\x97\\xf0\\xd3\\x37\\x54\\xd3\\x6e\\x2b\\xba\\xeb\\xa3\\x89\\x40\\xbf\\x41\\xf1\\x27\\x78\\xc2\\x2a\\x59\\x2c\\x7b\\x97\\x7b\\x6b\\xb5\\xf6\\x44\\xdb\\x04\\x1f\\x9a\\xfb\\x9e\\xbd\\xe1\\x46\\x94\\xec\\x03\\x57\\xfc\\x0a\\xf5\\xbd\\xa3\\xcb\\x8b\\x37\\x1f\\x8e\\xdd\\xbe\\x82\\x3e\\x39\\x3e\\x5f\\xeb\\x68\\xbb\\x4c\\x3b\\xff\\xb8\\xcf\\x7c\\x91\\x95\\x89\\xef\\xc0\\xaa\\x56\\xda\\xef\\x38\\xf9\\xbd\\x26\\xc2\\xb0\\xc0\\x87\\xba\\x81\\xf5\\xae\\x61\\x41\\x17\\xed\\x14\\xd6\\x76\\xcd\\xcf\\x16\\x81\\xb9\\x99\\x97\\xf7\\xac\\xf2\\x29\\x95\\xb1\\xbc\\xaa\\x2e\\x2a\\xae\\x4e\\x17\\x8b\\x5a\\xdf\\xac\\xd7\\xc6\\xb3\\xb1\\xfa\\x07\\xfd\\x48\\x31\\xcc\\xc3\\x7f\\xb9\\xc0\\xa5\\x07\\x17\\xb6\\x62\\xe3\\xd8\\xff\\x88\\x8d\\x6d\\xd0\\xc2\\xb5\\x02\\x96\\x7a\\x70\\xda\\x58\\x3d\\xe7\\x56\\x16\\x07\\x4e\\x59\\x3f\\xf8\\xc0\\x55\\xc3\\xab\\xb5\\x41\\x57\\x77\\x4e\\x63\\x93\\x88\\x78\\x67\\xa3\\xcd\\xd0\\x75\\x1d\\x9a\\xdd\\x29\\x6b\\xdc\\xdd\\xde\\xf2\\xda\\x51\\xa7\\xb3\\xcb\\x9f\\x7a\\xb5\\x35\\x96\\xdb\\x66\\x85\\x0a\\xdf\\xc1\\x19\\x36\\xf3\\x82\\x21\\xab\\xb8\\xb1\\x5f\\x16\\xa5\\xbb\\xf4\\xad\\x5f\\xef\\x22\\xf8\\x05\\xb7\\xbc\\xd2\\x57\\x7f\\x11\\xbc\\x5a\\x7f\\xc2\\xb3\\x73\\x72\\x96\\x3e\\xed\\x0d\\x50\\xe4\\xf0\\x6f\\x26\\xe1\\xc1\\x43\\xc3\\x9c\\x80\\xed\\x73\\xe0\\x6b\\x51\\x89\\x1b\\xae\\xac\\x6f\\x8e\\xc5\\xd5\\xcd\\x21\\xcd\\x1f\\x4e\\x91\\x8c\\xc6\\xd7\\x52\\x58\\x51\\xcf\\xa5\\xca\\xfb\\xbc\\x84\\x67\\xcf\\xb4\\x2a\\x25\\x9a\\x1d\\xc1\\xa0\\x86\\x2d\\xf2\\x7e\\x37\\x1f\\xb5\\x4d\\x9e\\x86\\x3b\\x7c\\x0b\\x39\\xba\\x66\\x32\\x9e\\x7c\\x29\\xf0\\xb1\\x09\\xc9\\x97\\x33\\xfc\\x12\\x3c\\xed\\xd9\\xd8\\x56\\x56\\x8a\\x5d\\x2b\\x27\\x18\\x02\\x8e\\xc8\\x7a\\xb2\\xb5\\x55\\x4e\\xd8\\x26\\x1f\\x0c\\xfd\\x1e\\xe3\\x10\\x36\\x07\\x8e\\x0e\\x69\\xdc\\x9b\\x7c\\x10\\x77\\x1d\\x31\\xfc\\x6c\\x97\\x2c\\xda\\x43\\xd9\\x4c\\x53\\xd7\\x9d\\xbb\\xd0\\x0c\\x33\\x59\\x5a\\x05\\xf9\\xb3\\x87\\x36\\xf3\\x80\\x4e\\x82\\x57\\x37\\x19\\xa9\\x2b\\xaa\\x7d\\x4e\\x6b\\x23\\x06\\xfb\\x8a\\x2a\\xdb\\x41\\x62\\xdc\\xca\\xb4\\x3a\\x82\\xcb\\xe7\\x8a\\xf5\\x98\\xe2\\xff\\x6a\\x52\\x45\\x38\\x5b\\x48\\x81\\xe0\\x27\\x5c\\xd1\\x62\\x01\\x67\\x11\\xbc\\xa4\\x2f\\x1d\\x07\\x73\\x2a\\x21\\xfc\\x36\\x20\\x67\\x38\\x1a\\x97\\x29\\xd6\\xc2\\x1b\\xa8\\x39\\x82\\x7f\\x80\\xe3\\xe2\\xe4\\x07\\x4d\\x46\\x5e\\x4a\\xd2\\x75\\x34\\x00\\x38\\xf9\\x80\\x99\\xa6\\x98\\x31\\x6e\\xdc\\xd0\\xdc\\x81\\x76\\x37\\x5e\\x8c\\xe6\\x5c\\xc9\\xa9\\x30\\x76\\x14\\x50\\x82\\xcd\\x7f\\xfe\\xfe\\xbf\\x47\\xec\\x9d\\xae\\x19\\x05\\xaa\\x0f\\x3c\\xaa\\x06\\x8d\\x33\\x9e\\x0b\\x69\\x70\\x32\\xa1\\x6d\\xd4\\x5a\\x17\\xba\\xa4\\x41\\xdf\\xc2\\x60\\x2d\\xbf\\x76\\x3c\\x0c\\x07\\xdb\\x08\\x70\\x5d\\x7c\\xcf\\x0e\\x9c\\x98\\x98\\xbc\\xfa\\xff\\x1c\\x5b\\xfa\\xc7\\x01\\x3b\\xba\\x05\\xa6\\x7d\\xe0\\xfe\\x3c\\xc0\\x17\\x86\\xb0\\xc9\\x54\\xa9\\x8e\\x2f\\xc6\\x64\\xc9\\x5a\\x5e\\x5d\\x89\\x1a\\xd5\\x47\\x06\\x49\\x85\\xc7\\x84\\x0a\\xa2\\x74\\xf2\\xb0\\x77\\x4a\\x47\\x75\\xb3\\x3d\\x90\\xff\\xfc\\xfd\\x7f\\x1f\\xb0\\xa3\\x7c\\x5e\\x4c\\xaa\\x52\\x7c\\x65\\xbf\\x47\\xeb\\xb2\\x34\\x6e\\x8e\\xc7\\xe4\\xcc\\x31\\x4b\\x65\\xf9\\x57\\xd7\\x67\\x31\\xd3\\x46\\x28\\x54\\xe5\\xad\\x66\\x33\\x7e\\x23\\x98\\xd1\\x4e\\x03\\x16\\x55\\x35\\x24\\x5b\\x3a\\xbb\\xe5\\x80\\xd4\\xe2\\x97\\x12\\x12\\xeb\\xd9\\x82\\xd7\\x36\\x3b\\x12\\x23\\xb2\\x90\\xc0\\xdb\\xdc\\xb6\\x5d\\x29\\xef\\x99\\x9e\\x4a\\x45\\xfe\\x2b\\xf2\\x9c\\xb9\\x3d\\x87\\xc4\\x50\\xdc\\x24\\xab\\x59\\x31\\xe3\\xea\\x2a\\xe4\\xa6\\x4f\\x1b\\xdb\\xd4\\x62\\x8b\\xeb\\xa7\\xe3\\x1d\\xb8\\x96\\xaa\\x57\\x0a\\xf3\\x5f\\xa5\\x6a\\x07\\x15\\xac\\xb7\\x2b\\x5d\\x49\\xeb\\xb3\\x22\\x28\\x56\\xd1\\x2e\\x4f\\xdc\\x2e\\xd4\\x72\\xd2\\x58\\x5d\\x9b\\x93\\x52\\xdc\\x88\\xea\\xc4\\xc8\\xab\\x21\\xaf\\x8b\\x99\\xb4\\xa2\\x70\\xd3\\x3a\\xe1\\x0b\\x39\\x2c\\xb4\\x72\\x3b\\x0e\\xa8\\x0c\\xf3\\xf2\\x77\\x50\\xde\\x74\\xe8\\x86\\xba\\x05\\x75\\xba\\xe3\\xa4\\xb7\\x1b\\xd5\\x9e\\xd4\\x98\\xb6\\xb7\\x39\\x76\\xb0\\x07\\xad\\x4e\\x14\\x6d\\x33\\x8f\\x30\\x5b\\x30\\x84\\x9c\\xec\\x65\\xb2\\x1e\\x34\\xb9\\x3f\\x8f\\x39\\x24\\x1c\\xf0\\xa2\\xdd\\x87\\xbb\\x76\\x18\\x40\\x02\\xb7\\x32\\xa3\\x94\\x73\\x5e\\x22\\x29\\xe5\\x6a\\xf9\\xe0\\x87\\xdf\\x2d\\x29\\xc0\\xe5\\x17\\xcb\\x21\\x74\\xa1\\xab\\x21\\x57\\xa5\\xfb\\x37\\x26\\xec\\x14\\xcb\\xbd\\xac\\x61\\x23\\x7b\\x11\\x82\\x2f\\xe3\\xf3\\xc7\\xb9\\x12\\x8d\\xdc\\xc3\\xad\\x27\\x79\\xad\\xa3\\x10\\x85\\xa2\\x2a\\x06\\x6a\\xd4\\x8d\\xf0\\x4c\\x33\\x17\\x50\\xa5\\xf1\\xbd\\xfe\\xff\\xe4\\x7f\\x09\\x68\\x67\\xdb\\x44\\xaa\\xbb\\xbd\\x26\\x89\\xec\\xd8\\x71\\xbc\\xef\\x63\\x8b\\xd4\\x26\\x07\\x81\\x57\\xdc\\x58\\x82\\xd6\\xf2\\x18\\x04\\xd9\\x34\\xbc\\x82\\x02\\x0c\\x66\\xb3\\x63\\xb8\\xd3\\x19\\xf2\\xf1\\x02\\x6e\\x20\\xc3\\xb5\\x98\\x4b\\x45\\x50\\x4a\\xb6\\x2b\\x50\\x51\\x7f\\xc9\\xea\\xa0\\xe1\\xa4\\xac\\x30\\x96\\xf1\\x1b\\x2e\\x2b\\xb0\\xce\\xeb\\x89\\x11\\xf5\\x0d\\x16\\xa4\\x22\\xa8\\x41\\xde\\xd6\\xb3\\xa8\\xe6\\x04\\x8a\\x51\\x8f\\xa4\\xf9\\xf8\\x39\\xac\\xee\\xca\\x5d\\x13\\x00\\x6d\\xa8\\x35\\xfa\\x8d\\xa3\\xde\\x8b\\xde\\x83\\xea\\xe5\\xc6\\x9f\\xdd\\x1b\\x76\\x54\\x63\\xdc\\xf9\\xfb\\x8b\\xe0\\xb5\\x9d\\x08\\x6e\\x3f\\xcb\\xbb\\xf8\\xee\\xca\\x91\\xce\\xda\\x85\\x52\\xee\\xe1\\x40\\xdf\\x0a\\x76\\xa5\\xad\\x13\\xb1\\x1a\\x38\\xfb\\x28\\x93\\x22\\xa8\\x4f\\x38\\x68\\x0f\\x7d\\xa2\\xe3\\x2c\\x3f\\xd7\\x1c\\x52\\x7c\\xb4\\xea\\x39\\xcd\\xbc\\xe1\\xea\\x3c\\x49\\x3a\\xa6\\x93\\x64\\xf1\\x69\\x04\\xd2\\xd0\\x4a\\xd0\\xde\\xa1\\x37\\x03\\x28\\xd0\\xe3\\x4c\\x79\\x2e\\x8c\\xb9\\x13\\x60\\x23\\x8f\\x2e\\xc4\\xa7\\xf1\\x2a\\xb7\\x5c\\x6b\\x73\\xff\\x1b\\xa6\\x85\\x38\\x01\\xba\\x14\\x96\\xcb\\xca\\x5f\\x65\\x5c\\x8a\\xb0\\x4a\\xdb\\xa8\\xeb\\x9d\\x13\\xac\\x05\\x37\\x77\\x09\\x08\\xd9\\xa8\\x3f\\xc1\\xc3\\x38\\x68\\xad\\xc4\\xf0\\x56\\xd7\\x25\\x3b\\xe3\\x73\\x51\\x9d\\x71\\x23\\xa8\\xaf\\x34\\x45\\x0f\\xf7\\xe8\\xd0\\xec\\x75\\xc8\\xeb\\x6d\\x5f\\x1b\\x86\\x8c\\xc6\\x9f\\x68\\x12\\x86\\xbf\\xa2\\x8a\\x85\\x03\\x1c\\x78\\x13\\xe4\\xe7\\xba\\x11\\x03\\xf6\\xce\\x71\\xaf\\x01\\xfb\\xa2\\xae\\x95\\xbe\\xbd\\xdf\\x58\\xed\\x9d\\x5e\\x90\\x6c\\xa4\\x69\\xf8\\x87\\x87\\xd5\\xc9\\x0c\\x3e\\x61\\xb8\\x3b\\x8e\\x88\\x08\\xfe\\x06\\x53\\x63\\xce\\x6c\\xc2\\xa3\\x7e\\x44\\xee\\x9f\\x2b\\x26\\x28\\xa7\\x28\\xd6\\xfa\\xaa\\x16\\x06\\x91\\x6b\\xd6\\x82\\x24\\x76\\x35\\x39\\xff\\x20\\x14\\x25\\xf7\\x6d\\x1d\\xde\\x78\\x5d\\x2b\\x3f\\x52\\xcf\\xd7\\xae\\xe2\\x2f\\xb4\\xdf\\xf4\\xb2\\x45\\xb5\\x56\\xd4\\xb8\\x3b\\x22\\x30\\x19\\xe8\\x06\\xe3\\xd3\\xa6\\x11\\xae\\x37\\x3a\\x25\\x5c\\x2f\\x79\\x16\\x85\\x92\\xbb\\xac\\xa3\\x7e\\x76\\x67\\x97\\x3f\\x6d\\x5e\\xec\\x8d\\xbc\\x6f\\x1b\\x7f\\xda\\x6e\\x96\\xba\\xaf\\x41\\x6a\\xeb\\x9d\\xd9\\x6a\\x84\\x7a\\x31\\x3f\\xbd\\x98\\x9f\\xbe\\x25\\xf3\\xd3\\xd6\\x13\\x7f\\x97\\xc9\\xe9\\xdb\\x30\\x36\\x6d\\x9d\\xe2\\x5d\\x06\\xa6\\x67\\x69\\x5a\\xea\\x34\\xa3\\x3b\\xcd\\x49\\xcf\\xd6\\x90\\xb4\\x75\\x6a\\x1d\\x8d\\x47\\xbf\\x1d\\xb3\\xd1\\xd6\\x15\\xbb\\xc3\\x54\\xf4\\x0c\\x8d\\x44\\x5d\\x04\\x32\\x51\\x76\\x11\\x13\\xc7\\xc9\\xc3\\xa9\\xa0\\x18\\xcb\\x59\\x86\\xee\\x7c\\x50\\x4e\\x2a\\xce\\xec\\x2a\\x2d\\x3a\\x01\\x6e\\xeb\\xd8\\x0e\\x69\\x70\\xdd\\x65\\x2f\\x12\\x18\\xa9\\xd8\\xe3\\xca\\x60\\xd9\\xf9\\xdb\\x8b\\x4f\\x6f\\xcf\\x4e\\x3f\\xbf\\x3d\\x6f\\xcb\\x77\\xeb\\x56\\x7a\\x8b\\x24\\x76\\xb7\\x0d\\x62\\x98\\x48\\x62\\x1b\\x1e\\x70\\x04\\x79\\xc3\\x4f\\xee\\x0c\\x6c\\xf8\\xa9\\x69\\xe4\\xba\\x56\\xf7\\x97\\x0b\\xef\\xc5\\xe5\\xee\\xc5\\x3f\\xb6\\xdf\\xce\\xae\\xd7\\xf3\\x0b\\x06\\x4e\\x71\\x8a\\x39\\x73\\x72\\xcf\\x4c\\x57\\xa5\\xf1\\x71\\xab\\xe3\\xf3\\x90\\x49\\x25\\x55\\x51\\x35\\xa5\\x13\\x2e\\xbe\\x7c\\x19\\x9f\\x9b\\x11\\x63\\x6f\\x44\\xc1\\x1b\\x03\\x56\\x98\\x52\\xab\\x43\\xcb\\x7e\\xfc\\xf8\\xfe\\x3f\\x20\\x1e\\x1b\\x9e\\x18\\x04\\x5c\\x13\\x40\\xe5\\x95\\x1c\\x81\\x85\\x2d\\xc2\\xb5\\xb1\\x37\\x02\\x05\\x15\\x78\\x73\\xc1\\x17\\x8e\\x8a\\x19\\xac\\x5c\\x61\\x41\\x16\\x99\\x89\\x6a\\xe1\\x28\\xe6\\xb5\\x60\\x11\\x41\\xd5\\x75\\x1c\\x2b\\xcc\\xfb\\xf0\\xc9\\x2b\\x61\\x31\\xeb\\xea\\xae\\x08\\xc9\\x3b\\x57\\x6d\\x8b\\xc5\\xf5\\x1e\\xb6\\xd6\\x4c\\x7d\\x24\\x6d\\xfc\\x96\\x1b\\xb2\\x58\\xad\\x1d\\xed\\x96\\xfd\\xdd\\x6e\\x9f\\xd9\\x6c\\xe2\\xd8\\x60\\xdc\\x40\\xf2\\x0c\\x7f\\xad\\x8c\\xd9\\x0d\\x36\\xda\\x31\\x30\\x88\\x44\\xda\\xce\\xd6\\xd4\\xcd\\x61\\x40\\xeb\\xeb\\x00\\xac\\xd8\\x32\\x44\\x7b\\x91\\xb3\\x17\\x87\\x88\\xec\\x64\\xc8\\xdd\\xc6\\x02\\x45\\x44\\xca\\xac\\xf6\\x27\\xc5\\xcf\\xe5\\xdf\\x35\\x93\\x50\\xfd\\x35\\x8e\\x97\\x2c\\x32\\xec\\xff\\xfe\\xf1\\x4f\\xff\\xf4\\xff\\x02\\x00\\x00\\xff\\xff\\x7d\\xa3\\x14\\xcb\\xc4\\x98\\x0c\\x00\")\n\nfunc olmManifests0260CrdsYamlBytes() ([]byte, error) {\n\treturn bindataRead(\n\t\t_olmManifests0260CrdsYaml,\n\t\t\"olm-manifests/0.26.0-crds.yaml\",\n\t)\n}\n\nfunc olmManifests0260CrdsYaml() (*asset, error) {\n\tbytes, err := olmManifests0260CrdsYamlBytes()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tinfo := bindataFileInfo{name: \"olm-manifests/0.26.0-crds.yaml\", size: 825540, mode: os.FileMode(420), modTime: time.Unix(1730300877, 0)}\n\ta := &asset{bytes: bytes, info: info}\n\treturn a, nil\n}\n\nvar _olmManifests0260OlmYaml = []byte(\"\\x1f\\x8b\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xec\\x5a\\x6d\\x6f\\x1b\\xb9\\xf1\\x7f\\xaf\\x4f\\x31\\x10\\xfe\\x80\\xff\\x2d\\xb2\\x92\\xe5\\xc4\\xae\\xb3\\x40\\x80\\x73\\x9d\\xdc\\xe5\\x50\\xdb\\x11\\x6c\\xa7\\x6f\\x0e\\x41\\xc1\\xe5\\x8e\\x56\\xac\\xf9\\xb0\\x47\\x72\\xa5\\xe8\\x8a\\x7e\\xf7\\x82\\xcb\\x7d\\x16\\x25\\xcb\\x4e\\xee\\x52\\x14\\xe1\\x1b\\x49\\x24\\x87\\x33\\x9c\\x99\\x9d\\x87\\x9f\\x36\\x8a\\xa2\\x11\\xc9\\xd9\\xdf\\x51\\x1b\\xa6\\x64\\x0c\\xab\\xd9\\xe8\\x81\\xc9\\x34\\x86\\x1b\\x22\\xd0\\xe4\\x84\\xe2\\x48\\xa0\\x25\\x29\\xb1\\x24\\x1e\\x01\\x48\\x22\\x30\\x06\\xc5\\xc5\\x08\\x80\\x93\\x04\\xb9\\x71\\xb3\\x00\\xb9\\x4a\\x23\\x83\\xb4\\xd0\\xcc\\x6e\\x26\\x0f\\x45\\x82\\x5a\\xa2\\x45\\x33\\x61\\x6a\\x8a\\x72\\xa1\\x34\\xc5\\x18\\x34\\x1a\\xab\\x19\\xb5\\x98\\x1e\\x48\\x12\\xad\\x6a\\xa9\\x38\\xb1\\x68\\xec\\x63\\x64\\xa4\\x48\\x99\\x7d\\x0a\\x9f\\x92\\xe0\\xa9\\x5c\\xd6\\x44\\xcb\\xa7\\x30\\x71\\xfb\\xb7\\x78\\x3c\\x4f\\xed\\x39\\x6a\\x62\\x95\\x36\\xcf\\x50\\x7e\\x42\\x0c\\x72\\x26\\xf1\\xbb\\xea\\x9d\\xea\\xbd\\xae\\xef\\x50\\xaf\\x18\\xc5\\x0b\\x4a\\x55\\x21\\xed\\xd0\\x1e\\x41\\xb7\\x8f\\x6a\\x1b\\x44\\xc6\\x13\\x93\\x8a\\xd8\\xef\\x29\\x2d\\xe7\\x9f\\x8f\\xa1\\x85\\x75\\x42\\xe8\\x84\\x14\\x76\\xa9\\x34\\xfb\\x8d\\x58\\xa6\\xe4\\xe4\\xe1\\xbc\\x94\\xb2\\xb1\\xfd\\x25\\x2f\\x8c\\x45\\x7d\\xab\\x78\\xc8\\xfa\\x66\\x63\\x2c\\x8a\\x98\\x2a\\x69\\xb5\\xe2\\x1c\\x75\\xdc\\xc8\\xc2\\xd9\\x02\\xe9\\x86\\x72\\x8c\\x04\\x91\\x24\\x43\\x3d\\xd2\\x05\\x47\\x13\\x8f\\x22\\x20\\x39\\xfb\\x49\\xab\\x22\\x37\\x31\\xfc\\x32\\xfe\\xf3\\xf8\\xd3\\x08\\x9c\\xfe\\x54\\xa1\\x29\\x76\\xa6\\x56\\xa8\\x93\\xf2\\xe7\\x9a\\x58\\xba\\x1c\\xbf\\x80\\x31\\x67\\xc6\\xba\\xcf\\x0c\\xcb\\x0f\\xaa\\x91\\x58\\x74\\xdf\\x8a\\x3c\\xad\\xbe\\xe5\\xf5\\xde\\x14\\x39\\xfa\\x29\\xff\\x8d\\x3a\\xf1\\xa8\\xbb\\xa2\\x9b\\x43\\x43\\x09\\xaf\\x48\\x12\\x26\\xd3\\xf1\\xa7\\x51\\x04\\x52\\xc9\\xdb\\x4a\\x8c\\x8f\\xb7\\x57\\x21\\x49\\xdc\\xcf\\x2f\\xd3\\xe1\\x5f\\x99\\x4c\\x99\\xcc\\x1e\\x33\\x64\\xe2\\xb7\\x45\\xce\\x68\\x5a\\x71\\xbc\\xc5\\x85\\xdb\\x59\\x2b\\x6e\\x0f\\xd7\\x11\\xc0\\xb6\\xe1\\x9e\\x65\\x2e\\x53\\x24\\xff\\x44\\x6a\\x4b\\x8b\\x05\\x7d\\xf3\\xab\\xb8\\x60\\x13\\x3f\\x26\\x54\\x69\\x54\\xee\\x43\\xb4\\x9a\\xfb\\x70\\x75\\x7d\\xa9\\xe4\\x82\\x85\\x14\\x46\\xfd\\x05\\xb7\\x4e\\x24\\x79\\x6e\\xda\\x13\\xde\\x62\\xce\\xd5\\x46\\xa0\\xb4\\x8f\\xe8\\x7c\\x5b\\xd4\\x7e\\x40\\x23\\x79\\x3e\\x20\\x30\\x39\\x52\\xb7\\x66\\xac\\x26\\x16\\xb3\\x8d\\xdf\\x67\\x37\\x39\\xc6\\x70\\xab\\x38\\x67\\x32\\xfb\\x58\\x3a\\x66\\xe9\\xdf\\x39\\x67\\x94\\x98\\x18\\x66\\x8e\\x02\\x9d\\x2f\\x2a\\xed\\x29\\x84\\xf3\\xd9\\xab\\x0e\\xab\\x10\\x33\\x00\\x8b\\x22\\x77\\x3e\\x5b\\x11\\x75\\x2e\\xe3\\x06\\xef\\xd1\\x87\\x4f\\x00\\xa8\\x45\\x2e\\xbf\\x57\\xf1\\xe9\\x52\\x49\\x8b\\x9f\\x6d\\x4b\\xaa\\x0b\\x79\\x61\\x6e\\x94\\xbc\\x55\\xca\\xc6\\x60\\x75\\x81\\xcd\\x92\\x41\\x4a\\x95\\xc8\\xe7\\x5a\\x2d\\x18\\xc7\\x96\\xa4\\xb9\\x76\\x21\\x2d\\x13\\xf8\\x16\\x17\\xa4\\xe0\\xb6\\x61\\xd4\\x75\\x9b\\x9b\\x03\\x7c\\xc6\\x0d\\xe7\\xa4\\x84\\x49\\xd4\\x9d\\x4b\\x45\\x61\\xbb\\x75\\xa4\\x0b\\xdf\\xa8\\x54\\x08\\xe7\\x6a\\x3d\\xd7\\x6c\\xc5\\x38\\x66\\xf8\\xce\\x07\\x80\\xd2\\x61\\x16\\x84\\x1b\\xec\\xed\\xa5\\x24\\x27\\x09\\xe3\\xcc\\x32\\x34\\xfd\\x53\\x00\\x52\\xad\\xf2\\x18\\x7e\\x81\\xf1\\xc5\\xd5\\xd5\\x18\\x3e\\x75\\x56\\xa9\\x12\\x82\\xc8\\xb4\\x4b\\x10\\xc1\\x34\\x61\\x72\\xea\\xbd\\xa9\\x91\\x44\\x67\\xa6\\xbf\\x29\\x8a\\x1a\\xd7\\xeb\\xcd\\xff\\xdf\\xff\\x7f\\x98\\xbf\\xbb\\xbd\\xb8\\xff\\x70\\xfb\\x8f\\x9b\\x8b\\xeb\\x77\\x77\\xf3\\x8b\\xcb\\x77\\x7f\\x1a\\x50\\xae\\x35\\xb3\\x78\\x67\\x89\\x2d\\x8c\\x53\\x6d\\x6f\\x75\\x3c\\xee\\xfc\\x64\\x82\\x64\\x18\\xc3\\xaf\\x05\\xd9\\xb8\\xe8\\xd4\\x68\\x7f\\xa1\\x89\\xc0\\xb5\\xd2\\x0f\\x4e\\xcc\\x1f\\xcc\\x92\\x9c\\x9c\\x9e\\xc5\\x2f\\x8f\\x5f\\x9d\\xcf\\xce\\x5e\\xbe\\xc6\\xf3\\xd7\\xe4\\x98\\x26\\x27\\xe7\\x27\\x0b\\x3a\\x3b\\x3f\\x3d\\xa5\\xb3\\x64\\x91\\xa6\\xf8\\xfa\\x0c\\xe9\\x29\\xe2\\xcb\\xb3\\x74\\x46\\xcf\\x4e\\x67\\xf4\\x24\\x3d\\x4e\\xff\\xf2\\x9a\\x9e\\xa7\\x27\\xaf\\x5e\\xe3\\x4b\\x4c\\x4f\\x87\\x7c\\xe7\\x05\\xe7\\x73\\xc5\\x19\\xdd\\xc4\\xf0\\xf3\\xe2\\x46\\xd9\\xb9\\x46\\x83\\x8d\\xb1\\xa1\\xcc\\x99\\xda\\x0e\\xb4\\x1d\\xb5\\x5e\\x30\\x57\\xda\\xc6\\x70\\x7e\\x7c\\x7e\\x3c\\xb0\\x87\\xf7\\x08\\x81\\x2e\\xfd\\x9a\\xce\\x1a\\x67\\x2b\\x94\\x68\\xcc\\x5c\\xab\\x04\\xfb\\xc7\\x2e\\xad\\xcd\\x7f\\x42\\x3b\\xb4\\x6c\\x4e\\xec\\x32\\x86\\xe9\\x12\\x09\\xb7\\xcb\\xdf\\x86\\x8b\\xbb\\xf8\\x1b\\xba\\x44\\x27\\xc1\\xfb\\xfb\\xfb\\x79\\x67\\x49\\x23\\x49\\xd9\\x37\\xe4\\x6f\\x51\\x0b\\x26\\x4b\\x0f\\xbf\\x46\\x63\\x9c\\x09\\x2a\\xf5\\xff\\x48\\x38\\x4f\\x08\\x7d\\xb8\\x57\\x57\\x2a\\x33\\x1f\\xe4\\x3b\\xad\\x7b\\x4f\\x11\\xca\\x55\\xdf\\x3b\\xbd\\x86\\xb7\\x3d\\xb1\\x27\\xc8\\x8a\\xf0\\x02\\x7f\\xd4\\x4a\\x0c\\x6f\\xb5\\x60\\xc8\\xd3\\x2a\\x7f\\x05\\x56\\xe6\\xe5\\xa5\\xeb\\x68\\x36\\x09\\x3f\\x07\\x01\\x09\\xb6\\x99\\xef\\x0c\\x0b\\x6d\\x6d\\xd1\\x23\\xd2\\xf8\\x6b\\x81\\x66\\xe8\\x72\\x00\\x34\\x2f\\x62\\x98\\x1d\\x8b\\xc1\\xb4\\x40\\xa1\\xf4\\x26\\x86\\xd9\\xd9\\xf1\\x35\\xab\\xd6\\xa4\\x4a\\xf1\\xae\\x17\\xcb\\xdd\\xe8\\xd7\\x7b\\xca\\xc4\\xc0\\x99\\x2c\\x3e\\x7f\\x49\\xa2\\xa2\\xc4\\x12\\xae\\xb2\\xa7\\x25\\xab\\x2d\\xa2\\xdf\\x3b\\x61\\x05\\xa4\\x7c\\x46\\xd2\\x0a\\x9c\\xf2\\x3f\\x93\\xb8\\x82\\x77\\x7b\\xe4\\x56\\xf0\\x8d\\x93\\x57\\x25\\xf3\\xde\\x04\\x76\\xd4\\xc9\\x60\\x47\\xbd\\x95\\x7e\\xea\\x73\\x09\\x8b\\x96\\x05\\x9d\\x20\\xb9\\x2b\\x27\\x51\\xff\\xec\\xd2\\xc3\\x9b\\x3d\\x59\\xa9\\xd9\\xdf\\xea\\x5d\\x63\\xc6\\x8c\\xd5\\x9b\\xb8\\xd3\\xa2\\xb5\\x0c\\x0a\\xcb\\x78\\x54\\x66\\x9d\\xde\\xc2\\x1f\\x9f\\xf9\\x9c\\x30\\x06\\x6d\\xe4\\x58\\x70\\x45\\xd2\\xa8\\x30\\xa8\\x23\\x96\\xbe\\xe9\\xb9\\xe6\\xf7\\xcc\\xdc\\x8e\\xef\\x99\\x79\\x5f\\x66\\xfe\\xba\\x89\\xec\\xfc\\x4b\\xf2\\xd8\\x76\\x8f\\x79\\x70\\x4f\\xbc\\x9d\\xdd\\x48\\x96\\x69\\xcc\\x88\\x45\\xd7\\xef\\x46\\x98\\x32\\x3b\\x48\\x67\\xbb\\xcf\\x6b\\x49\\xad\\x8a\\x48\\x2a\\x98\\x8c\\x61\\xec\\x1e\\xaf\\xf1\\x53\\x08\\xb1\\x04\\x8a\\x2a\\xba\\x30\\x4c\\x11\\xea\\x53\\xb7\\x91\\x0b\\x53\\x24\\x86\\x6a\\x96\\x3b\\x4e\\xa6\\x8f\\x1d\\x1c\\x82\\x56\\x7c\\x7a\\x1e\\xd7\\xaa\\x13\\xae\\xb2\\x51\\x85\\x2d\\x99\\x12\\x22\\xf1\\xb1\\xbb\\xda\\xeb\\x66\\x98\\x34\\x96\\x70\\x9e\\x73\\xe2\\x77\\xec\\x91\\xb8\\x15\\xea\\xf7\\x35\\xf8\\x8a\\xe1\\xfa\\x5b\\x1a\\xfc\\x09\\x74\\x4e\\xd4\\xaf\\xe2\\x28\\x5f\\xcf\\x64\\x2f\\xa0\\x61\\x99\\x95\\x42\\xf4\\x8d\\x58\\x61\\x65\\x35\\x74\\xe6\\xb1\\xb4\\x2d\\x3f\\xcb\\x09\\x7d\\x20\\x19\\x9a\\xc9\\x61\\xd2\\x57\\xdb\\x05\\x91\\x6c\\xe1\\x22\\x8f\\xf7\\xe5\\xfe\\xdc\\x94\\x51\\x25\\x0f\\x93\\xe5\\x69\\x90\\x50\\xb5\\x5a\\x0a\\x1f\\xf0\\xad\\x8c\\xab\\x84\\xf0\\xa8\\x8b\\x4b\\x77\\x4b\\xe5\\x66\\xfa\\xeb\\x72\\xed\\x96\\x85\\x43\\x96\\x5c\\x34\\x95\\xb7\\x25\\x3a\\x43\\xdb\\xe0\\xe9\\x95\\xb7\\x47\\x4f\\x41\\xc6\\x08\\xcf\\x97\\x64\\x80\\x2c\\x56\\xc0\\x5c\\x45\\x1a\\x10\\xaf\\xb6\\x6f\\x59\\x71\\x3d\\xd6\\x3c\\x28\\x2e\\x26\\x0d\\x40\\xbd\\x3a\\x9e\\x9c\\x9c\\x4d\\x8e\\x9b\\x1b\\xa4\\xcc\\xe4\\x9c\\x6c\\x7c\\x31\\x3c\\xf7\\xc7\\xc2\\x5d\\x7d\\x6e\\x8a\\x8d\\x67\\xc6\\x70\\x8b\\xb9\\x2f\\x25\\x0c\\x10\\xd9\\x68\\xb0\\x96\\x05\\xec\\x92\\x58\\x60\\x06\\xc8\\x8a\\x30\\x4e\\x12\\x8e\\xb0\\xd0\\x4a\\x00\\x81\\xcc\\xd5\\x07\\x70\\xe9\\x9f\\x83\\xbb\\xd2\\xeb\\x60\\xbd\\x64\\x74\\x09\\x6b\\xc6\\x79\\xe9\\x89\\x7c\\x85\\x60\\x15\\x90\\xb0\\x02\\x26\\x23\\x00\\xc1\\xe4\\xdf\\x8a\\x04\\x1b\\x6d\\xce\\x26\\xb3\\xd9\\xc4\\x65\\xe8\\x07\\xdc\\xac\\x95\\x4e\\x9d\\x43\\x1e\\x0d\\x7d\\xf6\\xe8\\x05\\x1c\\x29\\x2e\\xdc\\x47\\xad\\xb1\\x23\\xe7\\xc1\\x82\\xb0\\x6e\\x4d\\x5f\\x57\\xf3\\xb7\\x98\\xc2\\x7b\\xe2\\x2b\\x25\\x14\\x84\\xf1\\xd2\\x68\\xd2\\x2c\\xd9\\xc2\\xb6\\xde\\xf0\\x83\\xc6\\x74\\x49\\xac\\x33\\xdf\\x08\\x20\\xd7\\x6a\\xc5\\x52\\xac\\xd2\\xec\\xf0\\x1c\\xce\\xe4\\x43\\x8f\\xc5\\x96\\x86\\x01\\x0a\\xcd\\xe3\\xb2\\x50\\x31\\xf1\\x74\\x9a\\x31\\xbb\\x2c\\x92\\xd2\\x35\\x42\\x65\\xe3\\x4e\\x74\\x77\\x6a\\x35\\xe2\\x54\\x10\\xa7\\xbc\\x69\\xfe\\x90\\x4d\\xab\\xfb\\x46\\x8d\\x8b\\x54\\x51\\xe7\\x5a\\xa5\\x58\\x49\\xe4\\x3b\\xa5\\x0f\\x6b\\x79\\xd3\\x6b\\xd2\\x4d\\x91\\xbb\\x12\\x08\\xd3\\xa6\\xe5\\xaa\\xb7\\xde\\x31\\x99\\x71\\x3c\\x74\\xf7\\x75\\xc1\\x2d\\x3b\\x74\\xf3\\x05\\xe7\\xed\\x53\\xb4\\x63\\x6f\\x75\\x03\\xaf\\xe9\\xa6\\xe7\\x85\\xb4\\x6d\\xb4\\x61\\xd0\\x59\\x56\\x51\\x79\\xee\\x2a\\x34\\x53\\x46\\xe4\\x7a\\x25\\x7a\\x66\\x33\\xe8\\x9a\\x52\\x8e\\xbd\\x4e\\xb0\\x0d\\xbc\\x83\\x8a\\x7a\\x07\\x9c\\xff\\x48\\xf5\\x17\\x41\\x05\\xd4\\x13\\x4a\\xd1\\x18\\x8d\\x2e\\x47\\x75\\xcb\\x6d\\x1f\\x7e\\x87\\xd5\\x7b\\x59\\x8d\\x0c\\x26\\x33\\xb4\\x8f\\xc9\\x39\\xc0\\x14\\x83\\x32\\x95\\xbd\\x81\\x6f\\xd9\\xf6\\xca\\xd1\\x67\\xe8\\x7e\\xbb\\xcc\\xd0\\x9b\\x28\\x53\\xc4\\x01\\x32\\x05\\xd3\\xd6\\x01\\x72\\xf6\\x72\\xed\\x1f\\x24\\xeb\\xfe\\x5c\\xfb\\xb8\\xd0\\xc3\\xa0\\xf5\\x6c\\xb1\\xdb\\x07\\xa1\\xe3\\xe6\\xe1\\x7c\\xe1\\x47\\xf7\\x51\\x01\\x18\\xe2\\x48\\xf5\\x08\\xe3\\x49\\x9d\\x6b\\x75\\x57\\x86\\x3d\\x8b\\x20\\x9f\\x3f\\xca\\x26\\x23\\x78\\xf0\\x69\\xb0\\x7e\\x57\\xe8\\x6c\\xb0\\xd2\\x82\\x55\\x27\\x3d\\x44\\x65\\xd8\\xd1\\x40\\x18\\xbc\\xaa\\x47\\x09\\x3f\\x85\\xaf\\x3e\\x44\\xb2\\x9a\\xd3\\x06\\x88\\x56\\x3d\\x86\\xc8\\xd6\\x41\\x2c\\xb6\\x35\\x0c\\x8f\\x01\\x43\\xb0\\x1f\\xf6\\xea\\x9c\\xb1\\x03\\xfe\\x6a\\xae\\xb7\\x1b\\x06\\x6b\\x0f\\x79\\x5e\\x04\\xf4\\x23\\xdc\\x63\\xd6\\x63\\x57\\xaf\\xd9\\xdf\\x15\\x82\\xd6\\xfc\\xd8\\xef\\xb8\\x07\\xab\\xf2\\x69\\x48\\x5b\\x25\\xd4\\x1e\\xbc\\xcd\\x8f\\xdd\\xa8\\x5b\\x7d\\xad\\x2d\\xec\\xad\\xbe\\x55\\x89\\xc0\\x6d\\xe5\\xe6\\xe1\\xae\\x68\\xf5\\xe6\\x55\\x68\\xda\\xbf\\x83\\x80\\x91\\x4b\\x8c\\x81\\xf5\\xf1\\xe9\\xab\\x57\\x2f\\xc7\\x41\\xc2\\xaa\\x8a\\x0e\\xc1\\xf1\\xf5\\xa6\\x3e\\xb2\\xe7\\xc7\\xb7\\x42\\xb2\\x3a\\xdc\\xbb\\x78\\xd6\\x05\\x5f\\x93\\x8d\\xd9\\xda\\x17\\xc0\\xb3\\x20\\x84\\x69\\x39\\xf5\\x04\\x0c\\x9a\\x6b\\x65\\x15\\x55\\x3c\\x86\\xfb\\xcb\\xf9\\xd6\\xfa\\x1e\\x74\\xcb\\x8f\\x1d\\x18\\x93\\x1f\\x5d\\xcc\\xe8\\x2e\\xb8\\x63\\x2f\\x16\\xd5\\xde\\x6f\\x87\\xf4\\xfb\\xc0\\xaf\\xff\\x02\\xf1\\x9e\\x8f\\x8d\\xd5\\xd7\\x0b\\xd6\\x48\\xf5\\x62\\x18\\x27\\xf3\\x63\\x07\\x5a\\xe6\\x47\\x8d\\x99\\x9d\\xb6\\x98\\x59\\x3b\\x56\\x8a\\x17\\x02\\xaf\\x5d\\xcc\\x0b\\x7a\\x95\\x8f\\x4c\\x56\\xe4\\x8b\\x6d\\x57\\x04\\x10\\x8e\\xce\\xff\\x0b\\x36\\xb5\\x22\\x1f\\x85\\xce\\xde\\x19\\xee\\xc2\\x87\\xa2\\xc8\\xed\\xe6\\x2d\\xd3\\x31\\xfc\\xeb\\xdf\\x65\\xf7\\x62\\xcb\\xa8\\x17\\x43\\xd9\\x3b\\xfa\\x8e\\xbc\\xdf\\xdd\\x95\\xaf\\x96\\x54\\xe1\\x3b\\xc5\\x05\\x93\\xcc\\xb6\\xd5\\xaf\\x5a\\x4b\\x4c\\xeb\\x4e\\x35\\xf3\\xef\\x9f\\xec\\x2d\\x62\\x2a\\x81\\x56\\x9d\\x17\\x97\\xfc\\x8c\\x6f\\x5a\\xab\\x9e\\xe6\\xba\\x2a\\x60\\x6a\\x0c\\xb2\\x1b\\xbf\\x87\\xc5\\x4d\\xa8\\xeb\\x1c\\xd0\\xf7\\x5a\\xcf\\x8b\\xe1\\xa6\\xb2\\xd1\\x6c\\xdc\\x03\\x32\\x94\\x4e\\x6c\\x4c\\x7d\\xcf\\x89\\x9f\\x99\\xb1\\x4c\\x66\\xfd\\xa6\\xd3\\xb5\\xad\\x29\\xd8\\x25\\x32\\x0d\\xfe\\x2d\\x94\\xeb\\xb6\\xa2\\x6d\\x8b\\xa7\\x9b\\x9d\\x89\\x27\\x14\\x4e\\x9e\\xd5\\xe5\\x77\\xa5\\xda\\xf3\\x0e\\xde\\xb2\\x48\\x98\\x8a\\xda\\xff\\x6b\\x76\\x80\\x10\\x5e\\x07\\xf7\\x65\\xc2\\xcf\\x74\\x4e\\x47\\x3b\\xe3\\x76\\x79\\x60\\xfd\\x07\\x50\\xfb\\x67\\x4b\\xcf\\x1a\\x97\\x4a\\x88\\x42\\x32\\xbb\\x69\\x3a\\x7c\\xa7\\xa2\\xbc\\x48\\x38\\x33\\x4b\\xd4\\x2d\\x74\\xf2\\xbe\\x48\\x7c\\x43\\xe3\\x78\\xce\\x55\\xea\\x55\\x5a\\x75\\x67\\xfd\\xc4\\x5c\\x2d\\xf5\\xdf\\xaa\\xf3\\xb0\\xe9\\x5d\\xaf\\xe6\\xac\\xff\\x08\\x9a\\xab\\xba\\xcf\\x73\\x6d\\x9f\\x45\\xbd\\x22\\x3c\\x86\\xb3\\x63\\x31\\xfa\\x4f\\x00\\x00\\x00\\xff\\xff\\x43\\x90\\x59\\x30\\x4c\\x2a\\x00\\x00\")\n\nfunc olmManifests0260OlmYamlBytes() ([]byte, error) {\n\treturn bindataRead(\n\t\t_olmManifests0260OlmYaml,\n\t\t\"olm-manifests/0.26.0-olm.yaml\",\n\t)\n}\n\nfunc olmManifests0260OlmYaml() (*asset, error) {\n\tbytes, err := olmManifests0260OlmYamlBytes()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tinfo := bindataFileInfo{name: \"olm-manifests/0.26.0-olm.yaml\", size: 10828, mode: os.FileMode(420), modTime: time.Unix(1730300876, 0)}\n\ta := &asset{bytes: bytes, info: info}\n\treturn a, nil\n}\n\nvar _olmManifests0270CrdsYaml = []byte(\"\\x1f\\x8b\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xec\\xbd\\x79\\x77\\x1c\\xb7\\xb1\\x38\\xfa\\xbf\\x3f\\x05\\x0e\\x93\\xfb\\x48\\x3a\\x33\\x43\\x29\\xdb\\x2f\\xe1\\x4d\\xe2\\xc3\\x4b\\xca\\x0e\\x9f\\x25\\x8a\\x47\\xa4\\x9d\\x77\\x7f\\xb6\\x6f\\x8c\\xe9\\xae\\x99\\x41\\xd8\\x0d\\x74\\x00\\xf4\\x90\\x93\\xeb\\x7c\\xf7\\x77\\x50\\x05\\xf4\\x32\\x1b\\x67\\x69\\x49\\xa4\\x0c\\xe4\\x9c\\x58\\x9c\\xee\\xc6\\x52\\x28\\xd4\\x5e\\x85\\x7e\\xbf\\xff\\x19\\x2f\\xc4\\xb7\\xa0\\x8d\\x50\\xf2\\x94\\xf1\\x42\\xc0\\x83\\x05\\xe9\\xfe\\x32\\x83\\xbb\\x3f\\x98\\x81\\x50\\x27\\xd3\\x97\\x9f\\xdd\\x09\\x99\\x9e\\xb2\\xf3\\xd2\\x58\\x95\\xbf\\x03\\xa3\\x4a\\x9d\\xc0\\x05\\x8c\\x84\\x14\\x56\\x28\\xf9\\x59\\x0e\\x96\\xa7\\xdc\\xf2\\xd3\\xcf\\x18\\xe3\\x52\\x2a\\xcb\\xdd\\xcf\\xc6\\xfd\\xc9\\x58\\xa2\\xa4\\xd5\\x2a\\xcb\\x40\\xf7\\xc7\\x20\\x07\\x77\\xe5\\x10\\x86\\xa5\\xc8\\x52\\xd0\\xd8\\x79\\x18\\x7a\\xfa\\x62\\xf0\\xc7\\xc1\\x8b\\xcf\\x18\\x4b\\x34\\xe0\\xe7\\xb7\\x22\\x07\\x63\\x79\\x5e\\x9c\\x32\\x59\\x66\\xd9\\x67\\x8c\\x49\\x9e\\xc3\\x29\\x4b\\xb8\\xe5\\x99\\x1a\\xd3\\x24\\xcc\\x40\\x15\\xa0\\xb9\\x55\\xda\\x0c\\x12\\xa5\\x41\\xb9\\xff\\xe4\\x9f\\x99\\x02\\x12\\x37\\xfa\\x58\\xab\\xb2\\x38\\x65\\x4b\\xdf\\xa1\\xfe\\xc2\\x24\\xb9\\x85\\xb1\\xd2\\x22\\xfc\\xcd\\x58\\x9f\\xa9\\x2c\\xc7\\x7f\\xfb\\xc5\\xd3\\xb0\\x37\\x38\\x2c\\xfe\\x9e\\x09\\x63\\xbf\\x5e\\x7c\\xf6\\x5a\\x18\\x8b\\xcf\\x8b\\xac\\xd4\\x3c\\x9b\\x9f\\x30\\x3e\\x32\\x13\\xa5\\xed\\x55\\x3d\\xbc\\x1b\\x2e\\xe1\\xd6\\xe8\\x84\\x1e\\x0b\\x39\\x2e\\x33\\xae\\xe7\\xbe\\xfd\\x8c\\x31\\x93\\xa8\\x02\\x4e\\x19\\x7e\\x5a\\xf0\\x04\\xd2\\xcf\\x18\\xf3\\x20\\xf4\\x5d\\xf5\\x19\\x4f\\x53\\xdc\\x16\\x9e\\x5d\\x6b\\x21\\x2d\\xe8\\x73\\x95\\x95\\xb9\\xac\\x86\\x72\\xef\\xa4\\x60\\x12\\x2d\\x0a\\x8b\\xa0\\xbf\\x9d\\x00\\x2b\\x34\\x58\\x3b\\x43\\x90\\x30\\x35\\x62\\x76\\x02\\x61\\xec\\xea\\x2b\\xc6\\xfe\\x61\\x94\\xbc\\xe6\\x76\\x72\\xca\\x06\\x0e\\xc2\\x83\\x54\\x98\\x22\\xe3\\x33\\x37\\x9b\\xc6\\x5b\\xb4\\x4d\\x17\\xf4\\xac\\xf1\\xbb\\x9d\\xb9\\xa9\\x1b\\xab\\x85\\x1c\\xaf\\x9b\\x8a\\x7b\\x6f\\xf3\\x39\\x10\\x68\\x6e\\x67\\xc5\\xe2\\x14\\xe6\\x7e\\xdc\\x74\\xfc\\xa2\\x1c\\x66\\xc2\\x4c\\x40\\x6f\\x3e\\x89\\xea\\x93\\x85\\x39\\x5c\\x2f\\x79\\xb2\\x62\\x22\\x8d\\x4e\\xc3\\x81\\x1a\\x2c\\x1c\\x86\\x85\\x01\\xce\\xc6\\x8b\\x6b\\x4c\\xb9\\x0d\\x3f\\xd2\\x4b\\xd3\\x97\\x3c\\x2b\\x26\\xfc\\xa5\\xff\\xd1\\x24\\x13\\xc8\\x79\\x8d\\x0f\\xaa\\x00\\x79\\x76\\x7d\\xf9\\xed\\x6f\\x6e\\xe6\\x1e\\xb0\\x36\\x74\\x5a\\x78\\xce\\x84\\x61\\x9c\\x69\\x28\\x94\\x11\\x56\\xe9\\x99\\x83\\xd6\\xf9\\xcd\\xb7\\xa6\\xc7\\xce\\xdf\\x5d\\x98\\x1e\\xe3\\x32\\xad\\x0e\\x1e\\x2b\\x78\\x72\\xc7\\xc7\\x60\\x06\\x0b\\x73\\x55\\xc3\\x7f\\x40\\x62\\x1b\\x3f\\x6b\\xf8\\x67\\x29\\x34\\xa4\\xcd\\x59\\x38\\xf0\\x04\\x98\\xcc\\xfd\\xec\\xe0\\xdf\\xf8\\xa9\\xd0\\x6e\\x4c\\xdb\\x38\\xc8\\xd4\\x1a\\x54\\xae\\xf5\\xfb\\xdc\\x0a\\x0f\\x1d\\x18\\xe8\\x3d\\x96\\x3a\\x02\\x07\\x06\\x51\\xc0\\x9f\\x31\\x48\\x3d\\xec\\x08\\x35\\x84\\x71\\xeb\\xd7\\x60\\x40\\x12\\xc9\\x73\\x3f\\x73\\xe9\\xd7\\x34\\x60\\x37\\xa0\\xdd\\x87\\xee\\xb8\\x97\\x59\\xea\\x28\\xe1\\x14\\xb4\\x65\\x1a\\x12\\x35\\x96\\xe2\\x5f\\x55\\x6f\\x86\\x59\\x85\\xc3\\x64\\xdc\\x82\\xb1\\x0c\\x4f\\xad\\xe4\\x19\\x9b\\xf2\\xac\\x04\\x02\\x65\\xce\\x67\\x4c\\x83\\xeb\\x97\\x95\\xb2\\xd1\\x03\\xbe\\x62\\x06\\xec\\x8d\\xd2\\xc0\\x84\\x1c\\xa9\\x53\\x36\\xb1\\xb6\\x30\\xa7\\x27\\x27\\x63\\x61\\x03\\x0d\\x4f\\x54\\x9e\\x97\\x52\\xd8\\xd9\\x09\\x92\\x63\\x31\\x2c\\x1d\\x39\\x3c\\x49\\x61\\x0a\\xd9\\x89\\x11\\xe3\\x3e\\xd7\\xc9\\x44\\x58\\x48\\x6c\\xa9\\xe1\\x84\\x17\\xa2\\x8f\\x93\\x95\\x48\\xc7\\x07\\x79\\xfa\\x0b\\xed\\xa9\\xbe\\x39\\x9c\\x03\\xdf\\x52\\x64\\x66\\x81\\x6c\\xae\\x85\\xb5\\x23\\x9e\\x84\\x45\\xf4\\x39\\xad\\xa5\\x06\\xa9\\xfb\\xc9\\x41\\xe5\\xdd\\xab\\x9b\\x5b\\x16\\x26\\x40\\x60\\x27\\x08\\xd7\\xaf\\x9a\\x1a\\xd8\\x0e\\x50\\x42\\x8e\\x40\\xd3\\x9b\\x23\\xad\\x72\\xec\\x05\\x64\\x5a\\x28\\x21\\x2d\\x1d\\xe9\\x4c\\x80\\xb4\\xcc\\x94\\xc3\\x5c\\x58\\x83\\x38\\x07\\xc6\\xba\\x7d\\x18\\xb0\\x73\\x64\\x61\\x6c\\x08\\xac\\x2c\\xdc\\x49\\x4a\\x07\\xec\\x52\\xb2\\x73\\x9e\\x43\\x76\\xce\\x0d\\xbc\\x77\\x50\\x3b\\x88\\x9a\\xbe\\x03\\xdf\\xe6\\xc0\\x6e\\x72\\xe0\\xc5\\x0f\\x16\\xce\\x18\\x63\\x81\\x43\\x6e\\xf4\\xf2\\xaa\\x43\\xc9\\xe8\\x04\\x2e\\xa3\\xc0\\x6c\\xcd\\x59\\x74\\x8d\\xa7\\xa9\\x06\\xb3\\xe4\\xc1\\xc2\\x81\\xa4\\x17\\x09\\x4f\\x26\\xca\\xb8\\xfd\\xe3\\x96\\xbd\\x7d\\xfd\\x86\\x25\\x5c\\xb2\\xd2\\x80\\x3b\\x3c\\x89\\x92\\xd2\\x21\\x84\\x55\\x8c\\x3b\\x5e\\xd6\\x87\\x07\\x61\\x10\\x81\\x34\\x8c\\x85\\xb1\\x7a\\x36\\x60\\x5f\\x2a\\x9d\\x73\\x7b\\xca\\xfe\\x14\\x7e\\xea\\x63\\x77\\x4a\\x33\\x51\\xfc\\xe5\\xf4\\x4f\\x85\\xd2\\xf6\\x2f\\xec\\xad\\xcc\\x66\\xae\\xd3\\x94\\xdd\\x4f\\x40\\xb2\\x9b\\x6a\\x6d\\xec\\xcf\\x8d\\x3f\\xbe\\xd2\\x45\\x32\\x60\\x97\\x63\\xa9\\x74\\x78\\xd3\\x61\\xd5\\x65\\xce\\xc7\\xc0\\x46\\x02\\x32\\xc4\\x6b\\x03\\x76\\x30\\xbf\\x83\\x6b\\x77\\x91\\x91\\xb8\\x34\\x12\\xe3\\x37\\xbc\\x78\\x14\\x34\\xe7\\xe1\\x4d\\x37\\x96\\x1b\\xbe\\xc9\\xbc\\xeb\\x87\\x56\\x21\\x2a\\xbb\\x25\\xb9\\x7f\\xf2\\xe4\\x8e\\x71\\x3f\\x4a\\xce\\x8b\\xbe\\xc1\\x63\\xd3\\x00\\xd3\\x66\\x10\\x38\\x0f\\x1d\\x38\\xf8\\xd5\\x3f\\x5f\\x7a\\xca\\x35\\xd8\\x76\\xd9\\xcd\\x95\\x6d\\xfd\\x6d\\x2d\\x86\\x3c\\x0a\\xb4\\x37\\xcb\\xb8\\xc8\\x06\\x63\\x8c\\x75\\x91\\x5c\\xab\\x94\\x96\\xfd\\xe8\\x28\\x5f\\x35\\xdf\\x66\\xf0\\x50\\x28\\x03\\x86\\xa5\\x62\\x34\\x02\\xed\\xe8\\x8e\\x9a\\x82\\xd6\\x22\\x05\\xc3\\x46\\x4a\\xe3\\x7e\\x15\\x2a\\xc5\\x33\\x59\\xed\\x5f\\x8b\\xd5\\x5e\\xab\\x74\\xd3\\x8d\\x71\\x43\\x23\\xc3\\x20\\x64\\xf4\\x68\\xb8\\x72\\xb9\\x4b\\x4f\\x3b\\x7b\\xe4\\xf0\\xba\\xc6\\x47\\x28\\xfe\\xcf\\x96\\x3f\\x9d\\x83\\xc7\\x99\\x7f\\x39\\x60\\xaa\\x97\\xa8\\x3c\\xe9\\x38\\x34\\x6e\\xf9\\x87\\xa6\\xea\\x73\\xd9\\x74\\x37\\x98\\xf2\\x26\\xd3\\x76\\x4d\\xaa\\x14\\xce\\x1e\\x99\\xfe\\xc2\\x12\\x2e\\xf0\\x8f\\x21\\x18\\xfc\\xbc\\x9a\\x2a\\x72\\xf0\\xb4\\xcc\\x90\\xd4\\x94\\x59\\x7b\\x47\\x57\\xad\\x63\\xc3\\xb5\\x6c\\xba\\x1e\\x7a\\x0f\\x46\\xa0\\x35\\xa4\\x17\\xa5\\xc3\\xdf\\x9b\\x6a\\x56\\x9e\\x48\\xd1\\xcf\\xaf\\x1e\\x20\\x29\\x57\\x9d\\xb1\\x95\\x4b\\x77\\x42\\xb1\\x5f\\x26\\x68\\x76\\x2f\\xb2\\xcc\\x0f\\xe7\\x08\\x4a\\x78\\xe0\\xd6\\x8b\\x72\\x8c\\x03\\x8f\\x21\\x22\\x6d\\xb8\\x15\\x66\\x34\\x43\\x70\\x54\\x00\\x83\\x07\\xc7\\xb3\\x51\\x63\\x41\\x8c\\x17\\x23\\x01\\x29\\x1b\\xce\\x3c\\xbb\\x76\\xc4\\xb3\\xc7\\x86\\xa5\\x65\\xc2\\x22\\x2f\\x4f\\x26\\x4a\\x19\\x60\\x9c\\xe0\\x8e\\xfd\\x4e\\x85\\x42\\x49\\x89\\x29\\x09\\x8e\\xfe\\xe4\\x8e\\x21\\xfb\\x83\\xd3\\xe8\\x7e\\x80\\x33\\xaf\\x3f\\x13\\x86\\xe5\\x8e\\xe2\\x57\\xb0\\x0a\\xe8\\xe8\\xba\\xb9\\x17\\x76\\x82\\x7f\\x8c\\x9d\\xc8\\xed\\xa4\\x30\\x53\\xe6\\xae\\xd3\\x7b\\x10\\xe3\\x89\\x35\\x3d\\x26\\x06\\x30\\xc0\\xdd\\x05\\x9e\\x4c\\x1a\\xdd\\xe6\\x00\\xd6\\x30\\x9e\\x65\\x61\\x0a\\x4d\\x94\\x20\\xbe\\x99\\x3b\\x11\\x85\\x1d\\x55\\x32\\x8c\\x97\\x37\\x7a\\x15\\x5f\\x9d\\xdf\\xb5\\xa5\\xe0\\xea\\x31\\xb0\\xc9\\xe0\\xb8\\xc7\\x12\\x95\\x17\\xa5\\x75\\x30\\x71\\x73\\x1c\\xce\\x98\\xb0\\x4e\\xce\\x26\\x79\\x49\\xab\\x72\\x4c\\x2b\\x81\\xcc\\x0f\\x1c\\x84\\x55\\xe2\\x4c\\x8e\\x38\\x38\\x1d\\x51\\x8e\\xd9\\x01\\x2d\\xee\\x20\\xc8\\x9f\\xae\\x3b\\x41\\x8b\\xc0\\xf5\\xe5\\xdc\\x26\\x13\\x2f\\x02\\x27\\x4a\\x6b\\x30\\x85\\x92\\xf8\\x25\\x3e\\x79\\x55\\xcf\\xed\\x3f\\xab\\x8f\\x8e\\xcc\\x71\\x0d\\xcc\\x89\\x18\\x4f\\x02\\x2c\\xb9\\x06\\xfc\\xad\\xbd\\x07\\xeb\\xce\\x48\\x7d\\x4e\\xb8\\xd6\\x2d\\x5d\\x72\\x59\\x13\\x16\\xf2\\x47\\x4e\\xc9\\x02\\x6a\\x9f\\x49\\x06\\x79\\x61\\x67\\x0d\\x9c\\x68\\xec\\x9e\\x05\\x9d\\x57\\x30\\xc0\\x0d\\xc6\\xe3\\x6a\\x68\\x7d\\x22\\x2f\\x32\\x91\\x08\\xeb\\x31\\x84\\xbd\\x60\\x47\\x88\\x22\\xc2\\x3a\\x52\\xc6\\xa4\\xea\\xab\\xe2\\x78\\xc0\\xce\\xd0\\x7c\\xb1\\xc1\\x00\\x52\\x55\\xfd\\xfb\\x8e\\xdc\\xa0\\x46\\xd5\\x7d\\x3d\\xba\\xb6\\x0d\\x89\\x0a\\xb5\\xd5\\x32\\xdd\\x62\\xeb\\xfb\\xf9\\x83\\x4c\\xe6\\xa5\\xbc\\xe5\\xaf\\x13\\x4c\\x1e\\x7d\\x75\\x53\\xf2\\x16\\xde\\x0e\\x73\\xd8\\xe4\\xed\\xf9\\xad\\x26\\x94\\x36\\x90\\x41\\xe2\\x54\\x52\\x07\\xfb\\x1e\\xe3\\xc6\\xa8\\x44\\x38\\x29\\xbf\\x46\\xda\\x36\\xa6\\xd3\\x4a\\x1e\\x87\\x3d\\xdb\\x16\\xfe\\x6c\\xeb\\xf5\\xbb\\x36\\x7f\\xf0\\x36\\xfd\\x6e\\x01\\x1a\\x99\\x70\\xc2\\xef\\x68\\x0e\\x2a\\x2d\\x82\\x35\\x9c\\xe1\\xd3\\x43\\xc3\\x32\\x3e\\x84\\xcc\\x6c\\x06\\x04\\xb6\\xd5\\xa9\\xad\\xdb\\x86\\xe7\\x77\\xe5\\x82\\x56\\x2e\\xc4\\xeb\\x98\\xd5\\xc6\\x3b\\xa2\\xed\\x74\\x33\\x2e\\xa4\\xf1\\xfa\\x73\\x8f\\x71\\x76\\x07\\x33\\x52\\xb5\\x9d\\x06\\x1f\\x0c\\x17\\xf8\\xb2\\x06\\x62\\x37\\x0e\\x39\\xee\\x60\\x86\\x2f\\x79\\xbd\\x7b\\x8b\\xe9\\x6e\\x8d\\x1c\\xd4\\xb6\\x39\\xa6\\x75\\xeb\\xbb\\x89\\x6e\\xf9\\x45\\x58\\xf4\\x16\\x9f\\x6d\\x8f\\xbf\\xd4\\xee\\x60\\xad\\xe4\\xb5\\xac\\x2d\\x88\\x24\\x88\\x93\\xb8\\x1f\\xb8\\x49\\xc8\\xbf\\xc2\\x1e\\xf3\\xa2\\xc8\\x04\\xa0\\x3e\\xbf\\xe5\\x30\\x6b\\xb5\\x80\\x75\\x2d\\x40\\x6f\\xaf\\x75\\xbd\\xab\\x0c\\x1a\\x84\\x90\\x87\\x86\\x90\\xcf\\x9d\\xf4\\x89\\x28\\x48\\xbf\\x35\\x80\\x07\\x37\\x58\\x7e\\xbe\\xe5\\x99\\xa8\\x4d\\x6d\\x06\\xf9\\xec\\xa5\\xec\\xb1\\x2b\\x65\\xdd\\x7f\\x5e\\x39\\x4d\\xd8\\xf4\\xd8\\x85\\x02\\x73\\xa5\\x2c\\xfe\\x39\\x60\\x5f\\x59\\xc2\\xf5\\xd7\\x1b\\x52\\xb6\\x0e\\x00\\x44\\xf3\\xdd\\x0b\\x3c\\x67\\x92\\x68\\x8a\\x5b\\x7e\\xd3\\x66\\x64\\x06\\xec\\x92\\xc4\\x96\\xea\\xe0\\x0a\\xc3\\x2e\\xa5\\x13\\x0e\\x3d\\x18\\xd0\\x8a\\x87\\xef\\xfa\\x2e\\xf2\\xd2\\xa0\\x91\\x47\\x2a\\xd9\\x47\\x19\\x60\\x69\\x1f\\x04\\x3d\\xd7\\x4f\\x13\\x7e\\x6b\\xba\\x5b\\xdd\\xd5\\x57\\x68\\x6b\\x78\\xbd\\xf2\\xe3\\x09\\x9f\\xa2\\x48\\x27\\xe4\\x38\\xab\\x84\\xb7\\x1e\\xbb\\x9f\\x88\\x64\\x42\\x52\\xf7\\x10\\xc8\\x34\\x58\\x68\\x70\\x0c\\x8b\\x1b\\x47\\xaa\\xdc\\x2f\\x63\\xd0\\x4e\\xd8\\x15\\xa1\\x3f\\x32\\x4c\\x66\\x3c\\x81\\x94\\xa5\\x28\\x5a\\x92\\x91\\x8d\\x5b\\x18\\x8b\\x84\\xe5\\xa0\\xc7\\xc0\\x0a\\xc7\\x49\\x76\\xdb\\xfd\\xed\\x08\\x3b\\xb5\\xad\\xc9\\x7b\\x73\\xc0\\xad\\xd0\\x0d\\x59\\xe4\\x97\\x4e\\xd6\\xfd\\x40\\xdc\\x11\\xe5\\xea\\xc8\\x1d\\x23\\x77\\x9c\\x6b\\x91\\x3b\\x56\\x2d\\x72\\xc7\\x47\\x5a\\xe4\\x8e\\x91\\x3b\\xbe\\x77\\xee\\x48\\xba\\xec\\x0e\\xca\\xf3\\xdf\\xc8\\xc4\\x31\\xaf\\x2d\\x23\\xa7\\x0d\\x6e\\xba\\xb6\\xda\\xec\\xf8\\xcd\\x8d\\x27\\x38\\xb7\\xa8\\x6a\\x0b\\x72\\x92\\x68\\x2e\\xc7\\xc0\\x5e\\xf6\\x5f\\xbe\\x78\\xb1\\x8d\\x52\\xed\\x37\\x72\\xa3\\x2f\\x46\\xde\\xd3\\x23\\xa4\\xfd\\xcd\\xaf\\xd7\\x7e\\xb1\\xca\\xfe\\xd6\\x81\\xd5\\xd4\\xe3\\x78\\x65\\xc8\\x6b\\xc9\\x0e\\x2b\\x0c\\x9f\\x48\\x9d\\xa4\\xb2\\x2c\\x07\\xcb\\xb8\\x6d\\x99\\x8a\\x44\\x0e\\xbd\\xca\\x55\\x80\\x08\\xef\\xbd\\x94\\xc1\\x02\\x9b\\x32\\x25\\xbd\\x1d\\xcf\\x01\\x7f\\xb0\\xdb\\x0c\\x12\\xe0\\xe4\\x52\\x1b\\x42\\x35\\x0b\\x95\\xbb\\x51\\x85\\xb4\\xe1\\xb8\\xb8\\x29\\x40\\x80\\x0a\\x3b\\x82\\xc1\\x78\\xc0\\xd2\\x12\\x3f\\xe3\\xd2\\xbb\\x4d\\x8f\\x69\\xb6\\x66\\x66\\x2c\\xe4\\x68\\xc9\\x55\\x1a\\xff\\xe3\\xa6\\x6d\\xf5\\xcc\\xbd\\x0c\\x53\\x90\\xb6\\xe4\\x59\\x36\\x63\\x30\\x15\\x89\\xad\\xd6\\x87\\x5e\\x5b\\x61\\xc9\\xd8\\xbe\\x99\\x89\\x70\\x23\\xd1\\x61\\x73\\x71\\xa1\\xbf\\x80\\xc1\\xe6\\x91\\x6f\\xb6\\xe1\\xf6\\x0b\\x7d\\x6f\\x72\\x26\\xe7\\x78\\x21\\xad\\x64\\xb0\\x52\\x58\\xb5\\xae\\x5f\\xb2\\x81\\xe3\\x3f\\x11\\xb9\\xde\\xbe\\x7b\\xdc\\xe4\\xca\\xb6\\xa6\\x64\\x5b\\x50\\xaf\\x79\\xb1\\xb4\\xcc\\x32\\x87\\x18\\x64\\x85\\x5d\\x5c\\xc0\\x12\\xeb\\x28\\x2d\\xa9\\x85\\xcc\\x64\\x78\\x27\\x13\\xf3\\xd9\\xd5\\x85\\x83\\x8a\\x7b\\xe7\\x56\\x15\\x2a\\x53\\xe3\\x59\\x13\\xd2\\x14\\x5e\\x24\\xf2\\x22\\x18\\xc7\\x39\\x33\\xe5\\xd0\\x0b\\x0d\\x0e\\xfd\\xae\\xe6\\xb6\\x26\\x5a\\xfe\\xa2\\xe5\\x2f\\xea\\x36\\x0b\\x2d\\xea\\x36\\x55\\x8b\\xba\\xcd\\x23\\x2d\\xea\\x36\\x51\\xb7\\x89\\x96\\x3f\\x16\\xb9\\xe3\\x1a\\x98\\x44\\xee\\xc8\\x22\\x77\\x5c\\xb9\\xae\\xc8\\x1d\\xd7\\x82\\x27\\x72\\xc7\\xc8\\x1d\\x97\\xb5\\x42\\xa5\\x7b\\x04\\x3a\\x16\\x2a\\x5d\\x13\\xe7\\x48\\x56\\x9f\\x44\\xf5\\x33\\x95\\x70\\xeb\\xe3\\xf2\\xdd\\x27\\xde\\xce\\x67\\x78\\x4e\\x86\\xa8\\x1e\\xfb\\x97\\x92\\x40\\xc1\\x6b\\x6e\\x6f\\xd0\\x9c\\xa4\\xec\\x04\\xb4\\x7b\\xfd\\xc8\\x1c\\xaf\\x0d\\x6c\\x8a\\x71\\x92\\x31\\x4e\\xf2\\xc9\\xc7\\x49\\x4e\\xb8\\xa1\\x7d\\x25\\xa2\\xb4\\x3a\\x6c\\xb2\\x71\\x20\\x6f\\x41\\xe7\\xcf\\x34\\x6a\\xd2\\xa1\\x8b\\xdf\\x6e\\xcc\\x78\\xaa\\xb7\\x94\\x56\\x9e\\x7a\\x7f\\x01\\xa4\\xd7\\xed\\xf5\\x7a\\x79\\x19\\x17\\xc5\\xd3\\x14\\x52\\x56\\x80\\xee\\x13\\x8a\\x28\\x36\\x12\\x32\\x5d\\xb2\\xd6\\x00\\x9f\\x8f\\x1a\\xfd\\xd8\\x5e\\xc7\\x47\\x0c\\x81\\x6c\\x4f\\x64\\x07\\x9b\\x6b\\xd3\\x70\\xdc\\xa2\\xf0\\x4f\\x22\\x20\\x72\\x5b\\xa9\\xbe\\xcf\\xac\\x37\\xf2\\x7e\\xbd\\xa1\\x5c\\xbf\\xbd\\x68\\x8e\\x02\\x75\\x30\\x09\\xef\\xae\\x57\\xa2\\x58\\xfe\\xcf\\x12\\xf4\\x0c\\xf3\\x3f\\x6a\\x81\\xb5\\xca\\xad\\xf3\\x3e\\x32\\x61\\x58\\xc2\\x0d\\x71\\x8a\\x6d\\x55\\xcb\\x2d\\xd5\\xa8\\xdd\\xf4\\x94\\xdd\\x2d\\xd1\\x6c\\x1e\\x2e\\xf3\\x5d\\x91\\x4e\\x1a\\x74\\x70\\x82\\xd9\\x52\\x25\\x7c\\x89\\x17\\xa0\\xb6\\xfe\\x6f\\x35\\x9f\\x5d\\x45\\xb7\\x9d\\x04\\xb7\\xa5\\x48\\xf1\\x84\\x95\\x73\\xb6\\xbb\\x82\\xce\\x76\\x56\\xd2\\xd9\\x4e\\x8a\\x3a\\xdb\\x55\\x59\\x67\\x7b\\x28\\xec\\x6c\\x37\\xa5\\x9d\\xcd\\xa3\\x82\\xdb\\x21\\x2f\\x65\\xbd\\x1f\\xfd\\x9d\\xed\\xa3\\xa2\\xb2\\x3d\\xf4\\x78\\x36\\xbf\\xd4\\x0a\\x4d\\xf5\\xfb\\x52\\xea\\x11\\xd7\\x5b\\x7a\\xfd\\x87\\x06\\xd6\\x6e\\x3a\\x3d\\x9b\\x07\\x95\\x57\\x86\\x05\\x2a\\xb4\\xcf\\x44\\xc3\\xff\\x20\\xea\\x36\\xdb\\x4b\\xe5\\x66\\xbb\\xab\\xdd\\x6c\\x77\\xcc\\x40\\x56\\xf7\\x1a\\xdd\\xa9\\xfb\\x32\\x4c\\xea\\x85\\x58\\x04\\xe6\\xe0\\x8e\\xd8\\xff\\x3a\\x4e\\x80\\xfb\\xf2\\x6f\\x56\\x70\\xa1\\x8d\\x93\\xef\\xbc\\xcd\\xa4\\xf9\\xcc\\x6b\\xe7\\xcd\\x6e\\x72\\x4a\\x21\\x76\\xa4\\x7a\\xca\\x33\\xc7\\x7b\\x28\\x8e\\xc3\\xeb\\x45\\xae\\xf7\\x79\\x36\\xdd\\x63\\xf7\\x13\\xa7\\x6d\\x3a\\x2a\\x55\\xe5\\x3b\\x1f\\xdc\\xc1\\xec\\xa0\\xb7\\x80\\x48\\x07\\x97\\xf2\\x80\\x78\\xd4\\x02\\xea\\x54\\x0c\\x4d\\xc9\\x6c\\xc6\\x0e\\xf0\\xd9\\x41\\xd7\\x9c\\x7d\\x07\\xc6\\xd5\\x2c\\xa1\\xb2\\x2b\\x5f\\xd8\\x01\\x4b\\x64\\x28\\xeb\\xd2\\xbd\\xb0\\x49\\x5c\\x84\\x1c\\x1b\\x61\\x14\\x53\\x33\\x18\\x0c\\xb5\\x68\\x30\\x97\\x2a\\x6a\\x04\\x71\\x0c\\x7f\\x4f\\x83\\xf2\\x5b\\x4a\\x5f\\xe9\\x22\\xe4\\x9c\\xfb\\xce\\x88\\x49\\x2d\\x86\\x34\\xf9\\x8d\\x57\\x12\\x0c\\x0a\\x76\\x50\\x99\\x88\\x1a\\x1f\\xe3\\xbb\\x03\\x0a\\x07\\xa9\\xb9\\x9d\\x4c\\xe7\\x03\\x44\\xea\\x2f\\x50\\x46\\xcc\\x81\\x4b\\xc3\\x0e\\x82\\xed\\xe9\\xd0\\xd4\\x6f\\x1c\\x0c\\xea\\xec\\xbe\\xaa\\xc7\\xa3\\xff\\xfd\\xf7\\x71\\x2b\\xa3\\xaf\\xee\\x30\\x4a\\xda\\x51\\xd2\\x8e\\x92\\xf6\\x16\\x5f\\x45\\x49\\x7b\\x75\\x8b\\x92\\xf6\\x16\\x2d\\x4a\\xda\\x51\\xd2\\x5e\\x37\\x70\\x94\\xb4\\xa3\\xa4\\xfd\\xf8\\xe0\\xbb\\x49\\xda\\xbb\\xc6\\x09\\x35\\xe5\\x5e\\xef\\x9c\\xa3\\x42\\x66\\xdc\\x8a\\xa4\\x8e\\x21\\x0a\\x6f\\xd1\\xbf\\xba\\x95\\xb7\\x9b\\xb2\\xf4\\x72\\x69\\xbb\\x29\\x91\\x2f\\xe8\\x16\\x83\\x47\\x44\\xeb\\x4a\\xf8\\x5e\\xf8\\x72\\xbd\\xd4\\xfd\\xb4\\x62\\xa1\\x76\\xc0\\x8d\\x86\\x43\\x61\\x47\\xe4\\xb8\\x0d\\xae\\x70\\x5f\\xf8\\x6f\\x08\\xb5\\x9f\\x3c\\x65\\x47\\xc1\\xe3\\x72\\xec\\x80\\x2f\\x95\\x6d\\x3f\\x94\\x56\\xf4\\xeb\\x37\\x2a\\x1f\\x0c\\xba\\x17\\x5b\\xf9\\x36\\x2d\\xb7\\x44\\xe5\\x75\\xaf\\x3c\\xc5\\xf5\\x7e\\x3a\\x12\\x02\\xba\\x35\\x07\\x61\\x7c\\x79\\x43\\x8c\\x96\\xd0\\xa5\\x94\\xae\\x57\\x25\\x83\\xfb\\x98\\x68\\x0e\\xd5\\xe3\\xf3\\x98\\x47\\xc2\\x12\\xce\\x07\\x25\\xa6\\x1a\\x4a\\x0d\\x7f\\x27\\xb7\\x54\\x02\\xd1\\x87\\xf2\\x2b\\xe9\\x3d\\xa2\\xee\\x97\\xe0\\xf5\\x0d\\x48\\x89\\x2b\\x12\\xd5\\xe8\\x03\\xf6\\x0a\\xf1\\xb0\\xd9\\xb1\\x30\\x08\\x1f\\x9e\\x65\\xea\\x7e\\x1b\\x92\\xf4\\xa1\\xd2\\xa2\\xee\\xb7\\x4e\\x8b\\x9a\\xf3\\xdf\\xc5\\xac\\xa8\\x9f\\x49\\x56\\x14\\x3e\\xa4\\x23\\xd4\\x79\\x7a\\x14\\xfb\\x9b\\x2f\\x40\\xa8\\x01\\x41\\x95\\x97\\x99\\x15\\x45\\x1d\\x2b\\x65\\x68\\xa8\\x8c\\xa4\\xcc\\x91\\x8f\\x3c\\x69\\xe3\\xa5\\x1b\\x8d\\x27\\x93\\x79\\xfc\\xc4\\xfe\\x30\\xb6\\xca\\xe0\\xa1\\xf5\\xd1\\x1d\\x3c\\xcb\\x7c\\x4e\\x51\\x10\\x49\\x29\\x84\\x45\\x7c\\xec\\xc8\\x84\\x0b\\x5f\\xb3\\xb5\\xd2\\x66\\x90\\xc8\\x1c\\x39\\x5a\\x98\\xb9\\x0d\\x75\\x54\\x6d\\x0d\\x11\\x25\\xa5\\x68\\x0a\\x81\\xf5\\x8e\\xc5\\x14\\x64\\x4d\\x49\\x8f\\xcc\\xf1\\x71\\xe0\\xe1\\x9d\\x52\\xf8\\xf7\\x42\\xa1\\xff\\xd4\\xa0\\xa4\\x7f\\xd9\\x84\\x46\\xe3\\x82\\x2a\\x2a\\x5d\\x83\\xaf\\xa6\\xd1\\x1f\\x33\\x04\\x63\\x1b\\x3f\\xff\\x76\\x36\\x86\\x1d\\xfc\\xfb\\x1f\\xd0\\xb7\\xff\\x7c\\x32\\xcb\\x3e\\xb2\\x85\\xf1\\x63\\xc4\\xd6\\x3f\\x79\\xab\\x62\\x0c\\xae\\xaf\\xdb\\xbe\\xc1\\xf5\\xef\\xdd\\x72\\xf8\\x71\\x63\\xec\\x9f\\x81\\xb5\\xf0\\x63\\xc6\\xd8\\x47\\x0b\\xe1\\xda\\x4d\\x79\\x6a\\xa1\\xef\\xed\\xb6\\x93\\x45\\x30\\x5a\\x03\\x77\\xe6\\xc2\\x5b\\x32\\x9c\\x7d\\xad\\x80\\x5b\\x62\\xc4\\x8e\\x7e\\xf6\\xe8\\x63\\xff\\x30\\x3e\\xf6\\x28\\xf1\\x6e\\xd8\\xa2\\xc4\\xbb\\x12\\x28\\x51\\xe2\\x65\\x51\\xe2\\x7d\\x6c\\x79\\x51\\xe2\\x5d\\x0b\\x9e\\x28\\xf1\\xae\\xdd\\x94\\x28\\xf1\\x46\\x89\\x97\\x3d\\x37\\x89\\x77\\x97\\x2a\\x5d\\xd1\\xd7\\xbd\\x97\\xaf\\x7b\\x5b\\x6a\\xb1\\x15\\x8d\\xd8\\x12\\x0f\\xb6\\xf6\\x6d\\x47\\xbf\\xf6\\x53\\xf1\\x6b\\x6f\\x9c\\xf0\\x2f\\xad\\xd8\\x37\\xe9\\xbf\\xb9\\x57\\xab\\x32\\xff\\xf9\\x54\\x89\\x94\\x15\\xa5\\xf5\\xf9\\xd4\\x31\\xfb\\xbf\\x8b\\xec\\xff\\x16\\xe4\\x63\\x09\\x80\\x8d\\x4a\\x00\\xac\\x82\\x59\\xac\\x03\\x10\\xeb\\x00\\x74\\xec\\x84\\x8e\\x75\\x00\\x62\\x1d\\x80\\x58\\x07\\x20\\xb4\\x98\\x9d\\xc4\\x62\\x76\\xd2\\x46\\x2d\\x66\\x27\\xad\\x6e\\x31\\x3b\\xe9\\xc9\\x5a\\x5f\\x59\\xcc\\x4e\\x7a\\xda\\x96\\x58\\x16\\xb3\\x93\\xa2\\x75\\x76\\xc3\\x8d\\x7a\\x86\\xd9\\x49\\xb1\\x0e\\xc0\\x53\\x8d\\x51\\x60\\x51\\xd2\\x8e\\x92\\x76\\x94\\xb4\\xa3\\xa4\\xbd\\xbe\\x45\\x49\\x7b\\x8b\\x16\\x25\\xed\\x28\\x69\\xaf\\x1b\\x38\\x4a\\xda\\x51\\xd2\\x7e\\x7c\\xf0\\x58\\x07\\xe0\\x19\\xc5\\x46\\xb0\\x58\\x07\\x20\\xc6\\x4b\\xc4\\x3a\\x00\\x3f\\xdf\\x3a\\x00\\x2d\\xdf\\xfd\\xc7\\x2b\\x06\\xb0\\xfd\\x34\\x62\\x45\\x80\\x58\\x11\\x20\\x56\\x04\\x88\\x15\\x01\\x42\\x8b\\x15\\x01\\xa8\\x3d\\x25\\x5b\\x63\\xcc\\x8f\\x5a\\x09\\x94\\x98\\x1f\\xc5\\x62\\x7e\\xd4\\x63\\xcb\\x7b\\x06\\x76\\xc3\\x98\\x1f\\xf5\\x04\\x6d\\x85\\x31\\x3f\\x2a\\xda\\x05\\xe7\\x37\\xe7\\x99\\xe4\\x47\\xc5\\x8a\\x00\\x4f\\xd1\\xdb\\x1e\\x25\\xde\\x0d\\x5b\\x94\\x78\\x57\\x02\\x25\\x4a\\xbc\\x2c\\x4a\\xbc\\x8f\\x2d\\x2f\\x4a\\xbc\\x6b\\xc1\\x13\\x25\\xde\\xb5\\x9b\\x12\\x25\\xde\\x28\\xf1\\xb2\\xe7\\x26\\xf1\\xc6\\x8a\\x00\\xb1\\x22\\x40\\xac\\x08\\xf0\\x1c\\x3d\\xdc\\x8f\\xee\\x34\\x3c\\x58\\xcd\\x13\\x7b\\xae\\xa4\\x05\\xb9\\xd2\\xaf\\xdd\\xda\\xd0\\x57\\xad\\x4f\\x1c\\x91\\x1c\\x89\\x71\\xa9\\xbd\\x0c\\x3e\\x7e\\x77\\x7d\\xce\\x12\\x6e\\x79\\xa6\\xc6\\xec\\x5a\\xe1\\x21\\xf5\\x83\\x54\\x3f\\xe7\\x60\\x79\\xca\\x2d\\x27\\x97\\x24\\x6e\\xa8\\x56\\x53\\x91\\xe2\\x61\\x4d\\xe1\\x81\\x89\\x9c\\x8f\\x01\\x0f\\x58\\x89\\xc9\\xea\\xf7\\x90\\x65\\xfd\\x3b\\xa9\\xee\\x25\\x9b\\x82\\x36\\x8d\\xe3\\xfe\\xa3\\x2a\\xf2\\x1f\\x99\\x01\\x3d\\xa5\\x2c\\x7a\\x78\\x28\\xdc\\x66\\x09\\x4b\\x14\\x23\\x8c\\xd8\\xec\\xb6\\xf6\\xc5\\x9d\\xd3\\xd3\\x1b\\x4a\\x23\\x17\\xa6\\x5e\\x0b\\x4e\\xdb\\x8d\\xfd\\xb9\\x13\\x15\\x3e\\x77\\x48\\x5b\\x9a\\x80\\x6b\\x23\\x91\\x41\\x7f\\xc8\\x0d\\xa4\\xa1\\x7f\\xe3\\x30\\x4e\\xe9\\x94\\xe6\\x50\\x5a\\x91\\x89\\x7f\\x81\\xa7\\x3a\\xc0\\x6d\\xa9\\x61\\xd5\\x76\\x6d\\xc0\\x07\\x1e\\x57\\x32\\xfa\\x2c\\xe1\\xc9\\x04\\x2e\\xc4\\x6a\\xf5\\xa0\\x1f\\xa6\\xba\\xfa\\xa5\\x4d\\xf4\\x85\\x30\\xce\\xc6\\x55\\x23\\xce\\xfd\\x07\\x41\\x23\\x48\\x85\\xc6\\x23\\x3a\\x63\\xc6\\x2a\\x1d\\x20\\x5a\\x68\\xe8\\x27\\x3c\\x4b\\xca\\x0c\\x0f\\xe4\\xd9\\xf5\\x25\\x8d\\xf4\\x78\\xdd\\x87\\x47\\x88\\x58\\xbd\\xe8\\x2d\\x66\\x1c\\x3e\\x59\\x3f\\xe7\\x45\\x2c\\x40\\x79\\x01\\x15\\xf5\\x7d\\xa6\\x9d\\x43\\xae\\xf4\\xec\\x96\\xeb\\x31\\x6c\\x76\\x1e\\x0f\\xde\\x34\\xbe\\x98\\x3f\\x8e\\xbf\\xfc\\xea\\xed\\x9b\\x57\\x6f\\x5e\\x5f\\xbe\\xb9\\xbc\\xf5\\x14\\x6c\\xa4\\xf4\\xd2\\x83\\xea\\xc5\\x60\\xd2\\xc7\\xd5\\xc8\\xfa\\x89\\xb0\\x4c\\xe4\\xc2\\x56\\x5f\\xd1\\x49\\xeb\\x79\\x4a\\x86\\xe1\\x28\\xa5\\xb4\\x22\\x07\\x0a\\xa6\\xe0\\xd6\\x3a\\x66\\xe9\\x4e\\x41\\x0e\\x60\\xb1\\xf2\\x44\\xce\\xef\\xc0\\x91\\x2e\\x36\\x2e\\xb9\\xe6\\xd2\\x42\\x20\\x8e\\xc2\\xd2\\x47\\xa9\\x62\\x46\\x79\\x81\\x5e\\x78\\xad\\xdf\\xcd\\xc3\\x80\\x97\\xdd\\xaf\\x43\\xac\\xc6\\x84\\x4f\\xa9\\xc4\\xc1\\x48\\x39\\x2a\\xe8\\xb6\\x22\\x57\\xa9\\x18\\x89\\x84\\xd4\\x2e\\x96\\xf3\\xb4\\xf2\\xc3\\x7b\\xe9\\x0d\\x74\\x45\\xd2\\xeb\\x05\\x9c\\xb2\\xfe\\x02\\x78\\x40\\x4e\\x85\\x56\\x12\\x65\\xca\\x29\\xd7\\x82\\x0f\\x33\\xbf\\xaa\\x21\\x99\\xe8\\xb0\\xdf\\x7a\\x82\\x92\\x0d\\x67\\x16\\x8c\\xef\\xc9\\x43\\xcb\\xd7\\xa2\\x58\\xf3\\xdd\\xf7\\x92\\x00\\x4d\\xe2\\x48\\xcd\\x14\\xdd\\x9b\\x62\\xc4\\x84\\x3d\\x74\\xec\\xc8\\x08\\x4f\\x84\\x34\\xa4\\x65\\x12\\x16\\xad\\x6c\\xa1\\x05\\x89\\xbc\\xbc\\xda\\x3b\\x4f\\xfc\\xb8\\x61\\x79\\xe9\\xb8\\x8b\\xe3\\xb6\\xc6\\x88\\x61\\x06\\x3d\\xc7\\x53\\x45\\xf3\\xdd\\x21\\x38\\x38\\xe0\\x17\\xc8\\xf7\\xa6\\xe0\\x76\\xd8\\x61\\x0e\\x89\\x33\\x00\\x8e\\xb1\\x2a\\x2c\\x24\\xc1\\x89\\x89\\xa6\\x30\\xe2\\x65\\x46\\x7c\\x87\\xc0\\x8c\\x5b\\x35\\x53\\xa5\\x6e\\x91\\xd5\\x09\\x77\\x98\\x83\\xa7\\x22\\x04\\xa8\\xe0\\x19\\xee\\xb1\\x14\\x9c\\xe0\\x26\\xa4\\xa3\\xe4\\x63\\xa5\\x52\\x27\\xbf\\x69\\xf5\\x20\\x72\\xec\\xcd\\xa3\\x56\\x05\\x9f\\xe1\\x8c\\xa5\\xaa\\x1c\\x66\\xd5\\x86\\x39\\x52\\xea\\xa9\\x7d\\xc1\\x93\\x3b\\x37\\x16\\x76\\xcc\\xb8\\x65\\x27\\x36\\x2f\\x4e\\xf0\\x2f\\xff\\xff\\xfe\\x0d\\x33\\xf8\\x87\\x51\\x32\\xc8\\x01\\x8d\\x69\\x0e\\xe6\\xe0\\x2f\\x0c\\x1b\\x82\\xb1\\x7d\\x18\\x8d\\x94\\xb6\\xff\\xe9\\xa0\\x55\\x4a\\x44\\x3c\\xa9\\xaa\\xa5\\x87\\xcd\\x2c\\xdd\\x61\\x47\\x38\\x29\\xc4\\xc9\\xd6\\x09\\x51\\x7a\\xc9\\x61\\x6b\\xa0\\xc1\\xe0\\x60\\x15\\xdd\\x75\\x87\\x46\\xcb\\x53\\xf6\\x3f\\x47\\xdf\\xff\\xea\\xa7\\xfe\\xf1\\x17\\x47\\x47\\xdf\\xbd\\xe8\\xff\\xf1\\x87\\x5f\\x1d\\x7d\\x3f\\xc0\\x7f\\x7c\\x7e\\xfc\\xc5\\xf1\\x4f\\xe1\\x8f\\x5f\\x1d\\x1f\\x1f\\x1d\\x7d\\xf7\\xf5\\x9b\\xaf\\x6e\\xaf\\x5f\\xfd\\x20\\x8e\\x7f\\xfa\\x4e\\x96\\xf9\\x1d\\xfd\\xf5\\xd3\\xd1\\x77\\xf0\\xea\\x87\\x0d\\x3b\\x39\\x3e\\xfe\\xe2\\x97\\x2b\\x26\\xc4\\xe5\\xec\\xed\\x68\\x1d\\xb7\\xd9\\x2c\\xa0\\xac\\xbf\\x09\\x89\\x7e\\xe8\\xdf\\x95\\x43\\xd0\\x12\\x2c\\x98\\xbe\\x90\\xb6\\xaf\\x74\\x9f\\x3e\\x38\\x65\\x56\\x97\\xb0\\xf4\\x33\\x27\\x4e\\x3d\\x66\\x85\\x6f\\x91\\xc8\\xab\\xc6\\x07\\x73\\x16\\x47\\x5f\\x86\\xc5\\x1b\\x04\\xdc\\x90\\x15\\xad\\x2b\\x48\\x7a\\x19\\xb9\\xcd\\x0d\\xc2\\xe0\\x80\\xdd\\x2c\\xf9\\x12\\x65\\x3e\\xff\\xc6\\xa1\\x21\\xe9\\xd0\\xcc\\xf7\\x33\\x17\\x64\\x46\\x34\\x10\\xfb\\xdc\\x5d\\x36\\xd8\\x4e\\x23\\x7c\\x74\\x3f\\x0a\\x2d\\x94\\x16\\x76\\x76\\x9e\\x71\\x63\\xae\\x78\\x0e\\x1b\\x41\\xf7\\x72\\x54\\x4b\\xda\\x3d\\x77\\xd8\\x1c\\x39\\xf6\\xfc\\x87\\xb4\\x9f\\xd0\\x2f\\x52\\x0e\\x27\\xc4\\x36\\xde\\x0f\\x10\\x0a\\xef\\x54\\x67\\x26\\x9c\\x3e\\xa5\\xd9\\xbf\\x40\\x2b\\x5f\\x45\\x47\\x03\\x09\\xc2\\xe1\\xf1\\x7a\\xe0\\xad\\x59\\xab\\x81\\xa4\\xc4\\xb5\\x3a\\xa6\\xfd\\xe0\\xc4\\xd9\\x91\\x18\\x6f\\xc6\\x70\\x6f\\x96\\x7d\\xca\\x12\\x2e\\xdd\\xb4\\xb1\\x8a\\xd2\\x88\\xfd\\x98\\xc1\\x98\\x27\\xb3\\x1f\\xdd\\xf4\\x7f\\xd4\\xe0\\x26\\xe2\\x04\\xfd\\x1f\\x49\\x2e\\x6d\\x49\\x9e\\x87\\xbe\\x2c\\x96\\x61\\x20\\xb0\\xea\\x95\\x90\\xff\\x20\\xad\\xa0\\x52\\x78\\x34\\x06\\x8f\\x16\\x2a\\x1d\\x38\\xc8\\x0d\\xe6\\xe6\\x8e\\x34\\xa9\\x7a\\x58\\xf1\\xbd\\xef\\x3e\\xff\\x61\\xe1\\x4d\\x6f\\xdf\\xb0\\x8a\\xf4\\x88\\x26\\x7e\\xea\\x12\\x09\\xa6\\x23\\x6c\\x61\\x81\\xec\\x2c\\xcd\\x05\\x9a\\x54\\xd8\\xd1\\xf5\\xcd\\xd9\\x71\\x6b\\x25\\x8e\\xf5\\x12\\x8b\\x49\\x15\\x18\\x79\\x68\\x89\\xd9\\x4d\\xc0\\xd4\\x66\\x14\\x64\\x1b\\x18\\xc5\\x44\\xa7\\x05\\xc3\\x98\\xc2\\x98\\x0e\\x60\\x68\\x59\\x19\\x42\\x35\\xf8\\xcd\\x19\\xfb\\xd1\\x09\\x55\\x99\\x90\\x40\\xb0\\x2b\\xb4\\x98\\x8a\\x0c\\xc6\\x6e\\xc4\\x86\\x53\\x88\\x9d\\x97\\x5a\\x83\\xb4\\xd9\\x2c\\x94\\x57\\x5a\\xbe\\x2b\\xc2\\x38\\x82\\xde\\x46\\xb7\\x80\\x59\\x95\\x4a\\x57\\x6d\\x96\\x7b\\xdb\\x40\\x3a\\x60\\x37\\xf8\\xc5\\x8c\\xec\\x7f\\xfe\\x3d\\xdc\\x1b\\xe4\\x8b\\xab\\x36\\x97\\x69\\x30\\xae\\x63\\x21\\xe9\\x2b\\x91\\x12\\x8b\\x03\\xad\\x95\\xf6\\x21\\x97\\xa4\\x47\\xa8\\xcc\\x29\\x0b\\x95\\x7a\\xe2\\x58\\x93\\x09\\x52\\x55\\x82\\x22\\x81\\x8f\\x4b\\xf5\\x80\\x59\\x02\\xf8\\xd5\\x6b\\x6e\\x0b\\x15\\x56\\x55\\xf3\\x45\\xee\\x77\\xe9\\x26\\x37\\x2a\\x9d\\x56\\x52\\x69\\x53\\x78\\xe6\\x9a\\xa0\\x99\\x93\\x5f\\x9a\\xc3\\xf7\\x6a\\x3d\\x8e\\x0b\\x8f\\x6a\\x26\\x8c\\xa9\\x61\\x58\\x8a\\x0c\\x4d\\x2c\\x42\\xd7\\xea\\x11\\x22\\x32\\x6f\\x2a\\x6f\\xaa\\xc8\\x7d\\x6d\\xb3\\xb2\\x28\\x94\\xb6\\xb5\\xe2\\x9d\\xb4\\xb4\\x32\\x52\\x8c\\x97\\x00\\xc0\\x4d\\xab\\xd0\\x50\\x70\\x5d\\x51\\x6c\\x03\\x2c\\x99\\x70\\xe9\\xd8\\xbf\\x5b\\xe8\\x1b\\x85\\x71\\xa8\\x14\\xcc\\xec\\x86\\xe5\\x43\\x55\\x5a\\xc4\\x31\\x7f\\x56\\x47\\xaa\\x94\\x29\\x73\\x44\\xe5\\x94\\x4d\\xac\\x2d\\xcc\\xe9\\xc9\\x49\\xcd\\x8f\\x06\\x42\\x9d\\xa4\\x2a\\x31\\x27\\x89\\x92\\x09\\x14\\xd6\\x9c\\x84\\xd3\\x74\\x52\\xa8\\xb4\\x1f\\xfe\\xe8\\xf3\\x70\\x48\\x4e\\x0e\\x57\\xf1\\xf8\\x0d\\x38\\xa1\\x87\\xfc\\x29\\xa3\\xbd\\x5a\\xf1\\x16\\xc8\\x72\\x4d\\x25\\xa7\\xfe\\xfa\\x8f\\xdd\\x0b\\x35\\x18\\x97\\xbe\\x64\\x55\\x86\\x75\\xcf\\xd6\\xb8\\x37\\xdb\\xd6\\x9d\\xfa\\xfd\\xaa\\xfe\\x58\\x25\\x98\\x36\\xa8\\xdb\\xa1\\x69\\x76\\xbd\\x9e\\x68\\xaf\\xb3\\x7a\\x3d\\x62\\xe7\\x5a\\xa8\\x3d\\x86\\xb4\\xcd\\x89\\x7b\\xf5\\x44\\x51\\x00\\xb0\\x96\\x63\\xf5\\x31\\x27\\x9b\\xd3\\x13\\x47\\xae\\xe4\\x8c\\x39\\x7c\\xb6\\xbe\\x14\\x5d\\xa3\\x36\\x9b\\xd5\\x18\\x1c\\xfd\\xa7\\xca\\x54\\xdd\\x83\\xd1\\x08\\x12\\xfb\\x97\\x86\\x5d\\xa0\\x32\\x48\\x55\\xe6\\xe5\\x3f\\x85\\x7f\\xfd\\x65\\xb5\\x4a\\xb8\\x91\\x25\\x78\\x33\\x5f\\x1e\\x4d\\x69\\xbd\\x8d\\xae\\x6d\\xca\\xc1\\x0f\\xe6\\x58\\x36\\x41\\x80\\xfa\\x42\\x45\\x0e\\xbd\\x1d\\xde\\x20\\x45\\x96\\x4d\\x2f\\xef\\x38\\x9a\\xd1\\x78\\xd9\\x78\\x0a\\xd7\\xa0\\xb6\\xde\\x58\\x55\\x9b\\xd5\\x81\\x5d\\x29\\x9f\\x25\\x00\\x3d\\x76\\x8d\\x85\\xdb\\xea\\x5f\\x90\\x91\\x5d\\x29\\xca\\x17\\x58\\xab\\xfd\\x6f\\x6c\\xc4\\x7c\\xd4\\x9b\\xd9\\x02\\xc8\\xd7\\xb5\\xef\\x92\\x56\\xd6\\xf2\\x5d\\xd6\\x18\\xdc\\x32\\x4d\\xaf\\x83\\xcc\\x1d\\xcc\\x6a\\x7f\\x97\\xf7\\x8c\\xa2\\x39\\xb9\\x57\\x63\\x49\\x10\\x3e\\xc9\\x7d\\xf5\\x9f\\x3e\\xe0\\x57\\xe5\\x43\\x21\\x69\\x30\\xea\\x3a\\x6c\\x05\\xf6\\x1e\\x00\\x2a\\x53\\xfc\\x13\\x87\\xe9\\x02\\x5c\\x9b\\xb9\\x48\\x5b\\x30\\x7b\\xbb\\x85\\x43\\xb4\\x72\\xb1\\x2c\\x77\\x85\\x36\\xfc\\x9f\\xaf\\xfe\\x59\\xf2\\x6c\\xc0\\x2e\\x88\\x2a\\xe2\\xea\\xfd\\x4f\\xfe\\xa5\\x05\\x97\\xd0\\xbd\\xc8\\xd2\\x84\\xeb\\x14\\xb9\\x01\\x9d\\x51\\x66\\x14\\xed\\x1e\\xaf\\x04\\x8e\\x70\\xda\\xeb\\x3d\\xa2\\xc2\\x84\\xac\\xe0\\xda\\x8a\\xa4\\xcc\\x38\\xb2\\x2d\\x18\\x2b\\x3d\\xeb\\x04\\xa2\\x35\\xd2\\xdc\\x40\\xa2\\x64\\xfa\\x88\\x95\\x7e\\x05\\x75\\xf5\\xdf\\x36\\x61\\x8c\\x62\\x14\\x68\\xe1\\xe3\\xef\\x45\\x0e\\xf3\\x48\\x7a\\xd4\\x56\\x6e\\xd4\\x28\\x9c\\xea\\xea\\x88\\xf5\\x48\\xaa\\xb9\\x17\\x06\\x9a\\x4e\\x12\\x61\\x98\\xa0\\x04\\x9e\\xe3\\x06\\x79\\xac\\x4e\\xc5\\x80\\xfd\\xd7\\x2c\\xf0\\xab\\x1e\\x13\\x36\\x98\\xa6\\x51\\x6f\\xf6\\x63\\x7a\\x94\\xf5\\xc0\\xae\\x0f\\xd4\\x48\\x69\\x98\\x82\\x66\\x47\\xa9\\xc2\\x6f\\x30\\x47\\xe5\\x78\\xc0\\xfe\\xaf\\x13\\xf1\\xc9\\x06\\x31\\xa6\\x74\\x0a\\x8f\\xe2\\x41\\x12\\xb1\\x58\\x49\\x14\\x4d\\xf4\\x2f\\xd8\\x11\\xa5\\xb6\\x88\\x3c\\x87\\x54\\x70\\x0b\\xd9\\xec\\x98\\xa2\\x9b\\x42\\x72\\xcc\\x26\\x5b\\xb7\\x49\\x46\\x54\\x23\\x13\\xea\\xf7\\xbf\\x5d\\xf3\\x26\\x4e\\x76\\x8b\\x9d\\xfd\\x36\\x18\\xb9\\x6a\\xc8\\x90\\x94\\x39\\xb7\\x85\\x15\\x0f\\x52\\x6b\\x3c\\xde\\x0d\\x0f\\x77\\x43\\xf6\\x0b\\x64\\xa6\\xda\\xe0\\x7f\\x38\\x3c\\xe0\\x4c\\xc3\\x18\\xb1\\x9c\\x30\\x77\\x0f\\x1c\\x17\\xc9\\xf2\\x8c\\xae\\x47\\x38\\xda\\x7a\\x7b\\x76\\x9f\\x39\\xf1\\xff\\xf7\\xbf\\x4d\\xb9\\xe5\\x2b\\x5e\\xa0\\x3d\\x9f\\x15\\xcb\\x8c\\x03\\x8f\\x31\\xca\\xba\\xf3\\x55\\x9b\\xb5\\x81\\x81\\xd6\\x0f\\xbf\\x53\\x0f\\x28\\xea\\x2f\\xfb\\xb2\\xad\\x52\\xa3\\x49\\x8d\\x82\\x28\\xc2\\x7e\\xf7\\x35\\x8c\\x85\\xb1\\x7a\\xd6\\xb0\\x6c\\x7a\\x8f\\x86\\x62\\x42\\x1a\\xcb\\xa5\\x15\\x48\\xd9\\x58\\x78\\xb3\\xef\\x6d\\x83\\x4e\\xfc\\x1e\\xb0\\xb7\\x4e\\xd7\\x42\\x1b\\xd6\\xbd\\x63\\xd3\\x24\\x60\\xdf\\xce\\x0a\\x60\\x7f\\x6e\\xfc\\xf1\\x95\\x2e\\x12\\xc4\\x35\\x4f\\x68\\x08\\xb9\\x78\\x9a\\x6a\\x30\\x8b\\xf4\\x61\\x19\\xfa\\xac\\x5d\\x7f\\x50\\xf3\\x1f\\x05\\xc1\\xe1\\x75\\x30\\x08\\x78\\xc7\\xad\\x31\\x62\\xec\\xa4\\xcc\\x90\\x4a\\x19\\xcc\\xbc\\x2d\\x69\\x93\\xb4\\x02\\xfc\\x90\\x5c\\x30\\x90\\x57\\x4c\\x40\\xd8\\x20\\xf7\\x27\\x4a\\x9a\\x32\\x0f\\x11\\x91\\x4e\\xeb\\x29\\x40\\xa6\\x20\\x93\\x19\\xe6\\xde\\x64\\x53\\xd0\\x03\\xf6\\x8d\\x71\\x3b\\xc5\\xfe\\x2a\\xc6\\x4e\\xef\\xf3\\x83\\x36\\x45\\xa5\\xe0\\x46\\x9a\\x9b\\x81\\x30\\x8d\\x82\\xb4\\x18\\xe3\\xe9\\x64\\xa0\\xd0\\x43\\xc3\\x5d\\xe0\\x93\\x7c\\x42\\x9c\\xc9\\xfc\\x24\\x4a\\xb2\\xb5\\xde\\x56\\x29\\x9f\\xc1\\x08\\x1a\\xe0\\x42\\x07\\xde\\x2d\\x69\\xac\\xc8\\x95\\x56\\x28\\x23\\x42\\x2a\\x5a\\x45\\x47\\x5b\\x69\\xa3\\x6a\\x44\\x49\\x9d\\xd4\\x6f\\x5b\\x11\\xc6\\x80\\xa5\\xb9\\xc5\\xa0\\xe2\\x56\\x4a\\x02\\x3e\\x34\\xad\\x34\\x81\\xcc\\xbc\\x68\\x7b\\xda\\x9a\\xdf\\xd9\\x50\\xe5\\xbb\\x3d\\xe5\\x9a\\xa6\\x6b\\x2e\\xef\\x20\\x65\\x19\\x3c\\x88\\x44\\x8d\\x35\\x2f\\x26\\x22\\xc1\\xcc\\x45\\xf2\\xab\\x38\\x59\\xdd\\x92\\xef\\x7c\\x70\\xb8\\x12\\xd1\\x56\\x91\\xf1\\xa2\\x1c\\x66\\xc2\\x4c\\x60\\xa9\\x2c\\xb3\\x16\\x47\\x0d\\x24\\x1a\\xec\\x52\\x0a\\xd2\\x42\\xd1\\x1b\\x7a\\xaf\\x66\\xca\\x21\\xdc\\xcb\\x77\\xe0\\xc3\\x19\\x09\\xe7\\xf0\\xe0\\x39\\x10\\x27\\x89\\x3b\\x48\\xc1\\x43\\x51\\x57\\x93\\xae\\x60\\x38\\x60\\x97\\x36\\x18\\xa6\\xdd\\x17\\x77\\x00\\x05\\x61\\x1a\\xc6\\x1d\\x98\\x1c\\x6d\\x2a\\x46\\xc8\\x04\\x28\\xff\\x92\\xf2\\x58\\x01\\x82\\x99\\xd1\\x6a\\x01\\x24\\x06\\x01\\x1a\\xf8\\xc3\\xde\\x80\\xb4\\xcb\\x85\\x9a\\xf5\\x7a\\xd7\\x1a\\x9d\\x6b\\x3d\\x18\\x2b\\x9a\\xf2\\x38\\x24\\x6b\\x5a\\x14\\x78\\xa2\\xfb\\xb7\\x03\\x25\\x3e\\xd9\\x76\\x07\\x29\\x5d\\xf6\\x86\\xe2\\xb6\\x1e\\xa7\\x35\\xdf\\xb4\\x5e\\xf7\\xd1\\x00\\x86\\x4d\\xd4\\xbd\\xef\\x69\\xfe\\xd0\\x7a\\x8b\\x4d\\xd8\\xdb\\x54\\x98\\xc4\\x9d\\x74\\x48\\xd9\\xb9\\x92\\x26\\xe4\\xcc\\x72\\x49\\x69\\xb0\\x53\\x9e\\x11\\x2a\\x84\\x8e\\x0b\\x95\\xa1\\x7f\\x23\\x2d\\x83\\x3a\\x41\\xa1\\xad\\x90\\x0f\\x01\\x6b\\x5d\\x9b\\x30\\x95\\x15\\x6c\\xee\\x11\\x16\\xfb\\x18\\x17\\x0c\\xfc\\xe1\\x5a\\x65\\xd9\\x7a\\x2e\\xb6\\x56\\x2f\\xdd\\x44\\x2b\\x0d\\x00\\xd8\\xd8\\xff\\x7a\\x19\\x20\\xe6\\x6d\\x71\\x0e\\xa7\\x6b\\x0f\\x12\\xa2\\x86\\x13\\x75\\x2b\\xc0\\x0e\\xc1\\xde\\x03\\x48\\x96\\x4c\\x20\\xb9\\x33\\x75\\x80\\x06\\x56\\x9d\\x9f\\xdb\\x35\\x6f\\x7f\\x6a\\x53\\xac\\x4a\\x9e\\x72\\xbb\\x82\\x8a\\x86\\x01\\x20\\xb7\\x99\\x84\\xfb\\xf9\\x80\\x83\\x45\\x62\\xcf\\xa7\\x5c\\x64\\x7c\\x98\\x51\\xae\\x78\\xf5\\x57\\xaf\\x39\\x0f\\x11\\xf8\\x79\\x51\\x66\\x99\\x77\\x22\\xa1\\x03\\xd6\\x6a\\x3e\\x1a\\x89\\x04\\x63\\x50\\xd0\\xcd\\x5c\\x87\\x35\\x2d\\x5d\\xc2\\x4e\\xae\\x65\\x63\\xb9\\x2d\\x17\\xf6\\x68\\xcd\\x06\\xaf\\xdb\\x58\\xa7\\x87\\x88\\x95\\x06\\xa2\\xb9\\xfa\\xe1\\x2d\\x65\\xc5\\x4d\\x03\\x48\\xd9\\x6a\\xd9\\xbf\\x07\\xec\\x4a\\x59\\x1f\\x97\\xf1\\x06\\x8c\\x09\\xb1\\x1f\\xef\\x80\\x1b\\x25\\x1b\\xd4\\x15\\xa5\\x5f\\x2d\\xc6\\x42\\xf2\\xcc\\x2f\\xaa\\x69\\xdf\\xab\\x74\\x0f\\x8e\\x26\\xe5\\x5c\\x8c\\x35\\xb7\\x15\\x51\\xac\\xe7\\xed\\xb9\\x8b\\xe7\\x8b\\x64\\x09\\x1d\\xb0\\x33\\x39\\xc3\\xfd\\xf6\\x01\\x1b\\xae\\x67\\xab\\x55\\x5a\\x26\\xe0\\x9d\\xcf\\xa5\\x69\\x76\\xd2\\x29\\x19\\x6d\\xbb\\x17\\xce\\xc3\\x20\\x75\\x00\\x62\\x0a\\x96\\x0b\\xef\\x52\\x52\\x12\\x18\\x37\\x85\\xd3\\xe3\\x02\\x4e\\x92\\x29\\xbc\\x06\\x30\\x32\\x8b\\xb3\\xeb\\x4b\\xf6\\xce\\x67\\x12\\x0f\\x58\\xbf\\xdf\\x27\\xbf\\xa7\\xb1\\xba\\x4c\\x90\\xbf\\xb8\\x23\\x24\\x53\\xcf\\x29\\x08\\xfb\\x28\\xde\\xa6\\x11\\xbb\\xeb\\x2d\\x1f\\x24\\x82\\x15\\xdc\\x4e\\xd8\\x80\\x00\\x3f\\x68\\x80\\x82\\xb1\\x2f\\x1d\\xaf\\x79\\xe0\\x79\\xe1\\xf0\\xfe\\x7b\\x49\\xd4\\xfb\\x4b\\xa5\\x6e\\x68\\x93\\x68\\xcc\\xff\\x65\\x27\\x27\\xf3\\x38\\xa1\\x86\\x4e\\x44\\xf5\\x06\\x44\\x44\\x8d\\x91\\x52\\x87\\xa6\\xbd\\xa4\\x81\\xfb\\xf0\\x6b\\x0c\\xff\\x59\\x32\\x3a\\x8e\\xc5\\x35\\x9c\\xb2\\xef\\x0f\\xce\\xc2\\xe9\\xfb\\xfe\\xa0\\xc7\\xbe\\x3f\\xb8\\xd6\\x6a\\x8c\\x31\\xa1\\x72\\xfc\\xbd\\x0f\\xf2\\xfc\\xfe\\xe0\\x02\\xc6\\x9a\\xa7\\x90\\x7e\\x7f\\xe0\\xba\\xfd\\x15\\x06\\xf3\\xbe\\x01\\x3d\\x86\\xaf\\x61\\xf6\\x67\\xec\\xac\\xfa\\x39\\x70\\x84\\x3f\\x53\\xdc\\xaf\\xfb\\xdd\\xb1\\x60\\xc7\\xa7\\xfe\\x9c\\xf3\\xa2\\xfa\\xe1\\x0d\\x2f\\xaa\\x8f\\xcf\\x6b\\x3c\\xfb\\xee\\x87\\x1c\\x2c\\x9f\\xbe\\x1c\\xd4\\x3b\\xfa\\xe3\\x3f\\x8c\\x92\\xa7\\xdf\\x1f\\xd4\\xf3\\xef\\xa9\\x5c\\x60\\xd0\\xc4\\xec\\xfb\\x03\\xd6\\x1a\\xf5\\xf4\\xfb\\x03\\x1c\\x37\\xfc\\x1e\\x26\\x79\\xfa\\xfd\\x81\\x1b\\xc9\\xfd\\xac\\x95\\x55\\xc3\\x72\\x74\\xfa\\xfd\\x01\\xc6\\x22\\xf4\\x5e\\xf6\\x34\\x14\\x3d\\x27\\x30\\xfd\\xb9\\x1e\\xe1\\xfb\\x83\\x1f\\xdd\\x9e\\x9c\\x9c\\x78\\x17\\x86\\xbf\\x59\\xe1\\xdf\\xcb\\x8d\\xd5\\x8f\\xd2\\xfd\\xc7\\xe2\\x91\\xfa\\x2c\\xe3\\xc6\\xde\\x6a\\x2e\\x0d\\x8e\\x7f\\x2b\\xf2\\xe5\\x6e\\x5c\\xd2\\xe5\\xf0\\xbc\\xaf\\x7c\\xae\\x91\\x06\\xac\\x7c\\x4c\\xd8\\xb0\\xf2\\xf1\\x0a\\xee\\xb9\\x09\\xe7\\x5a\\x5c\\xc3\\x86\\x56\\xe7\\xc5\\x0f\\xeb\\x6c\\x08\\x27\\xcf\\x05\\x3b\\x4d\\xb5\\x3f\\x8e\\x07\\xf8\\xb7\\xc1\\x57\\xe9\\x70\\x47\\xdc\\xd3\\x37\\x8c\\x75\\xc6\\x7d\\xf3\\x01\\x3a\\xb5\\x82\\x7f\\xef\\x2b\\x78\\xb0\\x52\\xa6\\xa0\\x33\\x74\\x56\\xd5\\xbd\\x92\\x27\\x24\\x1d\\x30\\xb2\\x1b\\xf0\\xca\\x4a\\x83\\x71\\x74\\xc8\\x9d\\x64\\xc3\\x78\\x4d\\x31\\x3c\\xa1\\x47\\x47\\x3b\\x7c\\x11\\x13\\xea\\x06\\x19\\x5d\\x92\\x40\\x61\\x91\\xd3\\xed\\xee\\x62\\x66\\x0d\\xa3\\x8a\\x93\\xac\\xfa\\x76\\x35\\x7a\\x78\\xe4\\xd8\\x10\\xf0\\xfe\\x6d\\xf2\\xef\\x4f\\xca\\x9c\\x3b\\xd6\\xc1\\x53\\x0c\\xe3\\xa9\\x9e\\x91\\xfa\\x46\\xea\\x16\\x91\\x54\\x72\\x0a\\x91\\x8d\\x3f\\xec\\x83\\x07\\xb5\\x67\\x24\\xbc\\xca\\x56\\x7b\\xc4\\x62\\xb2\\xd1\\xe2\\x73\\xfe\\xf0\\x1a\\xe4\\xd8\\x4e\\x4e\\xd9\\x6f\\x7e\\xfd\\x7f\\x7e\\xff\\x87\\x15\\x2f\\x12\\x61\\x84\\xf4\\x2b\\x90\\xde\\x16\\xb4\\x21\\x18\\x16\\x3f\\x9c\\x37\\x1a\\x0e\\x42\\xfc\\xe5\\x60\\x5c\\xbf\\x53\\x19\\xb9\\x6b\\x0c\\xba\\xe7\\x18\\x83\\xe5\\xd9\\x65\\x59\\x38\\xb8\\x7c\\x89\\xd1\\xb5\\xc6\\x72\\x99\\x40\\xcf\\x09\\x49\\x4b\\x3b\\x13\\x15\\x01\\xcf\\x66\\xec\\xe5\\xaf\\xe9\\x06\\x22\\x1c\\x7a\\x81\\x7c\\x7f\\xf7\\xf0\\xc3\\x60\\xc9\\x94\\x85\\x61\\x7f\\xec\\xcd\\xcd\\x47\\x18\\xe6\\xb6\\x4a\\x8d\\x10\\x71\\x48\\xc5\\xd4\\x40\\x9c\\x30\\x18\\x03\\x16\\x39\\x21\\x54\\xf3\\x7d\\x6c\\xe3\\x1e\\xb3\\x07\\x6e\\x66\\x0b\\xcc\\x85\\x14\\x79\\x99\\x9f\\xb2\\x17\\x2b\\xe3\\x39\\x1d\\x49\\xdb\\x70\\x37\\xe9\\xe5\\x5a\\x10\\xe0\\x8e\\x74\\x8d\\x35\\xcf\\x73\\x8c\\xa3\\x17\\x29\\x48\\x2b\\x46\\x02\\x83\\x06\\x2a\\xd4\\x46\\x75\\x9f\\x3e\\x0c\\x31\\x28\\x15\\x14\\x31\\x3c\\xc5\\xd1\\xa1\\x06\\xb2\\x5f\\x93\\x9c\\xa3\\x91\\x03\\x7b\\xef\\x4d\\xd2\\x24\\x50\\xb3\\x02\\xe8\\x34\\x90\\x02\\xc3\\xe0\\xa1\\x20\\x51\\xb5\\xe1\\x86\\xc8\\x81\\x4b\\x21\\xc7\\xa6\\x8e\\xe7\\xf2\\xb7\\x4f\\xb9\\x87\\xf7\\x13\\xf0\\xde\\x73\\x68\\xfa\\x82\\x12\\xa7\\x2c\\xa5\\xa8\\x37\\xf1\\x3a\\x3c\\x10\\x03\\x40\\x49\\x46\\x9f\\xb7\\x69\\x3a\\xc9\\x31\\x87\\xec\\x9c\\x1b\\x08\\xa7\\xb1\\x19\\xcd\\x15\\x4a\\x21\\x55\\xa9\\x3d\\x9d\\x1d\\xd5\\x97\\x2f\\x7e\\xbd\\x76\\xcb\\xab\\xf7\\x56\\xbb\\xf0\\xaa\\x30\\xaf\\xef\\xce\\xfa\\xff\\x97\\xf7\\xff\\xf5\\xc3\\x91\\xff\\xc7\\x8b\\xfe\\x1f\\xff\\xde\\x3b\\xfd\\xe1\\xf3\\xc6\\x9f\\x3f\\xac\\x8e\\xce\\x5a\\x2e\\xcc\\xaf\\x40\\x1f\\xcf\\x44\\x82\\x9c\\x18\\x76\\xb4\\x17\\xa2\\x54\\x6e\\x75\\x09\\x3d\\xf6\\x25\\xcf\\x0c\\xf4\\xd8\\x37\\x12\\x59\\xc3\\x9e\\x40\\x5b\\xef\\xa1\\x76\\x5c\\xf9\\xc0\\x8d\\xba\\xca\\x53\\xee\\x5f\\xc1\\x29\\xad\\x7f\\xc7\\x4f\\x77\\x9d\\xfa\\xba\\x19\\x90\\x82\\xa9\\xa1\\x41\\x69\\x64\\x03\\xcf\\x28\\x9f\\x60\\xa4\\xd4\\xc0\\x4b\\xb8\\x83\\x44\\xe5\\x27\\xd5\\x73\\x12\\xad\\xdf\\x70\\x39\\x63\\x35\\x59\\x23\\xa1\\x74\\x1e\\xd3\\x0d\\x06\\xcc\\xf3\\x44\\x2b\\x63\\xea\\x22\\x3f\\x2c\\x13\\x77\\xc0\\xce\\x6a\\xbd\\xd1\\x11\\xcb\\x21\\x24\\x1c\\x65\\x71\\x3d\\x14\\x56\\x73\\x32\\xfa\\x06\\xb9\\xb2\\xb6\\x28\\x8d\\xca\\x8c\\x1d\\x39\\x75\\x75\\x80\\x81\\x64\\x0b\\xd4\\xd5\\x17\\x0c\\xe3\\x43\\x91\\xe1\\xbd\\x4d\\x4e\\x95\\x4e\\x94\\x1c\\x65\\xc2\\xab\\x00\\x79\\xa1\\xb4\\xe5\\xd2\\x86\\xac\\xa6\\x31\\x3c\\xd0\\x55\\x71\\xe4\\x76\\x10\\x86\\x1d\\xa5\\xd2\\xbc\\x7c\\xf9\\xeb\\xdf\\xdc\\x94\\xc3\\x54\\xe5\\x5c\\xc8\\x2f\\x73\\x7b\\x72\\xfc\\xc5\\xd1\\x3f\\x4b\\x9e\\xa1\\x97\\xf7\\x8a\\xe7\\xf0\\x65\\x6e\\x57\\x5f\\xba\\xb5\\x35\\x5b\\x7c\\xf9\\xfb\\x0d\\x4e\\xd1\\xd1\\x77\\x74\\x56\\x7e\\x38\\xfa\\xae\\xef\\xff\\xf5\\x79\\xf8\\xe9\\xf8\\x8b\\xa3\\xef\\x07\\x6b\\x9f\\x1f\\x7f\\x7e\\x82\\x31\\x92\\xd5\\x91\\xfb\\xe1\\xbb\\x7e\\x7d\\xfc\\x06\\x3f\\x7c\\x7e\\xfc\\x45\\xe3\\xd9\\xf1\\xb2\\xc3\\xd8\\x0a\\x5d\\x74\\x5a\\x40\\x3f\\xe7\\x45\\xff\\x0e\\x66\\x2b\\x0e\\xe7\\x4a\\x71\\x74\\xb1\\x23\\x82\\x58\\xce\\x8b\\x65\\xda\\xf7\\x48\\x8c\\xdf\\xf0\\xe2\\x1d\\x8c\\x40\\x83\\x4c\\x96\\x22\\xf9\\x9e\\x1e\\x18\\xa7\\x3f\\xac\\x79\\x84\\x11\\x58\\x3b\\x58\\x9d\\x1c\\xdf\\x21\\x4b\\xdb\\x3a\\x71\\x7a\\x03\\x6c\\xd9\\x4c\\x7e\\x94\\x6b\\xe2\\x17\\x1f\\x1d\\xa4\\x5a\\xe7\\xce\\x3d\\x84\\xf3\\xfd\\x2d\\xd9\\x8f\\x76\\xee\\xa7\\x14\\x2b\\x35\\xad\\xb6\\x0d\\xf3\\xf2\\x82\\x44\\x5f\\x24\\x3d\\x28\\xce\\x4d\\x94\\xd3\\xf3\\x4a\\x29\\xfe\\x59\\x02\\xbb\\xbc\\xa8\\xf2\\xe9\\x85\\x4c\\xb2\\x12\\x2b\\xf8\\x7d\\xf3\\xcd\\xe5\\x85\\xd3\\xdf\\xff\\xcb\\x93\\x9b\\x7b\\x60\\xa9\\x92\\x87\\x96\\xbd\\xbd\\x7a\\xfd\\xdf\\x68\\x0c\\xc0\\x37\\x7a\\xc4\\xd0\\x7d\\x52\\x6f\\x26\\x38\\x99\\xc9\\x3c\\x03\\x66\\xff\\x05\\x14\\x27\\x87\\x23\\x27\\xbc\\xa8\\xec\\x27\\x48\\xee\\x30\\xc2\\x2a\\x2b\\x0c\\x26\\x02\\x30\\x53\\x6a\\x3f\\x3b\\xd7\\x31\\x79\\x7c\\x31\\xf5\\xcf\\xfb\\x83\\x43\\x0e\\x03\\x66\\x82\\xec\\x14\\xdc\\x99\\x28\\x29\\x21\\x41\\xa7\\xb9\\x93\\x02\\xdf\\xc3\\xf9\\x70\\x88\\xfc\\xd6\\xcb\\xac\\x38\\xc6\\x0e\\x87\\xc1\\x3b\\xd4\\x76\\x46\\x0b\\x37\\x87\\x73\\x5a\\xe9\\x7b\\x3f\\x49\\x0b\\xeb\\xdd\\x69\\x44\\xb2\\x67\\xa2\\x67\\xf3\\xdd\\x23\\xf6\\xe7\\x85\\x30\\xae\\xb6\\xea\\x3c\\x97\\xb7\\x85\\xb6\\xd5\\xca\\x39\\x3a\\xe1\\x86\\x0d\\x01\\x24\\x9a\\x73\\xc9\\xfa\\x07\\xd2\\x63\\x1d\\xd4\\x86\\xd8\\xb2\\xe8\\x5b\\xd5\\x4f\\x97\\x6f\\xde\\x23\\x90\\x7b\\x1c\\x6a\\x6b\\x34\\xd7\\xb9\\xd2\\x18\\xdb\\x2a\\xaa\\xf7\\x93\\xd9\\x32\\x18\\x98\\xba\\x52\\x60\\x25\\x83\\x6c\\xbb\\xb0\\xd5\\x8a\\xc9\\x9c\\x55\\x17\\x35\\x0b\\x6f\\xd4\\xf0\\x7a\\xc6\\xe2\\x94\\x9c\\xf6\\xd8\\xb2\\x6c\\x58\\x85\\xde\\xbc\\xb6\\x65\\x6f\\xfb\\x39\\xd2\\x36\\xdf\\x80\\x9e\\x8a\\x9d\\x98\\xdf\\x63\\x07\\x33\\xa1\\x38\\x93\\xb3\\xf7\\x7f\\xac\\x9c\\xe8\\xb5\\xf3\\x20\\x68\\xfa\\x4b\\xd4\\x23\\xee\\x9b\\xb5\\xf1\\xef\\x08\\xc1\\x75\\x51\\xfe\\xdb\\xf4\\xb1\\x2d\\xb3\\x24\\x6a\\xd2\\x4a\\xf2\\x30\\x56\\x69\\x74\\xb9\\x37\\x7f\\x2b\\x87\\x95\\xa0\\x5c\\xf7\\xee\\x75\\x20\\xf6\\xbf\\xff\\xfe\\xec\\xb3\\x7e\\xbf\\xff\\x19\\x2f\\x44\\x60\\xb3\\x8c\\x17\\x02\\x1e\\x2c\\x48\\xba\\xb4\\xf8\\xee\\x0f\\x18\\xc6\\x3b\\x7d\\xf9\\xd9\\x9d\\x90\\xe9\\x29\\x3b\\x2f\\x8d\\x55\\x79\\x30\\x8b\\x63\\xe5\\x57\\xc4\\xcf\\xcf\\x82\\x19\\xc3\\x0d\\xc2\\xa5\\x54\\xb6\\x19\\x04\\xeb\\xd4\\x6f\\xed\\xc8\\x89\\xee\\x8f\\x41\\x0e\\x9c\\xb8\\x86\\x61\\xce\\xa0\\xb1\\xf3\\x30\\xf4\\xf4\\xc5\\xe0\\x8f\\x03\\xa7\\xf6\\x23\\x0e\\x79\\xeb\\x9f\\xb1\\x3c\\x2f\\x4e\\x31\\x53\\xfc\\x33\\x2f\\x94\\xb0\\x24\\x2b\\x0d\\x96\\xc7\\x45\\xf0\\xf9\\xef\\xcd\\xa0\\x0a\\x86\\x1b\\x24\\x4a\\x83\\x72\\xff\\xc9\\x3f\\x73\\xfa\\xb8\\x9b\\xc5\\x58\\xab\\xb2\\xa8\\xcb\\x8f\\xb4\\xde\\xf1\\xf2\\x8a\\x9f\\x2c\\x45\\xaf\\x35\\x10\\xbc\\xcf\\x54\\x46\\x17\\xd1\\x7a\\x20\\xd0\\xf0\\xfe\\x0c\\x79\\xc8\\xe1\\x73\\x27\\x7d\\x7e\\xbd\\xfa\\x9d\\xd7\\xc2\\xd0\\x91\\x2a\\xb2\\x52\\xf3\\x6c\\xd5\\x42\\xf0\\x15\\x33\\x51\\xda\\x5e\\xd5\\xd3\\xc2\\x1c\\x54\\x33\\x6d\\xfe\\xdb\\xbf\\x28\\x24\\x06\\x24\\xad\\xe8\\xed\\x33\\xc6\\x4c\\xa2\\x1c\\xfe\\x54\\x68\\x96\\x7e\\xc6\\x82\\x5b\\xce\\x77\\xde\\x6f\\x65\\xc2\\xa0\\x6f\\xf0\\x5c\\x65\\x65\\xde\\x74\\x52\\xf5\\x17\\xd9\\x8a\\x83\\x5a\\x50\\x8e\\xcf\\x6f\\xbe\\x6d\\x60\\xef\\x3f\\x8c\\x92\\xd7\\xdc\\x69\\x23\\x94\\x54\\x91\\x0a\\x53\\x64\\x7c\\x76\\xd5\\x96\\x8c\\x69\\x37\\x2f\\xe8\\xd9\\x67\\x8f\\x1c\\x9c\\x25\\xe3\\xcf\\xf9\\x16\\xd7\\x4f\\x61\\xda\\xd8\\xa7\\xe6\\xf0\\xdf\\x2e\\xfc\\xbe\\xe9\\xf0\\x61\\xf9\\xdc\\x8d\\xdc\\x08\\x68\\x51\\x12\\x42\\x15\\x14\\xb3\\x66\\x42\\x4b\\x5e\\xa1\\x19\\xbd\\x5b\\x7c\\xb0\\x62\\x4a\\xcd\\x2e\\x49\\x77\\x2d\\x26\\xdc\\x2c\\x82\\xf8\\x7a\\xee\\xd7\\x25\\xdd\\xd1\\x8b\\xd3\\x97\\x3c\\x2b\\x26\\x3c\\x98\\x61\\x4c\\x32\\x81\\xbc\\x11\\xea\\xa5\\x0a\\x90\\x67\\xd7\\x97\\xdf\\xfe\\xe6\\x66\\xee\\xc1\\x7c\\x12\\xf0\\x32\\xec\\x27\\xf1\\x9a\\x28\\x48\\xe5\\x59\\xc3\\xbd\\x73\\x72\\xef\\x8f\\x4b\\xbf\\xb9\\x29\\x20\\xf9\\x71\\xb0\\x30\\xf3\\x05\\xee\\xb4\\x5c\\xe4\\xec\\x57\\xa9\\xf2\\x73\\x3f\\x3b\\xf8\\x37\\x7e\\x5a\\xc5\\xd3\\x1a\\x74\\x71\\x8e\\x32\\xb7\\x43\\xad\\x1c\\x48\\xfc\\x1a\\x43\\x88\\x82\\xad\\xd1\\x13\\x52\\x0f\\xc7\\xca\\xb5\\x58\\x19\\x94\\xc9\\x58\\x4b\\xa1\\x0e\\xb4\\xa6\\x01\\xbb\\xc1\\x98\\xb3\\xca\\x51\\x91\\x28\\x39\\x05\\x6d\\x99\\x86\\x44\\x8d\\xa5\\xf8\\x57\\xd5\\x9b\\x99\\x73\\x74\\xe3\\xa9\\x95\\x3c\\x0b\\xb1\\xbb\\x68\\x54\\xe4\\x33\\xa6\\xe1\\x1f\\xe8\\x99\\x94\\x8d\\x1e\\x42\\x21\\xa1\\x2a\\xc5\\xa3\\xce\\xdf\\x18\\x0b\\x1b\\xa8\\x7e\\xa2\\xf2\\xbc\\x94\\xc2\\xce\\x4e\\x90\\x80\\x8b\\x61\\xe9\\x08\\xe7\\x49\\x0a\\x53\\xc8\\x4e\\x8c\\x18\\xf7\\xb9\\x4e\\x26\\xc2\\x42\\xe2\\x14\\x96\\x13\\x5e\\x88\\x3e\\x4e\\x56\\x92\\x5f\\x31\\x4f\\x7f\\x51\\xb1\\x9e\\xf9\\xe8\\xa3\\x95\\x9c\\x11\\x09\\xec\\x5a\\x58\\x3b\\xf2\\xea\\x73\\x10\\x1b\\x45\\x91\\x6a\\x90\\x06\\x03\\xee\\xbb\\x57\\x37\\xb7\\x95\\x12\\xe9\\xcf\\x25\\x42\\xb8\\x61\\xce\\xaf\\x81\\xed\\x00\\x25\\xe4\\x08\\x82\\xe9\\x35\\x14\\x56\\x00\\x99\\x52\\xb9\\x79\\xb4\\xff\\x65\\x02\\x25\\xaf\\x72\\x98\\x0b\\x0c\\x5b\\xc2\\x5c\\x65\\x0a\\x2e\\x3d\\x47\\xa6\\x87\\x66\\x25\\x8a\\x78\\x19\\xb0\\xcb\\x86\\x15\\xec\\xbd\\x83\\x1a\\x6d\\xcc\\x7d\\x07\\xbe\\xcd\\x81\\xdd\\xe4\\xd9\\x8b\\x1f\\x2c\\x91\\x00\\x03\\x2f\\x5d\\xb9\\x3b\\x2b\\xcf\\x30\\x4b\\x21\\xc9\\x78\\xc8\\x74\\xb1\\x90\\x65\\xec\\xed\\xeb\\x37\\x18\\x21\\x14\\xa2\\x2f\\xb3\\x6c\\xb1\\x3a\\x5d\\xc2\\x25\\xcb\\xb9\\xc4\\x88\\x86\\xa2\\x20\\xdb\\x38\\xf7\\x15\\xe2\\x43\\x30\\xca\\xa6\\x93\\x5f\\xa7\\x97\\xf6\\xd9\\x72\\x06\\x15\\x9e\\xfa\\x09\\xce\\x3d\\x59\\x27\\x0a\\x2f\\xc8\\x40\\x6b\\xa0\\x76\\x56\\xbf\\xeb\\x6d\\x04\\xa5\\x24\\x97\\x3f\\x96\\xd2\\xb8\\x83\\x10\\xab\\x98\\xf3\\x02\\xa5\\xbc\\x90\\xda\\xc8\\x9b\\x08\\x8e\\x19\\x37\\xb3\\x90\\x74\\x36\\x9c\\x31\\x27\\xc6\\x21\\x41\\xb0\\x4a\\xf9\\xc0\\x1c\\xf7\\x2d\\x12\\x06\\x0d\\x56\\x0b\\x98\\x36\\x0d\\xa4\\x95\\x23\\x6a\\x7b\\x9d\\x60\\xf3\\x34\\xda\\xb5\\x22\\x31\\x2f\\x84\\x97\\x5d\\xd2\\x4a\\xb0\\xdc\\x00\\x7a\\xd7\\x97\\x1e\\xdf\\x6a\\x71\\xd4\\x78\\x7c\\xf3\\xc5\\x30\\xbd\\x7c\\x50\\xc9\\xb5\\x38\\x92\\x47\\xac\\x94\\xd5\\x15\\x15\\x31\\xa0\\xb5\\x89\\x84\\x94\\xef\\xaf\\xb9\\x74\\x0f\\x96\\x22\\xf7\\x0e\\xd0\\x7a\\x4c\\x83\\x52\\xf7\\x72\\x75\\x74\\x40\\xb7\\x29\\x5e\\x4d\\xd8\\x55\\x3f\\x87\\x6a\\x32\\x75\\xd8\\x8c\\x55\\x78\\x5a\\x49\\x83\\x46\\xd8\\x55\\x05\\x67\\xa6\\x82\\x33\\x3e\\x1e\\x6b\\x8c\\x96\\x5d\\x19\\x69\\xb0\\x61\\x9a\\xd6\\x26\\xf5\\x20\\xfb\\x24\\xc9\\xaf\\x7d\\xc3\\x91\\xc1\\xb5\\x2f\\xac\\xb4\\xd0\\x86\\x17\\x16\\x85\\xc5\\x76\\xdb\\x2c\\xa1\\x8c\\xa3\\x19\\x2d\\x80\\x56\\xe9\\x47\\x72\\x57\\x36\\x2d\\x5a\\xb5\\x51\\xb1\\xaa\\xf6\\x3e\\xcf\\x4d\\xc4\\x3f\\x1d\\x62\\x4d\\xb1\\x8a\\x34\\x3b\\x72\\x90\\xd4\\xde\\x6c\\xef\\x26\\x29\\x40\\x3b\\x7d\\x9c\\xe2\\x89\\x39\\x4b\\x48\\x7e\\xab\\x08\\x4f\\xf0\\x0e\\x3f\\x32\\x9d\\x2d\\x0a\\xb6\\x6d\\x5e\\x15\\xb4\\x8f\\x21\\x55\\x8f\\xbc\\xb6\\x4d\\x1d\\xcf\\x26\\xd0\\x1e\\x7d\\x79\\xcb\\x42\\x60\\x0d\\x0e\\xd3\\x79\\xdf\\x0e\\x0c\\x9d\\x77\\xba\\x41\\x4e\\x0e\\xb5\\xb6\\x79\\x8b\\xdf\\xbf\\x69\\x46\\x92\\x68\\x7e\\xcf\\x40\\x26\\xca\\x11\\x8b\\xff\\xf7\\xe6\\xed\\x55\\xc8\\x5f\\xbb\\xb4\\x4c\\xe4\\x85\\xbf\\x2c\\x87\\xbd\\xe1\\xda\\x4c\\x78\\x06\\x54\\x1b\\xf9\\x1b\\x99\\xb7\\xfe\\x9e\\x0b\\x01\\x4f\\x21\\xe3\\x33\\xea\\x2c\\x85\\x44\\xa1\\x25\\x5e\\x69\\x56\\x38\\x01\\x37\\x2f\\x4a\\x4c\\xe1\\xc0\\xa7\\x38\\xee\\xa3\\x49\\x3a\\x3b\\x80\\xa6\\x36\\x51\\x0d\\x67\\x4b\\x2d\\xa0\\xed\\xf6\\xd0\\x4f\\x37\\xa5\\x01\\xcd\\xc9\\x6c\\x5a\\xbe\\x6e\\x8b\\xe2\\x75\\x1b\\xae\\xb2\\xca\\x90\\xb9\\x5e\\x63\\x63\\x6b\\xf6\\xb8\\x65\\x2e\\xd8\\xda\\x5b\\xb1\\x52\\x28\\x32\\x35\\x73\\x78\\xf1\\xf8\\x59\\xd9\\x70\\x3d\\x1b\\x9f\\xeb\\x4d\\xfb\\xdb\\xf4\\x2c\\x6f\\xd8\\x1f\\x19\\xa7\\xba\\xe8\\x69\\x99\\x02\\xb5\\x53\\x47\\xeb\\xdc\\x7f\\x5b\\x75\\xb4\\xc4\\xfe\\xb8\\xba\\xb7\\xf7\\xc2\\xfc\\xae\\x2f\\x83\\xb5\\xa1\\xf2\\xfa\\x7a\\xda\\x54\\xfd\\x89\\xb9\\x3b\\x5f\\x57\\x6e\\xe4\\x86\\x5c\\x5d\\x79\\x03\\xc9\\x5a\\x8f\\x79\\x49\\x3a\\xd4\\xa8\\x7b\\xb4\\x48\\xf6\\x7b\\x62\\x7b\\x8f\\x08\\x38\\xe1\\xb5\\x47\\xc4\\x9c\\xf0\\xda\\x63\\xc2\\x0e\\xb5\\x6d\\xf8\\xe8\\xe3\\x58\\x48\\xad\\x9d\\x3c\\xee\\x34\\x7b\\x2f\\xaa\\x57\\x3b\\x93\\xb6\\xb7\\xa2\\x73\\x4a\\xfe\\x38\\x9a\\x2f\\x99\\xe9\\x35\\x9a\\x6f\\x5b\\xe6\\xcf\\x55\\x13\\x66\\x47\\xab\\x4c\\xe6\\x03\\xa7\\x17\\x0f\\xd0\\x28\\xfb\\xdd\\x0f\\x03\\xea\\xf2\\x38\\x64\\xc3\\x7b\\xdb\\x86\\x78\\xa4\\xf3\\x50\\xd3\\x72\\x5e\\x2a\\xeb\\x1c\\x4c\\xd3\\xf5\\x5e\\xf8\\x95\\x90\\x3a\\xbb\\xbe\\x0c\\x06\\xd6\\x0f\\xb8\\xb5\\xa6\\x80\\xe4\\x09\\x48\\xdd\\x37\\xad\\x69\\xb4\\x64\\x6e\\x9f\\x07\\xea\\x04\\x6a\\x37\\x59\\x36\\xcc\\x54\\x72\\xe7\\x6d\\xc9\\xef\\x2e\\xaa\\x94\\x4b\\xa7\\x75\\x39\\xe1\\xc7\\x27\\x5c\\x32\\xf1\\x18\\x11\\x89\\x62\\x76\\x14\\xb3\\xa3\\x98\\xfd\\x5c\\xc4\\x6c\\xf2\\xd9\\x3c\\x05\\x4a\\x35\\x37\\x91\\x95\\xb4\\x8a\\xe2\\x61\\x23\\xb5\\x5a\\xd3\\x22\\xb5\\xc2\\x16\\xa9\\xd5\\x23\\xed\\xd9\\x51\\xab\\x8d\\x64\\xc0\\x0d\\xe2\\x3a\\xd7\\x1f\\xe4\\x68\\xe0\\x8e\\x06\\xee\\x68\\xe0\\xf6\\x2d\\xf2\\x32\\xdf\\x22\\x2f\\x8b\\xbc\\x2c\\x1a\\xb8\\xd7\\x75\\x19\\x0d\\xdc\\x5b\\x76\\x14\\x0d\\xdc\\xd1\\xc0\\xdd\\x6a\\xd1\\xc0\\x1d\\x0d\\xdc\\xd1\\xc0\\x1d\\x0d\\xdc\\x2b\\x5a\\x14\\xb3\\x77\\xec\\x34\\x8a\\xd9\\x6b\\xda\\xa7\\x2d\\x66\\x47\\x03\\x77\\xa4\\x56\\x91\\x5a\\x45\\x6a\\xf5\\x3c\\xa8\\xd5\\xfe\\x06\\xee\\x24\\x03\\x2e\\x97\\x2b\\xba\\x73\\x79\\x12\\xf8\\x5e\\xe3\\x6a\\x5f\\xca\\x2f\\xa1\\x5f\\x87\\x30\\xe1\\x53\\xa1\\x4a\\x5d\\x17\\x14\\x3b\\xbf\\xf9\\x96\\x8d\\xc1\\x1a\\x87\\x05\\xb0\\xfc\\xf2\\x91\\x3d\\x93\\xf2\\x41\\xf2\\x61\\xb6\\xb4\\xe3\\xc7\\x48\\x89\\xff\\x72\\xbd\\x41\\x7f\\xa8\\x94\\x5b\\xdd\\x22\\xc4\\x50\\xae\\x0f\\x72\\xf2\\x36\\x71\\xff\\x07\\xab\\xf4\\x8e\\xe5\\xc1\\xff\\xe7\\xef\\x2e\\xba\\x0a\\xf9\\xc7\\x5b\\x80\\xaa\\x5e\\x7d\\xc1\\x6a\\xac\\xb0\\xe9\\x6b\\x62\\xbe\\xbd\\x97\\x90\\x62\\x32\\x68\\x28\\xef\\xef\\x0e\\xbd\\x48\\x84\\xcd\\x66\\xd5\\xc0\\x4b\\x2f\\xb4\\x7b\\x3e\\xa9\\x03\\xe7\\xef\\x2e\\x36\\x77\\xa9\\x84\\x0d\\xf8\\x10\\xde\\x93\\xe8\\x1b\\x89\\xbe\\x91\\xaa\\x45\\x31\\x68\\xc7\\x4e\\xa3\\x18\\xb4\\xa6\\x7d\\xda\\x62\\xd0\\x53\\xf7\\x25\\x44\\x0f\\x00\\x8b\\x1e\\x80\\xf0\\x5a\\xf4\\x00\\x44\\x0f\\x40\\x37\\x60\\x8a\\x1e\\x80\\xe8\\x01\\x58\\xff\\x52\\x14\\x26\\x77\\xec\\x34\\x0a\\x93\\x6b\\xda\\xa7\\x2d\\x4c\\x46\\x0f\\x40\\xa4\\x56\\x91\\x5a\\x45\\x6a\\xf5\\x3c\\xa8\\xd5\\x73\\x0c\\x71\\x8f\\x86\\xd8\\x68\\x88\\x8d\\x86\\xd8\\xc8\\x8d\\x22\\x37\\x7a\\xa4\\x3d\\x3b\\x6e\\x14\\x0d\\xb1\\xdb\\x76\\x14\\x0d\\xb1\\xd1\\x10\\xbb\\xaa\\x45\\x43\\x6c\\x34\\xc4\\x46\\x43\\x6c\\x34\\xc4\\xae\\x6f\\x51\\x98\\xc4\\x16\\x85\\xc9\\x47\\xda\\xb3\\x13\\x26\\xa3\\x21\\x36\\x52\\xab\\x48\\xad\\x22\\xb5\\x7a\\x1e\\xd4\\x6a\\x7f\\x43\\xec\\x23\\x27\\xa9\\x85\\x32\\x4d\\xfb\\xa9\\x97\\x1c\\x43\\x3c\\x30\\x56\\xf6\\xf7\\x37\\xbe\\xd1\\x15\\x58\\xe1\\x82\\xfb\\x1e\\xcb\\x44\\x2e\\x42\\xdd\\x76\\xa5\\x1d\\x76\\xf4\\x13\\x6e\\xc0\\x2c\\xf4\\xb1\\x64\\xfc\\xf5\\x73\\x5f\\x7f\\x52\\xd7\\xde\\xc3\\x52\\x05\\x32\\x0b\\x19\\xfa\\xf1\\xb8\\xb2\\xf5\\x34\\x44\\xb2\\x01\\xec\\xdc\\xf8\\xee\\xc5\\xfa\\xde\\xda\\xc7\\x97\\xbd\\xc3\\x15\\xff\\x8f\\x92\\xef\\xc7\\xaf\\x55\\x1f\\x72\\x03\\xbf\\xff\\xed\\xc2\\x6d\\x20\\xcd\\x57\\x72\\x48\\x05\\xb7\\xbb\\xdf\\x7a\\x5e\\x0f\\xb1\\x1a\\x73\\x37\\x38\\x01\\xd5\\x34\\x76\\xec\\xc5\\x5f\\x57\\xf0\\xe8\\xde\\x39\\x04\\x4b\\x2f\\xe9\\xe5\\x70\\x6b\\xfe\\xfc\\x6d\\xd7\\x35\\xff\\x95\\x2b\\xae\\x75\\xa9\\x34\\xab\\xfb\\x09\\x84\\x6b\\xe2\\xfc\\x85\\x0e\\x26\\x74\\x2a\\x4c\\x95\\xeb\\xb0\\xf4\\x56\\xc2\\x3d\\x93\\x17\\xc2\\x38\\x4b\\x1e\\x3f\\xb6\\x69\\xcb\\xee\\xb4\\x58\\x0a\\xac\\x00\\xa0\\x0b\\xf2\\xab\\x5c\\x54\\x45\\x1c\\xe6\\x21\\x56\\x70\\xed\\xf8\\x44\\xf0\\xbf\\xa0\\xe8\\xd2\\x78\\x7b\\x0e\\xde\\xeb\\xef\\x68\\x5c\\x2b\\xaf\\x3c\\x2e\\xa7\\xf4\\x1b\\xb5\\x26\\x56\\xf9\\x7c\\x36\\x11\\x4f\\xfc\\xcd\\x52\\xd7\\xa0\\x73\\x61\\xcc\\xaa\\xf4\\x8c\\xf6\\xd4\\x1f\\x63\\x1e\\x1b\\x30\\x8d\\x15\\xf0\\x0f\\x2b\\x6a\\x4c\\xa7\\x12\\x22\\x49\\xed\\x1f\\xf2\\x84\\xe9\\x32\\xf3\\x57\\x6b\\xfb\\x4b\\x25\\x18\\x4f\\x12\\x55\\x4a\\xcb\\x24\\x40\\x4a\\x89\\x1f\\xcb\\x70\\x75\\x03\\x96\\xb3\\x81\\x14\\xb9\\xa9\\x0c\\xd9\\xa7\\x79\\x3e\\xfa\\x96\\x5f\\xc3\\x19\\x2d\\x61\\xe9\\x35\\x25\\xcd\\xb6\\xb9\\xcc\\x89\\xc3\\x3f\\xce\\xbb\\xb7\\x11\\x08\\x36\\x16\\x07\\xda\\x86\\x2e\\x95\\x89\\x64\\xf6\\xae\\xcc\\xc0\\x5f\\xbc\\x2a\\x24\\xf1\\xad\\xca\\x15\\xd6\\x54\\x14\\x0a\\x7c\\x1b\\x67\\x4f\\x37\\x3e\\xa7\\x0a\\xc8\\x40\\xe5\\x4b\\xbb\\xb4\\x3e\\x0f\\x77\\x3f\\xd2\\x85\\x49\\xee\\x23\\xc6\\x8b\\x22\\xc3\\xc4\\x2b\\xe5\\x78\\xf7\\xfd\\x44\\x24\\x93\\xfa\\xd6\\xda\\x65\\xaf\\x6d\\x2e\\xc3\\x6d\\xa4\\x64\\xb0\\xad\\x14\\x0d\\x16\\x8c\\xa7\\xc3\\xc7\\x50\\x85\\x6d\\xa9\\x71\\x30\\xba\\x78\\xe5\\x2b\\xad\\xca\\x62\\xc3\\xd7\\x17\\xed\\x6e\\xf4\\x75\\xb8\\xd3\\xb2\\x29\\x8e\\x84\\x87\\xde\\x99\\x19\\xee\\xe1\\x27\\xe3\\x9c\\x37\\xd6\\x0f\\x18\\xbb\\x1c\\xb1\\xbc\\xcc\\xac\\x28\\x32\\xfc\\x84\\xea\\xc5\\xd0\\xd5\\xdf\\x15\\xdf\\xe8\\x31\\x2e\\x67\\xc1\\x37\\xea\\x2f\\x5f\\x82\\x94\\xf1\\xb1\\xeb\\xd1\\x86\\x2b\\xd9\\xe9\\xd6\\xa6\\x32\\x77\\x32\\x48\\xc3\\xec\\x87\\x17\\x7c\\xba\\xef\\xab\\xde\\xd9\\xbd\\xc8\\x32\\xbc\\x14\\x3f\\xcb\\xd4\\x3d\\xa4\\x03\\x76\\x70\\x30\\x4f\\xca\\x13\\xa5\\x1b\\xf3\\x41\\x62\\x72\\xf0\\x79\\xeb\\x2d\\x47\\x39\\xea\\x09\\x6f\\x82\\x23\\x6c\\x6b\\xf1\\x9a\\x6d\\x27\\x62\\xb3\\xed\\x95\\x09\\xc6\\xa4\\x92\\xc1\\x6c\\xfc\\xcd\\xbb\\xd7\\xbb\\x21\\xc2\\x55\\xbb\\x0f\\x7f\\x4b\\x17\\x58\\xb7\\x2d\\x05\\xd7\\x56\\xf0\\x8c\\x95\\x3a\\x33\\x84\\x0b\\xdc\\x09\\xcc\\x3a\\x5c\\x73\\x36\\xe1\\xe8\\xf7\\x4e\\xc0\\xd0\\x7d\\x5a\\xec\\x73\\xda\\x7d\\xbf\\x39\\x74\\xc6\\x95\\xcc\\x66\\x8c\\xd3\\xd6\\x8c\\xca\\x2c\\xeb\\xb1\\x91\\x90\\xdc\\x91\\x6e\\x28\\x42\\xee\\x9d\\xd3\\x44\\xd9\\x8d\\x90\\x09\\xb8\\x35\\xf5\\x2b\\xe1\\x04\\x67\\xe4\\x7a\\x74\\x34\\xa2\\x3a\\xe8\\xa9\\xbf\\x9a\\xd9\\xdb\\x1d\\x8c\\x1f\\xc2\\x1d\\xfa\\x04\\x2f\\x94\\x75\\x52\\xad\\x17\\x7b\\xde\\xa9\\x0c\\xbd\\x35\\x95\\x49\\x19\\x6f\\x09\\xe3\\xcd\\xc7\\xff\\x25\\x24\\xaa\\x7b\\xec\\x1d\\x32\\x1f\\xa7\\x36\\x82\\xb0\\x13\\xa7\\x45\\x16\\x45\\x86\\x17\\xc8\\x3b\\x64\\xa9\\x91\\xf2\\xc8\\x94\\xc9\\xc4\\x2d\\xe9\\xa0\\x50\\xa9\\x39\\x70\\xa4\\xe8\\xc0\\x40\\xa2\\xc1\\x9a\\x83\\x63\\xf7\\xd7\\xfc\\x1a\\x70\\x7d\\xcd\\xef\\x4e\\x78\\x21\\x0e\\x8e\\x7b\\x0c\\x01\\x84\\x57\\x90\\x29\\x3b\\x79\\xbe\\x78\\x18\\xd6\\xda\\xba\\xf9\\xf2\\xb1\\x36\\x77\\xbf\\x6e\\xa3\\x07\\x7f\\x9f\\x96\\x2a\\xe8\\x7a\\x2a\\x47\\xe7\\x2d\\x60\\x66\\xa6\\x43\\x4a\\xba\\x39\\xbb\\xf6\\xb8\\xcd\\x11\\x7c\\xc6\\xce\\x24\\x03\\xf2\\x91\\x80\\x65\\x39\\x70\\xe9\\xdf\\x86\\x29\\xe8\\x99\\x9d\\xa0\\xdb\\xc4\\x54\\x04\\xe4\\xd9\\x03\\x7d\\x3f\\x80\\xfb\\x03\\x1f\\x80\\x5b\\x23\\x39\\xdd\\x79\\x38\\x0f\\xdc\\xc3\\xcf\\x0f\\xe7\\x09\\x69\\xcd\\x11\\x9e\\x2d\\x28\\x91\\x45\\xef\\x04\\xc6\\x6f\\xdd\\x97\\x6d\\x10\\xd2\\x4f\\x44\\x2d\\x2b\\xfa\\xf1\\xfa\\x35\\xdd\\x6f\\xe8\\x61\\xf5\\xb5\\x90\\xa9\\xa9\\xea\\xd9\\xa5\\xd5\\x3d\\xd6\\x0e\\xde\\x4b\\x81\\x8c\\x33\\x7c\\x8e\\x00\\x5e\\x14\\x81\\x37\\x15\\x5b\\x1f\\xe9\\xbe\\xa1\\x23\\x3d\\x05\\xb5\\x06\\xef\\x4b\\x6c\\x49\\x4a\\x8e\\x4e\\xf5\\xc8\\x79\\xe7\\x44\\x90\\x8c\\x0f\\x21\\x33\\xde\\xe0\\x02\\x8d\\xe9\\xb3\\xb3\\xd7\\x6f\\xaa\\x7b\\x43\\xf1\\x1e\\xee\\x0f\\xad\\xcc\\x6c\\x10\\x05\\xb0\\x70\\xfb\\xea\\x62\\xdb\\x5c\\x7e\\x45\\x50\\x6c\\x67\\x56\\x67\\x37\\x60\\xe9\\x98\\xe5\\xbc\\x70\\xa7\\x8c\\xfa\\x58\\x6a\\x15\\x7e\\x8d\\x90\\x7e\\xfc\\xb0\\x6c\\x25\\xf7\\x6f\\x7e\\x5b\\xe2\\xb2\\x41\\x36\\x3a\\x2a\\x9b\\x45\\x1a\\x6c\\x73\\xf6\\xd6\\x58\\x49\\xea\\x36\\x67\\x54\\x6d\\x21\\xb4\\xd7\\x0d\\xbc\\x34\\x9f\\xf0\\xa6\\xb1\\x35\\x05\\x43\\xa5\\x18\\xa8\\xf0\\x85\\x0e\\xbf\\xd7\\x5d\\x74\\xbc\\x05\\xdb\\x28\\x5e\\x4e\\xf7\\xce\\x20\\xb1\\x6a\\x7d\\xf1\\xcf\\xf0\\xb2\\x85\\xbc\\xc8\\x1e\\x3b\\x79\\x6c\\x6b\\x25\\x2d\\x17\\xf2\\x1d\\xf0\\x74\\x76\\x03\\x89\\x92\\xe9\\x86\\x04\\xb6\\xb5\\x1f\\x6f\\x84\\x14\\x79\\x99\\x33\\x59\\xe6\\x43\\x40\\x10\\x1b\\xea\\x0b\\x09\\x09\\x29\\xc0\\x9c\\x49\\xb8\\xcf\\x66\\xe1\\x12\\x7f\\x56\\xa8\\x34\\xd0\\x93\\xa1\\x53\\xd8\\x78\\x3a\\xc3\\x9b\\x47\\xb1\\x4c\\xb6\\x9c\\xb9\\x4e\\x84\\xad\\xb9\\x8f\\x66\\x89\\xe6\\xc6\\x89\\x45\\x3d\\xec\\x54\\x58\\xc7\\xb1\\x86\\x80\\x5e\\x3a\\x91\\x82\\xdb\\x63\\x3e\\xe5\\x22\\x73\\xa2\\xf5\\x80\\x5d\\xc0\\x88\\x97\\x19\\x5e\\xa0\\xcb\\x5e\\xb0\\x23\\x37\\x58\\xd0\\xc9\\x96\\x7d\\xe0\\xc4\\x5d\\xa3\\x9c\\x36\\x6f\\x7c\\x55\\x0d\\x9c\\xd0\\xf1\\x16\\x7e\\x87\\x4d\\xaa\\xb8\\x86\\xb6\\x69\\x35\\xd7\\xd0\\x0a\\x5e\\x9a\\x4d\\x55\\xf9\\xd6\\xc6\\x5c\\xca\\xd4\\x9d\\x87\\xa6\\x24\\xda\\x20\\xe9\\xc2\\xf8\\x9e\\x37\\x63\\xd9\\xeb\\xab\\xad\\x2c\\x99\\xb5\\x56\\x63\\x0d\\xc6\\x5c\\x00\\x4f\\x33\\x21\\x61\\x77\\xfc\\xba\\x9d\\x00\\xcb\\xf9\\x03\\xe2\\x98\\x15\\x39\\x38\\x49\\xa4\\x89\\x61\\xbc\\xb9\\x2a\\xab\\x58\\xce\\xef\\xa0\\x1a\\x9e\\x0d\\x61\\x84\\x17\\x24\\xe3\\x82\\x1b\\xbb\\x4f\\xf8\\x33\\xe2\\x22\\x73\\x1a\\xfa\\x6d\\x1b\\x36\\x78\\x57\\xb2\\xca\\x32\\xd0\\x84\\x38\\xee\\x6f\\x21\\x4b\\x0c\\xb1\\x2b\\xb4\\x42\\x65\\x92\\x3e\\x6d\\xf2\\x78\\xe4\\xa1\\xdc\\xbd\\x4c\\x74\\x38\\xdc\\xa5\\x7b\\x3d\\x07\\x8a\\x57\\x0f\\x09\\x19\\x0a\\x35\\x70\\x83\\xaf\\x11\\x6e\\x9a\\x52\\x8f\\x9c\\xea\\x18\\x34\\xce\\xc6\\x84\\xfc\\x25\\xec\\xec\\x4a\\x59\\x1f\\xc9\\x57\\x2d\\x10\\xbf\\xf6\\x57\\x44\\x83\\xb1\\x22\\xc7\\x03\\x96\\x96\\x3a\\x5c\\x58\\x8d\\x30\\xe3\\xcb\\xb7\\xbe\\x75\\x54\\x7e\\xff\\xe2\\xc5\\x86\\xf2\\xdb\\xfb\\x47\\x7a\\x0d\\xa8\\x29\\xef\\x82\\x2f\\x57\\x15\\x1d\\x0a\\xe4\\xdf\\xa9\\xc0\\x6e\\x8f\\x85\\x17\\x83\\xf1\\xe6\\x6d\\xd0\\xe8\\x71\\x15\\xc6\\x0a\\x39\\x2e\\x85\\x99\\xb0\\x21\\xd8\\x7b\\x00\\xc9\\xe0\\x81\\x6a\\xea\\xb0\\x7f\\x81\\x56\\xb8\\xa9\\x0e\\xbc\\xb5\\x9b\\xa1\\x05\\xb4\\x97\\x4f\\x07\\x62\\x53\\x61\\x84\\x92\\x7f\\x15\\xc6\\x2a\\x3d\\x7b\\x2d\\x72\\xf1\\x48\\x01\\xea\\xd0\\x16\\xdd\\x7e\\x15\\x04\\x55\\x96\\xb2\\x77\\xb4\\x15\\x37\\x40\\x0b\\xd6\\x80\\x56\\x50\\xab\\x48\\x3d\\x65\\xee\\x9c\\x0c\\x79\\x72\\xf7\\xde\\x00\\xfc\\xe2\\xa9\\x40\\x38\\xb0\\xeb\\x1d\\xa0\\x8a\\xf2\\x5e\\xd5\\x01\\x92\\x2d\\x42\\xca\\x57\\x0f\\x04\\x9f\\x16\\x94\\xef\\x27\\xca\\x00\\xbe\\x40\\x86\\x4a\\xfc\\x2c\\x38\\x16\\x84\\xa9\\x08\\x06\\xba\\x65\\x25\\x18\\xc6\\x47\\xa3\\xf6\\x1b\\xf5\\x61\\x47\\xc9\\x33\\x2f\\x8d\\x65\\x39\\xb7\\xc9\\x84\\x4c\\x59\\x2a\\xad\\xc4\\x89\\x43\\xe3\\xc5\\xfe\\x6d\\xa0\\xbc\\xb1\\x21\\x7a\\x7b\\x93\\x31\\xa3\\x79\\xbe\\x7a\\x70\\xba\\xe5\\xa3\\x1e\\xa1\\x76\\x6b\\x81\\x7c\\xbe\\x9b\\xb6\\x06\\x9c\\xb5\\x37\\xc4\\xcb\\x6d\\x39\\x5d\\xde\\x7f\\x8b\\x46\\xe4\\xfa\\x17\\xdc\\x85\\xb3\\xab\\x8b\\xcd\\x4d\\x31\\xbb\\x28\\xb8\\x5b\\xab\\xb8\\xf3\\xe6\\xf2\\x35\\x8b\\x0a\\x26\\x53\\xff\\xa4\\x6d\\x33\\x47\\x0d\\xc5\\xf4\\x18\\x67\\x77\\x30\\xeb\\x11\\x17\\x9b\\xbf\\x30\\x5f\\x43\\xe6\\x25\\x09\\xc0\\x7b\\xe3\\xdd\\x4b\\xf4\\xdd\\xe6\\x20\\xd9\\x01\\x7b\\xa8\\x6d\\xe7\\xce\\x08\\xad\\xef\\x26\\xba\\xe5\\x17\\x61\\xd1\\x5b\\x7c\\xb6\\x3d\\x82\\x53\\xbb\\x83\\xd9\\x76\\x1f\\xcc\\x6d\\xb7\\xdb\\x05\\xaf\\xfb\\xd0\\xbe\\xbb\\x1f\\x2a\\x41\\xaf\\xda\\xea\\xed\\xfc\\x4c\\xcd\\xb6\\xb5\\x89\\x2a\\xb4\\x00\\xc4\\xbd\\x96\\x57\\xa1\\x5f\\xd3\\xca\\xe4\\xd6\\x78\\x68\\x08\\x19\\xdd\\x99\\x9e\\x88\\x82\\xb2\\x1e\\xbc\\x33\\xc0\\x63\\x24\\xfb\\x96\\x67\\x22\\xad\\xba\\xa0\\xf3\\x7b\\x29\\x7b\\x4e\\x7c\\x72\\xff\\x41\\xa2\\x4b\\xe2\\xda\\x85\\x02\\x73\\xa5\\x2c\\xfe\\xf2\\xc1\\x00\\x44\\xd3\\xdc\\x0b\\x3c\\xd4\\x85\\xb7\\x42\\x23\\x95\\x41\\xc5\\x8b\\x22\\xee\\x03\\x18\\x2e\\xe7\\x23\\x77\\x0c\\xbb\\x94\\x4c\\xe9\\x00\\x07\\xf7\\xd0\\x77\\x44\\x5d\\x20\\x9f\\x18\\x92\\x83\\x03\\xed\\xd3\\x4b\\xfb\\xf0\\xe0\\x53\\xba\\x05\\xbd\\x35\\xdd\\xf9\\xae\\x50\\x3e\\xa0\\x27\\xa8\\x63\\x15\\x19\\x4a\\xbb\\x5e\\x54\\xe5\\xc1\\x51\\x2e\\x12\\x96\\x83\\x1e\\xa3\\xc7\\x25\\xd9\\xd8\\xe3\\xd0\\xde\\x94\\xed\\xe8\\x2e\\xb5\\xad\\xa9\\x6f\\x73\\xc0\\xad\\xb0\\x00\\x59\\x13\\x99\\x80\\xf6\\x61\\x6e\\xd4\\x43\\xcb\\xe4\\xf4\\xbf\\x8e\\x82\\xe3\\x1e\\xfc\\x9b\\x15\\x5c\\x68\\x33\\x60\\x67\\xcc\\x08\\x39\\xce\\xa0\\xf5\\xcc\\x6b\\x18\\xcd\\x6e\\x5c\\x0f\\xc2\\x30\\x47\\x6a\\xa7\\x3c\\xf3\\xba\\x14\\x97\\x0c\\xc8\\x66\\xe5\\x7a\\x9f\\x67\\xa9\\x3d\\x2f\\xa9\\x38\\xca\\x53\\x39\\xba\\x0e\\xee\\x60\\x76\\xd0\\x5b\\x40\\x9a\\x83\\x4b\\x79\\x40\\xbc\\x65\\x01\\x4d\\x2a\\x46\\x84\\x3e\\xb2\\x03\\x7c\\x76\\xd0\\x25\\x17\\xde\\x92\\xe1\\xec\\x6a\\x47\\x6b\\x0f\\xba\\x31\\x46\\x84\\xf8\\x90\\x1d\\x85\\xf5\\x96\\x96\\xe8\\xa3\\xa2\\xac\\x62\\xa5\\x01\\x92\\xd6\\xf1\\x94\\x31\\x08\\x72\\x26\\x4a\\x95\\xa8\\x98\\x4a\\xb8\\x47\\xe9\\xf1\\xc9\\x08\\x7e\\x4e\\x93\\x10\\x72\\xfc\\x4d\\x91\\x72\\xbb\\x51\\x78\\x2e\\xb5\\x16\\x44\\x0e\\xdf\\x51\\x27\\xac\\xc4\\x5e\\x1c\\x6e\\x8d\\xc4\\x98\\x15\\x5c\\xf3\\xdc\\x0c\\xd8\\xb5\\xaf\\xa7\\x8a\\x98\\x26\\x46\\x4d\\x5b\\xa2\\x87\\xdd\\xed\\xac\\x00\\xf6\\x67\\xf6\\xae\\x39\\x97\\x01\\xeb\\xf7\\xfb\\xec\\xf6\\xed\\xc5\\xdb\\x53\\x46\\xbf\\x90\\x94\\x6d\\x15\\x1b\\x29\\x54\\x82\\x54\\xa9\\xdd\\x50\\x53\\x90\\xa8\\xf8\\x3b\\xf9\\x5e\\x49\\x78\\x3b\\x72\\x27\\x84\\x5b\\x98\\x82\\x66\\xf7\\x6e\\xab\\x12\\x91\\x42\\x65\\xbd\\x1a\\x1c\\xbe\\x5f\\x3c\\xde\\x4d\\x32\\xc9\\xf9\\xc3\\x4d\\xa9\\xc7\\x5b\\x6c\\x00\\x5b\\xd8\\x84\\xa6\\xc9\\xa6\\x56\\x26\\x11\\xf5\\x9a\\xb9\\xe7\\x26\\x99\\x40\\x5a\\x66\\x90\\x32\\x3e\\x54\\x53\\x68\\x99\\x6c\\xdb\\x9f\\x21\\x4b\\x2f\\x21\\x7c\\xe8\\x78\\xde\\xd0\\xa8\\xac\\xb4\\x95\\xb2\\x7a\\x04\\x0f\\xa7\\xec\\x77\\xe8\\xda\\xe6\\xac\\x00\\x9d\\x80\\xb4\\x7c\\x0c\\xf3\\x66\\x00\\x7a\\xef\\xe5\\x8b\\xff\\x38\\xf6\\xfc\\xc8\\xf5\\xe8\\xad\\x27\\x2f\\x1c\\x46\\xbc\\xe1\\x0f\\xdf\\xc8\\xda\\x34\\x28\\x0c\\x7b\\x31\\x60\\x67\\x73\\x83\\xe1\\x77\\x59\\x52\\x66\\x68\\x6b\\x41\\x77\\x7d\\x63\\xc8\\xe1\\x8c\\x69\\x55\\xa2\\xc3\\x9e\\x95\\x45\\x5b\\x9b\\xfd\\xf5\\xef\\xfe\\xc3\\x29\\x7d\\x3c\\x2f\\x32\\x38\\x0d\\x65\\x98\\x49\\x6d\\x76\\x32\\x8c\\x55\\xec\\x37\\x2f\\xfe\\x83\\xa8\\xa7\\x3b\\x9f\\xb5\\x56\\x58\\xc3\\x8c\\x3b\\x80\\x95\\x05\\x13\\x39\\x85\\x73\\x42\\x36\\xab\\xeb\\x39\\xeb\\x36\\xfa\\x1b\\xcb\\xb5\\x35\\x3d\\x86\\x5e\\xfd\\x4a\\x38\\xb4\\xca\\xf2\\x6c\\x4e\\xcb\\x47\\x2d\\x1c\\xee\\x09\\x48\\xa9\\x42\\x98\\x00\\x1a\\xaa\\xd8\\xcb\\xdf\\xbc\\xf8\\x8f\\x45\\x73\\xca\\x5b\\x99\\x00\\x7e\\x89\\x5f\\x60\\x98\\xc5\\xd0\\x29\\xf7\\x77\\x22\\xcb\\x20\\xed\\x3d\\x3a\\xfd\\x51\\xa9\\xed\\x04\\x74\\x8f\\x81\\x34\\xc1\\x58\\xe5\\xe6\\x37\\x37\\x37\\xec\\x5d\\x97\\x52\\xa2\\x8c\\x40\\xd6\\x61\\xb4\\x68\\x35\\x2c\\x5c\\x7e\\xb1\\x8e\\x11\\x5a\\x96\\x2b\\x63\\x97\\x4f\\x79\\xf3\\xe3\\xe6\\x1a\\x97\\xb3\\xb7\\xa3\\x6d\\xc5\\x81\\xfe\\x0e\\x66\\x88\\xc5\\xaf\\x77\\x10\\x29\\x1f\\xfa\\x77\\x55\\xe2\\x6f\\x5f\\x48\\xdb\\x57\\xba\\x4f\\xdd\\x9c\\x32\\xab\\xcb\\xc7\\xbd\\x06\\x75\\xcb\\x5b\\x27\\xe0\\x03\\x90\\x81\\xb2\\x71\\xde\\x16\\x76\\xf5\\xbd\\x9c\\xfc\\xdd\\xcf\\x73\\xaa\\xee\\xe5\\x6a\\xca\\x81\\x84\\xd3\\xd3\\x8c\\x1d\\x4f\\x7d\\xdb\\xe2\\x36\\x77\\x6c\\xdc\\xe8\\xee\\xed\\xff\\xb3\\x88\\xdd\\x5b\\x90\\x03\\x7f\\x76\\xab\\xd3\\xee\\xe4\\x2a\\xf4\\x78\\xf4\\x36\\x18\\xbd\\x3a\\xb6\\xc4\\xf9\\xc8\\xe6\\xe4\\x5e\\xa0\\x61\\x96\\x50\\xae\\x85\\x13\\xbe\\x84\\x02\\xd1\\x3c\\x6a\\x87\\x8c\\xc5\\x88\\x02\\x77\\xce\\xcd\\xca\\x83\\x9e\\x01\\x37\\x76\\x19\\x28\\xe2\\x41\\x7f\\xbc\\xad\\x4f\\x02\\x98\\x6f\\x6d\\xa1\\xd3\\x49\\x48\\x08\\xf2\\xda\\xc6\\x78\\x4e\\x88\\x72\\xf0\\x0e\\xc8\\xc3\\x47\\x01\\x67\\x2d\\x21\\xea\\xa0\\x3a\\x12\\x6e\\xff\\xda\\xf2\\xd5\\xfb\\x0a\\x9b\\x09\\x46\\xce\\x5d\\x44\\x6b\\xff\\x69\\x23\\x38\\xd8\\x9b\\x4e\\x3d\\xf1\\xaa\\x3c\\x8a\\xe4\\xd2\\x24\\x7d\\x85\\xa2\\xfc\\xfc\\xc1\\x08\\xa3\\x0f\\x4c\\x01\\xc9\\x40\\x03\\x9e\\x3e\\x8a\\x46\\x26\\x05\\x08\\xf5\\xa2\\xb3\\xec\\x9e\\xcf\\xcc\\xc1\\x93\\x91\\xc2\\x73\\xb0\\x7c\\x7d\\xa2\\xc9\\x7c\\x6b\\x13\\xfd\\x1b\\xcb\\x65\\xca\\x75\\xea\\x67\\x79\\x78\\x68\\xaa\\x2e\\x07\\xec\\x0d\\xfa\\xe2\\xe4\\x48\\x9d\\xb2\\x89\\xb5\\x85\\x39\\x3d\\x39\\x19\\x0b\\x3b\\xb8\\xfb\\x83\\x19\\x08\\x75\\x92\\xa8\\x3c\\x2f\\xa5\\xb0\\xb3\\x13\\x74\\xc0\\x89\\x61\\x69\\x95\\x36\\x27\\x29\\x4c\\x21\\x3b\\x31\\x62\\xdc\\xe7\\x3a\\x99\\x08\\x0b\\x89\\x2d\\x35\\x9c\\xf0\\x42\\xf4\\x6b\\x99\\xdb\\x0c\\xf2\\xf4\\x17\\x61\\xa0\\xf7\\x2c\\x58\\xb7\\xce\\x20\\x5a\\xa7\\xf4\\x14\\xfa\\xa5\\xbc\\x93\\xea\\x5e\\xf6\\x51\\x13\\x36\\x5b\\x9d\\xc6\\xcd\\xa2\\x20\\x42\\x9b\\x83\\xf7\\x36\\x81\\x0f\\x85\\x4a\\xdf\\xfb\\x26\\xb8\\xc5\\xf4\\xb9\\x4c\\xfb\\xe4\\xb4\\x7c\\xcf\\x7b\\xb1\\x8b\\x6d\\xb8\\x5f\\x07\\x16\\x6c\\x12\\xf5\\x4e\\x6d\\x37\\x6d\\x8a\\x27\\x56\\x4c\\x61\\x27\\x27\\x78\\x68\\xad\\xed\\x7e\\x1b\\x02\\x4e\\xd3\\x52\\xd3\\x8e\\x37\\xbc\\xe1\\xc1\\xb7\\x93\\xf3\\x19\\xca\\x4a\\x38\\x36\\x53\\x24\\x0a\\x48\\x95\\x82\\xb7\\x9c\\x4e\\xd1\\x34\\x70\\xe3\\xc8\\xd1\\xad\\x13\\xa5\\xbd\\x8f\\x1c\\xed\\xc6\\x33\\x63\\x21\\x27\\xe2\\x46\\xdf\\x67\\x33\\x66\\xf5\\x8c\\x1c\\xeb\\xfa\\xce\\x29\\xaf\\xde\\xf3\\xed\\x34\\x86\\x3b\\x7c\\xcf\\x18\\x95\\x08\\x14\\x9d\\x6a\\xb8\\x06\\xb9\\x2d\\xd8\\x00\\x39\\x2b\\x94\\x11\\x38\\xb6\\xe7\\x99\\xdb\\x59\\xf6\\x76\\x67\\xb7\\x0d\\x37\\xdf\\xef\\x7f\\xbb\\xcd\\xd6\\x8d\\xb0\\xca\\xc9\\x96\\x56\\xfa\\x76\\x04\\xc6\\xa8\\x99\\x65\\xe0\\xb7\\xe7\\xd0\\x04\\xc5\\xd7\\x89\\x35\\x89\\x92\\xc6\\x6a\\x2e\\x56\\xe7\\x51\\x2d\\x6f\\x3b\\xba\\x52\\x76\\xf7\\x57\\x30\\xc4\\xa0\\xb3\\x9d\\x80\\xc2\\x96\\x27\\xc6\\x0e\\x31\\xb3\\x26\\x85\\x0a\\xd4\\x4d\\xc0\\x50\\x9a\\x55\\x88\\x45\\x74\\x84\\x6b\\x47\\xd3\\xec\\x0e\\x30\\x62\\x7b\\xc1\\x89\\xbe\\xa6\\x2a\\x4b\\xe9\\x05\\x4a\\xaf\\x37\\xd5\\xba\\x2e\\xc7\\x52\\x55\\x3f\\xbf\\x7a\\x80\\xa4\\xdc\\x34\\x27\\x7f\\xb1\\x2d\\xd8\\x02\\x83\\x41\\xc5\\x87\\xad\\xd0\\x24\\xdc\\xd1\\x0d\\x0f\\xbc\\xfc\\xa2\\x10\\xec\\x5e\\x90\\x31\\xdc\\x0a\\x33\\xa2\\x9c\\xb5\\x6a\\x23\\xa0\\xe1\\x38\\xad\\x50\\xb8\\x72\\x2f\\x23\\x8b\\xa3\\xd4\\x09\\x61\\x91\\xdc\\x24\\x13\\xa5\\x8c\\x3b\\xe5\\xb8\\x9f\\xd8\\xef\\x54\\x28\\xf2\\x19\\x62\\x02\\x8d\\x66\\xb9\\xa3\\x31\\x21\\x91\\xa6\\xee\\x9e\\x04\\xa7\\xfa\\x33\\x61\\x48\\x85\\xaf\\x20\\x18\\xbc\\x5c\\xae\\x1b\\x34\\x5c\\xba\\x3f\\xc6\\x28\\x75\\x19\\xcb\\x4c\\x99\\xbb\\x4e\\xef\\x41\\x8c\\x27\\xd6\\xf4\\x98\\x18\\xc0\\x00\\xb1\\x06\\x78\\x32\\x69\\x74\\x9b\\x03\\xd8\\xd6\\xbd\\x4d\\x4d\\x54\\x6b\\x5a\\x99\\x8f\\xaa\\xac\\x08\\x9f\\x0a\\xd4\\xab\\x78\\xcc\\xfc\\x5e\\x2e\\x05\\x57\\x8f\\x81\\x4d\\x06\\xc7\\x3d\\x56\\xa7\\xec\\xbb\\x39\\x0e\\x67\\x4c\\x58\\x70\\x34\\x1b\\x75\\x19\\xad\\xca\\x31\\xad\\x04\\x42\\x4c\\x28\\xce\\xab\\x4a\\x19\\x41\\x2f\\x6c\\x8a\\x3a\\xe7\\x01\\x2d\\xee\\xc0\\xed\\x1b\\xce\\xbc\\xcc\\x43\\x51\\x25\\x5c\\x1f\\x9a\\xe5\\xa1\\x4a\\x2c\\xd2\\x60\\x0a\\x45\\xda\\xea\\xbc\\xc1\\xfe\\x3f\\xab\\x8f\\x8e\\xcc\\x71\\x0d\\xcc\\x89\\x18\\x4f\\x02\\x2c\\xb9\\x67\\x04\\xed\\x3d\\xd8\\xfe\\xec\\xb1\\xbd\\x7c\\x31\\xd4\\x76\\xf4\\xc8\\x50\\x6b\\xfb\\xc6\\x43\\xbe\\x45\\x8d\\x55\\x8d\\xfd\\xb7\\xa0\\xf3\\x0a\\x8a\\x88\\x22\\x48\\x32\\xbc\\x9d\\x3c\\x5c\\xb1\\xe5\\x71\\x8c\\xbd\\x60\\x47\\x88\\x64\\xc2\\x1e\\x1a\\x44\\xf8\\xbe\\x2a\\x8e\\x07\\xec\\x8c\\xc9\\xb2\\x3a\\x73\\xeb\\x06\\x90\\xaa\\xea\\xdf\\x77\\xe4\\x06\\x35\\xaa\\xee\\x6b\\xc7\\x15\\xef\\x45\\xee\\xa8\\xed\\xe6\\x69\\x6f\\xb6\\xbe\\x87\\x00\\x3c\\x5e\\x34\\x74\\x5d\\x27\\x04\\xeb\\x1d\\x3b\\xd8\\x8f\\x74\\x87\\x3e\\xc2\\x2a\\x76\\xef\\x63\\x21\\x40\\x03\\x8f\\x6b\\x1d\\x85\\x01\\x3a\\xef\\x35\\xa5\\xa7\\xea\\x40\\xb6\\x4f\\x31\\xc1\\x62\\x57\\xac\\x60\\xdd\\x60\\x06\\xeb\\x08\\xae\\x6c\\xaf\\x08\\x9f\\xe5\\x6d\\x3e\\x0c\\x26\\x64\\x61\\xb5\\xa0\\xdd\\x22\\xf2\\xc3\\x19\\x3e\\xdd\\x32\\xf8\\x69\\x75\\xdb\\x97\\xd2\\xd5\\x6d\\x2f\\x9a\\x57\\xb7\\xb5\\x88\\xf7\\xf4\\x02\\x83\\x96\\xb7\\x8e\\xd0\\x96\\xda\\xfe\\xa4\\xad\\x6e\\xdb\\x87\\x16\\xad\\xea\\x67\\x87\\x80\\xa3\\xe5\\xad\\xab\\xb3\\x49\\x6d\\x87\\xe0\\xa4\\xe5\\x6d\\x41\\x44\\x7d\\x3f\\xb1\\x4a\\xcb\\xdb\\xce\\x46\\xd6\\xe5\\x6d\\xd7\\xb8\\xa6\\xe5\\x6d\\x2e\\xd5\\xf1\\x3d\\x05\\x39\\xf5\\xda\\x11\\x4e\\xec\\x2b\\x4b\\xe7\\xf8\\xf5\\x5e\\xfc\\xa4\\x6e\\x1d\\x83\\x78\\xb7\\xc8\\xa8\\xe5\\x6d\\x5e\\x00\\x7c\\x26\\x51\\x52\\x4b\\xba\\xfa\\xca\\xba\\x6e\\x5e\\xaf\\xfc\\x98\\x72\\xdc\\x43\\x9c\\x8f\\x57\\x28\\x7a\\x3e\\xf5\\x26\\xd8\\xa9\\x31\\x22\\xbb\\xd0\\x80\\xa5\\x0d\\x30\\x6c\\x2c\\xd8\\x61\\x3e\\x4c\\x60\\xd6\\xf2\\xd6\\x1d\\xe3\\xa4\\xd6\\x11\\xfb\\xa4\\xd6\\x19\\x72\\xa3\\xc0\\xf3\\x25\\xd9\\x85\\x3f\\xa2\\xac\\x43\\x96\\xe9\\x28\\xeb\\x44\\x59\\x67\\x8b\\x16\\x65\\x9d\\x4d\\x5b\\x94\\x75\\x56\\xb5\\x28\\xeb\\x2c\\x69\\x51\\xd6\\x89\\xb2\\xce\\x5e\\xed\\xe9\\xc9\\x3a\\x64\\xa9\\xea\\xcc\\x60\\xf6\\x37\\x32\\xb8\\xce\\x5b\\xc8\\x50\\x9a\\x0a\\x21\\x41\\x6d\\x53\\x99\\xe3\\xfd\\x37\\x9e\\xc4\\xde\\xa2\\x79\\xcd\\x47\\xba\\x6b\\x2e\\xc7\\xc0\\x5e\\xf6\\x5f\\xbe\\xd8\\x30\\x9d\\x70\\x79\\xdb\\x27\\xe8\\xa7\\xd9\\xb6\\x4d\\x3d\\x9c\\x6f\\xab\\x3c\\x12\\xef\\xcd\\xbb\\xe4\\x4f\\x6a\\xe5\\xf0\\x68\\x49\\x98\\x2b\\x1c\\x44\\x55\\x55\\xac\\x1c\\x2c\\xe3\\xb6\\x65\\x10\\x17\\x39\\x54\\x0e\\xd1\\x56\\x0a\\x73\\x1d\\x13\\xac\\xa4\\xf7\\x77\\xb8\\x4d\\x1d\\xec\\x36\\x83\\x04\\x38\\xc5\\xc1\\x0f\\xa1\\x9a\\x85\\xca\\x81\\x12\\x54\\xc3\\xa1\\x77\\x53\\x80\\x00\\x2b\\x76\\x04\\x83\\xf1\\x80\\xa5\\x94\\xec\\xcd\\xa5\\x8f\\x39\\x3b\\xee\\x35\\xdd\\xe3\\xb9\\x23\\xae\\x1a\\xff\\xe3\\xa6\\xed\\xfd\\xe3\\x30\\x05\\x69\\x4b\\x9e\\x65\\x33\\x06\\x53\\x91\\xd8\\x6a\\x7d\\x18\\x50\\x28\\x2c\\x39\\x3b\\xf7\\x71\\xa5\\xec\\x21\\x1e\\xee\\x2b\\x12\\xf6\\x17\\xce\\xd6\\x76\\xfe\\xea\\xd0\\xf6\\x97\\xdd\\x16\\xe6\\xb1\\x3b\\xbd\\x99\\x93\\x4b\\x08\\x42\\x83\\x95\\x6a\\x95\\x75\\xa3\\x91\\xbf\\x12\\xff\\x89\\x08\\xfe\\xf6\\xdd\\xae\\xee\\x31\\xd6\\x11\\x4f\\xd8\\x9b\\x0f\\xcc\\x2b\\x50\\x65\\x96\\x39\\xf4\\x26\\x8f\\xd9\\x22\\x08\\x96\\x78\\xb2\\x96\\x64\\xeb\\x90\\x9b\\x35\\x6f\\x64\\xed\\xe0\\x3b\\xb7\\xaa\\x50\\x99\\x1a\\xcf\\x9a\\x3b\\xe8\\xef\\x81\\xa9\\xcb\\xe3\\x70\\x66\\xca\\xa1\\x17\\x01\\xdd\\x21\\xba\\x9a\\xdb\\xf2\\xe8\\x0b\\x59\\xd9\\xa2\\x2f\\x64\\xa1\\x45\\xfb\\xc0\\x7c\\x8b\\xf6\\x81\\x2d\\x5a\\xb4\\x0f\\x2c\\x69\\xd1\\x3e\\xb0\\xd8\\xa2\\x7d\\x20\\xda\\x07\\xf6\\x69\\x9f\\xbe\\x7d\\x80\\x45\\x5f\\xc8\\xaa\\x16\\x65\\x9d\\xba\\x45\\x59\\x67\\xf3\\x16\\x65\\x9d\\xc5\\x16\\x65\\x9d\\x28\\xeb\\x44\\x59\\x27\\xca\\x3a\\xbb\\xb6\\x3d\\x90\\xbb\\x50\\x69\\xe7\\x29\\x32\\x85\\x4a\\xd7\\x64\\xc8\\x90\\xbd\\x3a\\x51\\xfd\\x4c\\x25\\x55\\x65\\x12\\xf7\\x89\\xf7\\x7c\\x18\\x9e\\x93\\x09\\xbd\\xc7\\xfe\\xa5\\x24\\x50\\x7a\\x02\\x95\\xbc\\xcd\\x81\\x29\\xbc\\x44\\xa2\\x50\\xe9\\x91\\x39\\xde\\x21\\xf0\\x3c\\x66\\xd8\\xc4\\x0c\\x9b\\x9f\\x41\\x86\\xcd\\x84\\x1b\\x5f\\x38\\x09\\x49\\xeb\\xea\\x84\\x9b\\xc6\\xf1\\xbf\\x05\\x9d\\xff\\x6c\\xf3\\x6d\\x1c\\xc2\\x79\\x84\\xc1\\x7b\\xea\\x6a\\xa4\\x20\\xd8\\xa5\\xde\\xb7\\x0b\\xe9\\x75\\x1b\\x62\\x5e\\x2f\\xa3\\x2b\\x7a\\xd2\\x14\\x52\\x56\\x80\\xee\\x13\\x92\\x29\\x36\\x12\\xbe\\x7e\\xd8\\x1c\\xfe\\x7a\\x08\\x3f\\xf3\\xbc\\x99\\x36\\x24\\x9e\\x75\\xf2\\x4c\\x7b\\x29\\x9d\\xf9\\xa6\\x9a\\x2e\\xba\\x16\\x57\\x7c\\x76\\xa9\\x34\\xdd\\x68\\xa5\\x7d\\x66\\xbd\\x3b\\xed\\xeb\\xbd\\xf4\\xd2\\xae\\x94\\x48\\x54\\xf2\\x6e\\xb6\\x2a\\x93\\xbc\\xba\\x2d\\x2d\\x6e\\xfb\\xcf\\x12\\xf4\\x8c\\xa9\\x29\\xe8\\x5a\\x31\\xaa\\x6e\\xf7\\xe9\\x55\\x97\\xd4\\x24\\xdc\\x17\\x50\\xee\\xc6\\xc0\\xd3\\x89\\x29\\xa2\\x4b\\x4d\\xbd\\x6b\\xaf\\x21\\x7b\\x62\\xd5\\x93\\x57\\xb7\\x6e\\x15\\x87\\x0e\\xd5\\x86\\xe7\\x56\\x8b\\x79\\x75\\xeb\\xd4\\xfc\\xc6\\x3a\\x36\\xc1\\xb1\\x0e\\xcd\\x70\\xac\\x5b\\x53\\x1c\\xeb\\xdc\\x1c\\xc7\\xba\\x34\\xc9\\xb1\\x0f\\x5e\\x41\\x7a\\x75\\xeb\\xd8\\x7c\\xc4\\x3a\\xb7\\xd2\\xb1\\x67\\x58\\x8f\\x7a\\x75\\x7b\\x0f\\xe0\\xee\\xd2\\x62\\xc7\\x62\\x75\\xeb\\xbd\\x5b\\xd7\\x06\\x35\\xd6\\xb5\\x51\\x8d\\x75\\x8d\\x87\\x3b\\x55\\xd1\\x5e\\xdd\\x62\\x7d\\xed\\xf7\\x20\\xa7\\x75\\x26\\x44\\xec\\x5b\\x93\\xfb\\xb1\\x89\\x76\\x80\\x93\\xd5\\xdd\\xbf\\x1f\\x4a\\x01\\x22\\x2e\\x5d\\x5f\\x38\\xeb\\xc6\\x6e\\xdc\\xf5\\x85\\xa1\\x9a\\xcd\\x8b\\x51\\x43\\xdc\\x2a\\x62\\x34\\xfe\\x9e\\x06\\x83\\x57\\x29\\x1b\\xc5\\xe3\\x1a\\x9d\\x2d\\x5c\\x3d\\x53\\x9b\\xce\\xaa\\xcb\\x67\\x9c\\x52\\x50\\x5f\\x5a\\xd5\\xf8\\x18\\xdf\\x1d\\x50\\x38\\x69\\x2d\\x4d\\xc8\\x74\\x3e\\xc0\\xb4\\xfe\\x02\\xf5\\x0b\\xba\\x0e\\xf7\\x20\\xd8\\xb1\\x0f\\x4d\\xfd\\xc6\\xc1\\xa0\\x79\\x73\\xae\\xef\\xf1\\xe8\\x7f\\xff\\x7d\\xdc\\xaa\\xde\\x52\\x77\\x18\\xb5\\xbf\\x8d\\x5b\\xd4\\xfe\\xf6\\x6a\\x51\\xfb\\x5b\\xd9\\xa2\\xf6\\xb7\\x47\\x8b\\xda\\xdf\\x66\\x2d\\x6a\\x7f\\xab\\x5b\\xd4\\xfe\\xa2\\xf6\\xb7\\x43\\x8b\\xda\\x5f\\xd4\\xfe\\x76\\x6d\\x3f\\x63\\xed\\xaf\\xdb\\xa8\\xe6\\xa6\\x2e\\xe6\\x83\\x44\\x50\\x7e\\xb4\\xdc\\x8a\\xa4\\x8e\\x78\\x0e\\x6f\\xd1\\xbf\\xba\\xd5\\x01\\x9b\\xfa\\xdd\\x72\\x0d\\xb0\\xa9\\x25\\x2e\\x68\\xc1\\x83\\x47\\xd4\\xbd\\x4a\\x21\\x5c\\xf8\\x72\\xbd\\x26\\xf8\\xa9\\x45\\x6e\\x77\\x86\\x89\\x0d\\x97\\x70\\xa7\\xa8\\x78\\x1b\\x02\\xcb\\xea\\x8b\\xdb\\xab\\xa8\\xb3\\x94\\x1d\\x05\\x5f\\x3c\\x5e\\xc4\\x22\\x95\\x6d\\x3f\\x94\\x56\\xf4\\xeb\\x37\\x2a\\xef\\x3c\\x06\\xd5\\xb4\\xf2\\xf9\\x5b\\x2e\\xe4\\x2a\\x86\\xad\\x8a\\x8f\\xaa\\xb1\\xc7\\x91\\x47\\xd0\\xad\\x39\\xe0\\xc5\\xb7\\x23\\x21\\x29\\xd2\\x31\\x5c\\x1a\\xa4\\x64\\x08\\x9a\\x22\\x7a\\x4a\\x57\\x2f\\x78\\x3c\\x27\\xd1\\x17\\xe7\\x83\\xf2\\x6f\\x0d\\xbb\\x46\\x94\\x0f\\xc7\\x43\\xc6\\xa5\\x4f\\x86\\x55\\x32\\xdc\\x6a\\x4f\\x37\\xd5\\xd7\\xf2\\x72\\x75\\x17\\x4b\\x35\\xfa\\x80\\xbd\\x42\\xac\\x6f\\x76\\x2c\\x0c\\xc2\\xc7\\x5f\\x13\\xd1\\x0d\\x22\\x3f\\xad\\xc2\\x0d\\xf7\\x5b\\x17\\x6e\\x98\\x8b\\x18\\x89\\x75\\x1b\\x62\\xdd\\x86\\xbd\\xea\\x36\\xe0\\x43\\x3a\\xdc\\x9d\\x17\\x70\\x60\\x7f\\xf3\\xd7\\x2b\\x69\\x40\\x50\\xe5\\x65\\x66\\x45\\x51\\x47\\x60\\x1b\\x1a\\x2a\\x23\\x4d\\x62\\xe4\\x23\\x41\\xdb\\xf8\\xee\\x46\\xe3\\xc9\\x64\\x1e\\xef\\xb1\\x3f\\x8c\\xd8\\x36\\x48\\x4e\\x7c\\xb4\\x25\\x5e\\x86\\x84\\x15\\x07\\x82\\xda\\x41\\x21\\xa5\\xe2\\xf9\\x47\\x0a\\x5e\\x20\\xc1\\x36\\xb5\\xd6\\x4c\\x77\\x75\\x39\\x3a\\x9f\\x39\\x94\\x70\\x14\\x7b\\x0d\\x83\\x68\\x5e\\x68\\x81\\x51\\xab\\x62\\x0a\\xb2\\xe6\\x12\\x47\\xe6\\xf8\\x38\\x48\\x43\\x9d\\x72\\xaf\\xf7\\xc2\\x7d\\xfe\\xd4\\xe0\\x12\\x7f\\xd9\\x84\\xff\\xe0\\x82\\x2a\\x0e\\x54\\x83\\xaf\\xe6\\x3f\\xcf\\x3b\\x24\\x72\\xff\\xe8\\xb6\\x2e\\x2c\\x72\\x9d\\x45\\xb5\\x7d\\xf4\\x88\\xb6\\x9f\\x53\\xed\\x8b\\x27\\xe9\\xc3\\x78\\x72\\x5a\\xc7\\xa7\\xe1\\xb7\\x88\\x09\\xa3\\x9b\\xb7\\xe7\\x90\\x30\\xfa\\x91\\x7c\\x13\\xcf\\x27\\x6f\\xf4\\xd9\\xfa\\x23\\x9e\\x4b\\xde\\x68\\xf4\\x41\\x6c\\xd5\\x3e\\xd5\\x74\\xce\\x76\\xeb\\xd0\\xe7\\x10\\xfd\\x0d\\x1d\\xcb\\x54\\x9d\\x30\\xff\\xf7\\xe3\\x67\\xe8\\x04\\xff\\x3a\\x8d\\x2e\\x8b\\x91\\x65\\x1f\\x33\\xb2\\x2c\\x6a\\x61\\x51\\x0b\\x6b\\xb7\\xa8\\x85\\x2d\\xb4\\xa8\\x85\\x6d\\xd1\\xa2\\x16\\xb6\\xba\\x45\\x2d\\x6c\\xb1\\x45\\x2d\\x2c\\x6a\\x61\\x1b\\xb4\\xa8\\x85\\x45\\x2d\\x6c\\xd3\\xf6\\x33\\xd3\\xc2\\xba\\xab\\xb7\\x1e\\x23\\xbc\\xde\\x43\\x84\\x57\\x37\\x94\\xb0\\x03\\xfa\\xd7\\x09\\xd6\\x75\\x14\\xd1\\x15\\xa3\\xb9\\x9e\\x76\\x34\\xd7\\x9e\\x65\\xe7\\xa4\\x15\\xef\\xa7\\xf4\\x5c\\x73\\xb7\\x57\\xd5\\x9f\\xe3\\x53\\x25\\x52\\x56\\x94\\xd6\\x57\\xdf\\x8a\\x35\\xe8\\x9e\\x72\\x0d\\xba\\xd6\\x8e\\xc6\\x42\\x74\\x1b\\x15\\xa2\\x5b\\x05\\xb3\\x58\\x8d\\x6e\\x45\\x7b\\x3a\\x31\\x66\\xb1\\x1a\\xdd\\xb6\\x2d\\x56\\xa3\\x5b\\xde\\x62\\x35\\xba\\x35\\x2d\\x56\\xa3\\x8b\\xd5\\xe8\\x62\\x3d\\x82\\x3d\\x5a\\xac\\x47\\xb0\\xa4\\xc5\\x7a\\x04\\xbb\\xb7\\x58\\x8f\\x60\\xa3\\x16\\xeb\\x11\\xc4\\x7a\\x04\\xed\\x16\\xbd\\x50\\xfb\\xb5\\x58\\x8f\\x60\\xcf\\x16\\x3d\\x53\\xb1\\x1e\\xc1\\x5e\\x1d\\xc6\\x6a\\x74\\x9f\\x54\\xcc\\x20\\x8b\\xda\\x5f\\xd4\\xfe\\x36\\x6e\\x51\\xfb\\x5b\\xd9\\xa2\\xf6\\xb7\\x47\\x8b\\xda\\xdf\\x66\\x2d\\x6a\\x7f\\xab\\x5b\\xd4\\xfe\\xa2\\xf6\\xb7\\x43\\x8b\\xda\\x5f\\xd4\\xfe\\x76\\x6d\\x3f\\x63\\xed\\x2f\\x56\\xa3\\x7b\\xf2\\xb1\\x8a\\xec\\x29\\x66\\x24\\xc5\\x6a\\x74\\x31\\x7e\\x71\\xa7\\xed\\x8e\\xd5\\xe8\\x1e\\x6f\\x3f\\xfb\\x6a\\x74\\xad\\x58\\xba\\x8f\\x57\\x92\\x6e\\xfb\\x69\\xc4\\xba\\x74\\xb1\\x2e\\x5d\\xac\\x4b\\x17\\xeb\\xd2\\xc5\\xba\\x74\\xb1\\x2e\\xdd\\xe6\\xed\\xe9\\x7b\\x33\\x9e\\x9c\\xfe\\xf1\\x69\\x78\\x30\\x62\\x45\\x84\\xcd\\x5b\\xac\\x88\\xb0\\xb2\\xc5\\x8a\\x08\\xb1\\x22\\x42\\xf4\\x46\\xec\\xd2\\x62\\x45\\x84\\x2d\\x5b\\xf4\\x3c\\xc4\\x8a\\x08\\x5b\\xb5\\x58\\x97\\xee\\x93\\x89\\x31\\x8b\\x5a\\x58\\xd4\\xc2\\xda\\x2d\\x6a\\x61\\x0b\\x2d\\x6a\\x61\\x5b\\xb4\\xa8\\x85\\xad\\x6e\\x51\\x0b\\x5b\\x6c\\x51\\x0b\\x8b\\x5a\\xd8\\x06\\x2d\\x6a\\x61\\x51\\x0b\\xdb\\xb4\\xfd\\xcc\\xb4\\xb0\\x58\\x97\\xee\\x49\\xc7\\x7a\\xc5\\xba\\x74\\x4b\\x5a\\x8c\\xeb\\x7a\\xda\\x71\\x5d\\x3b\\xe2\\x0a\\x2f\\xad\\xca\\x55\\x29\\xed\\x0d\\xe8\\xa9\\x48\\xe0\\x2c\\x49\\xdc\\x5f\\xb7\\xea\\x0e\\xb6\\x8c\\x25\\x6a\\xab\\xa1\\x6b\\xba\\x65\\x42\\xa6\\x22\\x41\\x45\\xf2\\x7e\\x02\\x58\\x56\\xce\\xc9\\xb7\\xf8\\x1e\\xe3\\xf4\\x22\\xb3\\xf8\\x66\\x8d\\x5e\\x38\\x4f\\x47\\xd4\\x30\\xc0\\x06\\xbb\\xde\\x16\\x5e\\x04\\xa1\\xa1\\x52\\x19\\x70\\xb9\\xc5\\x97\\x9e\\x1b\\x82\\xde\\xf2\\x34\\xb7\\x00\\xf2\\xda\\x93\\xe2\\xba\\x33\\x36\\x84\\x4c\\xc9\\xb1\\x8f\\xe7\\xf1\\x27\\x60\\xc0\\xce\\xeb\\x17\\x12\\x2e\\xf1\\xf0\\x94\\x5a\\x83\\xb4\\xd9\\x0c\\xe1\\x80\\x05\\xae\\x50\\x6b\\xc8\\xd5\\x14\\x52\\x24\\xd9\\x18\\x46\\x44\\x72\\x24\\xb7\\x2c\\x03\\xee\\xc6\\x92\\x50\\x0f\\xe6\\x0e\\x0f\\x67\\xd7\\xd8\\x3f\\x75\\x3a\\x04\\x1f\\xda\\xb4\\x13\\x10\\xb7\\xa7\\x8d\\x3b\\x51\\xc3\\x39\\xcb\\x86\\x17\\x9b\\x90\\x2f\\x25\\xa8\\x1f\\x35\\x56\\x88\\x47\\x73\\xa6\\x4a\\x76\\xcf\\x49\\x52\\xd2\\xa5\\xc4\\xc3\\x8c\\x4b\\x77\\xa0\\xdd\\x72\\xf0\\x3d\\x64\\x92\\xdd\\xcd\\x0f\\x7d\\xa4\\x6a\\x5b\\x7e\\xb6\\x8f\\x39\\x80\\xeb\\xf1\\x4e\\x4c\\xaa\\xb5\\x35\\x87\\x67\\x7a\\x5c\\x92\\x48\\xe8\\x51\\x19\\xa4\\xd5\\x33\\x8c\\xb7\\x23\\x99\\xa2\\x81\\x89\\x39\\x1f\\xc3\\xe1\\xa1\\x61\\xe7\\x6f\\x2e\\x1c\\xf9\\x2b\\x8d\\xa3\\xd6\\xbe\\xca\\x9e\\x27\\x87\\x85\\x56\\x53\\x91\\x3a\\xe4\\xfe\\x96\\x6b\\xc1\\x87\\x99\\x93\\x3b\\x47\\xa0\\x41\\x3a\\xb1\\xe0\\x97\\x47\\xdf\\x9e\\xbd\\xfb\\xfb\\xd5\\xd9\\x9b\\x57\\xc7\\x28\\x81\\xc2\\x43\\xc1\\xa5\\x3b\\x15\\xa5\\xa9\\x03\\x45\\xfd\\x70\\x6e\\x20\\x90\\x53\\xa1\\x95\\x74\\xf3\\x43\\x5d\\x8d\\xb3\\x69\\xe8\\x35\\xa9\\x0e\\x83\\x06\\xa3\\xb2\\x29\\xa4\\x24\\x27\\x57\\xa3\\x05\\xae\\x23\\x64\\x51\\xda\\xa0\\x3b\\x62\\xf8\\xa2\\x3b\\x40\\x32\\x99\\x70\\x39\\x76\\xf3\\xbc\\x50\\xa5\\xeb\\xef\\x97\\xbf\\xc4\\x19\\x69\\x48\\xcb\\x84\\x24\\x27\\x1e\\xb0\\xf6\\x97\\xbd\\xc0\\x29\\x1c\\xad\\x37\\x54\\x12\\xd1\\x24\\xbc\\x08\\x73\\x6e\\x2e\\xcb\\xcc\\xa4\\xe5\\x0f\\xa7\\x14\\xbf\\x77\\xf0\\xcb\\xc6\\xa3\\x83\\x50\\x4e\\x52\\xb9\\x21\\x88\\xdf\\xd0\\xac\\x32\\xac\\x64\\x98\\xb1\\x83\\xe6\\xdb\\x03\\xf6\\xca\\x8d\\x01\\x69\\x13\\x80\\x14\\x7e\\x09\\x53\\xd0\\xa8\\x79\\x7a\\xf0\\xf5\\x98\\x86\\x31\\xd7\\x69\\x06\\x06\\x03\\x0f\\x03\\x6d\\x26\\xed\\xc0\\x03\\x0c\\x2a\\xbd\\x56\\x2a\\xbb\\x8c\\x98\\xb0\\x37\\x0a\\x83\\x10\\x47\\xea\\x94\\x4d\\xac\\x2d\\xcc\\xe9\\xc9\\xc9\\x5d\\x39\\x04\\x2d\\xc1\\x82\\x19\\x08\\x75\\x92\\xaa\\xc4\\x9c\\x58\\x6e\\xee\\xcc\\x89\\x90\\xee\\x70\\xf5\\x53\\x6e\\x79\\xbf\\x71\\xaa\\x4f\\x88\\x73\\xf7\\x13\\x95\\xe7\\x5c\\xa6\\x7d\\xee\\xb1\\xab\\x5f\\x6d\\xeb\\xc9\\x2f\\x3c\\x4f\\xed\\xf3\\xea\\x2d\\x21\\xfb\\xbc\\x6f\\x26\\x90\\x65\\x87\\x3b\\xe0\\xf3\\x7e\\x32\\xdf\\x1e\\xb2\\xde\\x5e\\x32\\x9e\\x5f\\xfb\\xfe\\x07\\xf8\\x55\\x75\\x5e\\x09\\x06\\x03\\x76\\xa5\\xac\\x8f\\x8f\\xf5\\xa1\\xd8\\x48\\x47\\x11\\xbe\\x2b\\x8f\\xf4\\xab\\xab\\xdb\\x77\\xff\\x7d\\xfd\\xf6\\xf2\\xea\\x36\\x9e\\xec\\x78\\xb2\\xe3\\xc9\\xde\\xe3\\x64\\x83\\x9c\\xee\\x7d\\xaa\\x83\\xcc\\xd9\\x38\\x26\\xd5\\x7e\\x23\\xa7\\x36\\x60\\xc3\\x31\\xa8\\x36\\x60\\x6f\\x09\\x91\\xda\\x47\\x83\\x7a\\x0b\\x02\\xaf\\xe4\\xf4\\x5b\\xde\\xb6\\xb0\\xcb\\xa5\\xe0\\x60\\xfe\\x05\\x12\\x94\\x2b\\x19\\x7c\\x9f\\xf8\\xf8\\x3d\\xac\\x59\\xfb\\xba\\xaf\\x76\\x92\\x22\\xa9\\xed\\xef\\x5a\\x72\\x43\\xef\\x6e\\x68\\x68\\x6d\\xdf\\x15\\xcf\\xeb\\x0a\\xd5\\x4b\\x76\\x6d\\xc0\\xde\\x04\\xb5\\x87\\x9d\\xff\\xfd\\xf2\\xe2\\xd5\\xd5\\xed\\xe5\\x97\\x97\\xaf\\xde\\xed\\xae\\x47\\x77\\x60\\x71\\x41\\x9b\\x42\\x47\\x00\\x38\\xdc\\x91\\x4b\\x16\\x1a\\xa6\\x42\\x95\\x26\\x9b\\x55\\x56\\x90\\xe5\\x44\\x60\\xfe\\xf4\\x7b\\xbf\\xef\\xac\\xd2\\xc7\\x97\\x7e\\x16\\x99\\x6d\\xb7\\xcc\\xf6\\x02\\x46\\xbc\\xcc\\x48\\x7b\\x3a\\x38\\x18\\xec\\xc2\\xe5\\xa8\\x75\\x85\\xbe\\x5f\\x6a\\xb5\\x47\\x05\\xe6\\x16\\x0a\\xdf\\x50\\xed\\xf6\\x91\\xd2\\x2b\\x8f\\xf1\\xa1\\x8f\\x3e\\x68\\xb1\\x1e\\x2f\\x3c\\x92\\x85\\xce\\x4b\\x8f\\xe4\\x24\\xdb\\x13\\x3a\\x7b\\x7a\\x19\\xba\\xf1\\xbd\\x27\\x4a\\x8e\\xc4\\xf8\\x0d\\x2f\\xbe\\x86\\xd9\\x3b\\x18\\xed\\x67\\x26\\x6e\\xc3\\x1b\\xad\\x8f\\xde\\x95\\x8c\\xb6\\x4a\\xc7\\xce\\x68\\xb0\\xfd\\xdc\\x34\\x9d\\x39\\x69\\xba\\x8a\\xce\\xd8\\x3f\\x32\\xa3\\xbb\\x40\\x8a\\x4e\\x82\\x28\\x16\\xea\\xe1\\x93\\x1d\\xda\\x5b\\x94\\xbb\\x8a\\xb1\\xe9\\xc4\\x73\\xbf\\x1f\\x97\\x0f\\xad\\xcd\\xec\\x9a\\xec\\xde\\xd3\\x59\\xbb\\xa9\\xda\\x91\\x28\\x99\\x40\\x61\\xcd\\x89\\x9a\\x3a\\xce\\x05\\xf7\\x27\\xf7\\x4a\\xdf\\x39\\x3d\\xc2\\xe9\\xae\\x7d\\xc2\\x5a\\x73\\x82\\x3e\\x83\\x93\\x5f\\x90\\x1b\\xec\\xf6\\xed\\xc5\\xdb\\x53\\x76\\x96\\xa6\\xfe\\x72\\x93\\xd2\\xc0\\xa8\\xcc\\xfc\\x75\\x02\\x03\\xc6\\x0b\\xf1\\x2d\\x68\\x23\\x94\\xec\\xb1\\x3b\\x21\\xd3\\x1e\\x2b\\x45\\xfa\\xc5\\xee\\xc4\\x39\\xb4\\x0e\\x77\\x41\\x15\\xe4\\xea\\xec\\x78\\x27\\x6e\\xd0\\xc7\\x32\\x6b\\xf1\\xae\\x8a\\x88\\x38\\xae\\x25\\xac\\x41\\xdc\\x0c\\x56\\x67\\x2f\\x64\\x74\\x04\\x9a\\xed\\x4d\\xf4\\xf3\\x0d\\xb7\\xb0\\x5b\\xba\\x7a\\x58\\x13\\x56\\x72\\x71\\x7a\\x44\\x2d\\x54\\x7a\\xca\\x4c\\x59\\x14\\x4a\\x5b\\xc3\\x72\\xb0\\xdc\\x29\\xbd\\x03\\x87\\x61\\xbd\\xf6\\x9f\\xe8\\xab\\xea\\xb1\\x1f\\xab\\x1f\\xd1\\xe1\\x64\\xbe\\x3b\\x3c\\xfc\\xd3\\xd7\\xaf\\xfe\\xfb\\x2f\\x87\\x87\\x3f\\xfc\\xd8\\x7c\\x8a\\xac\\x90\\xa2\\x80\\xda\\xaf\\x98\\x02\\x92\\x81\\x54\\x29\\x5c\\xe1\\x18\\xf8\\xa7\\x69\\xb9\\x59\\xfc\\x03\\xcb\\x6d\\x69\\x06\\x13\\x65\\xec\\xe5\\x75\\xf5\\x67\\xa1\\xd2\\xf9\\xbf\\xcc\\x1e\\x12\\x07\\x7b\\x9a\\x8c\\x01\\xb7\\xe8\\x9a\\xdb\\xc9\\x13\\x61\\x0f\\x35\\x2d\\xe9\\xf8\\xa8\\xfa\\x5e\\x9b\\x97\\xe8\\xe4\\x1c\\xff\\xf9\\x65\\x00\\x81\\x93\\x9e\\xee\\xb5\\xb0\\x16\\x5d\\x6f\\x3e\\x15\\x5c\\x8d\\x7a\\xee\\xd4\\xd6\\x62\\xe7\\xf4\\xe5\\xde\\xf5\\x51\\x3a\\x25\\x6d\\xd5\\x0e\\x76\\x0c\\x30\\x84\\x88\\x87\\x16\\x1d\\xe4\\x8a\\xc1\\x2e\\xba\\x98\\xcf\\xae\\x2f\\xd9\\x94\\x20\\xfc\\x64\\x80\\x13\\xd2\\x7b\\xbf\\x7c\\xaf\\x34\\xae\\xba\\x74\\xc9\\x83\\xaa\\xd2\\x10\\x4f\\x29\\x28\\xa8\\x4a\\x32\\x66\\x99\\xc8\\x85\\x8f\\x35\\xf4\\x17\\x34\\x19\\x76\\x44\\x3f\\x0e\\x92\\xa2\\xec\\xf9\\x17\\x06\\x39\\xe4\\x4a\\xcf\\xaa\\x3f\\xa1\\x98\\x40\\xee\\x34\\xad\\xbe\\xb1\\x4a\\xf3\\x31\\xf4\\xaa\\xcf\\xe9\\xb3\\xea\\x2f\\xfa\\xb0\\x35\\xc0\\xe2\\xd7\\xa4\\x0a\\xd7\\xae\\x52\\x4f\\x91\\x21\\xfd\\xf4\\x68\\x5b\\x00\\xfd\\x13\\x21\\x6d\\x15\\x66\\x5c\\xbd\\x07\\x91\\xb0\\xb2\\xc4\\x91\\xc0\\x59\\x41\\x11\\xf5\\xc9\\xa9\\xca\\xca\\x1c\\x4c\\xaf\\x12\\x83\\xc8\\x1a\\x20\\xa7\\x4e\\xb3\\x34\\x4f\\x4a\\x50\\x4b\\xc5\\x54\\x98\\x2e\\xc2\\x88\\x97\\xc8\\x69\\xc2\\x47\\xe4\\xab\\xd2\\x16\\xa5\\xf5\\xf5\\x66\\x1a\\x17\\xbb\\x29\\x83\\x76\\x8b\\xaa\\x28\\x40\\x8b\\xec\\xbf\\x3c\\xd8\\x3f\\x1a\\x9d\\x5b\\x0b\\x5a\\x9e\\xb2\\xff\\x39\\xfa\\xfe\\x57\\x3f\\xf5\\x8f\\xbf\\x38\\x3a\\xfa\\xee\\x45\\xff\\x8f\\x3f\\xfc\\xea\\xe8\\xfb\\x01\\xfe\\xe3\\xf3\\xe3\\x2f\\x8e\\x7f\\x0a\\x7f\\xfc\\xea\\xf8\\xf8\\xe8\\xe8\\xbb\\xaf\\xdf\\x7c\\x75\\x7b\\xfd\\xea\\x07\\x71\\xfc\\xd3\\x77\\xb2\\xcc\\xef\\xe8\\xaf\\x9f\\x8e\\xbe\\x83\\x57\\x3f\\x6c\\xd8\\xc9\\xf1\\xf1\\x17\\xbf\\xdc\\x7b\\xea\\x5c\\xce\\xde\\xee\\x49\\x40\\xa9\\xf5\\x3b\\x2b\\x17\\x34\\xdf\\x63\\x47\\x71\\xd6\\x0f\\xfd\\x5a\\x69\\xea\\x0b\\x69\\xfb\\x4a\\xf7\\xa9\\xeb\\x53\\x66\\x75\\xb9\\x1f\\x31\\xa9\\x99\\x52\\xd7\\xe7\\x3f\\xdc\\xde\\x75\\x5a\\x33\\xa4\\x8a\\x5d\\x3f\\x99\\x03\\x6e\\x20\\xd1\\x60\\x3f\\x84\\x25\\x87\\x46\\x0a\\x72\\xca\\x5c\\xcc\\xe3\\xa7\\xc6\\xe7\\x7e\\x0e\\xc6\\x9d\\x2a\\x64\\x10\\xf7\\xb5\\x96\\x44\\x47\\x5a\\xe5\\x03\\xd6\\x70\\x6f\\x4c\\x31\\xe1\\xc3\\xbf\\x77\\x07\\x7b\\x58\\x41\\x43\\x8b\\xc6\\xa0\\x68\\x0c\\x5a\\xd1\\x1e\\x35\\x06\\xdd\\x10\\x1e\\x3e\\x59\\x4b\\x10\\xc8\\xe9\\xae\\x2e\\x8c\\xa5\\x1e\\xf4\\xa0\\xeb\\x58\\xc5\\x0a\\x55\\x94\\x19\\xb7\\x2b\\x3c\\x63\\x4b\\xdc\\xe9\\xfe\\xa8\\xd7\\xf1\\xc8\\x75\\x30\\x0d\\x31\\xb4\\x7c\\xb9\\x0f\\x93\\x9d\\x65\\x19\\x13\\x92\\x0e\\x3e\\x76\\x10\\x1c\\x66\\x1a\\x48\\xb5\\x61\\x9c\\xfc\\xd9\\x53\\x37\\x85\\x7b\\x5f\\x56\\xae\\x19\\x97\\x63\\x98\\xb1\\x5c\\x5b\\x8c\\x3d\\xc6\\xb2\\x73\\xc4\\x4a\\xbc\\xf7\\x49\\xc8\\xba\\xf8\\x5c\\x25\\x1c\\x56\\xb9\\x20\\x4b\\x6f\\xc6\\xcc\\xb8\\xb1\\x61\\xda\\x38\\x1b\\xcb\\xef\\xd0\\xdb\\x98\\x40\\x0a\\x32\\x01\\x4c\\x4c\\x2b\\xa1\\x5e\\xeb\\xd0\\xe9\\x6d\\xec\\x95\\x9c\\x52\\x1f\\x9c\\xa5\\x25\\x05\\x83\\x10\\xf9\\x5b\\xde\\xc7\\xa7\\x15\\x80\\xe0\\x10\\xf1\\x26\\x5c\\x60\\x5c\\xc5\\x21\\x20\\xd5\\xaf\\x34\\xec\\x2a\\xbf\\xaf\\xb2\\xb2\\x9a\\x8f\\x13\\x79\\xb0\\x3f\\xcf\\xac\\x3c\\x5b\\x7b\\x09\\x43\\x0b\\xcc\\xb2\\x36\\x3f\\xb7\\x99\\xe4\\xa7\\xe0\\x0c\\xdc\\x9f\\x7d\\xfe\\xec\\x58\\x67\\x47\\x6c\\xb3\\x1b\\x96\\xb9\\x85\\xef\\xa4\\x4b\\x36\\xd9\\x85\\xb3\\xa4\\xd0\\x30\\x12\\x0f\\x1d\\x9d\\xd3\\x33\\x59\\x5b\\x62\\x44\\x0a\\xd2\\x8a\\x91\\xa0\\x3b\\xef\\x0b\\x0d\\x05\\xc8\\xb4\\x2a\\x5c\\x8a\\xc9\\xe1\\xb2\\x0d\\x9b\\x27\\x19\\xcc\\x43\\x02\\x77\\xb7\\xa4\\xec\\x66\\x99\\xb0\\x1f\\xe9\\x18\\x8b\\x74\\x6c\\xe7\\xf6\\x81\\xe8\\x98\\xc7\\xdc\\xa7\\x43\\xc4\\x30\\xf2\\x7c\\xff\\xe8\\xf7\\xf3\\x76\\x28\\x3b\\x22\\xf2\\xd6\\x88\\x56\\x67\\x76\\x9d\\x60\\x2f\\x86\\xb2\\x24\\xab\\x34\\xec\\x8a\\x34\\x5a\\x45\\xc1\\x6b\\x6c\\x22\\xc6\\x0e\\xb2\\x19\\x4c\\x21\\xf3\\x72\\x13\\xcb\\xb9\\xe4\\x63\\xca\\xef\\xb6\\x2a\\x98\\x6a\\x9d\\xa2\\xe5\\xf0\\x58\\x8b\\x74\\x21\\xee\\x1e\\xe5\\x78\\x87\\xdb\\x99\\xe2\\x29\\x3e\\xd4\\x2a\\xcb\\x40\\x1b\\x96\\x89\\x3b\\x60\\x17\\x50\\x64\\x6a\\xe6\\xd3\\xb5\\x65\\xca\\x6e\\x2c\\xb7\\x0e\\xab\\x6f\\xc0\\xee\\xe6\\xf6\\xdd\\x0b\\x63\\x71\\xc6\\xd7\\x65\\x96\\x5d\\xab\\x4c\\x24\\x3b\\x19\\x55\\xda\\x3b\\x77\\x89\\xfb\\x55\\x94\\x59\\xc6\\x0a\\xec\\x72\\xc0\\xde\\x4a\\x24\\x1a\\x67\\xd9\\x3d\\x9f\\x99\\x1e\\xbb\\x82\\x29\\xe8\\x1e\\xbb\\x1c\\x5d\\x29\\x7b\\x4d\\xd2\\x77\\x3b\\xe0\\x8e\\x5e\\x64\\x62\\xc4\\x4e\\xb1\\xba\\x8d\\x65\\x96\\x8f\\x51\\x77\\x0a\\x6e\\xc0\\x9e\\x83\\x7f\\xb3\\x03\\xa2\\x0f\\xf7\\xc2\\x2c\\x55\\x56\\xf6\\x46\\x9c\\x5f\\x60\\x4f\\x8e\\x56\\xd1\\xdf\\x1f\\x7c\\x9b\\x32\\x31\\x82\\x64\\x96\\x64\\xfb\\x1f\\xad\\xb3\\x04\\x03\\x18\\xea\\x8c\\xf3\\x06\\x7e\\xfb\\x6a\\xea\\x3e\\xc7\\x13\\xb5\\x40\\x21\\x19\\x95\\x39\\xa7\\xfa\\xed\\x35\\xaa\\x57\\x33\\x22\\x6d\\xd7\\x74\\xaa\\x24\\xee\\xcc\\x3c\\xf7\\x65\\x9b\\x85\\x32\\xf6\\xc6\\x69\\xe8\\x9d\\x14\\x43\\x3f\\xbc\\x0e\\xdd\\x31\\x2c\\xf9\\x9c\\x65\\x90\\x32\\x91\\xe7\\x90\\x3a\\x2d\\x3e\\x9b\\x31\\x3e\\xb2\\x98\\x6b\\xdb\\xb2\\x10\\x24\\x1a\\x08\\x6b\\x7d\\x15\\x93\\x09\\x97\\x69\\x06\\x9a\\x8d\\xb8\\xc8\\xbc\\x3d\\xa0\\xf5\\xbe\\x05\\x9d\\x0b\\x89\\x66\\x01\\xf2\\xc8\\xa2\\x89\\xc1\\xfd\\x95\\x24\\x4a\\x87\\xf2\\xf4\\xc2\\x9a\\xf0\\xa8\\x3e\\x98\\xc8\\x47\\x1a\\x08\\x30\\xef\\x5a\\x66\\xc3\\x4c\\x25\\x77\\x86\\x95\\xd2\\x8a\\x8c\\x26\\xa3\\xd4\\x1d\\x4b\\x54\\x5e\\x64\\x78\\x74\\xf6\\x38\\x59\\xd5\\x3f\\xfb\\x15\\x2a\\xf5\\x5d\\xef\\xe6\\xe4\\x17\\xf5\\x23\\xfc\\x61\\x57\\x86\\xde\\x81\\x20\\xd6\\x85\\x18\\x06\\x0f\\x90\\x74\\x96\\xe7\\xff\\xea\\x01\\x92\\x46\\x61\\x09\\xbc\\x8f\\x01\\x4f\\x34\\xe6\\x79\\xf2\\x3b\\xf8\\x84\\x2a\\xd9\\xed\\x91\\x4b\\xd7\\x6c\\x2d\\xf8\\x9d\\x53\\x9f\\xa1\\x10\\x96\\x1f\\x82\\x65\\x42\\x22\\x7d\\xf3\\xf9\\x75\\x4c\\x48\\xe3\\x38\\x7b\\xeb\\x30\\xd0\\xd1\\xf3\\x42\\x2b\\x4b\\x85\\xc6\\x2a\\x08\\xb3\\x2a\\x90\\x3a\\xf4\\x85\\x05\\x06\\x94\\xb2\\xec\\xe8\\xf0\\xe4\\xf0\\x78\\xc1\\xfe\\x78\\xe8\\x24\\x90\\x0c\\x88\\xd6\\x86\\xc4\\xbd\\x6a\\x52\\x46\\xe4\\x45\\x36\\xc3\\x79\\x1c\\xa6\\x3d\\x26\\x6c\\x88\\xb4\\xd6\\xa5\\x0c\\xb3\\xf2\\x49\\x7f\\x3d\\x66\\x14\\xb3\\x9a\\x87\\xea\\x2a\\xf4\\xab\\x7b\\xc9\\xea\\xd2\\x53\\xf9\\xa3\\xc3\\x9f\\x0e\\x7b\\x0c\\x6c\\x72\\xcc\\xee\\x95\\x3c\\xb4\\x38\\xfd\\x01\\xbb\\x55\\x4e\\x94\\xae\\x3b\\x9a\\xa9\\x92\\x49\\xa0\\xc0\\x7e\\x78\\x28\\x32\\x91\\x08\\x9b\\xcd\\x90\\x62\\x31\\x55\\x5a\\xca\\x21\\xe6\\x36\\x24\\x1b\\xbe\\x7a\\x10\\xd6\\xc7\\xab\\x39\\x92\\xf1\\x02\\xa1\\x49\\x54\\x8b\\x71\\x27\\xe6\\x4c\\xe1\\x64\\x02\\x3c\\xb3\\x13\\x0a\\x12\\x91\\x4a\\xf6\\xff\\x05\\x5a\\x61\\x0e\\xa2\\xf4\\x4f\\x3e\\xb9\\xaa\\x7f\\x9d\\x68\\x0e\\x8e\\x88\\x7e\\x05\\xdd\\x5d\\xe2\\xf3\\xd7\\xdb\\xdb\\xeb\\xaf\\xc0\\xce\\x91\\x0c\\x37\\x4a\\x08\\xdd\\x41\\x6b\\x00\\xe8\\x91\\xd2\\xf9\\x13\\xa0\\x1d\\xdd\\x38\\x2b\\xfb\\xac\\x50\\xfa\\x29\\x90\\xb0\\x89\\x32\\x7b\\xed\\x25\\x5b\\xd8\\x4f\\x65\\x2c\\x6a\\x43\\x5e\\x1a\\x93\\x90\\xb8\\x1d\\x6c\\xc7\\x90\\x84\\x7b\\x6e\\x2e\\xaf\\x07\\xec\\xbf\\x55\\xe9\\x56\\x33\\xe4\\xc3\\x6c\\x56\\x55\\x62\\x30\\x60\\xd9\\x81\\xeb\\xea\\xc0\\x91\\x27\\x87\\x0d\\x7f\\x05\\x9e\\x3a\\x15\\xc5\\x51\\x0f\\xe0\\x4f\\xe3\\x3e\\x2b\\xe6\\xcf\\x83\\x9f\\x5b\\xb7\\x7c\\xa0\\x34\\x56\\xe5\\x6c\\xe2\\x97\\xdd\\x4e\\xbd\\xf4\\x27\\x63\\x80\\xa7\\x27\\xe4\\x35\\x69\\x28\\x88\\xc2\\xf9\\x6f\\x3e\\x39\\xfa\\xb5\\x40\\x37\\x08\\xee\\xfe\\xf7\\x21\\x96\\xb1\\x4a\\x9a\\x60\\xf3\\x17\\x3a\\x51\\x62\\x90\\x24\\x60\\x39\\x54\\x83\\xdd\\x5c\\x25\\xcd\\xf6\\x84\\x6b\\x8f\\xee\\x9c\\xc8\\x39\\xdf\\x11\\x3a\\xf5\\xf6\\x8f\\xf5\\xea\\xb4\\xf2\\x68\\x37\\x71\\x03\\x6c\\x99\\x91\\xd5\\xe3\\x0c\\x59\\x5f\\xc8\\x9e\\x83\\xe6\\x98\\xe0\\x43\\x4d\\xb8\\x54\\x52\\x24\\x3c\\x13\\xff\\x82\\x94\\x95\\x85\\x92\\x3e\\x7e\\x0e\\xe5\\x9c\\x84\\x1b\\xe8\\xa3\\x53\\x57\\x5a\\x5f\\x33\\xad\\xce\\x56\\x74\\xc7\\xd1\\x2a\\x85\\xc2\\x07\\xba\\xf1\\x1c\\x7d\\xa4\\xf1\\x9e\\x6e\\x81\\xcd\\x0f\\x01\\xe6\\x6e\\x50\\x8c\\x75\\x09\\x81\\xa2\\x83\\x00\\xf2\\xc5\\xf0\\x71\\xab\\x9c\\xb6\\x8b\\x09\\x9e\\x44\\xc2\\x91\\x18\\x19\\xd0\\xd3\\xfd\\x51\\xa0\\xbb\\xa5\\xab\\xdd\\xed\\x0a\\xa1\\x2d\\xc9\\xc6\\xd6\\x4c\\x96\\xf9\\x10\\x74\\x9d\\xff\\xa2\\xed\\x22\\x40\\x1a\\xf1\\x0f\\x57\\xf4\\x7a\\x30\\x1a\\xb7\\x2f\\x69\\x74\\x5f\\xfe\\xfe\\x77\\xbf\\xfb\\xcd\\xef\\x06\\xd4\\x7d\\x15\\x0b\\x21\\xd9\\xe5\\xd9\\xd5\\xd9\\xdf\\x6f\\xbe\\x3d\\xc7\\x14\\xdc\\x7d\\xa1\\xda\\x51\\xa0\\x67\\xd7\\x61\\x9e\\x9d\\x06\\x79\\xbe\\xd7\\x10\\x4f\\x4c\\x2c\\xd9\\x9b\\x8a\\xb4\\x3d\\x0c\\xd8\\xa5\\xc3\\x00\\xa7\\x1d\\x3a\\xbd\\xd6\\x4b\\x98\\x8d\\x92\\x68\\x4e\\xa2\\x6d\\x9b\\x6b\\xdd\\x51\\x7b\\x12\\x67\\xcc\\x26\\xc5\\x8d\\x4a\\xee\\x3a\\xd4\\x9e\\x2e\\xa0\\xd0\\x90\\x90\\x35\\xee\\xf6\\xfc\\x9a\\x7a\\x77\\x5a\\xec\\xd5\\xdb\\xdb\\x3a\\xa1\\x01\\xa3\\x7e\\xd8\\xeb\\x60\\xc5\\xfa\\xab\\xb7\\xd7\\x39\\xcd\\xf7\\x0e\\x0a\\x5b\\x19\\x08\\x86\\x3c\\xb9\\xbb\\xe7\\x3a\\x45\\xfb\\x19\\xb7\\x62\\x28\\x32\\x41\\x25\\x86\\xc3\\xd5\\x93\\x52\\x51\\x58\\x21\\x95\\x52\\x53\\xa3\\xf9\\x02\\x9e\\xb5\\xd1\\x15\\x0d\\x63\\xc4\\x02\\x47\\x5c\\x64\\x68\\xa7\\x2d\\xa5\\x15\\x39\\xf8\\xb8\\xa3\\xa4\\xa8\\x0c\\x87\\x4d\\xcb\\x79\\x54\\xf1\\x42\\x7b\\xb2\\x2a\\xde\\xe1\\xdb\\xe0\\x3b\\xdc\\x5a\\xdb\\xdb\\x37\\xfa\\xf1\\x09\\xb3\\x3a\\xcf\\xe2\\x28\\xed\\x24\\xb2\\xba\\x9f\\x05\\xab\\x2b\\x34\\xdc\\x58\\x55\\x74\\xe4\\x8b\\xa1\\xce\\x56\\x78\\x62\\x86\\x30\\x52\\x8e\\x08\\xaf\\x74\\xad\\x84\\x9b\\x88\\x25\\xa6\\x20\\x06\\xdb\\x99\\x6a\\xb9\\x4f\\x28\\xee\\xd3\\x94\\xc9\\x24\\x98\\x41\\x25\\x18\\x73\\x82\\x4e\\x97\\xb2\\x20\\xdd\\x18\\xc9\\x75\\xa9\\xa1\\xe7\\x56\\x07\\x39\\xce\\xae\\x57\\xe7\\x52\\xb8\\xe1\\x41\\xd2\\x8f\\x60\\x13\\xb2\\x0f\\x37\\x08\\x39\\x96\\x1f\\xf5\\xd3\\x9f\\x77\\xd6\\x24\\x9a\\x9b\\x09\\x60\\x11\\x13\\x78\\x10\\xe1\\xce\\x95\\x6b\\x95\\x1e\\x1e\\xd6\\x4b\\x71\\x8c\\x65\\xac\\x79\\x02\\xac\\x00\\x2d\\x94\\x63\\x46\\xa5\\xb4\\xa9\\xba\\x97\\x6c\\x08\\x63\\x21\\x4d\\x00\\x85\\xeb\\x3b\\xc0\\x0c\\xbd\\x3e\\xc2\\x54\\xe5\\xe7\\x06\\xec\\x5d\\xab\\xa4\\x8a\\x4f\\x76\\x4a\\x54\\x7d\\x34\\xfd\\x9c\\xe7\\xfd\\x55\\xc8\\xb1\\x1a\\x17\\x33\\x57\\x10\\x0e\\x41\\xb8\\x76\\x83\\x29\\x1f\\x95\\x12\\x47\\x4e\\x21\\xe3\\x33\\x8a\\x69\\x1d\\x09\\x89\\x9a\\xa3\\x36\\xc7\\x1d\\xf8\\xb5\\x1c\\x08\\xeb\\x67\\x2b\\xe7\\x81\\x17\\x02\\xf0\\x64\\xb2\\x9f\\x8b\\x39\\x3a\\xc2\\x36\\x6c\\xd1\\x11\\xb6\\x4f\\x27\\xd1\\x11\\x16\\x1d\\x61\\x8f\\xb4\\xe8\\x08\\x8b\\x8e\\xb0\\xb9\\xf6\\x64\\xb5\\xa4\\xe8\\x08\\xdb\\xb9\\x45\\x47\\xd8\\xfa\\x16\\x1d\\x61\\x1b\\xb4\\xe8\\x08\\xdb\\xb0\\x45\\x47\\xd8\\xea\\x16\\x1d\\x61\\xfb\\x4d\\x26\\x3a\\xc2\\xa2\\x23\\xcc\\xb7\\x9f\\x9f\\x75\\x30\\xb4\\xe8\\x08\\x5b\\xe8\\x24\\x3a\\xc2\\xa2\\x23\\x6c\\xe3\\xf6\\x64\\x55\\xbc\\xe8\\x08\\xa3\\x16\\x1d\\x61\\xed\\xf6\\xf3\\x62\\x75\\xc1\\x8d\\x74\\xed\\x14\\xca\\xfd\\xf3\\xf3\\xae\\xd1\\x75\\x21\\x12\\xef\\x8d\\x6a\\x5e\\x80\\x57\\x0d\\xd5\\xb8\\xf3\\xae\\x51\\xe2\\x24\\xa4\\x15\\x79\\xbf\\x53\\xed\\xcd\\x5a\\x9a\\xfb\\xb5\\xad\\x43\\x24\\x24\\x4c\\x9a\\x93\\x42\\xd1\\xff\\xd5\\xee\\x90\\x86\\x1f\\x84\\xd4\\xea\\xdd\\xf3\\xef\\x3e\\x5a\\x66\\xd9\\x3e\\xce\\x8f\\x0f\\xe3\\xf8\\x78\\x22\\x5e\\xa2\\x0e\\x9c\\x1d\\xd1\\xd1\\xf1\\xc9\\x39\\x3a\\x3e\\x9d\\x1b\\x80\\xbd\\xff\\xff\\x76\\xa2\\xc1\\x4c\\x54\\xb6\\x33\\xa2\\xb7\\x90\\xfc\\x8d\\x90\\x22\\x2f\\x73\\x87\\x73\\xc6\\xe1\\xb3\\x98\\x56\\x81\\x06\\xa6\\x42\\x57\\xa2\\xd8\\x64\\xab\\x74\\x2f\\x8a\\x14\\xb0\\x70\\x2b\\x17\\x99\\xdb\\x46\\xcc\\x45\\x9d\\xf0\\xa9\\xc3\\x75\\x53\\x26\\x09\\x00\\x5e\\x0b\\xd7\\xd4\\x70\\x7e\\x33\\xa8\\x46\\xaa\\xae\\x01\\x79\\xb9\\x1f\\xbd\\xd9\\x8f\\x89\\x53\\x69\\x55\\xec\\xe5\\x37\\xbf\\xde\\xa9\\x8f\\xb1\\x2e\\xba\\xa1\\xcb\\x5f\\xbd\\xbb\\x3e\\x6f\\x5e\\xf9\\x2d\\x03\\x59\\x16\\x72\\xaa\\x32\\x84\\x2a\\xa7\\x97\\x9c\\xb0\\xf6\\x11\\x89\\xf4\\xfe\\x6a\\xc7\\x5e\\x2a\\x47\\x17\\x3c\\x62\\x5f\\xa9\\xba\\x6d\\x37\\x73\\xb2\\x73\\xdb\\x72\\x34\\xc6\\xbd\\xa4\\x0a\\xfe\\x1b\\xcb\\xce\\x7b\\x53\\xb7\\xfd\\xe5\\xd9\\xfd\\x8f\\x03\\xc3\\x12\\x3b\\xb8\\xf0\\xce\\x00\\x7c\\xe0\\xaf\\x9c\\x0e\\x2c\\xb8\\xa9\\xb8\\x84\\x5b\\xad\\xac\\x62\\x45\\xc6\\xeb\\x7b\\xa9\\x70\\x07\\xfe\\x8a\\x7c\\xe3\\x7c\\x02\\xc9\\xdd\\x3b\\xef\\xa3\\x3d\\x32\\x00\\x95\\x3c\\x39\\x16\\x76\\x52\\x0e\\x07\\x89\\xca\\x4f\\xdc\\x31\\xa6\\xff\\x1b\\x66\\x6a\\x78\\x92\\x73\\x63\\x41\\x3b\\x11\\xd3\\xb3\\xa5\\x7e\\xe2\\x7a\\x11\\x72\\x3c\\xc8\\xd3\\xe3\\x01\\xfb\\x5e\\x52\\x76\\x7d\\x7d\\x0f\\x66\\xa3\\xb6\\x84\\x1b\\x3f\\xd4\\xf9\\x18\\x82\\xa3\\x88\\x4a\\x37\\xaf\\x2f\\x1f\\xce\\x70\\x7a\\x83\\x7d\\x0a\\x35\\xef\\xcd\\x46\\xf6\\xf4\\x8f\\x7f\\x78\\xdf\\x78\\xa4\\x5c\\xac\\x03\\x23\\xc9\\x73\\xf3\\x81\\x77\\x16\\x0b\\xd2\\x81\\xef\\xfb\\x09\\xf9\\xbd\\x9f\\x8c\\x38\\xfb\\x54\\x7c\\xdd\\x4f\\xb0\\xda\\x75\\x07\\xfe\\xed\\x2e\\x7c\\xdb\\xdd\\xf9\\xb5\\xdf\\x43\\x51\\xe8\\xe7\\xec\\xcf\\xee\\xd0\\xe8\\xd7\\x91\\x1f\\xfb\\x43\\xf8\\xb0\\x3b\\x59\\xf5\\xbe\\xbe\\xeb\\x0f\\xe7\\xb7\\xee\\x66\\xb9\\x5d\\xaa\\x1b\\xcf\\xd5\\x57\\xdd\\x81\\xf1\\xbe\\x4b\\xc3\\x7d\\x67\\x46\\xfb\\xf7\\xe6\\x9b\\xde\\xdf\\x2f\\xfd\\x04\\x7c\\xd2\\x7b\\x03\\x59\\x48\\x61\\x05\\xcf\\x2e\\x20\\xe3\\xb3\\x1b\\x48\\x94\\x4c\\x77\\xe6\\x63\\x73\\xb5\\x48\\xab\\xf3\\x63\\xa8\\x5b\\x6f\\xc1\\x6a\\x27\\x7a\\x4c\\xb8\\x2f\\xb9\\xee\\xf4\\x36\\x4a\\x6c\\x09\\x5e\\x0e\\x2f\\xb6\\xa0\\xbf\\x99\\x66\\xf9\\x24\\xfd\\x16\\xec\\xc9\\x98\\xca\\x28\\xeb\\xa5\\xcb\\x4d\\xfc\\xab\\xba\\x67\\x6a\\x64\\x41\\xb2\\x23\\x21\\xc3\\x3e\\x1e\\x37\\x94\\xcd\\xda\\x6e\\x59\\xa1\\xb5\\x7b\\xfa\\xf2\\x45\\x78\\xf9\\xd3\\x33\\x48\\xa2\\xe9\\xd5\\x98\\xf7\\x6f\\x1f\\xf6\\x03\\x3d\\x6e\\x20\\xf6\\x2f\\x8e\\xca\\xac\\x6d\\x24\\x26\\xc3\\x71\\x9b\\xde\\xbc\\xac\\x8b\\x46\\xbf\\xc4\\x7e\\xab\\xd3\\xc6\\x65\\xca\\x7c\\x26\\xdc\\xa7\\xb7\\x69\\x7b\\x47\\xdc\\xb4\\x45\\xbf\\x2a\\xc2\\xe6\\x31\\x7b\\xf2\\xed\\xf9\\x75\\x34\\x27\\x3f\\x2d\\xa3\\xcc\\x47\\x8a\\x5a\\x79\\x82\\x82\\xee\\x33\\x8d\\x54\\x89\\x82\\xee\\x16\\xad\\x91\\x1b\\xfb\\x95\\xe6\\x09\\x5c\\x77\\x2e\\x23\\x84\\xe3\\xc4\\xd2\\x52\\x73\\x4f\\x00\\x2b\\x91\\x2f\\x1c\\x1e\\x09\\x90\\xd2\\x69\\xaa\\xf2\\x89\\x31\\x53\\x77\\x54\\x66\\xd9\\x8c\\x6c\\x0e\\xad\\xec\\x6b\\xf2\\xc2\\xcf\\x27\\xf3\\xa2\\xe1\\x7f\\xc9\\x28\\xb5\\x60\\x59\\x68\\xe5\\x79\\xa6\\x2e\\xa5\\x74\\x34\\xb8\\xbe\\xf9\\x0d\\x05\\x49\\x2c\\x46\\xcd\\x5b\\x29\\xc3\\x46\\x8c\\xdd\\xf4\\x1d\\xff\\xc3\\x6c\\xe2\\x3a\\x34\\xb1\\xd5\\xa1\\xfb\\x7a\\xa4\\x74\\x22\\x86\\xd9\\x8c\\x4d\\x78\\x56\\x5d\\xf3\\xc3\\xd9\\x9d\\xc8\\x32\\xdf\\xcd\\x80\\xdd\\x80\\x25\\xc7\\x05\\xf1\\xce\\x4c\\xc9\\x31\\x4e\\x8e\\xcb\\x70\\xbd\\x24\\x24\\xee\\xdb\\x24\\x03\\x2e\\xcb\\x82\\xc6\\x73\\x9c\\x78\\xa6\\x4a\\x1d\\xc6\\x1b\\x54\\xee\\x8f\\x8a\\x03\\x4b\\x91\\xf5\\x1a\\x97\\xd8\\xad\\xdd\\xd8\\xda\\x44\\x63\\x9c\\x00\\xf0\\x36\\x14\\xdf\\xee\\x35\\xfb\\x0c\\xf5\\xd1\\x4d\\xe3\\x0a\\xa3\\x42\\xab\\xa9\\x48\\xc9\\x87\\x12\\xc0\\x86\\xd7\\x65\\xd3\\x35\\x45\\xd5\\x79\\x96\\x4a\\xf6\\x25\\x8c\\x39\\x0a\\x2a\\xfe\\x14\\xd1\\x9e\\x51\\x3f\\x14\\x5b\\x20\\x53\\xbc\\xb8\\xc8\\x49\\xf8\\xaa\\x68\\xa5\\xf3\\x4f\\x05\\x5d\\xb9\\xdc\\x80\\x1c\\x3b\\x92\\x8a\\x29\\x8c\\x54\\x2d\\xa5\\xb0\\x74\\x8d\\xff\\xa4\\xb4\\x2c\\x55\\xf7\\xf2\\xd8\\xdb\\xac\\x84\\x61\\x9c\\x0d\\xc1\\xf2\\x46\\xac\\xa9\\x67\\x70\\x86\\x81\\xe4\\xc3\\xcc\\xed\\x39\\x86\\x62\\xdd\\x2e\\x05\\x10\\x1b\\x01\\xb7\\xa5\\x06\\x36\\xe6\\x16\\x96\\xca\\x39\\xb4\\xde\\xf5\\xe0\\x15\\xc6\\x1b\\x58\\x47\\xac\\x94\\x06\\xf6\\x64\\xef\\x9d\\x09\\x47\\xbf\\xff\\xed\\x6e\\x34\\x42\\xe4\\xa0\\x4a\\xfb\\x41\\xb4\\xbf\\xfb\\x89\\x48\\x26\\x4d\\x61\\x56\\xe4\\x60\\x98\\x2a\\xe7\\xd4\\xe2\\x97\\xfe\\xb3\\xe5\\x3b\\x14\\x55\\xc0\\x65\\x6d\\x57\\xf3\\xf1\\x12\\xeb\\xd7\\x7c\\x39\\x86\\xfa\\x7e\\x6f\\x8c\\x20\\xbf\\xb8\\xba\\xf9\\xfb\\xeb\\xb3\\xff\\x7a\\xf5\\x7a\\xc0\\x5e\\xf1\\x64\\xd2\\xac\\xc9\\x21\\x19\\x47\\xa2\\x81\\x84\\x62\\xc2\\xa7\\xc0\\x38\\x2b\\xa5\\xf8\\x67\\xe9\\xdd\\xca\\x47\\xd5\\xb7\\xc7\\x9d\\x56\\xa4\\xdf\\x91\\xfb\\x3a\\x6a\\xb3\\x13\\xc6\\x2f\\xbd\\xf4\\x0e\\x7b\\xf3\\x11\\x5b\\xca\\x00\\x5e\\x53\\xb3\\x20\\x3e\\x55\\xbe\\xec\\x19\\xa9\\x08\\x28\\x70\\x61\\x60\\xfd\\xc5\\xdb\\x57\\x37\\x18\\xb0\\x5f\\x68\\xaa\\x54\\x82\\x11\\x5e\\xf8\\x1c\\x7b\\x1a\\x82\\xfb\\xc2\\xdf\\x4f\\x3c\\x60\\x67\\x72\\x46\\x0f\\xe9\\x4c\\x09\\xc3\\x32\\x61\\x2c\\x20\\xd7\\xf3\\x62\\x5b\\xf0\\x92\\x1f\\xbc\\x18\\xe0\\xff\\x0e\\x18\\x4f\\x53\\xed\\xe4\\xba\\x2a\\x70\\x2d\\x59\\x88\\x24\\x25\\xc9\\x4f\\x0c\\xb3\\xc6\\x02\\x24\\x58\\x8a\\x53\\x7b\\xa3\\x52\\x3f\\x73\\xe4\\x24\\xe8\\x21\\x23\\x36\\x68\\xac\\xe6\\x16\\xc6\\x22\\x61\\x39\\xe8\\x31\\xb0\\x82\\xdb\\x64\\xc2\\x72\\x3e\\x63\\x89\\xd2\\xba\\x2c\\xe8\\x36\\x83\\x94\\x5b\\x3e\\x60\\x5f\\x2a\\xcd\\xf2\\x70\\x88\\x1d\\xce\\x3b\\x3e\\x7c\\xb3\\x3c\\x72\\xa0\\x3e\\xd9\\xcd\\x7f\\x0a\\x63\\x4a\\x30\\x27\\x2f\\x5f\\xfc\\xe1\\xd7\\xbf\\xfb\\xdd\\x27\\x75\\x01\\x5e\\x15\\xda\\x8b\\x71\\x2f\\x8d\\x0b\\xf0\\x78\\xd8\\x05\\xda\\x75\\xba\\x10\\x51\\xc8\\x71\\xd6\\xc4\\xaf\\xdd\\x18\\xc0\\xbe\\x5a\\xe6\\xbe\\x3a\\x66\\xbf\\x5e\\xc1\\xf5\\xae\\xaa\\x66\\x27\\x17\\xf1\\xd5\\x73\\xe8\\xe8\\xfa\\xaa\\x9a\\x0f\\x06\\xc5\\xca\\xd3\\x06\\xd5\\xbc\\x91\\xf8\\xf2\\x3a\\x1c\\x4c\\x2f\\xe7\\xe4\\x73\\xd7\\xd8\\x16\\x75\\x0c\\x54\\x8f\\xbd\\x60\\x7f\\x62\\x0f\\xec\\x4f\\xa8\\x68\\xfd\\x7e\\xdf\\xcb\\xbe\\xf6\\x55\\x81\\xba\\x08\\x69\\x72\\xfa\\xfd\\xe5\\x75\\x47\\x10\\xff\\x9b\\x23\\x9a\\xae\\x47\\x07\\x55\\xab\\xd8\\x50\\x78\\xc1\\x1e\\x1e\\x2c\\x68\\x27\\x68\\xfa\\x9d\\xf8\\xa8\\xd7\\xa4\\xb9\\x09\\x7e\\x40\\x34\\x23\\xc7\\xc3\\xe5\\xa8\\x1d\\x46\\xb5\\x1d\\xa2\\xb9\\xcf\\xff\\xaa\\x8c\\xbd\\xf2\\x54\\xa8\\x7d\\xe1\\x4f\\xdd\\x5b\\x8e\\x84\\xbf\\x45\\xc6\\x1c\\xdf\\x30\\xb6\\x3e\\x60\\x86\\xa5\\x0a\\xa3\\xba\\x28\\xc4\\x79\\x22\\xf6\\x08\\xd6\\x78\\x3a\\x68\\xbc\\x9f\\xff\\xbe\\xb5\\x9f\\xeb\\x76\\x6a\\xce\\x94\\x82\\x3a\\x90\\x17\\xb1\\x1a\\x35\\xba\\x0a\\x95\\x7a\\xe9\\xcc\\x4d\\x2b\\x6d\\xf0\\x8c\\x35\\xe2\\x99\\xb7\\xda\\x54\\xf6\\x66\\xc4\\x25\\x77\\x9e\\x12\\x2e\\x29\\xc9\\x64\\x04\\x5a\\x53\\x54\\xfa\\x70\\x16\\x82\\x03\\xf7\\xde\\xbc\\xbd\\x4e\\x52\\xa1\\x95\\x55\\x89\\xda\\xe3\\x26\\xb7\\xb6\\xb7\\xdb\\x77\\x87\\x40\\x28\\x08\\x77\\x3d\\xe4\\xbf\\xb9\\xb8\\xee\\xb1\\xdb\\xf3\\x6b\\xbc\\xdd\\xea\\xe6\\xfc\\xf6\\xba\\xad\\xb3\\x1c\\xdc\\x9e\\x5f\\x1f\\x7c\\x54\\x50\\xb0\\x20\\xf0\\xa1\\x89\\x7a\\x87\\x4e\\x5a\\x26\\x28\\x27\\x4d\\xf6\\x73\\x5e\\xf4\\xef\\x60\\xb6\\x23\\x4f\\xed\\x82\\xaf\\xf7\\xab\\x1d\\xee\\x64\\x41\\x04\\xe6\\x9c\\x17\\x5b\\xf7\\xa6\\x81\\xa7\\xe2\\x03\\x65\\x7a\\x85\\xb0\\xdb\\x6a\\xcc\\xe5\\x29\\x5f\\xb9\\x9a\\x42\\x4a\\x52\\x7a\\xf8\\x02\\x64\\x5a\\x28\\xe1\\xe4\\xc5\\x98\\x07\\xb6\\xfd\\xd7\\x31\\x0f\\x6c\\xe3\\x16\\xf3\\xc0\\x62\\x1e\\xd8\\x62\\x7b\\x32\\x81\\xb3\\x31\\x0f\\xec\\xd3\\xf2\\xe0\\xc7\\x3c\\xb0\\xed\\xdb\\x47\\x77\\xdc\\xc7\\x3c\\xb0\\xe5\\x2d\\xe6\\x81\\xc5\\x3c\\xb0\\xcd\\x5a\\xcc\\x03\\xdb\\xbe\\x3d\\xb9\\x90\\xa3\\x98\\x07\\xb6\\x55\\x8b\\x79\\x60\\x8b\\x2d\\xe6\\x81\\xad\\x68\\x31\\x0f\\x6c\\x45\\x8b\\x79\\x60\\x8b\\x2d\\xe6\\x81\\x6d\\xd7\\x62\\x1e\\x58\\xcc\\x03\\xfb\\xa4\\xc3\\x63\\x59\\xcc\\x03\\xf3\\x2d\\xe6\\x81\\x7d\\x12\\x41\\x80\\x2c\\xe6\\x81\\x6d\\xd4\\x62\\x1e\\x58\\xcc\\x03\\xdb\\xa5\\xc5\\x3c\\xb0\\x4f\\xc5\\x28\\x13\\xf3\\xc0\\x62\\x1e\\xd8\\xcf\\x47\\xd0\\x8d\\x79\\x60\\x31\\x0f\\x2c\\xe6\\x81\\xc5\\x3c\\xb0\\xb5\\xb3\\x88\\x79\\x60\\x9f\\x82\\x0a\\xa8\\xc1\\x88\\x7f\\xc1\\xb5\\xca\\x44\\x32\\xdb\\x3b\\x4a\\xf1\\x9d\\xbf\\xf8\\xd8\\xf8\\x6e\\x59\\x81\\xfd\\x36\\x42\\xab\\xf6\\xc8\\x3c\\x79\\x62\\x09\\x37\\xef\\x1a\\x80\\x6b\\x26\\xde\\x54\\x97\\x3f\\xbf\\x07\\x10\\x3c\\x89\\xe4\\x9b\\xb0\\xc0\\xab\\xdd\\x3d\\x29\\xfd\\x70\\x01\\x01\\x81\\x6f\\x37\\xbb\\xc5\\xde\\x2a\\x42\\x73\\x21\\x1d\\xc5\\x83\\x1f\\x36\\x33\\x22\\x2b\\x4c\\xb0\\xaa\\xa2\\x60\\x62\\x25\\x82\\xf0\\xa2\\xc8\\x04\\x98\\x01\\xbb\\xa9\\x2e\\xe0\\x41\\xea\\x65\\x4e\\x59\\x52\\x94\\x3d\\x96\\x43\\xae\\xf4\\x6c\\x0f\\x6d\\xa2\\x03\\x81\\xb3\\xb5\\x6b\\x1d\\x81\\xec\\x1d\\xf5\\x19\\xc0\\xe0\\x94\\x88\\xa2\\xc8\\x66\\x24\\x4c\\xd5\\xa9\\xa4\\x15\\xd4\\x44\\x20\\x2e\\x29\\x8a\\x3b\\x73\\x51\\x1e\\xc2\\xb6\\xd4\\xb0\\x2b\\x65\\xdf\\x79\\x84\\xff\\x68\\xb1\\xf6\\xab\\xa2\\xca\\xb9\\x55\\xb9\\x48\\x76\\x21\\xd8\\x44\\x63\\xf7\\x8f\\x29\\x3f\\x57\\x79\\x51\\x5a\\x68\\x91\\x6d\\x02\\x16\\x49\\x72\\xc2\\x34\\x55\\xb8\\xfd\\xa3\\xc1\\x13\\x25\\x47\\x62\\xec\\x45\\xf1\\x13\\xba\\xd1\\xbd\\x5f\\xad\\xa7\\xdf\\xb8\\x45\\xfd\\x19\\x86\\x82\\x27\\x19\\x17\\xbb\\xfb\\xed\\xdb\\xa1\\x55\\xe7\\xd8\\x17\\x66\\xe8\\xd6\\xc1\\x55\\x18\\xa3\\x5b\\x41\\xab\\x57\\x05\\x2e\\x09\\x3a\\x26\\x83\\xf0\\x88\\x3e\\xee\\x51\\xa4\\xaf\\xd3\\x3f\\x50\\xe8\\x5c\\xb2\\xa1\\xdf\\xcb\\x5a\\x3c\\x96\\x8c\\x67\\xc5\\x64\\xbd\\x80\\xec\\x26\\x72\\x31\\x93\\x3c\\x17\\x49\\xc0\\x98\\xb3\\x2c\\x53\\x09\\x29\\x44\\x6d\\x11\\x39\\xf4\\x4d\\xfd\\xb9\\x41\\xf2\\xbc\\xb4\\x7c\\x98\\xc1\\x80\\x5d\\x52\\x86\\x90\\x92\\xd9\\xcc\\x61\\x93\\x01\\x1b\\x1c\\x1f\\x7e\\xfb\\x77\\x8e\\xc1\\xda\\x3f\\x00\\x63\\xcf\\xe0\\x8b\\xa5\\xd2\\x10\\x6e\\x08\\x65\\x43\\x81\\x74\\xa7\\x4c\\x49\\x60\\x20\\xad\\x9e\\xb9\\xbd\\xbb\\x56\\xe9\\x8d\\xdb\\xbe\\xd6\\xdb\\x7b\\x27\\x49\\xed\\x19\\x73\\xd1\\x45\\xbc\\xc5\\x9e\\xb1\\x16\\xdd\\x44\\x48\\xec\\x1f\\x1d\\xb1\\xe8\\xe6\\x6d\\xe4\\x2d\\x36\\x03\\x1f\\x5b\\xbb\\x5a\\xa8\\x74\\xb0\\xe4\\x54\\x06\\xd1\\xe0\\x5a\\xa5\\x8e\\xc1\\x69\\x68\\x5e\\x85\\xe7\\xf5\\x43\\x3c\\x20\\x39\\xbf\\x43\\x15\\x9b\\xdb\\x9a\\xf3\\xf1\\x29\\x17\\x99\\x3b\\x42\\x4b\\xf2\\xf1\\xf7\\x0b\\x9c\\xe8\\x40\\x34\\xe8\\x3a\\x19\\x8c\\xed\\x8b\\x41\\x5d\\x26\\x73\\x31\\xbc\\xb9\\x2b\\x17\\xbb\\x55\\x7f\\x60\\x0b\\x8c\\xf7\\x35\\xf6\\xd5\\x08\\xc7\\x72\\x38\\x91\\xf3\\x07\\xd4\\x59\\x79\\xae\\x4a\\x69\\x29\\xc3\\x8b\\xf8\\x73\\x45\\xf4\\x29\\x68\\xed\\xc9\\x71\\x5e\\xd6\\x0d\\xd9\\xe1\\x69\\x48\\x81\\xb9\\xee\\x22\\x9a\\x9c\\x5b\\x0b\\x5a\\x9e\\xb2\\xff\\x39\\xfa\\xfe\\x57\\x3f\\xf5\\x8f\\xbf\\x38\\x3a\\xfa\\xee\\x45\\xff\\x8f\\x3f\\xfc\\xea\\xe8\\xfb\\x01\\xfe\\xe3\\xf3\\xe3\\x2f\\x8e\\x7f\\x0a\\x7f\\xfc\\xea\\xf8\\xf8\\xe8\\xe8\\xbb\\xaf\\xdf\\x7c\\x75\\x7b\\xfd\\xea\\x07\\x71\\xfc\\xd3\\x77\\xb2\\xcc\\xef\\xe8\\xaf\\x9f\\x8e\\xbe\\x83\\x57\\x3f\\x6c\\xd8\\xc9\\xf1\\xf1\\x17\\xbf\\xdc\\x79\\xca\\x7b\\xdb\\xa8\\xbb\\xb3\\x50\\x77\\x64\\x9f\\x7e\\x2f\\xd6\\x69\\x1f\\xc7\\xd9\\xd1\\x59\\xf4\\x31\\xe8\\x0b\\xa7\\xd1\\x5b\\x90\\xd6\\x9d\\xc6\\xc0\\x25\\x51\\x11\\xa9\\xfa\\x11\\x86\\xa9\\x5c\\x58\\xa7\\xc0\\x39\\xb1\\x86\\x37\\x33\\xcf\\xe6\\xd4\\x13\\x4f\\x07\\x30\\xf7\\x92\\x63\\x8a\\x58\\x23\\x6b\\xab\\xa1\\xd5\\xa8\\x60\\x8a\\x45\\xf5\\x48\\x32\\x91\\x17\\x19\\xe4\\x20\\x2d\\x9e\\xe7\\x7e\\x90\\x04\\x51\\x5f\\x1c\\xd4\\x33\\x49\\x48\\x62\\x87\\x87\\x04\\x20\\xf5\\x83\\x45\\xd2\\xf1\\x78\\x8b\\xa4\\xe3\\x53\\x24\\x1d\\x7b\\x1b\\x2f\\xe6\\xe9\\x46\\xa3\\x3b\\xaf\\x8c\\x99\\x60\\xf7\\x41\\x8b\\x46\\x95\\x65\\xa2\\x46\\xe8\\xd5\\x98\\x8a\\xb4\\xe4\\x59\\xb3\\xae\\x45\\xa8\\xb0\\x30\\x68\\x2a\\x4b\\x39\\x9f\\x2d\\xe8\\x46\\x42\\x8a\\x66\\x41\\x8c\\x5e\\xe5\\x77\\xc2\\x17\\xbd\\x54\\x50\\x5b\\xbb\\x0f\\xce\\xb2\\x7b\\x3e\\x33\\x07\\x54\\x3b\\x49\\x2a\\xd9\\x9f\\xeb\\x80\\x29\\x1d\\xbc\\x55\\x4d\\xf1\\x73\\x49\\xca\\xcc\\xc2\\x62\\xda\\x29\\x33\\x5e\\x98\\x3d\\x3c\\x34\\xd5\\x9b\\xc1\\x9e\\xe5\\x67\\x58\\x47\\x6d\\x39\\xb4\\x40\\x4f\\x97\\x0d\\xda\\x64\\x1b\\x86\\xbc\\x9e\\x78\\x65\\x2e\\x6d\\xcf\\x9b\\x3c\\x54\\x58\\x89\\xc2\\x3d\\x1c\\x29\\xb7\\x70\\x2c\\x73\\x35\\x1a\\x41\\x62\\x4f\\x7d\\xee\\xcf\\x92\\x6f\\x28\\xf6\\xc5\\x0a\\x59\\xf2\\x2c\\x9b\\x35\\xee\\x3f\\x55\\x92\\xc1\\x83\\xb0\\xac\\x94\\x56\\x64\\x0e\\x92\\x4c\\xc3\\xb8\\xcc\\x78\\x53\\x1f\\xf5\\x23\\x06\\x27\\x64\\x3a\\x60\\x6f\\xa5\\x93\\xc7\\xd7\\xbc\\xec\\x98\\x45\\x06\\xd6\\x41\\x91\\x63\\x32\\x6f\\x1b\\xfc\\xe8\\x02\\x6c\\x21\\x64\\xbd\\xf4\\x30\\xdf\\xca\\x8d\\xe5\\xb1\\xa3\\xbe\\x25\\x3b\\x15\\xa3\\x91\\xeb\\x05\\x53\\xf9\\xa5\\xd2\\x39\\x5f\\x1c\\xc1\\xe7\\x21\\x53\\x1c\\x56\\xb3\\x12\\x07\\xd6\\x64\\x3b\\x70\\xfa\\x43\\xc2\\xf5\\x41\\xd3\\x1e\\x70\\x96\\xd9\\x89\\x2a\\xc7\\x93\\xa5\\x50\\x34\\x16\\x9d\\x6e\\x6e\\xc2\\x26\\xb8\\x47\\xe7\\x5f\\x71\\x7c\\x47\\x26\\x40\\x6c\\x4e\\x01\\xe1\\xd3\\x3d\\x17\\x76\\xd1\\xfa\\x4d\\xb1\\x13\\x04\\xa3\\x10\\xc2\\x87\\x5e\\x4c\\x48\\x1b\\x91\\x8f\\x12\\x1e\\xec\\xdc\\x28\\x03\\x76\\x49\\xf9\\x2b\\xbd\\x55\\x6f\\x54\\x93\\x6c\\x78\\x0e\\x83\\xaf\\x77\\x71\\x5d\\xa2\\x8a\\x24\\xc4\\x42\\x1d\\xf4\\x22\\x97\\xb3\\x10\\xd5\\x84\\x5e\\x41\\x0a\\x38\\xac\\x02\\xa6\\xb2\\x59\\xbd\\xbf\\x3b\\x19\\x64\\xf7\\x22\\x90\\x06\\x92\\x52\\x0b\\x3b\\x3b\\x57\\xd2\\xc2\\xc3\\x4e\\x91\\x1d\\x6d\\x4a\\x76\\xd3\\xee\\xb0\\x45\\xcb\\xc2\\x60\\x4c\\x15\\x94\\x89\\x3e\\x57\\xea\\x6f\\xa2\\xca\\x2c\\xc5\\xf2\\x12\\xa5\\x44\\xac\\xa6\\xba\\x41\\x60\\x69\\x7b\\x90\\xb2\\xa0\\xd6\\x3b\\x3f\\x48\\xf0\\x23\\x93\\x7b\\xfb\\x9f\\xa5\\x98\\xf2\\x0c\\xa4\\x6d\\x7c\\x71\\x8d\\x9e\\xd3\\xe6\\x47\\x9b\\xca\\x2e\\x96\\x9b\\xbb\\x5a\\x70\\x81\\x7e\\xa1\\xd2\\x5a\\x4e\\x39\\x09\\x4b\\xc2\\x9f\\xe0\\xc1\\x3e\\x47\\x63\\x23\\x52\\xfc\\x6b\\x2d\\xa6\\x22\\x83\\x31\\xbc\\x32\\x09\\xcf\\x50\\x3e\\xeb\\x46\\x24\\x3e\\x5b\\xd1\\x3b\\x6e\\xbc\\x56\\x99\\x71\\xbc\\xc3\\x89\\xa4\\x8e\\x7b\\x51\\xe8\\x01\\x5a\\xf4\\xc6\\x5c\\x48\\xaa\\xd4\\x57\\x84\\x8f\\x0d\\xc5\\x30\\x38\\x29\\xb7\\xe0\\xda\\x6d\\x70\\x15\\xab\\x80\\x44\\x6d\\xa8\\x54\\xe6\\x6b\\x30\\xe0\\xa9\\xf2\\xfd\\xfb\\x6a\\x24\\x52\\xfd\\x5d\\xc2\\xfd\\xdf\\x5d\\x6f\\x86\\x8d\\x32\\x3e\\xae\\x89\\x23\\xd8\\x85\\x28\\xa3\\xba\\xeb\\x95\\x0b\\xc0\\x02\\x07\\xa5\\x23\\xdd\\x8e\\xd6\\xd6\\x01\\x1b\\x4d\\x7a\\x70\\xca\\x5e\\x1e\\x23\\x3a\\x73\\xc3\\xaa\\x3e\\x52\\xf6\\xeb\\x63\\xa4\\x02\\xe7\\x67\\xd7\\x7f\\xbf\\xf9\\xef\\x9b\\xbf\\x9f\\x5d\\xbc\\xb9\\xbc\\x62\\x57\\xca\\x02\\xc9\\xee\\x0d\\x46\\x9a\\x54\\x86\\x72\\x37\\xcb\\xca\\x8f\\x31\\x50\\x66\\x80\\xb6\\x22\\xcc\\xa2\\x91\\xa9\\xba\\x37\\x3b\\x7b\\x73\\x08\\xfd\\x1c\\xf0\\x80\\xcb\\xdd\\xcc\\xd5\\xbc\\xe0\\x43\\x91\\x89\\x7d\\x24\\xe5\\x85\\xcc\\x96\\x66\\xa7\\xc8\\x6b\\xd2\\xf4\\x24\\xd5\\xaa\\x20\\x20\\x84\\xe0\\x9a\\x86\\xa1\\xb7\\xe5\\xbe\\x6f\\x66\\xe8\\xe2\\xfe\\x8e\\xda\\x1d\\x8e\\x35\\x97\\xb6\\x16\\x3b\\xea\\x3d\\xd3\\x8e\\x79\\x63\\x3d\\xaa\\x3d\\xb7\\xe3\\xe3\\x29\\x30\\x5d\\x58\\x3b\\x79\\xda\\x5d\\x7d\\x95\\xb3\\x34\\x85\\xb4\\x05\\xfe\\xbd\\xa3\\x18\\x9f\\x5a\\x5e\\xe4\\x79\\x58\\x5c\\xc3\\x7d\\xcf\\xae\\xdf\\xde\\x5c\\xfe\\x7f\\x73\\x78\\x3c\\x2b\\xf6\\x4b\\xd0\\xea\\xa6\\x56\\x97\\x56\\x45\\x67\\xbb\\xfb\\xce\\xd7\\x82\\x8a\\xfb\\xfb\\x24\\xf6\\xb7\\xe2\\x96\\xdd\\xa4\\x05\\xbc\\x2b\\x65\\xbb\\xc8\\x72\\xdd\\x3f\\xcb\\x55\\x0a\\x03\\x76\\x5d\\xc5\\x27\\xb6\\x9f\\x36\\xf5\\x07\\x0d\\xcc\\xbd\\x22\\xad\\x40\\x8d\\xa9\\x21\\xa2\\x59\\x45\\x75\\x91\\x5a\\xd5\\x22\\x9b\\x84\\x7c\\xc4\\x33\\xf3\\xb1\\xa9\\xf1\\x3e\\xbc\\xd1\\xc9\\x11\\x6f\\x54\\x29\\xbb\\x89\\xfb\\xaf\\x7a\\x63\\x29\\x48\\x65\\xbd\\x60\\xed\\x66\\x89\\x15\\x38\\xb5\\x4a\\x18\\xd9\\x18\\x1b\\x49\\x60\\x2d\\xfe\\x66\\x28\\x46\\x32\\xb0\\x46\\x61\\x02\\xb0\\xaf\\xab\\x9e\\x29\\xbc\\xa4\\x34\\x30\\x2f\\xa0\\x7b\\xd6\\x58\\x5b\\x1d\\x5d\\xef\\x1a\\x78\\x8a\\x86\\x83\\x82\\xdb\\x09\\xa9\\x8a\\x39\\x37\\x77\\x90\\xd2\\x0f\\x5e\\x34\\xab\\x1c\\xc0\\xa8\\xe3\\x87\\xa1\\x6e\\xdd\\xbc\\x83\\xaf\\x17\\x45\\x32\\xca\\x2c\\x41\\x2f\\xb1\\x53\\x8d\\x3f\\xea\\xae\\xef\\x71\\x08\\x1d\\x50\\xde\\xca\\x6c\\xf6\\x4e\\x29\\xfb\\x65\\x55\\xd8\\xab\\x13\\x0c\\xf8\\x9b\\x97\\x96\\xdb\\x0e\\x78\\x14\\x27\\x39\\x8e\\xdb\\xc7\\xdd\\xc0\\x43\\xd5\\xac\\x29\\x76\\x51\\xef\\xf8\\x73\\x3f\\x52\\xba\\x94\\x67\\xe6\\x2b\\xad\\xca\\x9d\\x99\\xd8\\x82\\xb0\\xf9\\xd5\\xe5\\x05\\x92\\xa2\\xd2\\x87\\x48\\x4b\\xab\\x67\\x58\\xcc\\x70\\xb1\\x22\\x7d\\xa5\\x18\\x7c\\xe3\\x83\\xbc\\x9b\\x67\\xa2\\x8e\\xc7\\x65\\x6f\\xf8\\x8c\\xf1\\xcc\\xa8\\x00\\x4b\\xef\\x9e\\x9f\\xd7\\x42\\xbd\\x8a\\xeb\\x1e\\x0f\\x95\\x9d\\x2c\\xe8\\xb6\\xee\\x40\\x2d\\x7e\\xd7\\x6b\\x44\\x4c\\xd7\\x71\\x4d\\x42\\x2e\\x7c\\x6e\\xd1\\xf7\\x5b\\x68\\x48\\x20\\x05\\x99\\x7c\\xec\\x6d\\xff\\xd8\\x81\\xc6\\x88\\x3a\\x57\\x4a\\xba\\x83\\xd9\\x09\\xf2\\x5c\\x56\\x11\\xe6\\x1e\\xa4\\x4d\\x54\\x41\\xe7\\xbe\\xd7\\xfe\\x38\\x9a\\x4e\\xf1\\x58\\x96\\x06\\x4d\\x4f\\x23\\x54\\x1f\\x69\\x27\\xbf\\x2e\\x87\\x90\\x39\\xc8\\x3b\\x95\\x14\\xeb\\x21\\x73\\x4b\\xe6\\x0c\\x91\\xf3\\x31\\x30\\x6e\\x2b\\x4c\\xb3\\x8a\\x81\\x34\\xa5\\xf6\\x9b\\xd8\\x34\\x8f\\xf9\\xa1\\xbe\\xb9\\xbc\\x60\\x2f\\xd8\\x91\\x1b\\xeb\\x18\\xf1\\x67\\xc4\\x45\\x86\\xc1\\xec\\x68\\x53\\x9d\\xd3\\x51\\x47\\xa1\\x0b\\x9c\\x12\\x22\\x2f\\x53\\x9a\\x88\\x44\\x8f\\x49\\xc5\\x4c\\x99\\x4c\\xc2\\x9c\\x9c\\xde\\x1b\\xd4\\x66\\x9f\\x80\\x89\\x1e\\xe4\\xa7\\x89\\xeb\\x1f\\x97\\x42\\x7d\\x63\\x40\\x77\\x46\\xa0\\xbe\\xd9\\x81\\x40\\x35\\xc5\\x28\\x87\\x73\\x6d\\xe8\\x11\\x62\\xe5\\x60\\x79\\xca\\x2d\\xf7\\x84\\x2b\\xbc\\xf0\\x64\\xb7\\xf4\\xe7\\x4d\\xbe\\x0c\\xbc\\x16\\xb2\\x7c\\xa0\\x84\\xa7\\xee\\x4c\\x2d\\x37\\xaf\\xb0\\x5b\\x96\\x04\\xa8\\xe3\\xae\\x53\\x10\\x71\\x1a\\xac\\x29\\x4d\\xab\\x79\\x0b\\x57\\x7a\\x2b\\xc4\\x44\\xa4\\x13\\x9c\\x82\\xfa\\xc0\\x09\\x27\\x5c\\xa6\\x2a\\x5f\\x18\\xcc\\x09\\x91\\xd0\\xba\\xcb\\x65\\xc0\\x22\\xf6\\xb5\\xdb\\x13\\x31\\x0a\\x65\\x30\\x85\\x3d\\xaa\\x9d\\xcf\\xdf\\x5d\\xe3\\x7a\\x73\\xc0\\x09\\x18\\x81\\xdd\\xb3\\x8c\\x0f\\x21\\xf3\\x01\\xa7\\x14\\xc6\\xbe\\x88\\x81\\x1f\\x3b\\x0b\\x56\\xab\\xac\\xbb\\xb2\\x1d\\xef\\x54\\x06\\x94\\x56\\x16\\x00\\xe1\\xba\\x7f\\x16\\x70\\xc0\\x4e\\xba\\x82\\x03\\x6a\\x83\\x2d\\x38\\xa0\\x5e\\xfb\\x1c\\xe0\\x50\\xee\\xc1\\xea\\xd9\\x3c\\x1c\\x9c\\xdc\\xd0\\x86\\x03\\x32\\xef\\xa7\\x0e\\x07\\x03\\x49\\xa2\\xf2\\xe2\\x5a\\x2b\\xa7\\x76\\x76\\xc6\\x9b\\x7c\\xb7\\xb5\\xcf\\x90\\x0c\\x1b\\x4b\\x42\\xd0\\x91\\x17\\xb4\\x5f\\xe6\\xba\\x91\\x50\\xca\\x2d\\x31\\x89\\x90\\x55\\xfa\\xff\\x34\\x78\\x16\\x92\\x9e\\x79\\x46\\x16\\x7a\\x69\\xb9\\x17\\xdd\\x97\\xfe\\xc1\\x73\\x66\\x07\\x5d\\xd4\\x64\\xd8\\xc3\\xd8\\xd9\\x09\\x37\\x52\\x09\\xcf\\xf0\\x36\\x9b\\xfd\\x50\\x8e\\xcd\\xa3\\xdd\\x7c\\xc7\\x8d\\x34\\x62\\xf4\\x51\\xe2\\x6f\\x8d\\x8c\\x09\\x8e\\x86\\x96\\x60\\xc2\\x94\\x2a\\x85\\x86\\x2f\\x9b\\xa2\\xb0\\x6f\\x29\\xdd\\x14\\xdf\\x0b\\x19\\xcc\\x4e\\xae\\x08\\x6e\\xe5\\xb4\\xf5\\xb5\\x55\\xbe\\x26\\xfb\\x9b\\xea\\x8e\\x1c\\x37\\x41\\x90\\x18\\xcf\\x50\\x70\\x3b\\xe9\\x31\\x0d\\x19\\xe5\\x3e\\x7b\\x22\\x70\\x47\\x1a\\xe4\\x21\\x1e\\x89\\xd0\\x69\\x38\\x0f\\x61\\xe8\\x90\\x60\\x51\\xf7\\x8c\\xd2\\xd3\\x88\\x28\\xad\\x30\\xec\\xe0\\x75\\x58\\xfb\\x81\\x7f\\xe7\\xea\\xed\\x6d\\x33\\x78\\x88\\xcb\\x19\\x45\\x10\\x52\\x04\\xce\\xc7\\x26\\xbc\\x9d\\x32\\xa0\\x03\\x82\\x42\\xb5\\xd9\\x64\\x08\\xbd\\x13\\x32\\xf5\\x59\\xc4\\x2d\\x58\\x56\\x97\\xd6\\x91\\x98\\x8c\\xf9\\xe9\\x22\\x6d\\x92\\x9e\\x53\\xf6\\xbd\\x64\\x15\\x40\\x59\\x7f\\x67\\xec\\x79\\x47\\x12\\x75\\x30\\xe1\\xf5\\xd7\\xdb\\x65\\xab\\x41\\xe6\\xbb\\xf9\\x46\\x22\\x6a\\xb8\\x71\\xfb\\x4e\\xb1\\x5f\\x7c\\x2f\\xac\\xe5\\xa3\\xd6\\x2d\\xf6\\xc4\\xb1\\x6b\\x25\\xe7\\x6f\\xd4\\x6d\\x90\\xf8\\x13\\x87\\xd2\\x56\\xc8\\xb1\\x69\\x2a\\x3a\\x3c\\xcb\\x5a\\xb6\\xf2\\x65\\x9a\\x4e\\xd8\\xe1\\xea\\x8a\\xc2\\x45\\x0d\\x63\\xae\\xfa\\xc1\\x73\\xd1\\x52\\x32\\x27\\x6d\\x3c\\x73\\x1d\\x65\\x9c\\x1b\\x7e\\xae\\x1d\\x24\\xac\\xe0\\xd9\\x4d\\xb1\\xfb\\x9d\\x2a\\x6c\\xa1\\x7e\\xff\\x9b\\x9b\\xb3\\x76\\xd7\\xc8\\xcb\\x7d\\xea\\x0d\\xe0\\x73\\xc6\\xd3\\x5c\\x18\\x83\\x76\\x32\\x18\\x4e\\x94\\xba\\x63\\x47\\x6b\\xaf\\x96\\xec\\x1b\\x31\\x36\\x27\\x1e\\xe7\\xfb\\x6e\\xf6\\xc7\\x4c\\xc8\\xac\\x0a\\x9a\\x42\\x35\\x59\\xda\\x2a\\xdb\\x07\\x07\\x49\\xaa\\x59\\xe0\\x1e\\xfa\\x8b\\xb6\\x7c\\x2c\\xc3\\xe2\\x34\\xe9\\x6a\\x2d\\x87\\x05\\x1f\\x9d\\x60\\x2f\\x6e\\xcf\\x7e\\x19\\xd3\\x8f\\x6e\\xd1\\x95\\xc7\\xed\\xf9\\xb2\\xf2\\x4b\\xe1\\x48\\xc2\\xe5\\x47\\x07\\x92\\x97\\x3d\\x12\\x30\\xdd\\x55\\xb3\\xfe\\x6b\\xdd\\x27\\x4b\\x81\\xe2\\x4f\\x01\\x83\\xa3\\xf8\\xca\\x18\\x3c\\x34\\x5b\\x1f\\x62\\x8d\\x2a\\xff\\xe9\\x61\\x3b\\xc6\\x33\\x73\\xd0\\xe4\\x18\\xb4\\x6b\\x9a\\x0e\\xdf\\xfa\\x92\\xb7\\xaa\\x26\\x2f\\x45\\xd5\\x3a\\x81\\xa5\\x39\\x13\\x22\\x6f\\x47\\xf5\\x95\\x36\\x21\\xfc\\xd8\\xaa\\x70\\x49\\x5c\\x2e\\x1e\\xdc\\x28\\xcd\\xaf\\xe6\\x42\\x53\\xa5\\x92\\xfd\\xe5\\x8f\\x8f\\x07\\xec\\x52\\x56\\x01\\xfd\\x3d\\xb7\\xda\\xe6\\x8b\\x21\\x82\\xcb\\x3a\\x62\\xd8\\xbc\\x60\\x10\\xe7\\xdf\\xb4\\x3f\\x39\\x21\\x4b\\x97\\x1d\\x60\\xc6\\x3e\\x56\\x65\\xd6\\xb4\\x2c\\x77\\x7a\\x6c\\xd0\\xc2\\xec\\x3b\\x75\\x2c\\x26\\xf0\\xca\\x7d\\x2c\\xce\\xee\\x95\\xf7\\x65\\x75\\x7e\\x1e\\x7e\\x04\\xb6\\x77\\x74\\x6e\\x23\\x6c\\xb8\\x83\\xd0\\xdc\\x66\\x10\\xb2\\x58\\xf4\\x5b\\x5d\\xab\\x74\\x31\\x36\\xd9\\x17\\x67\\xad\\x4a\\x24\\x34\\x64\\x21\\xa9\\xbc\\x26\\xd0\\xa8\\x92\\xea\\xef\\xca\\x4a\\x7d\\x08\\xbc\\x57\\xd1\\x29\\xbc\\xb9\\xdd\\x73\\x5d\\x5f\\xaa\\x71\\x4d\\x5c\\xaf\\x4e\\x68\\xad\\x6e\\x9a\\xab\\x22\\xaa\\xff\\x81\\x87\\xb2\\x8a\\xe7\\x0c\\x65\\x23\\xaf\\xab\\xcf\\x21\\xe4\\x3e\\xf8\\x3b\\x23\\x31\\x57\\xdd\\xaa\\x60\\x01\\xf0\\xa1\\xee\\x3e\\x6e\\xd4\\x29\\x60\\x5c\\xf3\\xdc\\x91\\x42\\xc3\\x3c\\x08\\x86\\x30\\x16\\x14\\x57\\x58\\xd1\\xb5\\xc3\\x46\\xb0\\x7c\\x8f\\xc4\\x26\\x61\\x59\\x2e\\xc6\\x13\\x42\\x14\\xc6\\xb1\\xc0\\x16\\x0b\\xbe\\xb9\\x4c\\xf1\\x14\\xef\\x9a\\xc6\\xb4\\x08\\xae\\x73\\x47\\x5f\\x79\\x32\\x41\\x47\\x1f\\x97\\x2c\\x2d\\x35\\x5e\\x9f\\x64\\x81\\xa7\\xb3\\xbe\\xb1\\xdc\\x3a\\x89\\x12\\xb4\\xd7\\xcb\\xc2\\xfc\\xe3\\x5d\\x79\\x6b\\x5b\\xbc\\x2b\\x6f\\xc3\\x16\\xef\\xca\\x8b\\x77\\xe5\\x2d\\xb6\\x27\\x13\\x64\\x19\\xef\\xca\\xfb\\xb4\\xaa\\x1c\\xc7\\xbb\\xf2\\xb6\\x6f\\x1f\\xbd\\xb8\\x71\\xbc\\x2b\\x6f\\x79\\x8b\\x77\\xe5\\xc5\\xbb\\xf2\\x36\\x6b\\xf1\\xae\\xbc\\xed\\xdb\\x93\\x2b\\xcb\\x1e\\xef\\xca\\xdb\\xaa\\xc5\\xbb\\xf2\\x16\\x5b\\xbc\\x2b\\x6f\\x45\\x8b\\x77\\xe5\\xad\\x68\\xf1\\xae\\xbc\\xc5\\x16\\xef\\xca\\xdb\\xae\\xc5\\xbb\\xf2\\xe2\\x5d\\x79\\x9f\\xf4\\x15\\x22\\x2c\\xde\\x95\\xe7\\x5b\\xbc\\x2b\\xef\\x93\\xb8\\x28\\x81\\xc5\\xbb\\xf2\\x36\\x6a\\xf1\\xae\\xbc\\x78\\x57\\xde\\x2e\\x2d\\xde\\x95\\xf7\\xa9\\x18\\x65\\xe2\\x5d\\x79\\xf1\\xae\\xbc\\x9f\\x8f\\xa0\\x1b\\xef\\xca\\x8b\\x77\\xe5\\xc5\\xbb\\xf2\\xe2\\x5d\\x79\\x6b\\x67\\x11\\xef\\xca\\xfb\\x14\\x54\\x40\\x63\\x53\\xb1\\x53\\x89\\xcd\\x4d\\xaa\\x01\\xf9\\x30\\xee\\x46\\xf2\\xfd\\xb0\\x1c\\x8d\\x40\\x23\\xe5\\xc2\\x91\\x17\\xc2\\xaa\\xea\\xc2\\x87\\xf3\\xae\\x5c\\xb0\\x3d\\x2c\\x2c\\xe4\\x33\\x5e\\x56\\x7c\\xee\\xb3\\xfd\\xb1\\x14\\xa6\\x06\\x83\\xb5\\x70\\x24\\x7b\\xf5\\xf6\\xcb\\x25\\xa5\\x87\\x76\\x8e\\x37\\xdc\\x35\\x7a\\x1a\\xe7\\xfc\\x56\\xee\\xe6\\x85\\x5f\\x01\\xf0\\x65\\x19\\x58\\x1e\\xee\\x49\\xa6\\x8c\\x0f\\x7d\\x47\\x60\\x25\\x13\\x2e\\x25\\x04\\x7d\\x4f\\x58\\xb4\\xa3\\x0c\\x01\\x24\\x53\\x05\\x78\\x1f\\x38\\x67\\x46\\xc8\\x71\\x06\\x8c\\x5b\\xcb\\x93\\xc9\\xc0\\x8d\\x24\\x03\\xb0\\xeb\\x38\\x75\\xff\\x8b\\xb1\\x1a\\x78\\x4e\\x40\\xd7\\x90\\x73\\x41\\x5d\\x31\\x9e\\x68\\x65\\x0c\\xcb\\xcb\\xcc\\x8a\\xa2\\xea\\x8c\\x19\\xc0\\x94\\x14\\x62\\x54\\x15\\x30\\x30\\x5e\\xae\\x0e\\x6e\\xef\\xd5\\xa3\\xf9\\x69\\x29\\x39\\x5f\\x09\\xb9\\x87\\xf7\\x0a\\xe4\\x85\\x9d\\x55\\x11\\xbe\\xc0\\x46\\x42\\x1b\\xcb\\x92\\x4c\\x20\\xb7\\xc6\\x11\\x29\\x39\\x19\\xfb\\xab\\xea\\x8b\\x4b\\x3f\\x53\\xe3\\xa7\\x2a\\x53\\x14\\x5b\\x0b\\x6b\\x28\\x5e\\xb6\\xee\\xd0\\x77\\x95\\x0a\\xe3\\xc5\\x7c\\xd3\\x63\\x3c\\x14\\x26\\x23\\x40\\x87\\x99\\x22\\xa8\\x03\\x67\\xa1\\xde\\xfd\\x4f\\x8d\\xee\\x9a\\x05\\x9a\\xab\\x80\\xe2\\x1a\\xd1\\xb1\\xf2\\x58\\x40\\xce\\x5e\\x2b\\x1f\\xa2\\x16\\x28\\xfc\\xf5\\x39\\x73\\xc7\\x00\\x37\\x40\\xc2\\xd4\\xe1\\x00\\x24\\xe0\\xf8\\x2b\\x5f\\x81\\xf5\\x1f\\x1c\\xe9\\x1b\\x4c\\xf1\\x0d\\x18\\xc3\\xc7\\x70\\xbd\\xa3\\xa3\\x61\\x95\\x46\\x86\\xbe\\x86\\x7a\\x63\\x10\\x15\\xb2\\xd6\\x15\\x85\\xcd\\xb8\\xcd\\xb6\\x18\\xc4\\x72\\x9a\\x53\\x25\\xfc\\xdc\\x6b\\x61\\x2d\\xe0\\xa6\\x62\\x09\\x3b\\xf4\\x88\\xce\\x67\\xb8\\x1f\\xce\\x45\\x7f\\xbe\\x09\\x9d\\xd4\\x1f\\x3b\\xa2\\x2e\\x53\\x8a\\xc5\\x1c\\x02\\x1b\\x6a\\x01\\x23\\x36\\x12\\x18\\xe0\\x89\\x21\\x97\\x3d\\xaa\\x68\\xc4\\xc9\\x0a\\x60\\x8c\\xd3\\x77\\x95\\x0c\\xb2\\x6c\\x98\\xd7\\x80\\xfd\\xcd\\x4f\\xcc\\xea\\x52\\x26\\xbc\\x51\\x2c\\x16\\x73\\x34\\xc5\\x88\\x8d\\x31\\x64\\xd3\\x4b\\x8b\\xbf\\x7d\\xf1\\xc7\\xdf\\xb3\\xe1\\xcc\\xb1\\x34\\x94\\xac\\xac\\xb2\\x3c\\xab\\x16\\x99\\x81\\x1c\\x3b\\x58\\xd1\\xf1\\x6c\\x67\\x19\\x56\\x10\\xc0\\x5b\\x81\\x68\\xe2\\x2f\\x7f\\x7d\\x37\\x6c\\xf3\\xd8\\x93\\x14\\xa6\\x27\\x0d\\xf8\\xf5\\x33\\x35\\x5e\\x76\\x8f\\xde\\x07\\x2f\\x21\\xbe\\x04\\xcd\\xba\\xb9\\x15\\x21\\x94\\xd6\\x62\\x13\\x75\\x4f\\xb2\\xfe\\x12\\xec\\xa9\\x13\\x96\\x0a\\x55\\x94\\x19\\x19\\x9d\\xbf\\xac\\xf2\\x73\\x4b\\x03\\x8b\\x59\\x74\\x4b\\xcf\\x05\\x9a\\x49\\x7d\\x17\\xf3\\x85\\xc9\\x29\\x52\\x37\\x0c\\xa9\\x7c\\xd6\\x89\\x37\\xe4\\x55\\x15\\xb6\\x50\\x11\\xfa\\x92\\x67\\xd9\\x90\\x27\\x77\\xb7\\xea\\xb5\\x1a\\x9b\\xb7\\xf2\\x95\\xd6\\x4a\\xb7\\xe7\\x92\\x71\\x47\\x2d\\x27\\xa5\\xbc\\xa3\\x9b\\x60\\xaa\\x1a\\x04\\x6a\\xec\\x5d\\xb9\\x21\\xc5\\x61\\xd9\\x82\\x29\\x21\\x3d\\x10\\xe1\\xc5\\x8b\\x11\\xe0\\x41\\xd4\\xba\\x8e\\x64\\xe0\\xc6\\x27\\x8c\\x6c\\xf6\\x6f\\x9a\\xc8\\xf6\\xeb\\x17\\xbf\\xfd\\x03\\xa1\\x2e\\x53\\x9a\\xfd\\xe1\\x05\\x46\\x73\\x9b\\x1e\\x1d\\x62\\xa4\\x6d\\x8e\\x51\\xe4\\x3c\\xcb\\x9c\\xda\\xd0\\x44\\x4a\\x07\\xe8\\x65\\x48\\xf8\\xc1\\x71\\xd0\\xee\\x8f\\x6e\\x1b\\x8b\\x52\\xb7\\xb7\\xff\\x4d\\xf7\\x68\\x58\\x03\\xd9\\xa8\\x47\\xf9\\x4a\\x95\\x5a\\x73\\x88\\x8c\\xe1\\xd0\\x53\\x1f\\x4c\\x1a\\x7b\\x02\\x02\\xd0\\x54\\x65\\x65\\x0e\\x17\\x30\\x15\\x5d\\x5c\\xf6\\xd9\\xea\\x2d\\xa8\\xfa\\x99\\x30\\x98\\x1a\\x36\\xcc\\x54\\x72\\xc7\\x52\\xff\\xb0\\x11\\xdf\\x32\\x5f\\x6a\\xfb\\xf9\\xde\\xdb\\xdc\\x5c\\x7f\\x2b\\xb6\\x27\\xe7\\x45\\x51\\x65\\x0f\\x69\\x7e\\xdf\\x02\\x06\\x9e\\x49\\x4c\\xf8\\x7f\\xfe\\xf7\\x36\\xd3\\x8a\\x1c\\xdd\\xdc\\xb9\\x8b\\x9d\\x03\\x82\\xf6\\xb7\\x51\\xd7\\xb3\\xef\\xe8\\x76\\xce\\xba\\xc3\\x70\\x1a\\x0a\\xfc\\x37\\xe5\\x9b\\x2c\\xe4\\x4b\\x56\\x29\\x77\\x15\\x62\\x90\\x00\\xe0\\xd0\\x07\\x49\\xf2\\x47\\xbb\\x5f\\x98\\xed\\x1d\\xd8\\xd4\\x82\\x8b\\x5c\\x73\\xc5\\x25\\x67\\x05\\x68\\x23\\x8c\\xe3\\xcb\\xdf\\xe2\\x81\\xa2\\xbb\\x4d\\x6b\\x13\\xe0\\xc7\\x01\\x02\\x1d\\x6e\\xac\\x4f\\xbc\\x3f\\xa5\\xbc\\x56\\xa9\\xef\\x10\\x49\\x21\\xd5\\x66\\x5e\\x22\\xd6\\xb6\\xa5\\xda\\x0e\\x19\\xea\\xc7\\x26\\x95\\xdf\\xd6\\xd0\\x6c\\x53\\x4a\\xf7\\x4b\\x45\\x2a\\xe9\\xad\\x4f\\x89\\x40\\xe2\\xfa\\x9e\\x2b\\x7d\\xac\\x26\\xdf\\x11\\x19\\x40\\xc2\\xe8\\x37\\xb7\\x4d\\x09\\x5b\\xca\\x23\\x1d\\x94\\x86\\x48\\xef\\xf5\\xc0\\x01\\x23\\x2f\\xb8\\x3b\\x13\\xfe\\x53\\x76\\x78\\x7a\\xf8\\x51\\x89\\x24\\x81\\x48\\xab\\x82\\x8f\\xf7\\xba\\x2c\\x67\\x0e\\x52\\xf3\\xdd\\x36\\x4b\\x35\\x38\\x35\\x08\\x9f\\x57\\x75\\xcd\\xf0\\x2d\\x48\\xeb\\x4a\\x34\\x58\\x67\\x88\\xbc\\xa3\\x01\\xc0\\xe1\\x6e\\x37\\x94\\x6d\\xef\\xf9\\x8c\\x71\\xad\\x4a\\x99\\x7a\\xfb\\x52\\x65\\xe0\\x7b\\x33\\x37\\xf0\\x95\\x92\\x50\\x5f\\x22\\xdc\\xbe\\x7e\\x1b\\x2d\\xfa\\x42\\xb2\\x97\\x83\\x97\\x2f\\x3e\\x15\\x4e\\x85\\x2b\\x9c\\xe3\\x54\\x57\\x15\\xa7\\x22\\xfa\\xf4\\x51\\xd7\\x1a\\x4a\\xca\\x77\\xb4\\xde\\x37\\xde\\xc4\\x52\\x57\\x8c\\x17\\xa1\\x1e\\x35\\xfe\\x74\\xaf\\x85\\x85\\xc6\\x5d\\xa1\\x47\\xa8\\xb8\\x38\\xfd\\xb0\\x51\\xaf\\xe1\\x78\\xd9\\x55\\x0d\\x7b\\x02\\x69\\xbf\\x02\\x19\\xa6\\x1c\\xbe\\x47\\xba\\xe5\\x09\\x14\\x1e\\xb7\\x65\\x16\\x2e\\xb3\\x86\\x84\\x35\\x01\\x75\\x70\\xc0\\x8e\\xe8\\xcd\\x43\\x4a\\x75\\x3e\\xfe\\xa8\\xa8\\xe5\\x81\\xf6\\xea\\xa1\\xd8\\xa3\\x88\\xe5\\x5c\\x56\\x7d\\xc1\\xd1\\x06\\x57\\x74\\x08\\xc1\\xff\\x82\\x09\\x9f\\x02\\xa6\\x78\\x8b\\x8c\\xeb\\x0c\\x7d\\x8e\\x37\\x34\\x77\\x36\\x2c\\x2d\\x03\\x39\\x15\\x5a\\xc9\\x1c\\xa4\\x65\\x18\\x03\\x3f\\xcc\\xa0\\x79\\x55\\xfe\\x2f\\x8f\\xbe\\x3d\\x7b\\x87\\x01\\x0d\\xc7\\xbe\\x58\\x85\\x9f\\x65\\x69\\xc2\\x25\\x92\\xcd\\x99\\x34\\xba\\x7b\\x74\\xfb\\xc2\\x3c\\x1c\\x0c\\x91\\xe6\\x86\\x79\\xb9\\x71\\xf2\\xd2\\xd2\\x4d\\x91\\xf0\\x90\\x64\\xa5\\x11\\xd3\\x8f\\x45\\x49\\x7c\\xee\\xfd\\x85\\xd8\\x69\\x9f\\xe7\\xea\\x00\\xd4\\x80\\x5a\\x48\\xe9\\x47\\xd3\\xfa\\x92\\x34\\xc0\\x05\\x87\\xc9\\xa1\\xa9\\x52\\x03\\x9b\\x3e\\x70\\x6f\\x7a\\xf2\\x55\\x36\\x28\\x7c\\x2e\\x94\\x34\\x5c\\x10\\x21\\xb0\\xa2\\xcc\\xc7\\x35\\x42\\xa5\\xd2\\x9c\\xe3\\x0c\\xb7\\x03\\x6b\\x3b\\x20\\xb9\\x95\\x2d\\x78\\x71\\x75\\xd3\\x2c\\x4f\\x42\\xea\\x92\\x4a\\x07\\xec\\xba\\xfe\\xb1\\xae\\x61\\x83\\x15\\xc8\\x2a\\x25\\x12\\xf4\\xb8\\xae\\xda\\x3d\\x06\\x09\\x1a\\x85\\x04\\xd7\\x65\\xeb\\xfe\\x65\\x36\\xe4\\x86\\x9c\\x3c\\x17\\x57\\x37\\x64\\xb3\\xdd\\x0e\\x66\\x3b\\x8b\\xd9\\xbb\\x4b\\xa8\\x98\\xd2\\x82\\x69\\x0c\\x3b\\x08\\xb7\\xed\\x4b\\xc9\\x2a\\x83\\x95\\x03\\x0c\\x2a\\xa5\\xd4\\x31\\xbb\\xbc\\x66\\x3c\\x4d\\x35\\xba\\x7d\\xe6\\x92\\x6f\\x9c\\x7e\\x1e\\x7c\\x0b\\x58\\x2f\\x86\\x1b\\x68\\xce\\xa9\\x01\\x6e\\x24\\x71\\x35\\x60\\xd9\\x45\\x59\\x64\\x82\\xdc\\x08\\xcd\\x0f\\xea\\x3a\\x37\\x78\\x8b\\xd6\\xf6\\x48\\xbb\\x8f\\x9a\\xb7\\xb3\\x92\\xb7\\x07\\x15\\x52\\xbb\\x96\\x75\\x5c\\xb3\\x7b\\x1a\\x8c\\xca\\xa6\\x75\\xc5\\xde\\xb9\\x5d\\xf3\\x27\\x02\\x4d\\xe2\\xd5\\xae\\x85\\x2a\\x8e\\x1b\\xed\\x18\\x48\\xab\\x05\\x2c\\xee\\x16\\x7b\\xe7\\x46\\x2e\\xf1\\x34\\x55\\x1d\\x8a\\x29\\xa0\\x7f\\xdc\\x17\\xb0\\xa4\\x8f\\x1a\\x35\\x84\\xc9\\x37\\x4c\\x65\\x9c\\x81\\xeb\\x40\\xd1\\x70\\x56\\x3b\\x9e\\x44\\xf6\\xb1\\x10\\x61\\xde\\xd8\\x71\\x71\\x75\\x43\\x94\\x90\\x16\\x5f\\x5d\\xff\\xba\\x6c\\x97\\x6a\\xaa\\xb6\\x33\\x06\\x7e\\xb4\\xfa\\x43\\xfb\\x68\\x1e\\x73\\xb7\\xe7\\xf9\\x6b\\xff\\xf7\\x0a\\x64\\xd9\\x43\\xfc\\xdb\\x2b\\xd9\\x6e\\x8f\\xd1\\x0d\\x70\\x9d\\x4c\\x76\\x81\\xff\\x1a\\x42\\x40\\x9d\\xb2\\x54\\x51\\x24\\xc0\\x48\\x69\\x54\\x89\\xfb\\x48\\xde\\x33\\xa5\\xee\\xca\\x62\\x13\\x8a\\xee\\xbb\\xa1\\x1b\\xcd\\x36\\x22\\x10\\xad\\x2f\\x7e\\x56\\x34\\x3d\\x95\\x66\\x17\\x7f\\x6f\\x5b\\xf6\\x01\\x4b\\x12\\x0f\\xdd\\x5e\\x5e\\x25\\x50\\xa8\\x79\\xbd\\xe9\\x3c\\x2b\\x8d\\x05\\xfd\\xa5\\xd0\\x58\\xa0\\x9a\\x2a\\x2e\\x23\\x06\\x93\\x4d\\xe4\\xb0\\xf9\\xc2\\xdf\\x84\\x9d\\xf8\\xa2\\x8e\\x87\\xbd\\xf6\\x23\\xf7\\xb7\\xef\\xf8\\xd0\\xe9\\xb4\\x87\\x57\\x4a\\xc2\\xe1\\x60\\x5e\\xec\\xaa\\x48\\x79\\x45\\xd6\\x56\\xf2\\x14\\x3f\\x75\\x03\\x19\\xc5\\x8b\\xe2\\x83\\x06\\xae\\xdc\\xfa\\x7a\\x96\\x6e\\x84\\x40\\xff\\x0c\\x58\\xc6\\xb1\\x78\\x1c\\xbe\\x3d\\xa9\\x0b\\x50\\x52\\x45\\x29\\x2a\\xa0\\xa9\\xbc\\xa0\\x37\\x6b\\x82\\xa8\\x51\\x64\\xca\\xaa\\xd5\\xcb\\xde\\x45\\x9e\\xdb\\x1a\\x03\\xe8\\xb6\\x3e\\x5f\\x95\\xe4\\xb5\\x90\\x77\\x5b\\xa2\\x5f\\x3b\\xba\\xe4\\xd5\\x42\\x6f\\xad\\x8a\\xdc\\xe4\\xa3\\x15\\x92\\x82\\xef\\x1c\\x8b\\xe1\\x43\\x55\\xda\\x50\\xf9\\xc4\\x34\\x14\\x47\\x21\\xff\\x41\\x7b\\x81\\xf6\\xf6\\x82\\x6a\\xf9\\x2d\\xd3\\x11\\x4d\\x8f\\x8c\\x3e\\x41\\x09\\x34\\x33\\x69\\x39\\x16\\x1d\\xbd\\x50\\xc9\\x1d\\x68\\x96\\xb9\\x69\\x0c\\x58\\x1d\\xf8\\xd2\\xaa\\x73\\xa9\\x4b\\xd8\\x32\\xea\\x62\\x57\\x4b\\x07\\x14\\x13\\xc8\\x41\\xf3\\xac\\xd2\\xbe\\xf6\\x01\\xf5\\x6b\\x4f\\x38\\xab\\x5e\\x9b\\x31\\x29\\x54\\x2e\\xcd\\x17\\x68\\x74\\xe7\\xf0\\xd5\\xb2\\xb7\\x72\\x3e\\x0b\\xb5\\x62\\x85\\xc4\\x70\\x83\\x07\\x61\\xd0\\xac\\x5f\\xa8\\xb4\\x99\\x78\\x56\\x1a\\xd0\\xfd\\x2a\\x2d\\xd0\\xe7\\xde\\x98\\x2a\\x10\\x27\\x85\\x61\\x39\\x1e\\x0b\\x39\\xf6\\xd4\\x19\\x69\\x7a\\xa3\\x60\\x75\\xa5\\xe9\\x60\\xa4\\x77\\xa2\\x81\\x5b\\xca\\xd8\\x29\\x54\\x4a\\xf1\\x65\\xa2\\xf9\\x7e\\xae\\x52\\x7a\\x7d\\x38\\x23\\x6d\\x30\\xec\\x6c\\x1d\\x20\\x7d\\x29\\x99\\xd2\\xbe\\x00\\x03\\x4f\\x53\\x9c\\xfb\\xe2\\x0a\\xf1\\x69\\x7b\\x55\\xbd\\x2a\\x8e\\x83\\x22\\xbb\\xab\\xaf\\x1a\\x60\\x31\\xe5\\xd0\\x09\\x3b\\xa5\\xde\\xb6\\x76\\xe8\\xae\\x84\\x7f\\x27\\xa2\\xdf\\xae\\x2a\\x74\\x26\\xeb\\x2d\\x3e\\x6f\\x06\\xcc\\x71\\x66\\x21\\x2f\\x94\\xe6\\x7a\\x36\\xef\\xc2\\x74\\x44\\xca\\xa1\\x80\\x03\\xe0\\x1c\\xa4\\xae\\x55\\x8a\\x74\\x7c\\xc9\\xc6\\x4f\\xe9\\xaa\\xdc\\x25\\x7b\\xbf\\x14\\xc7\\x90\\x0a\\x4a\\xc5\\x02\\x44\\x1d\\xbd\\x36\\xc9\\x04\\xd2\\x12\\xa3\\xc7\\xc7\\x25\\xc7\\xab\\xbc\\xdd\\x29\\xf6\\xc6\\xee\\x99\\x0f\\xcb\\x23\\x64\\xa8\\x02\\xfe\\xaa\\x34\\x81\\x19\\x06\\xc9\\x60\\x7d\\x4e\\xf7\\x0b\\xd6\\xf9\\xa4\\xd0\\x40\\xba\\xc9\\x18\\x6f\\x35\\xad\\xa2\\x04\\x6f\\xeb\\xcb\\x15\\x70\\xb1\\x30\\x15\\x89\\x0d\\x1f\\x8d\\x56\\x21\\x4e\\xc2\\xab\\x0b\\x54\\xaf\\x95\\xaf\\x0b\\x98\\x80\\x23\\x46\\xd6\\xd4\\x4b\\xf1\\x51\\x25\\x58\\xf9\\xf3\\x7b\\xe9\\x98\\xc4\\x6a\\x5c\\xac\\x11\\xef\\x11\\x94\\x43\\xb9\\xba\\xbd\\x15\\x6b\\x8e\\x6f\\x05\\xa5\\x25\\x6b\\xdf\\xb6\\x24\\xd3\\x1e\\x42\\xf9\\xee\\x1e\\xb7\\x9d\\x3c\\x65\\xfb\\xc8\\xff\\x5c\\x8f\\xf7\\xd7\\x95\\xfe\\x7f\\xf6\\xfe\\xc7\\xb9\\x6d\\x1b\\xeb\\x17\\xc6\\xff\\x15\\x8c\\xb7\\x73\\x6d\\x6d\\x25\\x39\\x69\\x77\\x77\\x76\\x73\\xfb\\xdd\\x8e\\xd7\\x76\\x5a\\x4f\\x13\\x47\\xd7\\x76\\xda\\xdb\\x6f\\xd2\\xa7\\x0f\\x44\\x42\\x12\\x1e\\x93\\x00\\x97\\x00\\x65\\x6b\\xdf\\xbc\\xff\\xfb\\x3b\\x38\\x07\\x00\\x41\\x4a\\x76\\x6c\\x92\\xb1\\x65\\x97\\xdc\\x99\\x6d\\x2c\\x51\\x20\\x78\\x00\\x9c\\xdf\\xe7\\x73\\x76\\x0f\\xf2\\x79\\x91\\x42\\x4a\\x9a\\xd5\\x3c\\x4b\\x80\\x65\\xdc\\x73\\xe0\\xd7\\x32\\x22\\xeb\\xf0\\xed\\x51\\x58\\xc2\\x10\\xe6\\x66\\xbb\\x02\\x10\\xa3\\x0a\\xb5\\xf4\\x77\\xd6\\x1d\\x9e\\x27\\xc6\\x38\\xf3\\x5e\\xd4\\x92\\xb7\\x5a\\x2b\\xce\\x7a\\xf4\\xfc\\xd3\\x9c\\x15\\xcb\\x45\\x66\\xa4\\x31\\xe8\\x10\\x01\\xf4\\x48\\xb4\\xa0\\x62\\x0e\\x6e\\x70\\x59\\x98\\xf1\\xbe\\xfa\\x0a\\x66\\x94\\xb3\\xb8\\x88\\x6c\\xe7\\x05\\x97\\xff\\xfc\\x95\\xf3\\xfe\\x59\\xa0\\x20\\xe8\\x0f\\xa7\\x22\\x9a\\xb9\\x39\\x87\\xaf\\x85\\xa2\\xfa\\x15\\xe1\\x63\\x36\\x26\\x3b\\x5f\\x05\\x5f\\xed\\xe0\\xd3\\xb3\\x5c\\x9a\\x47\\xd8\\xd4\\x69\\x98\\x55\\xc2\\x35\\x1c\\x84\\x9d\\xf0\\xee\\x31\\x39\\x36\\xcf\\x80\\x88\\x88\\x27\\x60\\x90\\xdd\\x3b\\x2d\\xc9\\x37\\x24\\x39\\x9b\\xd3\\x3c\\x4e\\xa0\\xe2\\x6e\\xe6\\x95\\x12\\xac\\xcb\\xb1\\x04\\x83\\xd3\\x07\\xf9\\x74\\x42\\xea\\x4d\\xde\\xc9\\x3b\\x96\\x45\\x68\\xaa\\x2e\\xd5\\x3e\\xaa\\x32\\xa3\\x98\\x6a\\x3a\\x82\\x6e\\x15\\xc8\\x34\\xf6\\xd1\\xbc\\x1e\\x59\\xfc\\xd3\\x11\\xb5\\x7b\\x6a\\xe4\\x97\\x75\\xff\\x4f\\xb6\\xb2\\x6a\\x44\\xfd\\x5d\\x5c\\x8c\\xe8\\x08\\x90\\x48\\x9b\\xe7\\x8a\\x3e\\x42\\x5a\\x41\\x2b\\x4b\\xb7\\x05\\x0c\\x6e\\x5d\\x3d\\xf5\\x30\\xe8\\x40\\x03\\x68\\xb6\\x51\\xc2\\x5e\\xfb\\x0c\\x06\\x8b\\xf4\\x5a\\x39\\xc8\\xc7\\xa7\\x17\\x67\\xbf\\x4e\\xde\\x9d\\x9c\\x5e\\xf4\\xe7\\xb9\\x3f\\xcf\\xfd\\x79\\x6e\\x71\\x9e\\x99\\x58\\xb6\\x3e\\xcb\\xde\\xfe\\xd9\\x64\\x12\\xd6\\x20\\xec\\x82\\x8a\\xea\\x67\\x94\\x9c\\x75\\x2c\\x96\\x3f\\x53\\xa3\\xf0\\x65\\x39\\x53\\xa0\\x8b\\x18\\xbd\\x71\\x53\\x14\\xd5\\xde\\x80\\xfd\\xaa\\x0e\\x9f\\x7c\\x76\\xd6\\x23\\xe6\\x56\\x75\\x98\\xb3\\x72\\x1a\\x00\\x01\\x6c\\x5a\\xb5\\xb0\\x7f\\xdc\\xe1\\xef\\x27\\x47\\xc7\\xa7\\x17\\x27\\xaf\\x4f\\x8e\\xcf\\x1e\\x35\\xd9\\xa0\\x25\\xb8\\x5b\\x55\\x1a\\x37\\x94\\x92\\x59\\xce\\x96\\x5c\\x16\\x2a\\x59\\x79\\x14\\xda\\xcd\\x4c\\x60\\x3d\\x5f\\x4d\\xc4\\xd0\\x02\\xcf\\x01\\xed\\x6e\\xfc\\x59\\x2f\\x6c\\xbb\\x15\\xb6\\xd5\\xdc\\x8b\\x16\\xb8\\x1e\\x5d\\x6d\\xdf\\xd7\\xb9\\x4c\\x3b\\xda\\xc2\\xe7\\x68\\xb2\\x3b\\x97\\xf7\\xa6\\xfd\\xb4\\x6b\\x21\\x00\\x2a\\xa2\\xc7\\x2a\\x8f\\x25\\xde\\x80\\xd1\\x42\\xd3\\x4c\\xb7\\x68\\x0b\\xd0\\x09\\x68\\x68\\x37\\xf8\\x9a\\x98\\xa7\\xf0\\x96\\x66\\x3f\\xb1\\xd5\\x19\\x6b\\x09\\x1f\\x52\\x0b\\x35\\x24\\x2c\\x32\\x82\\x8e\\x5c\\xb2\\x15\\x46\\x20\\x0f\\xdd\\xc3\\xda\\x81\\x60\\x6e\\x21\\xe6\\xea\\x25\\x6b\\x83\\x87\\xdb\\x25\\x58\\xea\\x25\\x6b\\x91\\xb8\\xe8\\xae\\x35\\x40\\x4f\\xb3\\x84\\xa0\\xa7\\x99\\x35\\xdd\\x2a\\x08\\xd3\\x2f\\x00\\x0e\\xbb\\x1b\\x8a\\x7b\\xcb\\x67\\xf5\\xbd\\xd1\\x15\\xe4\\xd2\\x48\\x2e\\x76\\xb5\\x6f\\x93\\xb6\\x46\\xc6\\x62\\x1d\\xe1\\xae\\x55\\xfb\\x90\\x99\\xb2\\xff\\x27\\x04\\x8e\\xbd\\x78\\x77\\xf4\\xee\\x15\\x39\\x88\\x63\\x9b\\x3c\\x5c\\x28\\x36\\x2b\\x12\\x4c\\x03\\x56\\x63\\x42\\x33\\xfe\\x33\\xcb\\x15\\xf4\\x55\\xbb\\xe4\\x22\\x1e\\x92\\x82\\xc7\\xdf\\xb7\\x01\\x5d\\xc2\\xab\\xc3\\x55\\x90\\x2e\\x60\\xd3\\xed\\x4a\\x9c\\xdb\\x78\\x5c\\x28\\xbb\\x3c\\x13\\x21\\x58\\x19\\x08\\x7b\\xd3\\xe1\\xaf\\x58\\x25\\xa3\\x23\\xd2\\xb4\\x6d\\x21\\x47\\x70\\x09\\xbb\\xe5\\xab\\xbb\\x25\\x63\\xc5\\x3c\\x71\\x0f\\x50\\x15\\xbf\\x22\\xaa\\x00\\xa0\\x18\\xe5\\xfb\\xbe\\x41\\xc7\\xd1\\x61\\xf5\\x4f\\x95\\xd1\\x88\\x0d\\xc9\\x7f\\xfb\\x0f\\xa1\\xe1\\xb9\\xfa\\xb0\\xbb\\xfb\\xdd\\x4f\\xc7\\xbf\\xfe\\x73\\x77\\xf7\\xb7\\xff\\x0e\\xbf\\x05\\x51\\x08\\x56\\x73\\xed\\x16\\x88\\xef\\x08\\x19\\xb3\\x53\\x78\\x06\\xfc\\x69\\xd5\\xb5\\x83\\x28\\x92\\x85\\xd0\\xf6\\x0b\\xa8\\xea\\x1d\\x2f\\xa4\\xd2\\x27\\x13\\xff\\x67\\x26\\xe3\\xfa\\x5f\\xaa\\x15\\x92\\xd8\\x56\\x0a\\x06\\x58\\xa2\\x16\\xd5\\x29\\x78\\x75\\x27\\x1e\\x4a\\x5e\\xd2\\xf1\\x51\\xb5\\xa3\\xfa\\xfe\\x18\\xd1\\x82\\xa5\\x88\\x65\\xf4\\xda\\x91\\x00\\x7a\\xb8\\x3a\\xf8\\x00\\x01\\x35\\xd7\\x46\\x33\\xad\\xc2\\xca\\xed\\x2c\\x5f\\xee\\x6c\\x95\\x80\\xf1\\x2b\\xd8\\x31\\xc1\\x80\\x22\\x96\\x5a\\x78\\x90\\xbd\\x80\\x75\\x56\\x4a\\x19\\x8d\\x3d\\x98\\x9c\\x90\\x25\\x52\\x78\\x6b\\x88\\xe3\\xa2\\x60\\xaf\\xbf\\x28\\x8f\\x0b\\x63\\x6d\\x15\\x0b\\xf1\\x15\\x81\\x62\\x0a\\xf7\\xbd\\xad\\xb3\\x57\\x1e\\xfa\\x8a\\x19\\xc3\\x66\\x0f\\x3f\\x1c\\x47\\x59\\x31\\xb4\\x37\\x8c\\x53\\x96\\xca\\x7c\\xe5\\xff\\xf4\\x31\\xbe\\x91\\xd2\\x32\\xa7\\x73\\xa8\\xcb\\xc0\\x9f\\xe3\\xcf\\xfc\\x5f\\xf8\\xc3\\xca\\x03\\xd6\\x7f\\x8d\\xa6\\x70\\x54\\xe4\\x46\\x69\\x48\\x56\\x8e\\x23\\x37\\xc4\\x8b\\x28\\xaf\\x2d\\xe4\\x6d\\x8e\\xf4\\x5b\\xc2\\xda\\xfc\\xce\\x68\\xdb\\xb0\\x15\\xaf\\xea\\x86\\x2c\\x03\\xf5\\xa0\\x70\\x7a\\x2a\\x82\\x3d\\x69\\xeb\\x4e\\x87\\x5e\\x0d\\x42\\x6f\\x80\\x58\\x1a\\xcb\\xb2\\x31\\x72\\x56\\x79\\x75\\xc8\\xcd\\x62\\xbe\\xe4\\x4a\\xb6\\xa8\\x3e\\xf1\\x03\\xdd\\x9c\\x52\\x6f\\xa1\\x2f\\x30\\x71\\xc8\\xbb\\xcd\\xae\\x33\\x00\\x0b\\xf2\\xe7\\xb5\\xc6\\xf6\\x5f\\xb6\\xe9\\x4a\\x84\\x57\\x46\\xb5\\x66\\xb9\\x78\\x45\\xfe\\x6b\\xef\\xe3\\xd7\\x9f\\x46\\x83\\xef\\xf7\\xf6\\x3e\\xbc\\x18\\xfd\\xe3\\xb7\\xaf\\xf7\\x3e\\x8e\\xe1\\x1f\\x7f\\x1e\\x7c\\x3f\\xf8\\xe4\\xfe\\xf8\\x7a\\x30\\xd8\\xdb\\xfb\\xf0\\xd3\\xdb\\x1f\\x2e\\x26\\xc7\\xbf\\xf1\\xc1\\xa7\\x0f\\xa2\\x48\\x2f\\xf1\\xaf\\x4f\\x7b\\x1f\\xd8\\xf1\\x6f\\x77\\x1c\\x64\\x30\\xf8\\xfe\\xab\\xd6\\x53\\xef\\x00\\xbb\\x13\\xaf\\x2e\\x11\\x3c\\xab\\x23\\x76\\xb2\\xfd\\xbe\\x20\\x6c\\x3d\\x5e\\x6e\\x7b\\x75\\x7d\\xfe\\x5d\\xf6\\xf0\\xab\\x52\\x20\\x79\\x71\\xbd\\x35\\x07\\x5c\\xb1\\x28\\x67\\xfa\\x21\\x3c\\x39\\xf8\\xa4\\x00\\x41\\x60\\x57\\x11\\x6f\\x5a\\x3c\\x37\\x39\\xf7\\x47\\x70\\xee\\xf8\\xb6\\x76\\xb0\\xae\\xa5\\x26\\x3a\\xcb\\x65\\xea\\xaa\\xc2\\x21\\xbc\\xb1\\x84\\x4c\\x60\\x7b\\xdf\\x25\\x6b\\xd5\\x1c\\x15\\xaf\\xde\\x19\\xd4\\x3b\\x83\\x6e\\xb8\\x3e\\xeb\\x0c\\x3a\\xc7\\x7d\\xb8\\xb5\\x9e\\x20\\x26\\x96\\x4d\\x43\\x18\\x1b\\x23\\xe8\\xce\\xd6\\x09\\x21\\xd4\\xee\\x16\\x50\\x1b\\xbb\\xa3\\x5e\\xf6\\x83\\x2c\\x53\\x68\\x50\\xa0\\xa5\\x9b\\x63\\x98\\xe4\\x00\\x7a\\x35\\xe3\\xc1\\x87\\x01\\xca\\xb2\\x0b\\x34\\x6d\\x2c\\xc2\\x1f\\x5b\\x9a\\x29\\x78\\x88\\xe8\\x0a\\x18\\x24\\x24\\x3a\\x42\\xea\\xe9\\x2f\\x98\\x09\\x7a\\x89\\xc9\\xa1\\xc6\\x48\\xe3\\xa2\\x84\\xd1\\xf4\\xca\\x61\\x89\\xbd\\x4c\\x95\\x92\\x11\\x26\\xb5\\xfa\\x22\\x00\\x40\\x76\\xb3\\xd3\\x86\\xd9\\x40\\x83\\xf8\\x2c\\x67\\x11\\x8b\\x99\\x88\\x98\\xc5\\x65\\xae\\xf4\\xbe\\xa4\\x82\\x1c\\x8b\\xa5\\xc3\\xa6\\x8e\\x5d\\x49\\x09\\xcc\\x64\\xf3\\x18\\xcf\\x2b\\x01\\xc1\\x6c\\x44\\x1b\\x04\\x0b\\xf2\\x10\\x80\\xeb\\x97\\xd9\\xac\\x90\\x8a\\x21\\x67\\xa5\\x97\\xb5\\x59\\x7b\\xbc\\xd6\\x52\\xbc\\xbd\\xcc\\xf4\\x91\\xad\\x56\\xca\\xd0\\x9a\\xb0\\x2c\\xdd\\xcf\\x55\\x21\\xf9\\x1c\\x82\\x81\\xed\\xc5\\xe7\\x1f\\x4e\\x74\\x76\\x24\\x36\\xbb\\x11\\x99\\xf7\\x88\\x9d\\x74\\x29\\x26\\xbb\\x08\\x96\\x64\\x39\\x9b\\xf1\\xeb\\x8e\\xce\\xe9\\x81\\x28\\x3d\\x31\\x3c\\x66\\x42\\xf3\\x19\\xc7\\x12\\x93\\x2c\\x67\\x19\\x13\\x58\\x25\\x40\\xa3\\x05\\xf0\\x7e\\x2b\\x29\\xcb\\xe0\\xf4\\x36\\x26\\xf3\\xa0\\xc2\\xdd\\x2d\\x2b\\x3b\\xdf\\xa4\\xec\\xf7\\x7c\\x8c\\xf4\\x7c\\xac\\xf1\\xf5\\x40\\x7c\\xcc\\xee\\xdc\\xed\\x61\\x62\\x90\\x79\\xde\\x3e\\xe7\\xfd\\xb0\\x8a\\xb5\\x62\\xbb\\xd2\\xde\\x73\\xa3\\x95\\x65\\x47\\xfb\\x30\\x4a\\x23\\x07\\x74\\xab\\xfd\\x00\\x8f\\x9d\\x14\\x49\\xd2\\x11\\x3e\\xf5\\xee\\x09\\x50\\x23\\x2b\\x92\\xc4\\x96\\xe5\\x8e\\xc9\\x3b\\x01\\x47\\xf2\\x00\\xfa\\x20\\x0c\\xc9\\x29\\x5b\\xb2\\x7c\\x48\\x4e\\x66\\xa7\\x52\\x4f\\x50\\xb7\\xad\\xa6\\xb3\\xe1\\x8d\\x84\\xcf\\xc8\\x2b\\x63\\x35\\x29\\x4d\\x34\\x62\\xd1\\x07\\xc8\\x39\\x32\\xaf\\x0c\\x50\\x82\\x72\\xb5\\x48\\x43\\xbf\\x79\\x59\\xfe\\xe4\\x0a\\x26\\x47\\x8f\\xb4\\x4c\\xbe\\xd9\\x47\\x07\\xe6\\xa9\\x1d\\xc9\\x25\\xc8\\x41\\x52\\xa4\\x8d\\x8e\\x6c\\xaa\\x7a\\x7d\\x82\\x40\\x14\\x99\\x54\\xfa\\xdc\\x58\\xb1\\xdd\\x34\\x82\\x99\\xb8\\xe1\\xa0\\xb7\\x02\\x4d\\x12\\x16\\x57\\x3a\\x01\\x61\\x07\\x0b\\x5a\\xb5\\xa2\\xa1\\x1e\\xd7\\x37\\x54\\x60\\x64\\x41\\x45\\x9c\\xb0\\x1c\\x40\\xd1\\x55\\x1d\\xf9\\x89\\x97\\x5d\\x00\\x7c\\xdf\\x06\\x57\\xa0\\x49\\xa3\\x48\\xe6\\xb1\\xed\\xc0\\x6a\\x0b\\x25\\x61\\x32\\xfe\\x78\\x01\\xaf\\x4d\\xa9\\xa0\\x73\\x06\\x9e\\x85\\x35\\x68\\x5d\\x00\\x5c\\x56\\x41\\xf3\\x87\\x85\\x94\\x97\\x24\\x92\\x69\\x96\\xc0\\x01\\x68\\x71\\x3e\\xca\\xde\\x33\\x7e\\x8b\\x8e\\xcc\\xe8\\x6a\\x3f\\x68\\x4b\\x03\\x1f\\xb4\\xeb\\x4a\\xd3\\x4a\\x59\\xe9\\x42\\x55\\x61\\xd7\\x2c\\xea\\xac\\x6f\\xdd\\xf1\\x35\\x8b\\x82\\xc6\\x8b\\x66\\x49\\x6c\\xe7\\x45\\x2d\\xc1\\xb7\\xd1\\xbe\\x9f\\x6e\\x6b\\xb7\\x7c\\x57\\xae\\xf0\\x16\\x55\\x66\\xe1\\x55\\x03\\x5a\\x83\\x31\\x1d\\xae\\xb4\\x7d\\x04\\x40\\xf4\\x63\\x55\\x31\\x54\\x9e\\x39\\xa8\\xe9\\xca\\x61\\xc0\\xa3\\xb7\\x86\\xce\\xe6\\x93\\x8d\\xdd\\x58\\x50\\xfb\\x2c\\xa5\\x26\\x7b\\xbb\\xfb\\xbb\\x83\\x35\\x1f\\x5d\\x0d\\x9c\\xf8\\x22\\xf8\\x25\\x07\\x34\\xbe\\x0c\\xa0\\xed\\x58\\xb4\\x1b\\x0f\\x09\\xd7\\x8e\\xd9\\x22\\x28\\x00\\xcc\\xca\\x96\\xc3\\x41\\x87\\x7a\\x9d\\xd3\\x98\\x5b\\x2b\\x08\\x3e\\x35\\x37\\xe9\\xbc\\xb0\\x88\\x00\\x7b\\xbb\\x9f\\x76\\x87\\x84\\xe9\\x68\\x40\\xae\\xa4\\xd8\\xd5\\x30\\x7d\\x80\\xcf\\x28\\x54\\x30\\xd0\\x4a\\x16\\xd0\\xa5\\x0e\\x49\\xe0\\xb1\\x30\\x0c\\xc7\\x22\\xb2\\xc0\\x96\\x36\\x0b\\xaa\\x5d\\x19\\xde\\xf1\\x35\\xd7\\xae\\x8d\\x83\\x9c\\x91\\x17\\xd8\\x51\\x87\\x51\\xeb\\x25\\x4c\\xf8\\x92\\xed\\x2f\\x18\\x4d\\xf4\\x02\\x13\\x29\\x84\\x14\\x23\\x6c\\x8a\\x66\\x58\\x89\\xfd\\xa6\\x6d\\x4c\\xa1\\x9d\\xcb\\x2d\\xbc\\x5a\\xb8\\xdf\\xd6\\x27\\xd4\\x52\\xbb\\x36\\x4c\\xf4\\x87\\xe6\\x9d\\x5a\\xc9\\x5a\\x13\\xe3\\x8b\\x8b\\xc9\\x0f\\x95\\x5e\\xad\\xc0\\xc5\\xb5\\xce\\x5c\\x7a\\x4b\\x80\\x2b\\xb1\\x05\\xbc\\xa3\\x9b\\x80\\x5e\\xab\\xa6\\xad\\xa4\\x43\\x16\\xd6\\xb6\\x79\\x2b\\x59\\x6f\\x4a\\x7d\\xbf\\xae\\xad\\xe4\\x57\\x59\\x40\\xb7\\x39\\x3a\\x4d\\x56\\xe4\\x8a\\x0a\\xed\\x4a\\xf1\\x76\\xcc\\x50\\x3b\\x86\\x3d\\x99\\xdd\\xf0\\x23\\xa3\\x31\\xcb\\x15\\x70\\x0f\\x46\\x1b\\xe3\\x67\\xb9\\xab\\xb3\\x40\\x53\\x30\\xb7\\x6e\\xe5\\x40\\xa1\\xb4\\x4c\\xc9\\xc2\\xbe\\x76\\xb5\\x3c\\xd1\\x9e\\x8c\\x31\\x9c\\x1e\\x57\\xfb\\x93\\xb3\\x0c\\x39\\x9c\\xfd\\xcd\\xb3\\xe3\\x5f\\x6b\\x7c\\x03\\xe9\\x5e\\xc1\\x99\\x8f\\x42\\xb2\\x85\\xdd\\x48\\xb8\\x40\\x62\\x61\\x1f\\xc1\\x8e\\x78\\x69\\x07\\x09\\x02\\xa4\\xc3\\x24\\x01\\xd2\\xae\\xd8\\xb1\\x3e\\x10\\x04\\xbe\\xda\\xe7\\x43\\x75\\x96\\x77\\x40\\x3a\\x8b\\xad\\x93\\x4d\\x8e\\x48\\xbb\\x67\\x30\\x0b\\x16\\x7d\\x1e\\x15\\xe8\\xb8\\x88\\x0a\\x29\\x78\\x44\\x13\\xfe\\x1f\\x16\\x63\\x57\\x5c\\xcc\\x31\\x03\\x3d\\x27\\xa2\\x8a\\x8d\\x20\\xf0\\x29\\x90\\xff\\x05\\x6d\\x5e\\x85\\x39\\x8e\\x5a\\x4a\\x50\\x3e\\x20\\xd4\\x65\\xf8\\x23\\x3e\\xaf\\x7d\\xe6\\x02\\xe9\\x36\\x6e\\x4e\\xda\\x17\\x6d\\x86\\xd7\\xed\\x64\\xee\\x66\\x8b\\x91\\x2e\\x29\\x90\\x75\\x90\\x64\\xbd\\x9e\\x62\\xbd\\xd6\\xb3\\x1b\\x98\\x11\\xa2\\xc2\\x6e\\x8d\\x2c\\x6b\\xdb\\xc0\\x9c\\x6c\\xae\\x58\\xce\\x89\\xf0\\xfd\\x66\\x9f\\x46\\x13\\x73\\xd2\\x5d\\x32\\x64\\xd7\\xa9\\x90\\x9d\\x26\\x42\\x7e\\xd1\\x34\\x48\\x28\\xbe\\x68\\xcd\\x45\\xaa\\x5e\\x78\\x18\\xd2\\xec\\x00\\x63\\x1d\\x1a\\xbb\\xd6\\x6a\\x98\\xd6\\x87\\xe4\\x7a\\x62\\x54\\x9d\\xae\\xe6\\xa8\\x6d\\xc5\\x19\\xd3\\x51\\x76\\x2e\\xa3\\xcb\\x0e\\xad\\xa7\\x23\\x96\\xe5\\x2c\\x42\\x6f\\xdc\\xc5\\xe1\\x04\\x47\\x37\\x56\\xec\\xe9\\xbb\\x8b\\x32\\xe9\\x1f\\x32\\x63\\x4a\\xf7\\xe8\\x8f\\xd6\\x5f\\x67\\x2c\\xdf\\x4b\\x96\\x69\\xef\\x20\\x98\\xd2\\xe8\\xf2\\x8a\\xe6\\x31\\xf8\\xcf\\xa8\\xe6\\x53\\x9e\\x70\\xbd\\x02\\x17\\x40\\xce\\xa0\\xa2\\x40\\x48\\x4c\\xbd\\x43\\x28\\x46\\xe9\\x1a\\xaa\\xfa\\x6e\\xdf\\xde\\x53\\x06\\x7e\\x38\\x2b\\x02\\x67\\x94\\x1b\\xab\\xdf\\x77\\xcd\\xc5\\xdc\\x9c\\x28\\xf3\\x8e\\xc3\\xd0\\xff\\xdd\\x9b\\x78\\xee\\xda\\x5a\\x13\\x2f\\xe8\\x08\\x7b\\x5f\\x6b\\xaf\\x6d\\x86\\xe0\\x16\\x8b\\x3a\\x2b\\xe2\\x72\\xdf\\xf0\\xac\\x17\\x75\\x1d\\x8d\\xb7\\xbd\\xa2\\x2e\\xcb\\xd9\\xb9\\x96\\x59\\x47\\xb1\\x18\\x1c\\xec\\x86\\x48\\xcc\\x94\\xcd\\xa4\\x61\\xc2\\x37\\x86\\x56\\xe2\\x82\\x59\\x50\\xce\\x83\\xc9\\x89\\xf7\\x9d\\xc9\\x4a\\xf8\\x04\\x73\\x23\\x1d\\x12\\x67\\xc2\\x97\\x4c\\x30\\xa5\\xf6\\x21\\xe8\\x52\\x64\\xb6\\xe9\\xbf\\xed\\x6d\\x3b\\x34\\x6f\\xc7\\x52\\x98\\xdd\\xb0\\xac\\x37\\xb0\\x9d\\x75\\xe1\\x43\\xa6\\x23\\xf4\\x0f\\x07\\x8c\\x1c\\x9a\\x76\\xd9\\xe9\\xd7\\x83\\x35\\x51\\x4e\\xd5\\x02\\xbb\\xce\\xb2\\x6b\\xae\\x6d\\xe7\\xe4\\x09\\x22\\xf5\\x86\\xcd\\x6f\\xe7\\x39\\x8d\\x18\\xc9\\x58\\xce\\xa5\\x11\\x46\\x85\\xd0\\xb1\\xbc\\x12\\x64\\xca\\xe6\\x5c\\x28\\x47\\x0a\\xc0\\xda\\xb4\\x34\\x83\\xa8\\x0f\\x57\\x1e\\x98\\x6d\\x4c\\xce\\x2a\\xb0\\x23\\xb6\\x20\\x28\\x92\\xe5\\xd1\\xb4\\x73\\xae\\xc7\\xab\\x40\\x62\\x01\\x9d\\xb0\\x87\\x8b\\xa7\\x70\\xd8\\xd6\\xe6\\x73\\x53\\xde\\x2b\\x04\\x3c\\x39\\x66\\x09\\x5d\\x61\\xde\\x27\\x74\\xa4\\xe6\\xff\\x61\\xb9\\x1a\\x74\\x10\\xd7\\xc2\\xc6\\x4c\\xee\\xbb\\x1b\\xe7\\x01\\x20\\xa7\\x34\\x5a\\xb4\\x0b\\x14\\xf7\\x81\\xb0\\x3b\\x5e\\x7d\\x20\\xac\\xcd\\x20\\x7d\\x20\\xac\\x0f\\x84\\x7d\\xe6\\xea\\x03\\x61\\x7d\\x20\\xac\\x76\\x6d\\xad\\x95\\xd4\\x07\\xc2\\x1a\\x5f\\x7d\\x20\\xec\\xf6\\xab\\x0f\\x84\\xdd\\xe1\\xea\\x03\\x61\\x77\\xbc\\xfa\\x40\\xd8\\xcd\\x57\\x1f\\x08\\x6b\\x37\\x99\\x3e\\x10\\xd6\\x07\\xc2\\xec\\xf5\\xc7\\xf3\\x0e\\xba\\xab\\x0f\\x84\\xad\\x0d\\xd2\\x07\\xc2\\xfa\\x40\\xd8\\x9d\\xaf\\xad\\x35\\xf1\\xfa\\x40\\x18\\x5e\\x7d\\x20\\xac\\x7a\\xfd\\xb1\\x44\\x9d\\x0b\\x23\\x4d\\x8c\\x41\\xd9\\xbe\\xa9\\x30\\x98\\xa5\\x96\\xc7\\x3e\\xcb\\x12\\xae\\x36\\x51\\x86\\x87\\x89\\x30\\x6c\\x49\\x38\\xa6\\x83\\xa8\\x42\\x1f\\x51\\x78\\x76\\x11\\x85\\x6e\\xbc\\x71\\x1d\\x78\\xe2\\x5a\\xf3\\x64\\x1b\\x68\\xbf\\x58\\xe4\\x4c\\x2d\\x64\\xd2\\x78\\xa3\\x57\\x36\\xf9\\x5b\\x2e\\x78\\x5a\\xa4\\x66\\xcf\\x29\\xb3\\x9f\\xf9\\xd2\\x47\\xf4\\x55\\xd9\\x69\\x19\\x02\\xfd\\xe8\\x14\\x34\\x37\\xf2\\x98\\x01\\x8a\\x28\\xe5\\x89\\x59\\x46\\x28\\xfa\\x5c\\xd0\\xa5\\xd9\\xeb\\xaa\\x88\\x22\\xc6\\xa0\\x47\\x59\\x68\\x4a\\x7c\\x3b\\xf6\\x4f\\xf2\\x3d\\x29\\x5e\\xb6\\xe3\\x37\\xed\\xa4\\x25\\xe2\\x7c\\xc2\\x28\\xdf\\x7e\\xd3\\x68\\x8c\\x79\\x9e\\x75\\xc3\\x97\\x7f\\x38\\x9b\\x1c\\x06\\x7c\\x99\\x0a\\xc7\\x96\\xb9\\x58\\xca\\x64\\x89\\x9d\\x6c\\xe1\\x26\\xa3\\x15\\x3d\\x22\\x93\\x6e\\xaf\\xdf\\xb7\\xd2\\xed\\xbb\\x90\\x11\\x6d\\xd5\\xd7\\xaa\\xee\\x61\\x94\\xd4\\xaa\\x8b\\x66\\x0e\\x6b\\x89\\x70\\xf2\\x77\\x56\\x52\\x5b\\x73\\xb7\\xf6\\x8a\\x63\\xfb\\xe3\\x40\\x00\\xef\\x05\\x5e\\xbc\\x33\\x02\\xef\\xd8\\x3e\\xdf\\x4e\\x04\\x87\\x16\\x82\\x6b\\xb1\\xa4\\x25\\xc9\\x12\\x5a\\x36\\x49\\x82\\x15\\xf8\\x11\\xe4\\xc6\\xe1\\x82\\x45\\x97\\x67\\x36\\x18\\xba\\xa7\\x18\\xf3\\x99\\x2c\\x73\\xae\\x17\\xc5\\x74\\x1c\\xc9\\x74\\xdf\\x1c\\x63\\xfc\\xbf\\x69\\x22\\xa7\\xfb\\x29\\x55\\x9a\\xe5\\xfb\\xb1\\x8c\\xac\\x58\\x1a\\x45\\x66\\x14\\x2e\\xe6\\xe3\\x34\\x1e\\x40\\x1b\\xde\\x93\\x6a\\x53\\xc6\\x00\\x8a\\xc1\\x3c\\xdf\\x1a\\x70\\x64\\xca\\x0c\\x47\\x94\\x60\\xa4\\x07\\x78\\x6e\\x66\\x7a\\xf7\\x6e\\x9c\\x1b\\x5e\\xad\\xc5\\x48\\xcb\\x40\\xf4\\xc3\\x07\\xa1\\x7b\\xce\\x45\\x3a\\xf0\\x46\\x3c\\xb5\\x60\\x73\\x67\\x49\\x17\\x1d\\x04\\x99\\xb7\\x28\\xc0\\xbc\\x35\\xea\\xec\\xb6\\x04\\x95\\xb7\\x10\\x7a\\xb9\\x83\\x40\\x72\\x17\\x41\\xe4\\xee\\x02\\xc8\\x5f\\x00\\xa1\\xf8\\x29\\x07\\x8e\\x3b\\xf4\\xae\\x75\\x14\\x30\\x7e\\x88\\x60\\x71\\x27\\x6f\\xdd\\x36\\x48\\xfc\\x70\\x01\\xe2\\x6e\\x5e\\xb7\\x4b\\x73\\xe3\\xa9\\x06\\x85\\x3b\\xf0\\x92\\x77\\xe9\\x21\\xef\\xcc\\x3b\\xfe\\xc5\\x82\\xc0\\xed\\x03\\xc0\\x5b\\x10\\xfc\\x6d\\x4d\\x64\\x2e\\xb8\\xe6\\x34\\x39\\x62\\x09\\x5d\\x9d\\xb3\\x48\\x8a\\xb8\\xb1\\x1c\\xab\\x01\\x63\\xfa\\xf3\\xa3\\x70\\x58\\xeb\\xc1\\xaa\\x56\\x54\\x2c\\xa8\\xc5\\xff\\x36\\x76\\x1b\\x56\\x90\\xb8\\xc8\\x85\\x55\\x5b\\x20\\xe8\\x80\\xb3\\x6c\\x02\\xad\\x77\\x25\\xf3\\xcb\\x44\\xd2\\x58\\xed\\x67\\x12\\xff\\xaf\\xac\\x97\\x08\\x0a\\x25\\xf0\\x59\\xed\\x2a\\x25\\x1e\\xdb\\x55\\x86\\xe5\\x25\\x5d\\x2e\\xe2\\x8f\\xf2\\x8a\\xc8\\x99\\x66\\x82\\xec\\x71\\xe1\\xd6\\x71\\x10\\x18\\x9b\\xa5\\xdf\\xd2\\x6f\\x6b\\xf3\\xed\\xcb\\x17\\xee\\xe6\\xe7\\xe7\\x90\\x04\\xd7\\xab\\x52\\x5f\\xde\\x3f\\x6c\\x1f\\xf4\\x79\\x07\\xb1\\xbd\\x71\\x56\\x24\\x55\\x27\\x31\\x3a\\x8e\\xab\\xfc\\xe6\\x65\\x89\\x60\\xfc\\x12\\xc6\\xf5\\xa7\\x8d\\x8a\\x98\\xd8\\x92\\xb3\\xe7\\xb7\\x68\\xad\\x53\\x5b\\xaa\\xaa\\x9f\\x4f\\x65\\xf9\\x9c\\x3f\\xf9\\xe2\\x70\\xd2\\xbb\\x93\\xb7\\xcb\\x29\\xf3\\x48\\xe9\\x21\\x5b\\xa8\\xe8\\x3e\\xd1\\x94\\x90\\x5e\\xd1\\xbd\\xc7\\x15\\x14\\xa1\\xfe\\x90\\xd3\\x88\\x4d\\x3a\\xd7\\x11\\xdc\\x71\\x22\\x71\\x91\\x53\\xcb\\x00\\xbd\\xca\\xe7\\x0e\\x8f\\x60\\x2c\\xc6\\xd3\\xe4\\x0b\\x77\\xa1\\x24\\x76\\x56\\x24\\xc9\\x0a\\x7d\\x0e\\x95\\x32\\x67\\x8c\\xc2\\xd7\\xab\\x66\\xc1\\xf1\\xbf\\xe1\\x29\\xa5\\x62\\x99\\xe5\\xd2\\xca\\xcc\\xbc\\x10\\xc2\\xf0\\xe0\\xb2\\x0d\\x19\\x28\\x92\\x80\\xdd\\x4c\\x2b\\xb5\\xb9\\x8a\\xcf\\xcd\\xf4\\x8d\\xfc\\x83\\xb2\\xdd\\x32\\x07\\xb0\\x32\\xa0\\xf9\\xf5\\x4c\\xe6\\x11\\x9f\\x26\\x2b\\xb2\\xa0\\x89\\xef\\x39\\x43\\xc9\\x25\\x4f\\x12\\x3b\\xcc\\x98\\x9c\\x33\\x8d\\x81\\x0b\\x94\\x9d\\x89\\x14\\x73\\x98\\x1c\\x15\\xae\\xd7\\x21\\x8b\\xcc\\x6f\\xa3\\x84\\x51\\x51\\x64\\xf8\\x3c\\x23\\x89\\x57\\xb2\\xc8\\xdd\\xf3\\xc6\\x3e\\xfc\\xe1\\x25\\xb0\\xe0\\xc9\\x30\\xe8\\xa8\\x76\\xeb\\xc2\\x96\\x2e\\x1a\\x65\\x14\\x80\\x77\\x0e\\xab\\x7a\\x18\\x8e\\x29\\x97\\x2c\\xcf\\x79\\x6c\\xa3\\x09\\xf8\\x59\\x96\\xcb\\x25\\x8f\\x31\\x86\\xe2\\xc8\\x06\\xbd\\x9b\\xb1\\x67\\x8e\\x3f\\xcf\\x42\\x8a\\x91\\x60\\x73\\x0a\\x8a\\x8a\\x3d\\x45\\xb8\\x66\\x38\\x0e\\xe6\\x16\\x88\\x18\\xba\\xe8\\x18\\x0d\\x5f\\x66\\x95\\xba\\xf9\\x25\\xc7\\xfe\\xbf\\x01\\xe5\\xc8\\x9e\\x90\\x44\\x42\\x4a\\x68\\x21\\xb8\\xc6\\x9e\\xf2\\x8b\\x42\\x93\\x58\\x5e\\x89\\x81\\xf5\\x59\\x71\\x45\\x28\\x99\\x32\\x4d\\x83\\xa4\\x4e\\x2b\\xe0\\x14\\x61\\x82\\x4e\\x13\\xb3\\xe6\\x90\\xad\\x74\\xb1\\x91\\x40\\x64\\xc6\\xa8\\x2e\\x72\\x46\\xe6\\x54\\xb3\\x8d\\x7a\\x0e\\xbe\\xef\\xed\\xe4\\xe5\\xca\\x3a\\x58\\x67\\xa4\\x10\\x8a\\xb5\\x14\\xef\\x9d\\x29\\x47\\x7f\\xfb\\x4b\\x33\\x1e\\xc1\\x53\\x26\\x0b\\xfd\\x20\\xd6\\xdf\\xd5\\x82\\x47\\x8b\\x50\\x99\\xe5\\x29\\x53\\x44\\x16\\x35\\xb3\\xf8\\xa5\\xfd\\xd9\\xe6\\x15\\xea\\x4d\\xc0\\x4d\\x57\\x53\\xf7\\xf1\\x06\\xef\\x97\\x6d\\xcb\\xba\\x9e\\xd9\\x17\\xb4\\x9d\\x86\\xa4\\xed\\xa3\\xd3\\xf3\\xdf\\xdf\\x1c\\xfc\\xeb\\xf8\\x8d\\x3d\\x9f\\x22\\x14\\xfa\\x85\\xe0\\xff\\x2e\\x18\\xa1\\xa9\\x34\\xba\\x70\\x12\\x26\\x08\\x0e\\xc1\\xa2\\x0f\\x3e\\x80\\x93\\xdc\\x6d\\x2a\\x61\\x43\\x81\\x0c\\x3d\\xf2\\xdb\\x27\\x4c\\x42\\xa7\\xfd\\x2f\\x9f\\x2f\\xf9\\xd8\\xbd\\xc3\\x7c\\x57\\x0a\\xc8\\xd2\\x08\\x7a\\x87\\x51\\x22\\x98\\x36\\x27\\x0f\\x35\\x4a\\xec\\x25\\xc7\\xc5\\x3c\\x09\\x95\\xc9\\x66\\xec\\xaa\\xad\\x4d\\xd4\\xd6\\x22\\x1a\\x95\\x6f\\x30\\x69\\x6a\\x18\\x75\\xd2\\xc3\\xac\\x9c\\x43\\x47\\x9d\\x7f\\x4a\\xae\\xed\\xcc\\x00\\x6c\\xcd\\xec\\xcc\\x00\\x54\\x3d\\x4e\\x26\\x84\\xc6\\x71\\x0e\\x6a\\x0a\\x9c\\xfa\\xb4\\xd6\\x01\\x34\\x2b\\x33\\x76\\x86\\xe4\\x05\\xf9\\x8e\\x5c\\x93\\xef\\xc0\\x2c\\xf8\\x5b\\xdb\\x3e\\x49\\x6d\\x15\\xf6\\x2e\\x12\\x70\\x8c\\x35\\x7a\\x32\\xe9\\x88\\xe2\\xbf\\x2c\\xa8\\x86\\x11\\x0d\\x55\\xb5\\x24\\x53\\x6e\\xd5\\x50\\x76\\xad\\x59\\x6e\\xd4\\x22\\xbb\\x12\\x8f\\xda\\x61\\xca\\x4c\\xf0\\x01\\xb7\\x19\\xba\\xc9\\x4f\\x66\\xd5\\xa4\\x9f\\xfb\\x6d\\x34\\xf3\\x73\\x63\\xdf\\x9f\\x5a\\x2e\\x54\\xed\\xe6\\x52\\x8e\\x96\\x52\\x1d\\x2d\\xaa\\x6c\\xcc\\x28\\x18\\xaa\\x22\\x9c\\x62\\x09\\x6c\\x1c\\x13\\x72\\x17\\xbc\\x45\\x6a\\xc1\\xf6\\x6c\\xe3\\x76\\xd1\\xe6\\xca\\x7a\\xde\\xb6\\x52\\x35\\xc3\\x1f\\xe4\\xbc\\x55\\x0c\\x02\\xe8\\xa6\\x4c\\xc6\\x63\\x72\\x4c\\xa3\\x05\\x4c\\x2b\\x0e\\x64\\x86\\xb1\\x40\\x60\\xb0\\x05\\x5d\\x9a\\x85\\xb7\\xbf\\xc5\\x38\\x36\\x68\\x2b\\xde\\x3b\\x0a\\x7b\\xc9\\x9c\\xa7\\x88\\x0a\\x6c\\x41\\x3a\\x63\\x79\\x8e\\x39\\xd4\\xd3\\x95\\x4b\\x65\\x6b\\xbd\\x78\\xad\\x4e\\x52\\x96\\x4b\\x2d\\x23\\xd9\\xa2\\x09\\x56\\xbd\\x2e\\x03\\x86\\x03\\x22\\x64\\xb8\\x77\\x2d\\xe5\\xdf\\x1f\\x4d\\x86\\xe4\\xe2\\x70\\x02\\xad\\x8b\\xce\\x0f\\x2f\\x26\\x55\\x0d\\x7b\\xe7\\xe2\\x70\\xb2\\xf3\\xa8\\xa4\\x20\\xce\\xcd\\x06\\x0e\\xd5\\x06\\x83\\x54\\x1c\\x26\\x09\\x57\\x7a\\x94\\xd2\\x6c\\x74\\xc9\\x56\\x0d\\x65\\x6a\\x17\\x72\\x7d\\xe4\\x57\\xb8\\x93\\x17\\x42\\x32\\xa7\\x34\\xbb\\xf7\\x68\\x39\\xa3\\x31\\xef\\x0b\\x80\\xee\\x7e\\xf5\\x05\\x40\\x77\\xbc\\xfa\\x02\\xa0\\xbe\\x00\\x68\\xfd\\xda\\x9a\\x8c\\xc9\\xbe\\x00\\xe8\\x79\\x85\\x6e\\xfb\\x02\\xa0\\xfb\\x5f\\x8f\\x1e\\xb1\\xed\\x0b\\x80\\x36\\x5f\\x7d\\x01\\x50\\x5f\\x00\\x74\\xb7\\xab\\x2f\\x00\\xba\\xff\\xb5\\x75\\xb9\\x26\\x7d\\x01\\xd0\\xbd\\xae\\xbe\\x00\\x68\\xfd\\xea\\x0b\\x80\\x6e\\xb8\\xfa\\x02\\xa0\\x1b\\xae\\xbe\\x00\\x68\\xfd\\xea\\x0b\\x80\\xee\\x77\\xf5\\x05\\x40\\x7d\\x01\\xd0\\xb3\\xce\\x8b\\x24\\x7d\\x01\\x90\\xbd\\xfa\\x02\\xa0\\x67\\x91\\xfd\\x45\\xfa\\x02\\xa0\\x3b\\x5d\\x7d\\x01\\x50\\x5f\\x00\\xd4\\xe4\\xea\\x0b\\x80\\x9e\\x8b\\x53\\xa6\\x2f\\x00\\xea\\x0b\\x80\\xfe\\x38\\x8a\\x6e\\x5f\\x00\\xd4\\x17\\x00\\xf5\\x05\\x40\\x7d\\x01\\xd0\\xad\\xb3\\xe8\\x0b\\x80\\x9e\\x83\\x09\\x98\\x33\\xc5\\xff\\xc3\\x26\\x32\\xe1\\xd1\\xaa\\x75\\xc2\\xdf\\x99\\x6d\\x2d\\xab\\xec\\xb0\\x24\\x83\\x71\\x83\\xd4\\xaa\\x16\\x45\\x1c\\x5b\\x56\\xbb\\x72\\x16\\x10\\x2e\\xac\\x61\\xf1\\xed\\x75\\xbf\\x00\\x09\\xb6\\xa2\\x8e\\xc5\\xbd\\xe0\\x69\\xf3\\x48\\x0a\\x0c\\x62\\xac\\x46\\x24\\x5f\\x33\\xbf\\x45\\x6b\\x13\\x21\\x7c\\x91\\x8e\\x52\\xab\\x77\\xc3\\x52\\x38\\xbf\\x13\\xb4\\xf4\\x1c\\x8c\\xdf\\xb8\\x41\\x68\\x96\\x25\\x9c\\xa9\\x31\\x39\\xf7\\x2d\\x4e\\x80\\x7b\\xa9\\x57\\x24\\xca\\x8a\\x21\\x49\\x59\\x2a\\xf3\\x55\\x0b\\x6b\\xa2\\x03\\x85\\xb3\\xb2\\x6a\\x1d\\x91\\xec\\x0c\\xc7\\x74\\x64\\x30\\x46\\x44\\x96\\x25\\x2b\\x54\\xa6\\xca\\xca\\x41\\x4f\\x35\\xee\\x98\\x4b\\x0c\\xea\\x4e\\x2d\\xcb\\x83\\xeb\\x8a\\x19\\x76\\x2a\\xf5\\x99\\xdd\\xf0\\x8f\\x96\\xb6\\x7e\\x53\\x82\\x36\\xd5\\x32\\xe5\\x51\\x13\\x86\\x8d\\x3c\\xb6\\x43\\x6e\\x7d\\xe7\\x0c\\x6d\\x72\\xbc\\xe1\\x53\\x70\\x5d\\xab\\xcc\\x0c\\x92\\x97\\x43\\x26\\x39\\xa3\\xf1\\x0a\\x86\\x84\\x66\\x3e\\x81\\x55\\xfc\\x04\\x13\\xbd\\xa3\\x84\\xf2\\xe6\\x51\\xf9\\x6a\\xe2\\xd4\\x21\\x8c\\x45\\xcc\\x56\\x28\\x53\\xa7\\x20\\x03\\xd7\\x93\\x6f\\xe8\\xd3\\x92\\x38\\x1e\\x82\\xb1\\xfb\\x0a\\x7f\\x3c\\xc4\\x3c\\x5e\\x43\\x72\\x50\\x29\\x41\\xf1\\xe6\\x2a\\xb4\\xb8\\x3f\\x8a\\x52\\xf9\\x15\\x84\\x26\\xd9\\xe2\\x76\\xf5\\xd7\\x4c\\xe4\\x68\\x25\\x68\\xca\\x23\\xb7\\x31\\x0e\\x70\\xed\\x8c\\xb9\\x53\\x55\\x80\\xdd\\xd8\\x38\\x9e\\x79\\x48\\x9a\\x16\\x9a\\x4e\\x13\\x36\\x26\\x27\\x58\\x4a\\x23\\x05\\x74\\xba\\x87\\xfc\\x0b\\x1b\\xd6\\x70\\x9b\\xa8\\x69\\x86\\x55\\xfb\\xf4\\x8a\\x96\\xa9\\x15\\x1b\\x4f\\x0f\\x2c\\x08\\x96\\x0d\\x31\\x61\\x76\\xbe\\x14\\x8c\\x30\\xa1\\xf3\\x95\\x59\\xbb\\x89\\x8c\\xcf\\xcd\\xf2\\x55\\xee\\x6e\\x5d\\x4d\\xd4\\x32\\xa3\\xa2\\x8b\\x6c\\x8a\\x96\\x99\\x14\\xdd\\xe4\\x3f\\xb4\\xcf\\x7d\\x58\\x0f\\xe2\\x06\\x05\\x7e\\x61\\x5a\\x63\\x65\\x55\\x0d\\x0f\\xdb\\x70\\x2a\\x9d\\xe0\\x9f\\xc8\\xd8\\x88\\xaf\\x9c\\x85\\xad\\xc4\\xac\\xf5\\x07\\x07\\x24\\xa5\\x97\\x60\\x40\\x53\\x5d\\xca\\x35\\xba\\xa4\\x3c\\x31\\x47\\xa8\\x2c\\x0f\\x68\\xa9\\x2b\\xba\\xab\\x03\\xc1\\xdf\\x75\\xd5\\x14\\x69\\xbb\\x83\\xba\\xac\\x7a\\x22\\xd0\\xf9\\x28\\xe5\\xcd\\x2a\\xf8\\xc9\\x9a\\x0e\\xf8\\x06\\xc6\\x0a\\x92\\xad\\xcc\\x9e\\x48\\xe9\\x35\\x58\\xa4\\x34\\x95\\x85\\xd0\\x66\\xa7\\x44\\x32\\xcd\\x0a\\x5d\\x95\\x99\\x20\\x7e\\xef\\x6d\\xaa\\x46\\x52\\xcc\\xf8\\xdc\\xba\\xb8\\xf6\\x53\\x2a\\xe8\\x9c\\x8d\\xfc\\xb0\\xa3\\x92\\xf5\\xee\\xb7\\xb3\\x53\\x5b\\xb1\\x1d\\x1a\\xbb\\x02\\x97\\x49\\x17\\xb9\\xe2\\x54\\x6b\\x96\\x8b\\x57\\xe4\\xbf\\xf6\\x3e\\x7e\\xfd\\x69\\x34\\xf8\\x7e\\x6f\\xef\\xc3\\x8b\\xd1\\x3f\\x7e\\xfb\\x7a\\xef\\xe3\\x18\\xfe\\xf1\\xe7\\xc1\\xf7\\x83\\x4f\\xee\\x8f\\xaf\\x07\\x83\\xbd\\xbd\\x0f\\x3f\\xbd\\xfd\\xe1\\x62\\x72\\xfc\\x1b\\x1f\\x7c\\xfa\\x20\\x8a\\xf4\\x12\\xff\\xfa\\xb4\\xf7\\x81\\x1d\\xff\\x76\\xc7\\x41\\x06\\x83\\xef\\xbf\\x6a\\x3c\\xe5\\xd6\\x1e\\xe8\\xee\\xfc\\xcf\\x1d\\x79\\x9f\\xbf\\x88\\xef\\xd9\\x66\\x69\\x76\\x74\\x16\\x6d\\x86\\xf9\\xda\\x69\\xb4\\xfe\\xa1\\xdb\\x4e\\xa3\\x93\\x92\\x60\\x66\\xf8\\x71\\xb8\\x22\\x32\\xe5\\x5a\\x5b\\x2d\\x99\\x86\\x75\\x65\\x35\\xe3\\xc3\\xf2\\x01\\x3e\\x43\\x4e\\xcf\\x55\\x58\\x93\\x15\\xd8\\x2c\\xd2\\x39\\x5a\\xc1\\xf8\\x11\\x84\\xa7\\x59\\xc2\\x52\\x26\\x34\\x9c\\xe7\\x91\\xd3\\x04\\xc1\\x1a\\x1c\\x97\\x33\\x89\\xa8\\x30\\x3a\\x3b\\xbb\\x8e\\x18\\x8b\\xed\\xc3\\x7a\\xd6\\xf1\\xf9\\xab\\x67\\x1d\\xcf\\x91\\x75\\xb4\\x76\\x4d\\xdc\\xe6\\x94\\x58\\x73\\xde\\x99\\x93\\x8a\\x87\\xc5\\x79\\x7a\\xe0\\x76\\x5f\\x57\\x22\\x67\\x84\\xd1\\x68\\x11\\xfc\\xc0\\xe2\\x16\\x50\\x44\\x2d\\x40\\x04\\x14\\xba\\x5a\\x33\\x93\\x6a\\x08\\x47\\x98\\xdc\\x6f\\x4f\\xba\\x72\\x31\\x22\\x54\\x28\\xa5\\xd8\\x0e\\xec\\x23\\xc5\\xa2\\x22\\xe7\\x7a\\x75\\x28\\x85\\x66\\xd7\\x8d\\x22\\xcd\\x37\\x85\\xda\\xcf\\xab\\x43\\x5b\\xa3\\xd8\\x66\\x0d\\xdb\\xef\\x88\\xcc\\xb0\\x46\\xf6\\x46\\xf4\\xa9\\x85\\x2c\\x92\\x18\\xb0\\x1d\\x0a\\x01\\xeb\\x80\\x30\\x21\\x4c\\x63\\x64\\x0c\\xa8\\x09\\xba\\x7b\\xfd\\x71\\x2e\\xd6\\x85\\x43\\xff\\xbb\\xe0\\x4b\\x9a\\x30\\xa1\\x83\\x5f\\x4c\\x20\\xba\\x13\\xfe\\xa8\\x91\\x83\\xee\\x91\\x9d\\x1b\\xa0\\x77\\x4e\\x72\\xbe\\xe4\\x09\\x9b\\xb3\\x63\\x15\\xd1\\x04\\xe4\\x41\\x37\\x22\\xf8\\xe0\\x86\\xd1\\x61\\x89\\x72\\x99\\x28\\x63\\x2b\\x19\\x11\\x68\\x0e\\x07\\x06\\x32\\xc1\\x83\\x30\\xa7\\x5c\\x90\\xd4\\x88\\xb3\\xcc\\xfd\\x58\\x61\\x44\\xd4\\x48\\xd5\\x8c\\xe6\\x66\\x29\\x7c\\xe4\\x13\\x4e\\xd4\\x54\\xca\\xc4\\x56\\x74\\x27\\xab\\x72\\x7c\\x8e\\x66\\x99\\x90\\xbf\\x0b\\x76\\xf5\\xbb\\x19\\x4d\\x91\\x59\\x42\\xe7\\x3e\\xe0\\x69\\x4e\\x56\\x3d\\x67\\xa1\\x1c\\xfa\\xc6\\x17\\x80\\x72\\xe9\\x82\\x11\\x9a\\x5c\\xd1\\x95\\x2a\\xc3\\xbf\\xe5\\x18\\x5c\\xbd\\x22\\x2f\\x07\\xb0\\xf1\\xa8\\x22\\x7e\\x8c\\x98\\x7c\\x33\\x80\\x24\\xc6\\xc3\\x83\\xc9\\xef\\xe7\\xbf\\x9e\\xff\\x7e\\x70\\xf4\\xf6\\xe4\\x94\\x9c\\x4a\\xcd\\x50\\x57\\x08\\x8e\\xb9\\x3d\\xfc\\x76\\x96\\xde\\x2b\\x3a\\x96\\x6a\\x0c\\xb6\\x29\\xe4\\xe4\\x8b\\x58\\x5e\\xa9\\xc6\\xbe\\x61\\xdc\\x7e\\x86\\x78\\x8c\\x8a\\x66\\xee\\x31\\x9a\\x51\\xe8\\xac\\xdd\\x42\\x32\\xaf\\xe5\\xc9\\x87\\x83\\x82\\x6a\\x14\\xc7\\xfb\\x71\\x2e\\x33\\x24\\x82\\x0b\\xd5\\x87\\xcc\\xf2\\xa8\\x96\\x81\\xe3\\xea\\xfd\\x60\\x7d\\x67\\xd5\\x01\\xe7\\x39\\x15\\xba\\x8c\\x59\\x97\\x6b\\x66\\x5b\\x7a\\x8f\\x5b\\x2f\\xc7\\xe3\\x29\\x4c\\x5d\\x78\\x57\\x68\\xdc\\x1d\\x5a\\xc3\\x41\\x1c\\xb3\\xb8\\x42\\xfe\\xd6\\x39\\x51\\xdb\\x56\\x65\\x75\\xe8\\x5e\\x2e\\x08\\x06\\x92\\xc9\\xbb\\xf3\\x93\\xff\\x5b\\xdb\\xc7\\xab\\xac\\x5d\\xb9\\x47\\x37\\x20\\x3a\\xb9\\xcc\\x3a\\x5b\\xdd\\x33\\x96\\xca\\x65\\xbf\\xbe\\xdb\\xb2\\xbe\\x5e\\x5a\\x76\\x93\\x64\\x7c\\x56\\x88\\x50\\xa0\\x89\\x60\\x7c\\x92\\xca\\x98\\x8d\\xc9\\xc4\\x67\\x3b\\x55\\xbf\\x0d\\x81\\x3a\\x73\\x46\\xcc\\x2d\\x42\\x73\\x9a\\x24\\xab\\x50\\x99\\xd2\\x12\\x51\\x56\\x2a\\x30\\x6e\\x21\\x23\\x9f\\xd1\\x44\\x3d\\x36\\x37\\x6e\\x23\\x1b\\x8d\\x1e\\xf1\\x56\\x16\\xa2\\x9b\\x2c\\x62\\x3f\\x1a\\x89\\x99\\x90\\xda\\x2a\\xc3\\x66\\x96\\x00\\x8d\\x97\\xcb\\x88\\xa0\\x4f\\x23\\x28\\x29\\xa9\\xc8\\x37\\x85\\x19\\x57\\x4e\\x34\\x72\\xe5\\x88\\x3d\\xf1\\x23\\x63\\xb0\\xba\\x50\\x4c\\x6d\\x16\\x8d\\xa5\\x97\\xc3\\x8c\\x9e\\x33\\x1a\\x83\\x19\\x93\\x51\\xbd\\xc0\\x8c\\xf0\\x94\\xaa\\x4b\\x16\\xe3\\x07\\x56\\x35\\xf3\\x01\\x27\\x70\\x90\\xbb\\x47\\x5d\\x98\\x79\\xbb\\xd8\\x12\\xa8\\x64\\x98\\xa7\\x0e\\x51\\x29\\x16\\x3f\\xf2\\xaa\\xb7\\x38\\x84\\x86\\x28\\xef\\x44\\xb2\\x3a\\x93\\x52\\xbf\\xf6\\x30\\x41\\x9d\\xec\\x80\\x5f\\xac\\xb6\\x5c\\x0d\\xf8\\x81\\x3a\\x49\\xe1\\xb9\\x23\\x58\\x0d\\x38\\x54\\x21\\x42\\xd1\\x51\\xb9\\xe2\\x4f\\xfd\\x48\\xe5\\x85\\x38\\x50\\x3f\\xe4\\xb2\\x68\\x2c\\xc4\\xd6\\x94\\xcd\\x1f\\x4e\\x8e\\x80\\x15\\x15\\x36\\xe1\\x52\\xe8\\x7c\\x95\\x49\\x8e\\xce\\xc1\\x1b\\x0c\\x83\\xf7\\x36\\x65\\x34\\x3c\\x13\\x65\\x76\\x1f\\x79\\x4b\\x57\\x84\\x26\\x4a\\x3a\\x5a\\xda\\x70\\x60\\xcd\\x5e\\x24\\xd6\\x18\\x35\\x5f\\x4f\\xa5\\x5e\\xac\\x59\\xa1\\xe6\\x40\\xad\\xff\\x6e\\x18\\xe4\\x5f\\x96\\x59\\x12\\x5c\\xac\\xfd\\x5c\\x43\\xac\\x29\\xcb\\x59\\xc4\\x62\\x26\\xa2\\xc7\\x5e\\xf6\\xc7\\x4e\\x5b\\x84\\xad\\x73\\x2a\\x85\\x39\\x98\\x9d\\x6c\\x9e\\x13\\x9f\\xaf\\x6a\\x49\\x1a\\x6e\\x15\\x08\\x26\\x5a\\xeb\\x8f\\x42\\xfe\\x2b\\x1c\\xcb\\x42\\xb1\\x1c\\x93\\x75\\xf3\\x82\\xe1\\x4a\\xfe\\x54\\x4c\\x59\\x62\\x28\\x6f\\x4c\\x52\\x00\\x2a\\xa5\\x1a\\x1d\\x0f\\x3c\\xa5\\x73\\x46\\xa8\\xf6\\x3b\\x4d\\x4b\\xc2\\x84\\x2a\\x72\\xbb\\x88\\x5c\\x93\\x58\\xb2\\x12\\x5d\\x8c\\x2a\\xf2\\xfe\\xe4\\x88\\xbc\\x20\\x7b\\xe6\\x59\\x03\\xd8\\x3f\\x33\\xca\\x13\\x48\\x8d\\x05\\x37\\x55\\xcd\\x46\\x9d\\xb9\\x21\\x60\\x4a\\xb0\\x79\\x89\\xcc\\x91\\x49\\x0c\\x89\\x90\\x44\\x15\\xd1\\xc2\\xcd\\xc9\\xd8\\xbd\\xce\\x6c\\xb6\\xe5\\x5c\\x10\\xb1\\xda\\xce\\xbd\\xfe\\xb8\\x1c\\xea\\xbd\\x62\\x79\\x67\\x0c\\xea\\x7d\\x03\\x06\\x15\\xaa\\x51\\x66\\xcf\\x55\\xa9\\x87\\x1b\\x2b\\x65\\x9a\\xc6\\x54\\x53\\xcb\\xb8\\xdc\\x0d\\x5b\\xbb\\xa4\\x7f\\x6c\\xf6\\xa5\\xd8\\x1b\\x2e\\x8a\\x6b\\x74\\x91\\x76\\xe7\\x6a\\x39\\x3f\\x86\\x61\\x61\\x0f\\x01\\xd5\\x61\\xd5\\x31\\x25\\xd1\\x67\\x6e\\x05\\xc9\\x45\\x27\\x95\\xbd\\x32\\xbc\\x41\\x4d\\x04\\x3e\\xe1\\x12\\xc0\\x8c\\x72\\x42\\x45\\x2c\\xd3\\xb5\\x87\\x41\\xb6\\x59\\xc5\\x5b\\x3e\\x26\\xfd\\xee\\xab\\x5e\\x5b\\xe2\\x14\\x4a\\xd8\\x92\\xb5\\x80\\x21\\xae\\xed\\xbc\\x37\\x66\\x34\\x43\\x1c\\xb7\\x23\\x60\\x78\\x92\\xd0\\x29\\x4b\\x6c\\x82\\x1b\\x26\\xc5\\xae\\xef\\xc0\\xc7\\xae\\xa9\\xcb\\x65\\xd2\\x1d\\x08\\xc0\\x99\\x4c\\x18\\x16\\xa9\\x38\\x42\\x98\\xe1\\x9f\\x04\\x1d\\x60\\x90\\xae\\xe8\\x00\\xd6\\x60\\x85\\x0e\\x60\\xd7\\x3e\\x05\\x3a\\x14\\x2d\\x44\\x3d\\xa9\\xd3\\xc1\\xe8\\x0d\\x55\\x3a\\x80\\xf0\\xde\\x76\\x3a\\x28\\x16\\x45\\x32\\xcd\\x26\\xb9\\x34\\x66\\x67\\x67\\xb2\\xc9\\x0e\\x5b\\xc6\\xf9\\xd0\\xb1\\xb1\\x21\\xe5\\x15\\x64\\x41\\xf5\\x66\\x9a\\x07\\xe5\\x69\\x54\\xa3\\x90\\x70\\x35\\x6a\\xff\\x2b\\x90\\x59\\xc0\\x7a\\xea\\x82\\xcc\\x8d\\x52\\x09\\x04\\x9a\\x5f\\xda\\x2f\\x9e\\xb2\\x38\\xe8\\xa2\\xc2\\xbb\\x85\\xb3\\xb3\\x13\\x69\\x24\\x23\\x9a\\x40\\x9b\\x89\\x76\\x5b\\x8e\\xd4\\xb7\\x5d\\x7d\\xe0\\xa0\\x28\\x11\\x62\\x94\\xf0\\x59\\x90\\xa1\\x4d\\xc1\\xd1\\xe2\\x5c\\x98\\x42\\xc6\\x2c\\x88\\x3a\\x63\\xd6\\xe7\\x05\\x16\\xaf\\xc1\\x7d\\xae\\x1e\\xd2\\xe8\\x15\\x36\\xff\\x86\\xc5\\x95\\x5f\\x6b\\x69\\x11\\x9e\\xdf\\xfa\\xe6\\x15\\x66\\x82\\x4c\\xc4\\x5c\\xcc\\xc1\\xaf\\x36\\x24\\x39\\x4b\\xb0\\x92\\xd2\\x32\\x81\\x4b\\xb4\\x20\\x77\\xe1\\x48\\xb8\\x41\\xdd\\x79\\x70\\x8f\\x76\\x09\\xdd\\xe5\\xc8\\xa0\\x3d\\xcd\\x90\\xd3\\x72\\x45\\x76\\xde\\xb8\\x77\\xdf\\xb1\\xf7\\x9c\\xbe\\xbb\\x08\\x33\\x14\\xa8\\x58\\x61\\xc6\\x12\\xfc\\xe4\\xd1\\x19\\x6f\\xa7\\x02\\x68\\x07\\xa9\\xe0\\x17\\x1b\\x1d\\xa1\\x97\\x5c\\xc4\\xb6\\x26\\xb1\\x42\\x4b\\x67\\x06\\x5b\\x35\\x19\\xaa\\x5d\\x79\\x1c\\xb2\\x9e\\x57\\xe4\\xa3\\x20\\x9e\\xa0\\x64\\xd4\\x78\\xf7\\x9c\\xa1\\x46\\xed\\x5c\\x78\\xa3\\xdb\\xfd\\xb2\\xfe\\x21\\xf5\\x61\\xde\\x0b\\xd8\\x1a\\xe6\\xb9\\x23\\x63\\xd8\\xaf\\xdf\\xe7\\xde\\xe5\\x51\\x51\\x50\\x2d\\x73\\xec\\xda\\xc8\\xf9\\x05\\x87\\x75\\x1a\\x7f\\x64\\xb6\\xb4\\xe6\\x62\\xae\\x42\\x43\\xa7\\xda\\x72\\x6c\\xb3\\xa5\\xe3\\x56\\x78\\x96\\xcb\\xd4\\x25\\x7c\\xd7\\x2d\\x87\\x6a\\x2d\\xf5\\x53\\xb1\\x52\\x12\\xa3\\x6d\\x3c\\x71\\x1b\\x65\\x9e\\x2a\\x7a\\x98\\x1b\\x4a\\x68\\x4e\\x93\\xf3\\xac\\x79\\x87\\x06\\xb2\\x86\\x06\\xfe\\xf6\\xfc\\xa0\\x3a\\x34\\xc8\\x72\\x9b\\xea\\xcf\\xe0\\x7b\\x42\\xe3\\x94\\x2b\\x05\\x7e\\x32\\x36\\x5d\\x48\\x79\\x49\\xf6\\x36\\x40\\x1b\\x07\\xe9\\x6f\\x8a\\xcf\\xd5\\xbe\\xdd\\xf3\\x23\\x33\\xfb\\x01\\xe1\\x22\\xf1\\x89\\x4e\\x60\\x26\\x0b\\xed\\xab\\x0b\\xe0\\x21\\x91\\x9f\\x05\\xac\\xa1\\xed\\x80\\x63\\x73\\x19\\xd6\\xa7\\x89\\x3d\\x6f\\xcc\\x2e\\x78\\x74\\x86\\xbd\\xbe\\x3c\\xed\\xea\\x2f\\x3f\\xbb\\x44\\xa7\\x76\\x6f\\xd7\\x41\\xaa\\x37\\xd2\\x11\\x95\\xcb\\x47\\x27\\x92\\xd5\\x3d\\x22\\xa6\\xba\\xc3\\xc6\\xfd\\xb1\\x1c\\x93\\xc4\\x0c\\xa1\\x0a\\x18\\x24\\x47\\xd1\\x1b\\xb3\\xe5\\xc0\\x6d\\xbd\\x0b\\x88\\x37\\xf6\\xa7\\xbb\\xa1\\xc2\\x7d\\x90\\x24\\x86\\x9a\\xd4\\x30\\xaf\\x5d\\x15\\x06\\x7c\\xcb\\xee\\x4b\\x1e\\xe1\\x93\\xcd\\x66\\x2c\\x02\\x85\\x25\\x9c\\x09\\xb2\\xb7\\xbd\\xb2\\x41\\x86\\xab\\x41\\xd4\\xd2\\x75\\x6f\\x4a\\xf9\\xb5\\x79\\x4a\\xf8\\xab\\x5a\\x0f\\x48\\x21\\xc5\\x68\\xf3\\xd7\\x83\\x31\\x39\\x11\\x3e\\x81\\x78\\x68\\xde\\x36\\xbc\\xd1\\x65\\x70\\x69\\xc3\\x0c\\xc3\\xce\\x5f\\x30\\xff\\xd0\\xff\\x64\\x94\\xac\\xbc\\xe8\\x60\\x67\\xb4\\xf1\\x2a\\x93\\xd0\\xb3\\xdc\\xe9\\xb1\\x01\\x0f\\xb3\\x1d\\xd4\\x88\\x18\\x27\\x2b\\xdb\\x78\\x9c\\xcd\\x2d\\x5f\\xca\\xeb\\xfc\\x34\\xe2\\x08\\xa4\\x75\\x6e\\x2d\\x42\\xab\\xf5\\xed\\x98\\xee\\x76\\xf5\\xed\\x98\\xee\\x78\\xf5\\xed\\x98\\xfa\\x76\\x4c\\xeb\\xd7\\xd6\\x64\\xde\\xf5\\xed\\x98\\x9e\\x17\\x90\\x66\\xdf\\x8e\\xe9\\xfe\\xd7\\xa3\\xe3\\x67\\xf6\\xed\\x98\\x36\\x5f\\x7d\\x3b\\xa6\\xbe\\x1d\\xd3\\xdd\\xae\\xbe\\x1d\\xd3\\xfd\\xaf\\xad\\x43\\xfe\\xed\\xdb\\x31\\xdd\\xeb\\xea\\xdb\\x31\\xad\\x5f\\x7d\\x3b\\xa6\\x1b\\xae\\xbe\\x1d\\xd3\\x0d\\x57\\xdf\\x8e\\x69\\xfd\\xea\\xdb\\x31\\xdd\\xef\\xea\\xdb\\x31\\xf5\\xed\\x98\\x9e\\x35\\x4a\\x3d\\xe9\\xdb\\x31\\xd9\\xab\\x6f\\xc7\\xf4\\x2c\\xb0\\xb8\\x49\\xdf\\x8e\\xe9\\x4e\\x57\\xdf\\x8e\\xa9\\x6f\\xc7\\xd4\\xe4\\xea\\xdb\\x31\\x3d\\x17\\xa7\\x4c\\xdf\\x8e\\xa9\\x6f\\xc7\\xf4\\xc7\\x51\\x74\\xfb\\x76\\x4c\\x7d\\x3b\\xa6\\xbe\\x1d\\x53\\xdf\\x8e\\xe9\\xd6\\x59\\xf4\\xed\\x98\\x9e\\x83\\x09\\xa8\\x74\\xcc\\x1b\\xe1\\x2e\\xde\\x05\\x22\\xc6\\xe6\\xf6\\x06\\x15\\xd9\\xd3\\x62\\x36\\x63\\x39\\x70\\x2e\\x78\\xf2\\x5a\\x5a\\x55\\x89\\x86\\x57\\x0f\\xe5\\x32\\x3d\\x04\\xb4\\x19\\x5b\\x06\\x71\\xc3\\xcf\\x6d\\x09\\x38\\xe0\\x23\\xe6\\x4c\\x01\\x40\\x8a\\x20\\xc7\\xef\\x5e\\x6f\\xc0\\xa3\\x69\\x9c\\x6f\\xd8\\x34\\xa5\\x16\\xe6\\xfc\\x4e\\x34\\x8b\\xc2\\xdf\\x40\\xf0\\x4d\\x65\\x39\\x96\\xee\\x51\\x22\\x95\\xcd\\x87\\x06\\x62\\x45\\x0b\\x2a\\x04\\x73\\xf6\\x1e\\xd7\\xe0\\x47\\x99\\x32\\x26\\x88\\xcc\\x98\\x8d\\x81\\x53\\xa2\\xb8\\x98\\x27\\x8c\\x50\\xad\\x69\\xb4\\x18\\x9b\\x27\\x09\\x47\\xec\\x32\\x79\\xd9\\x7e\\xa2\\x74\\xce\\x68\\x8a\\x44\\xcf\\x59\\x4a\\x39\\x0e\\x45\\x68\\x94\\x4b\\xa5\\x48\\x5a\\x24\\x9a\\x67\\x7e\\x30\\xa2\\x18\\xd4\\x29\\xa0\\xa0\\xf2\\xc4\\x80\\x7c\\xb9\\x32\\xe3\\x79\\x58\\x3e\\xcd\\x4e\\x4b\\x86\\x80\\x60\\x60\\x6d\\x0e\\x01\\xdc\\x3a\\xcd\\xf4\\x8a\\x98\\x57\\x4e\\x2c\\xae\\x6a\\xae\\x34\\x89\\x12\\x0e\\xd2\\x1a\\x9e\\x88\\x15\\xab\\x30\\xde\\xd0\\xc9\\x6a\\x61\\x67\\xaa\\xec\\x54\\x45\\x0c\\x6a\\x6b\\xa6\\x15\\x81\\x04\\xe1\\x72\\x40\\x3b\\x54\\xcc\\x95\\x55\\xf3\\xd5\\x90\\x50\\x87\\x56\\x85\\x84\\x76\\x33\\x05\\x52\\x3b\\xc9\\x82\\xa3\\xdb\\x8f\\x82\\xe1\\x02\\x94\\x4e\\x87\\xe0\\x6b\\x6b\\x75\\xb0\\x68\\x26\\xa1\\x73\\xbf\\x39\\x87\\x95\\x24\\xf9\\x52\\xa1\\xb0\\x3d\\x1c\\x6a\\xc7\\x00\\x16\\x40\\xb0\\xa5\\xd9\\x03\\x2c\\x62\\x46\\xbe\\xd2\\x1b\\x76\\xfd\\x83\\x6f\\x7a\\x4d\\xf3\\x39\\xd3\\xbe\\x8d\\x59\\xd3\\x2c\\xf2\\x6a\\xf2\\x49\\x88\\xa7\\x1b\\x1a\\x22\\x25\\xc9\\x80\\x3a\\xb6\\x1b\\x4a\\x50\\x99\\xb4\\x09\\xb0\\x17\\x67\\x68\\x71\\xca\\x36\\xdd\\xe0\\x14\\x23\\x4c\\xde\\x2c\\x5b\\xe8\\x64\\x34\\x62\\x8a\\xec\\x9d\\x4c\\x0e\\x87\\x64\\x72\\x72\\x64\\x33\\x34\\xe5\\x6c\\x53\\xa1\\x70\\x09\\xa8\\x6c\\x95\\xc4\\x4d\\x0f\\xf2\\x10\\x68\\xc1\\xf0\\x41\\x71\\xa5\\x7d\\xf6\\xc4\\xeb\\x57\\xd0\\x17\\x67\\x13\\x07\\x00\\x95\\xcb\\xe3\\xba\\x13\\x85\\x2d\\xbe\\xac\\x4f\\xc8\\x6c\\x05\\x54\\x68\\xec\\xe6\\x63\\x65\\x41\\x9f\\x03\\xf6\\x71\\xbf\\xf0\\x13\\xb1\\x54\\xb2\\x9d\\x7b\\x5c\\x44\\x1d\\x18\\x2c\\xc8\\x6b\\x6d\\xbf\\xaa\\xf4\\x1f\\x11\\x36\\xbb\\xa6\\x51\\x56\\x4d\\x2b\\x0b\\x29\\x50\\xc5\\xde\\x32\\xa5\\xe8\\x9c\\x4d\\x1a\\x86\\xb7\\x6e\\xf2\\x03\\x40\\x84\\xab\\x64\\x07\\xc0\\x80\\x92\\x4a\\xef\\xb5\\x30\\x5b\\xb8\\xaa\\x7c\\x93\\x14\\xe7\\xe4\\x77\\xd6\\x55\\xce\\xb5\\x66\\xc0\\x4a\\x00\\x4d\\x0f\\x16\\xbb\\x5e\\x6c\\xbf\\x5b\\xcb\\x39\\x7e\\xeb\\x06\\x29\\x7f\\x6c\\x54\\x09\\x11\\x63\\x06\\xf0\\x94\\x91\\x69\\xce\\xd9\\x8c\\xcc\\x38\\xa4\\x15\\x43\\xa2\\xef\\x10\\xc1\\x95\\x28\\xfa\\x9e\\x94\\x62\\x39\\xb6\\x5b\\x42\\x0b\\xca\\xcd\\x6b\\x4c\\x7e\\xb1\\x13\\xd3\\x79\\x21\\xb0\\x9d\\x96\\x55\\xee\\xa1\\x5c\\x94\\xcf\\xc8\\x1c\\x12\\x85\\xad\\x8d\\xf2\\x97\\x17\\xff\\xf8\\x1b\\x99\\xae\\x8c\\x22\\x05\\x1b\\x52\\x4b\\x4d\\x13\\xff\\x92\\x09\\x13\\x73\\x43\\x2b\\x14\\x0a\\xd5\\x82\\x47\\x4f\\x01\\x68\\x88\\x82\\x13\\x7f\\xf9\\xcd\\xe5\\xb4\\xaa\\xd9\\xed\\xc7\\x6c\\xb9\\x1f\\xd0\\x6f\\x94\\xc8\\xf9\\x98\\x1c\\xfa\\xfa\\xc2\\x22\\x8b\\xc1\\xcf\\xdf\\x1c\\x0b\\xbb\\xbb\\x6d\\xd6\\x0d\\x20\\xbc\\x43\\xf9\\x22\\x0b\\x79\\x85\\x16\\xe6\\x86\\xdd\\x53\\xd6\\x4e\\x65\\x32\\x2b\\x12\\x0c\\x75\\xbc\\xf6\\xa5\\xc2\\x85\\x62\\xeb\\x05\\x7d\\x1b\\xcf\\x05\\x38\\xe7\\xed\\x10\\x35\\x3e\\x6a\\xf3\\xc3\\xdd\\x23\\xa5\\x2d\\x80\\xb1\\xee\\x63\\x0f\\xf6\\x05\\xcc\\xe4\\x35\\x4d\\x92\\x29\\x8d\\x2e\\x2f\\xe4\\x1b\\x39\\x57\\xef\\xc4\\x71\\x9e\\xcb\\xbc\\x3a\\x97\\x84\\x1a\\x19\\xbd\\x28\\xc4\\x25\\x36\\xc1\\xf0\\x70\\x08\\x72\\x6e\\x13\\x08\\x1c\\x7a\\xf6\\xa6\\x17\\xc6\\xda\\x78\\x27\\xfa\\x9d\\xf1\\x5d\\x8e\\xc2\\xae\\x79\\x69\\x61\\x0b\\xc2\\xcc\\xf3\\x71\\x47\\x86\\xe3\\xab\\x70\\xb3\\x7d\\xf3\\xe2\\x2f\\x7f\\xc7\\xad\\x4b\\x64\\x4e\\xfe\\xfe\\x02\\x6a\\x08\\xd4\\x10\\x0f\\x31\\x48\\x54\\xa3\\x9e\\xa4\\x34\\x49\\x0c\\x23\\x0f\\x37\\xa5\\x21\\xf4\\xa6\\x4d\\xf8\\xe0\\x7b\\x50\\xb7\\xdf\\x6e\\x77\\x56\\xe0\\x2f\\x2e\\x7e\\xc5\\xbe\\x01\\x5a\\xb1\\x64\\x36\\xc4\\xd2\\x29\\x6f\\x4c\\xef\\x82\\x3a\\xb2\\x6b\\xb9\\x0f\\xd4\\xaf\\x6d\\x81\\xda\\xbd\\x94\\x49\\x91\\xb2\\x23\\xb6\\xe4\\x5d\\x74\\x31\\xac\\x8c\\xe6\\x1c\\x4c\\x09\\x57\\x20\\x07\\xa7\\x89\\x8c\\x2e\\x49\\x6c\\xbf\\x0c\\xb2\\xaa\\xea\\xa8\\xdf\\x4f\\xb7\\x21\\x6d\\xf8\\xfe\\x95\\x8c\\xb2\\x94\\x66\\x99\\xd1\\x01\\xa0\\x40\\x33\\xa7\\x57\\x15\\x62\\x94\\xfd\\x28\\x9e\\x7e\\x43\\x5a\\x7c\\x23\\xc3\\x37\\x1b\\x0f\\xd1\\x38\\x0d\\xad\\x7d\\x64\\xa4\\x9c\\x7d\\x47\\x8d\\x09\\xcb\\x01\\xdd\\x69\\xc8\\xe0\\xdf\\x58\\xe5\\xb4\\xa6\\x98\\x7b\\xd4\\x4a\\xbf\\x31\\x50\\x01\\x30\\xdb\\x07\\x58\\xf2\\xa3\\x35\\x4e\\x25\\xad\\xd3\\xe9\\x2a\\x74\\x11\\xb7\\x74\\xf7\\xa3\\x24\\x63\\xb9\\xe2\\xca\\xc8\\xe5\\x9f\\xe1\\x40\\x61\\x5b\\xc7\\xd2\\xf1\\xfc\\x38\\x44\\xc0\\xc3\\x0d\\x50\\xc9\\xed\\x39\\xa5\\xb1\\x53\\x70\\x40\\x60\\x85\\x08\\x13\\xbd\\x41\\xad\\xad\\x6a\\xb5\\xe7\\xc5\\x14\\xf6\\x0f\\xdc\\x7e\\x9f\\x56\\xb1\\x1d\\x4a\\xe2\\xc7\\xe6\\xb1\\x3f\\x97\\xcb\\x50\\x65\\xb1\\xe6\\x13\\xcf\\x63\\xf1\\xae\\xe7\\xc4\\x59\\xe1\\xfd\\x9e\\x2a\\x63\\xf5\\x93\\xef\\x88\\x7f\\x00\\x47\\xb5\\x8b\\x5b\\x65\\xa1\\x15\\xab\\x13\\x4f\\x58\\x60\\x0b\\x58\\x03\\x72\\x4c\\x30\\x69\\xc3\\x9c\\x09\\xfb\\x53\\xb2\\xfb\\x6a\\xf7\\x51\\xb9\\x2b\\x92\\x28\\x97\\x19\\x9d\\xb7\\x6a\\xf8\\x53\\xa3\\x54\\x7d\\xd8\\x10\\x6e\\xc2\\xd8\\x4f\\x01\\x2b\\xc9\\xec\\x5d\\x86\\x93\\x38\\x34\\x1d\\xc0\\x4a\\xc2\\x60\\xbe\\x23\\xb0\\xb5\\x2c\\x10\\x77\\xea\\x8a\\xae\\x08\\xcd\\x65\\x21\\x62\\xeb\\x0e\\xf5\\xfe\\xe8\\xb7\\xb5\\x07\\x9f\\x4a\\xc1\\xca\\xc6\\xab\\xd5\\x96\\xc5\\x10\\x80\\xe2\\x82\\xbc\\x1c\\xbf\\x7c\\xf1\\x5c\\x44\\x1c\\xb6\\x15\\xab\\x8a\\xb8\\x53\\x2f\\xe2\\x90\\x3f\\x3d\\xea\\xbb\\x3a\\x58\\xfc\\x8e\\xde\\xf7\\xad\\xf5\\xcd\\x94\\xa8\\xf7\\xdc\\x61\\x6a\\xc3\\x47\\x57\\x39\\xd7\\x2c\\xe8\\xaf\\xb8\\x07\\x16\\x8f\\x31\\x2c\\x03\\xcc\\x89\\xc1\\xa6\\x76\\x13\\x2d\\x89\\xd4\\x0e\\xe4\\x43\\x15\\xd3\\x2f\\xc8\\xb7\\x2c\\x83\\x82\\xe3\\xb6\\xc9\\x35\\xa6\\x6e\\x61\\x61\\x21\\xa1\\x76\\x76\\xc8\\x1e\\xde\\xb9\\x8b\\x95\\xf9\\x83\\x47\\xdd\\x5a\\x96\\x68\\xc7\\xd7\\x59\\x0b\\x20\\xce\\x1a\\x08\\x44\\x46\\xc1\\x79\\x97\\x75\\x48\\xc1\\x7f\\xb1\\x05\\x5d\\x32\\x40\\x24\\xe0\\x09\\xcd\\x13\\x08\\x91\\x9f\\xe3\\xdc\\xc9\\xb4\\xd0\\x84\\x89\\x25\\xcf\\xa5\\x00\\x3f\\x31\\x94\\x6c\\x4c\\x13\\x16\\xb6\\x17\\xff\\x6a\\xef\\xe7\\x83\\x33\\xc8\\xbf\\x19\\x60\\x5b\\x15\\x37\\xcb\\x42\\xb9\\x36\\xee\\xe1\\x4c\\x82\\xe1\\x3e\\xbb\\x7c\\x6e\\x1e\\x86\\x86\\xc0\\x73\\xdd\\xbc\\xcc\\x73\\xd2\\x42\\x17\\xd8\\xbb\\xe5\\x3a\\x4a\\x0a\\xc5\\x97\\x8f\\xc5\\x49\\x2c\\x54\\xc4\\x11\\x6f\\xb4\\xce\\x35\\xd8\\x8a\\x92\\x50\\x6b\\x08\\x14\\x65\\x98\\xe0\\x33\\x38\\xd7\\xbb\\xca\\x57\\xb2\\x86\\x29\\x1b\\xd6\\x67\\x45\\x52\\x3e\\x5f\\x68\\x9b\\xed\\x59\\x8b\\x1c\\x04\\x21\\xa8\\x14\\xdc\\xbc\\x8f\\xe9\\xbd\\x32\\x62\\xf7\\x20\\xe1\\x54\\xdd\\x57\\xe5\\x5a\\x2b\\x97\\xb4\\xa3\\x40\\xa2\\x87\\xb0\\x68\\x79\\x34\\xf1\\x4e\\x19\\xf3\\x20\\xf4\\x54\\x9e\\x4c\\x6c\\x04\\xcd\\xd1\\x8d\\x8b\\xff\\xc1\\xc4\\x1a\\x6f\\x96\\x60\\xa2\\x0c\\xfe\\x04\\xdd\\x8d\\x33\\x12\\xc0\\x05\\xb9\\x84\\x12\\x60\\xfe\\xd0\\xa2\\x00\\x2c\\x12\\x21\\xc5\\x68\\x11\\xc0\\x39\\x65\\x32\\xbe\\x67\\x29\\x61\\x53\\xc3\\xa3\\x91\\xc9\\xb1\\x99\\x82\\x64\\x21\\x93\\xd8\\x75\\x0f\\x47\\x5f\\xce\\x94\\xe9\\x2b\\xc6\\x04\\x39\\x99\\x00\\xfd\\xcc\\x2b\\x62\\x39\\xd7\\x66\\x2a\\x62\\x58\\xc1\\xb7\\xad\\xdf\\x44\\xcf\\xfb\\x6e\\xb0\\x16\\x56\\x49\\x1b\\x95\\xde\\xbf\\x69\\xeb\\x33\\xff\\xa3\\xa7\\x99\\xcb\\xc8\\xa6\\x53\\xb9\\x64\\x40\\xd2\\x38\\xce\\x99\\x6a\\x01\\x7c\\xf4\\x08\\x76\\x6a\\x2b\\x56\\xca\\x1b\\xf5\\xcf\\xa9\\x06\\x46\\x3c\\xd9\\x9c\\x6b\\x09\\xd4\\x77\\x38\\xaa\\xb0\\xf1\\x1e\\x98\\x83\\x9d\\x4c\\x0e\\x5b\\x70\\xaf\\xdd\\xf7\\x36\\x2e\\x62\\x86\\xda\\xdd\\x55\\x84\\x67\\x51\\x19\\x73\\x1d\\x93\\x32\\xdc\\x18\\x14\\x4a\\xa0\\xc6\\x78\\xbf\\x58\\x57\\x53\\x35\\x31\\x60\\x6a\\x2d\\x99\\x34\\x11\\x38\\x8c\\x61\\x2b\\xb6\\x14\\xdb\\xba\\x73\\x20\\xe8\\x00\\x6d\\x8a\\x2b\\xd4\\x50\\xee\\x17\\x21\\x41\\x5c\\xb2\\x04\\x32\\x79\\x9b\\x3a\\x32\\xf4\\x49\\xc8\\x35\\xc6\\x04\\xae\\x77\\x97\\x7e\\x18\\x70\\xf1\\x35\\x62\\x3e\\x18\\x2d\\x27\\x27\\x47\\x5d\\x6e\\x97\\x8c\\xc7\\x5b\\xb7\\x5d\\xde\\xab\\x7b\\x97\\xf4\\xdf\\xfe\\x92\\x80\\xe9\\xf7\\xb9\\xb7\\xc4\\x60\\x93\\x85\\xe9\\xb3\\x7f\\x43\\x9a\\xba\\xd4\\xc4\\xb6\\x4f\\xf4\\x99\\xb0\\x9b\\x12\\x3a\\x80\\x8b\\x54\\x9f\\x34\\x34\\x7f\\xcf\\x8a\\x04\\x36\\x69\\x99\\xdc\\xeb\\x33\\x93\\xa9\\xcf\\x0b\\x05\\x6d\\x80\\x2e\\x29\\x4f\\x40\\x7b\\x0e\\x0a\\xf7\\xd6\\x86\\x74\\xe1\\xf7\\x44\\xd2\\x18\\xcb\\x3d\\x2e\\x59\\x2e\\x58\\x42\\x52\\x19\\x17\\x09\\x7a\\xf3\\x7c\\x9b\\xde\\xb7\\xef\\x8e\\xde\\xbf\\x39\\x76\\x49\\x58\\xac\\x5c\\xce\\x21\\xa1\\x44\\xb0\\x2b\\x18\\x5d\\x80\\x42\\x12\\x59\\xe0\\x2e\\x5f\\xf6\\x63\\xce\\xd3\\xb9\\x4d\\xcb\\x40\\x33\\x14\\x1d\\x13\\xee\\x85\\x52\\xae\\xf9\\x9c\\xea\\x4a\\x4b\\x5b\\x32\\xcd\\x19\\xbd\\x94\\x85\\x26\\xcb\\x22\\x11\\x2c\\x2f\\xdb\\x4c\\xb2\\x25\\x13\\xe8\\x83\\x35\\x3f\\x30\\x8f\\x0d\\xb1\\x1a\\x79\\x5e\\x41\\xc8\\xb4\\xc0\\x69\\xe6\\x55\\xcc\\x58\\x34\\xb2\\x9a\\xbc\\x2d\\x31\\x82\\x2f\\x83\\x1e\\xcb\\x95\\x4e\\x8c\\x55\\xa7\\x09\\x4d\\xb2\\x05\\x1d\\x61\\x9b\\x0e\\x0b\\xad\\x06\\xb4\\x5e\\x48\\x21\\x73\\x0c\\xab\\x61\\x39\\xb1\\x3d\\xf8\\xd8\\xc7\\x0f\\x86\\x73\\xe8\\x92\\x98\\x46\\x73\\xee\\x32\\x60\\x6c\\xe2\\xcb\\xc3\\x1d\\x87\\xfb\\xbb\\x5b\\xaa\\x15\\xa2\\x55\\xf8\\x16\\x3b\\xa0\\x93\\x7d\\x13\\x19\\xdf\\x60\\x35\\x94\\x7a\\x17\\xdc\\x1f\\x76\\x9e\\xd6\\x92\\x50\\x82\\xee\\xf6\\x91\\x83\\xbf\\x81\\x4c\\xd9\\x26\\x6c\\xf0\\xde\\x42\\x13\\x2c\\x8f\\x49\\x91\\x24\\xe7\\x2c\\xca\\xd9\\x7d\\xc3\\x0c\\x55\\x4e\\x71\\x52\\x1b\\xeb\\x26\\x0b\\x20\\x30\\x67\\x01\\x13\\xc4\\xde\\x2c\\x4a\\xfc\\x81\\x20\\xcf\\xa9\\xac\\xc5\\xcd\\x8a\\x04\\x52\\xc3\\x01\\x82\\x1e\\x09\\x0e\\xb3\\x57\\x41\\x4c\\x97\\x2b\\x97\\x65\\x86\\xdc\\xa7\\xb2\\x0a\\x8a\\xf9\\x87\\xf9\\x1e\\x66\\x54\\x29\\xcc\\x3c\\xe0\\x22\\xe6\\x4b\\x1e\\x17\\x34\\x81\\x07\\x81\\x51\\x66\\x13\\xb6\\xa8\\xc5\\xfb\\xc6\\xb3\\x9c\\x3a\\x94\\xe0\\xfb\\xe6\\x30\\x97\\x67\\x72\\x1f\\xe7\\xfd\\x27\\x9c\\xde\\x8a\\x8b\\xf9\\x08\\x3e\\x31\\x0f\\xb6\\x33\\x1c\\x49\\x31\\xa2\\x23\\xb3\\x6d\\x9e\\x88\\xdd\\x02\\x38\\xf7\\xef\\xc0\\x30\\x38\\x73\\xeb\\xeb\\xd8\\x90\\x22\\x4c\\xc8\\x62\\xbe\\x00\\x62\\xe5\\x29\\x75\\x50\\x9a\\x09\\xd3\\x80\\x92\\x68\\xf3\\x19\\x30\\x89\\xcd\\xfe\\x36\\xb6\\x56\\x46\\x88\\x1a\\x59\\xdd\\x1b\\x4f\\xc4\\x76\\x69\\xea\\xe0\\xad\\x25\\xe3\\x07\\x6c\\xc6\\xd2\\x48\\xdf\\x7b\\x07\\xca\\x25\\xcb\\x97\\x9c\\x5d\\xed\\x5b\\xcd\\x6f\\x64\\x64\\xc2\\x08\\x29\\xa2\\xf6\\x81\\xb0\\xfb\\x7f\\x42\\xeb\\xe8\\xe2\\xdd\\xd1\\x3b\\xe8\\xdc\\x6d\\xbd\\xee\\x4e\\x54\\x19\\x51\\xa0\\xc6\\x84\\x66\\xfc\\x67\\x96\\x2b\\x00\\x55\\xbe\\xe4\\x22\\x1e\\x92\\x82\\xc7\\xdf\\x3f\\x60\\xc2\\x17\\x17\\xbc\\xcc\\x62\\x6d\\xc5\\xb5\\xde\\x58\\xae\\x64\\xab\\xe8\\xf9\\x7f\\x70\\x7b\\x06\\x12\\x74\\xca\\x12\\x29\\xe6\\x01\\x06\\x00\\x48\\xf3\\x13\\xc1\\xf5\\x5a\\x93\\x63\\x44\\x3a\\x05\\x0f\\x8f\\xcc\\x63\\xc8\\x15\\xe6\\x32\\xaf\\x84\\x33\\xcc\\x78\\x80\\xff\\x18\\x64\\x1c\\x1b\\x96\\xc6\\x2b\\xe3\\x41\\x1a\\x97\\x2a\\x75\\x24\\x4c\\x04\\x72\\xe5\\xc2\\x0e\\x1d\\xdb\\xe1\\x4a\\xa2\\x2c\\x5e\\x50\\x11\\xc3\\x9f\\x51\\x24\\xf3\\xd8\\xce\\x97\\x6b\\x9f\\xde\\x8c\\xc9\\x70\\x98\\x81\\x05\\x62\\x08\\x1b\\x7a\\xd4\\x9f\\x0c\\x6a\\x5a\\x9e\\x56\\x52\\x61\\x9d\\xd6\\x5e\\x08\\xfe\\xef\\x82\\x11\\x9a\\x4a\\xc3\\x88\\xeb\\xcd\\x12\\x6a\\x14\\x49\\xe9\\x0a\\x64\\x21\\x4c\\xf5\\x8d\\x2b\\xd7\\xb0\\x35\\xb6\\x6a\\x48\\xce\\x98\\x51\\xba\\x4a\\x98\\x80\\x21\\x79\\x53\\xc5\\x0d\\x18\\x9a\\xb9\\x9c\\x63\\x41\\xb3\\xfd\\x08\\x67\\x9f\\x33\\x25\\x8b\\x3c\\x62\\x67\\x18\\xe3\\x4c\\x5d\\x3e\\xdd\\xfa\\xcb\\x98\\x55\\xd1\\xf4\\x92\\x09\\xf4\\x29\\x19\\xd2\\x40\\x18\\xb7\\xc8\\x61\\x0d\\xa2\\x05\\x8b\\x0b\\x90\\x2a\\xd3\\x15\\x99\\x71\\x6c\\xb0\\x02\\xa2\\x9d\\xcf\\x17\\x4c\\x69\\x67\\x1b\\xed\\x43\\x8e\\x5a\\xd9\\xab\\xce\\x4d\\x00\\xb6\\x6f\\x90\\xcc\\x5e\\x7a\\x61\\x53\\x0a\\xb0\\xe5\\x70\\x64\\xa9\\x76\\xf5\\x5a\\xa8\\x0d\\xaa\\x22\\x75\\x67\\xb9\\x4e\\x69\\x35\\x26\\x6f\\xcc\\xa3\\x70\\x3f\\x05\\x9d\\x29\\x78\\x8d\\xb8\\x10\\x63\\xb6\\x6e\\x64\\x32\\xa3\\x6a\\x01\\x6d\\x5d\\xea\\x4b\\x60\\x9b\\x3e\\x44\\x45\\x6e\\x18\\x46\\xb2\\x82\\x42\\x4e\\x68\\xc7\\x0f\\xad\\x9b\\xa1\\x73\\xfb\\x26\\xbf\\x63\\xcb\\xfa\\x1c\\x33\\xd9\\x51\\x20\\xef\\x9e\\x8a\\x10\\x3b\\xf0\\xf5\\x16\\x86\\xf0\\x51\\x8d\\x13\\xe0\\x4a\\x1a\\x81\\xe5\\x70\\xdd\\x8c\\xc2\\xed\\x03\\xfe\\x86\\x2b\\x3c\\x9c\\x48\\x6a\\x1e\\xde\\x6f\\x14\\x96\\x6f\\x23\\x01\\x69\\x3e\\x6f\\xef\\xb8\\xdb\\x3d\\xc8\\xe7\\x05\\x1e\\x74\\xcb\\x85\\x4b\\x44\\xfa\\x71\\x2d\\xef\\x1e\\x94\\x29\\x63\\xab\\x1e\\xbe\\x3d\\x0a\\x0b\\xfd\\xc2\\x0a\\x26\\x57\\x26\\x39\\x26\\x3f\\xb7\\x0d\\xb3\\xd4\\xe3\\x2c\\x86\\xa1\\x97\\xc1\\x9b\\xb2\\xef\\x8a\\x61\\x1a\\xc9\\xd2\\x99\\x04\\xfe\\x69\\x4e\\xf3\\xe5\\x22\\x2b\\xb4\\x95\\x84\\x01\\x40\\x57\\xb4\\xa0\\x62\\x0e\\x6e\\x12\\x59\\x98\\xf1\\xbe\\xfa\\x0a\\x66\\x94\\xb3\\xb8\\x88\\x6c\\xd3\\x1a\\xb7\\x6b\\xbf\\x72\\x41\\x07\\x0b\\xa7\\x07\\xec\\x4a\\x45\\x34\\x73\\x73\\x0e\\x5f\\x4b\\xad\\x84\\xa6\\xd7\\xaf\\x08\\x1f\\xb3\\x31\\xd9\\xf9\\x2a\\xf8\\x6a\\x07\\x9f\\x9e\\xe5\\xd2\\x3c\\xc2\\x16\\x18\\xc1\\xac\\x12\\xae\\x21\\xd1\\x67\\x27\\xbc\\x7b\\x4c\\x8e\\xcd\\x33\\x20\\x10\\xeb\\x09\\x18\\xd4\\xc0\\x4c\\x4b\\xf2\\x0d\\x49\\xce\\xe6\\x34\\x8f\\x13\\xeb\\x30\\xbc\\x0a\\x0a\\xa7\\x3c\\xc1\\xd8\\x35\\x57\\x5a\\x59\\x6f\\x41\\x0b\\xe6\\xa4\\xa9\\xba\\x34\\xac\\xc8\\x1c\\xae\\x51\\x4c\\x35\\x1d\\x05\\xa7\\x7a\\x1f\\x4d\\xad\\x91\\x45\\x09\\x1f\\x51\\xbb\\xbb\\x4a\\xae\\xb5\\xff\\x27\\x5b\\x7f\\x3c\\xa2\\xfe\\x2e\\x6e\\x94\\x72\\xc0\\xeb\\x6e\\xae\\xea\\x3c\\x35\\x2f\\x71\\x0b\\xb0\\xf8\\xea\\x01\\x3e\\x2e\\x3b\\x48\\x00\\x0d\\xa0\\x4f\\x51\\xa9\\x32\\x79\\x3e\\x6a\\xf1\\xd0\\x6f\\x38\\xd2\\xc7\\xa7\\x17\\x67\\xbf\\x4e\\xde\\x9d\\x9c\\x5e\\xf4\\x27\\xbb\\x3f\\xd9\\xfd\\xc9\\x6e\\x71\\xb2\\x99\\x58\\xb6\\x3e\\xd5\\xce\\x7a\\xda\\x94\\xb7\\x50\\x87\\x7c\\x0d\\x4a\\xf0\\x9e\\x51\\x76\\xe8\\xb1\\x58\\xfe\\x4c\\x8d\\x32\\x6d\\xfd\\xda\\x36\\xe8\\xba\\x21\\x8d\\xc3\\xde\\x80\\xaa\\xfb\\xe1\\x93\\x4f\\x0f\\x7d\\xc4\\xe4\\xce\\x0e\\x93\\xe6\\x42\\xc7\\xca\\xa6\\x55\\x0b\\x9b\\x70\\x1e\\xfe\\x7e\\x72\\x74\\x7c\\x7a\\x71\\xf2\\xfa\\xe4\\xf8\\xec\\x51\\xb3\\x9d\\x5a\\x82\\xa1\\x56\\xe5\\x72\\x43\\x29\\x99\\xe5\\x6c\\xc9\\x65\\xa1\\x92\\x95\\x47\\x6d\\xdf\\xcc\\x04\\xd6\\x13\\x66\\x45\\x0c\\x1e\\x0f\\x07\\x4c\\xbf\\xf1\\x67\\xbd\\xb0\\xed\\x56\\xd8\\x56\\x93\\xbf\\x5a\\xe0\\x60\\x75\\xb5\\x7d\\x5f\\xe7\\x32\\xed\\x68\\x0b\\x9f\\xa3\\x2f\\xc6\\x05\\xdb\\x36\\xed\\xa7\\x5d\\x0b\\x99\\x53\\x11\\x3d\\x56\\x79\\x2c\\xf1\\x79\\x8c\\x3e\\x9a\\x66\\xba\\x45\\x1b\\x9d\\x4e\\x40\\xb6\\xbb\\xc1\\xa3\\xc6\\x84\\xb3\\xb7\\x34\\xfb\\x89\\xad\\xce\\x58\\x4b\\xb8\\xad\\x2a\\xbd\\x59\\xc2\\x22\\x23\\xe8\\xc8\\x25\\x5b\\x61\\x76\\xf1\\xa1\\x7b\\x58\\x3b\\xd0\\xe8\\x2d\\xc4\\x28\\xbf\\x64\\x6d\\xf0\\xe3\\xbb\\x04\\x17\\xbf\\x64\\x2d\\x32\\xa7\\xdd\\xb5\\x06\\x80\\x6d\\x96\\x10\\xf4\\x34\\xb3\\xa6\\x5b\\x05\\xf9\\xfd\\x05\\xc0\\xd4\\x9f\\x6f\\x1c\\xa5\\x7a\\x75\\xb8\\x0a\\x2e\\x7c\\xdb\\xf1\\x4a\\x60\\x24\\x7d\\x55\\x91\\x5d\\x9e\\x89\\x10\\xac\\x69\\x86\\xbd\\xe9\\x42\\x0f\\x56\\xc9\\xe8\\x88\\x34\\x6d\\xfb\\x70\\x12\\x5c\\xc2\\x6e\\xf9\\xea\\x6e\\xc9\\x58\\x31\\xe7\\xc2\\x03\\x3a\\xc6\\xaf\\x1c\\x06\\x88\\xf2\\xcd\\x33\\xa1\\x6d\\xf3\\xb0\\xfa\\xa7\\x4d\\x6b\\xf9\\x6f\\xff\\x61\\x42\\xa7\\x2c\\x51\\x1f\\x76\\x77\\xbf\\xfb\\xe9\\xf8\\xd7\\x7f\\xee\\xee\\xfe\\xf6\\xdf\\xe1\\xb7\\x20\\x0a\\x31\\xbc\\x5d\\xbd\\x05\\x00\\x4d\\x84\\x8c\\xd9\\x29\\x3c\\x03\\xfe\\xb4\\xea\\xda\\x01\\x86\\x50\\xec\\x17\\x80\\x47\\x30\\xc6\\xd4\\x3b\\xff\\x67\\x26\\xe3\\xfa\\x5f\\xaa\\x15\\xf2\\xe6\\x56\\x0a\\x06\\x58\\xa2\\x16\\xe5\\x71\\x78\\x75\\x27\\x1e\\x4a\\x5e\\xd2\\xf1\\x51\\xb5\\xa3\\xfa\\x7e\\x52\\xd1\\x82\\xa5\\x88\\xfd\\xf7\\xda\\x91\\x00\\x1a\\x61\\x3b\\xe0\\x13\\x01\\x68\\x11\\x46\\x33\\xad\\xc2\\xb0\\xee\\x2c\\x5f\\xee\\x6c\\x95\\x80\\xf1\\x2b\\xd8\\x31\\xc1\\x80\\x22\\x96\\x5a\\x78\\x90\\xbd\\x80\\xf5\\x69\\x2e\\xbe\\x01\\xed\\xc1\\xe4\\x84\\x2c\\x91\\xc2\\x5b\\x43\\x1c\\x17\\xde\\x7c\\xfd\\x45\\x79\\x9c\\x0f\\xa2\\xd6\\xab\\xd2\\x5f\\x61\\x5a\\x99\\xfb\\xde\\x22\\x84\\x28\\x0f\\x15\\xc9\\x8c\\x61\\xb3\\x87\\x1f\\x8e\\xa3\\xac\\x18\\xda\\x1b\\xc6\\x29\\x4b\\x65\\xbe\\xf2\\x7f\\xfa\\xca\\xe4\\x91\\xd2\\x32\\xa7\\x73\\x28\\x0c\\xc3\\x9f\\xe3\\xcf\\xfc\\x5f\\xf8\\xc3\\xca\\x03\\xd6\\x7f\\x8d\\xa6\\x70\\x19\\x4b\\xb5\\x1c\\xb9\\x21\\xd2\\x4d\\x79\\x6d\\x21\\x6f\\x73\\xa4\\xdf\\x12\\xd6\\x16\\xb5\\xc5\\x2b\\xab\\x5e\\xd5\\x0d\\xe9\\x3d\\x71\\xa8\\x70\\x7a\\x2a\\x82\\x3d\\x69\\x2b\\xe6\\x87\\x65\\x16\\x1b\\x78\\x03\\xc4\\xd2\\x58\\x96\\x8d\\x91\\x26\\xcb\\xab\\x43\\x6e\\x16\\xf3\\x25\\x57\\xb2\\x45\\xf9\\x9b\\x1f\\xe8\\xe6\\x8c\\x47\\x0b\\xda\\x83\\x59\\x5c\\xde\\x6d\\x76\\x9d\\x01\\xb8\\x9e\\x3f\\xaf\\x35\\xb6\\xff\\xb2\\x4d\\x17\\x3f\\xbc\\x32\\xaa\\x35\\xcb\\xc5\\x2b\\xf2\\x5f\\x7b\\x1f\\xbf\\xfe\\x34\\x1a\\x7c\\xbf\\xb7\\xf7\\xe1\\xc5\\xe8\\x1f\\xbf\\x7d\\xbd\\xf7\\x71\\x0c\\xff\\xf8\\xf3\\xe0\\xfb\\xc1\\x27\\xf7\\xc7\\xd7\\x83\\xc1\\xde\\xde\\x87\\x9f\\xde\\xfe\\x70\\x31\\x39\\xfe\\x8d\\x0f\\x3e\\x7d\\x10\\x45\\x7a\\x89\\x7f\\x7d\\xda\\xfb\\xc0\\x8e\\x7f\\xbb\\xe3\\x20\\x83\\xc1\\xf7\\x5f\\xb5\\x9e\\x7a\\x07\\x58\\xd7\\x78\\x75\\x89\\x78\\x5d\\x1d\\xb1\\x93\\xed\\xf7\\x05\\xdb\\xbc\\xe0\\xe5\\xb6\\x57\\xd7\\xe7\\xff\\xcc\\x71\\xcd\\x20\\xab\\xc7\\x89\\xeb\\xad\\x39\\xe0\\x98\\x16\\xfa\\x10\\x9e\\x1c\\x7c\\x52\\xb5\\x60\\xcc\\x9b\\x16\\xcf\\x4d\\xce\\xfd\\x11\\x9c\\x3b\\xbe\\x0d\\x2c\\xac\\x6b\\xa9\\x89\\xce\\x72\\x99\\x3a\\x58\\x0a\\x08\\x6f\\x60\\x01\\xa5\\xbd\\xef\\x92\\xb5\\x6a\\x26\\x8e\\x57\\xef\\x0c\\xea\\x9d\\x41\\x37\\x5c\\x9f\\x75\\x06\\x61\\x11\\xc1\\xf6\\x7a\\x82\\x98\\x58\\x36\\x0d\\x61\\x6c\\x8c\\xa0\\x3b\\x5b\\x27\\x04\\x7f\\xbc\\x5b\\x40\\x6d\\xec\\x8e\\x7a\\xd9\\x3f\\xb9\\x4c\\xa6\\x41\\x81\\x96\\x6e\\x8e\\x61\\x92\\x83\\x24\\x21\\x5c\\xe0\\xc1\\x87\\x01\\x7c\\x2d\\x16\\x43\\xd3\\xc6\\x15\\x11\\x2f\\xcd\\x14\\x7c\\xd5\\x55\\x05\\x3c\\x19\\x72\\x8b\\xb9\\x98\\xdb\\xc2\\x28\\x14\\x25\\x36\\xfa\\xc4\\x45\\x09\\x3b\\xed\\x95\\xc3\\xb2\\x57\\x01\\x55\\x4a\\x46\\xd0\\x14\\x0c\\x2b\\xad\\x3c\\x26\\xa5\\x9d\\x36\\xcc\\x46\\xd3\\x4b\\x88\\x36\\x46\\x2c\\x66\\x22\\x62\\xb6\\x8f\\x41\\xa5\\x57\\x34\\x15\\xe4\\x58\\x2c\\x5d\\x2f\\x87\\xb8\\xc0\\x64\\x10\\x64\\x7f\\x9b\\xc7\\x78\\x5e\\x09\\x08\\x66\\x23\\xda\\x20\\x58\\x90\\x87\\x00\\x5c\\xdf\\x5b\\xd8\\x14\\x52\\x31\\xe4\\xac\\xf4\\xb2\\x36\\x6b\\x27\\xdb\\x5a\\x8a\\xb7\\x97\\x99\\x3e\\xb2\\xd5\\x4a\\x19\\x5a\\x13\\x96\\xa5\\xfb\\xb9\\x2a\\x24\\x9f\\x43\\x30\\xb0\\xbd\\xf8\\xfc\\xc3\\x89\\xce\\x8e\\xc4\\x66\\x37\\x22\\xf3\\x1e\\xb1\\x93\\x2e\\xc5\\x64\\x17\\xc1\\x92\\x2c\\x67\\x33\\x7e\\xdd\\xd1\\x39\\x3d\\x08\\xea\\x09\\x79\\xcc\\x84\\xe6\\x33\\x8e\\x1d\\xb3\\xb3\\x9c\\x65\\x4c\\x80\\xab\\x15\\x4a\\x34\\x0c\\xef\\xb7\\x92\\xb2\\x0c\\x4e\\x6f\\x63\\x32\\x0f\\x2a\\xdc\\xdd\\xb2\\xb2\\xf3\\x4d\\xca\\x7e\\xcf\\xc7\\x48\\xcf\\xc7\\x1a\\x5f\\x0f\\xc4\\xc7\\xec\\xce\\xdd\\x1e\\x26\\x06\\x99\\xe7\\xed\\xb3\\xdf\\x0f\\xab\\xa9\\xec\\xb6\\x8b\\x7b\\xdb\\x12\\xe2\\x5a\\x81\\xbe\\x67\\x8d\\x5a\\x62\\xf2\\x1a\\xd6\\xb1\\xe5\\x04\\x6b\\xf6\\x51\\x6f\\x22\\x29\\x15\\x74\\x8e\\xad\\x28\\xb4\\xf4\\xe0\\x55\\x32\\xf7\\xed\\xc4\\xea\\x79\\xf7\\xa0\\xc7\\xbb\\x12\\x2f\\xf8\\x32\\x97\\x49\\xc2\\x72\\x45\\x12\\x7e\\xc9\\xc8\\x11\\xcb\\x12\\xb9\\x4a\\x6d\\xee\\x6b\\x4c\\xce\\x35\\xd5\\x66\\x57\\x9f\\x33\\xdd\\x2c\\xec\\xdb\\x0e\\xd5\\xc6\\x55\\xa1\\x77\\x84\\xfd\\x8f\\x65\\xed\\x50\\x14\\x4e\\x32\\x5b\\x41\\xf9\\x4e\\x00\\xd3\\x38\\x80\\xce\\x46\\x43\\x72\\xca\\x96\\x2c\\x1f\\x92\\x93\\xd9\\xa9\\xd4\\x13\\xd4\\xbe\\xab\\x09\\x77\\x78\\x23\\xe1\\x33\\xf2\\xca\\xd8\\x75\\x4a\\x13\\x8d\\xdd\\x65\\x82\\x02\\x75\\x99\\x57\\x06\\x28\\x71\\x0b\\xbb\\xa8\\xcf\\x5b\\xaf\\x3d\\x87\\x91\\x7c\\xe5\\x79\\xa3\\x48\\x46\\xab\\x65\\xf2\\xed\\xbb\\x5a\\x2f\\xd0\\x01\\xd6\\x93\\x96\\x50\\xd6\\xc1\\xfe\\x46\\x5c\\x05\\x87\\xc4\\x07\\x56\\x20\\x17\\x24\\x67\\x2a\\x93\\x42\\xb1\\x2a\\xcc\\xa8\\x9f\\x11\\x5a\\xbb\\xdd\\x62\\x18\\x37\\x16\\x9e\\x6d\\xc5\\x66\\x26\\x95\\x86\\x12\\xda\\x6e\\x9a\\xc2\\x4d\\xdc\\x70\\x50\\x91\\x4c\\x93\\x84\\xc5\\x95\\xae\\x80\\xd8\\xcd\\x8a\\x56\\x3d\\x04\\x16\\x0d\\xc5\\xf7\\xb7\\xc1\\x42\\xe5\\x4a\\x8d\\x73\\xe5\\x7e\\xdf\\x61\\xd2\\xf5\\x70\\x72\\xed\\xc5\\x6f\\xaa\\x6c\\x2e\\x0f\\x26\\xc8\\x91\\x60\\x03\\xac\\x01\\x9e\\x03\\x0c\\xbe\\x0a\\x1a\\x41\\x2d\\xa4\\xbc\\x24\\x91\\x4c\\xb3\\x04\\x8e\\x4e\\x8b\\x93\\x55\\xf6\\xa1\\xf3\\x5b\\x69\\x64\\x46\\x57\\xfb\\x41\\x8b\\x3a\\xf8\\xa0\\x5d\\x87\\xba\\x56\\x8a\\x58\\x17\\x6a\\x18\\xbb\\x66\\x51\\x67\\x3d\\x6c\\x8f\\xaf\\x59\\x14\\x34\\x61\\x06\\x48\\xb6\\xc8\\x21\\x44\\x98\\x13\\xdb\\xbe\\xb7\\x7e\\xeb\\x90\\x43\\x57\\x6e\\xfe\\x16\\xb5\\x74\\xe1\\x55\\x43\\xb1\\x84\\x31\\x1d\\xda\\xbf\\x7d\\x04\\x34\\x4e\\x01\\x5b\\x08\\xeb\\xeb\\x42\\x18\\x0d\\xbf\\x19\\xf1\\xe8\\xad\\x41\\x5f\\xfa\\x44\\x6a\\x37\\x16\\xb4\\x48\\x93\\x52\\x93\\xbd\\xdd\\xfd\\xdd\\xc1\\x9a\\xff\\xb1\\x06\\x19\\x7f\\x11\\xfc\\x92\\x03\\xd4\\x69\\x06\\xb8\\xa1\\x2c\\xda\\x8d\\x87\\x84\\x6b\\x97\\x69\\x8d\\x70\\x4f\\x30\\x2b\\x5b\\xf4\\x37\\x24\\x4a\\x12\\x9d\\xd3\\x98\\x5b\\x35\\x06\\x3e\\x35\\x37\\xe9\\xbc\\xb0\\x5c\\x7e\\x6f\\xf7\\xd3\\xae\\x6d\\xed\\x75\\x25\\xc5\\xae\\x86\\xe9\\x8f\\xc9\\x05\\xe2\\xc4\\xf8\\x81\\x56\\xb2\\x00\\x5c\\x28\\x24\\x41\\x96\\xf0\\x88\\xeb\\x64\\x05\\x1c\\x8b\\xc8\\x02\\x31\\xa9\\x8c\\xbc\\xb0\\xc5\\x86\\xc7\\xd7\\x5c\\xbb\\xe6\\x3a\\x72\\x46\\x5e\\x60\\x77\\x3d\\xc4\\x70\\xa2\\x0a\\x3a\\xac\\xef\\x2f\\x18\\x4d\\xf4\\x02\\x93\\x44\\x84\\x14\\x23\\x6c\\x90\\x6a\\x58\\x89\\xfd\\xa6\\x6d\\xbc\\xa4\\x9d\\x3b\\x31\\xbc\\x5a\\xb8\\x16\\xd7\\x27\\xd4\\xd2\\x72\\x30\\x4c\\xf4\\x87\\xe6\\x5d\\xdb\\xc9\\x1a\\x7a\\xdd\\xc5\\xc5\\xe4\\x87\\x4a\\xdf\\x76\\xe0\\xe2\\x5a\\x67\\x2e\\x75\\x07\\xbc\\x01\\x2c\\x9f\\xc9\\x3c\\xdd\\x02\\xde\\xd1\\x4d\\xb0\\xb2\\x55\\x03\\x77\\xd2\\x21\\x0b\\x6b\\xdb\\xc8\\x9d\\x6c\\x46\\x23\\xbc\\x7b\\x07\\x77\\xf2\\xab\\x2c\\x00\\x0c\\x84\\x4e\\x93\\x95\\x47\\x62\\x50\\x4c\\x93\\x1d\\x33\\xd4\\x8e\\x61\\x4f\\x66\\x37\\xfc\\xc8\\x68\\x8c\\x40\\x19\\x4a\\x33\\xda\\x48\\x75\\x0b\\xaf\\xce\\x82\\x68\\xc1\\xdc\\xba\\x95\\x03\\x85\\xd2\\x32\\x25\\x0b\\xfb\\xda\\xd5\\xd2\\x4b\\x7b\\x32\\xc6\\x70\\x7a\\x5c\\x5d\\x53\\xce\\x32\\xe4\\x70\\xf6\\x37\\xcf\\x8e\\x7f\\xad\\xf1\\x0d\\xa4\\x7b\\xa5\\x89\\x47\\x14\\x92\\x2d\\xec\\x11\\xc5\\x05\\x12\\x0b\\x71\\x67\\x3a\\xe2\\xa5\\x1d\\x24\\x3f\\x90\\x0e\\x13\\x20\\x48\\xbb\\x42\\xce\\xfa\\x40\\x10\\xd4\\x6b\\x9f\\xeb\\xd5\\x59\\x4e\\x05\\xe9\\x2c\\x6f\\x80\\x6c\\x72\\xb2\\xda\\x3d\\x83\\xde\\x17\\xf4\\xe7\\x80\\x3b\\xc6\\xc5\\x50\\x23\\x2a\\xa4\\xe0\\x11\\x4d\\xf8\\x7f\\x58\\x8c\\x1d\\xf2\\x31\\x7f\\x0e\\xf4\\x9c\\x88\\x2a\\x36\\x82\\xa0\\xae\\xb0\\x8d\\x3d\\x83\\x6a\\x45\\x73\\x1c\\xb5\\x94\\xa0\\x7c\\x78\\xe4\\x33\\x7c\\x5e\\xfb\\xac\\x0c\\xd2\\x6d\\x4e\\x00\\x69\\x5f\\x90\\x1a\\x5e\\xb7\\x93\\xb9\\x9b\\x2d\\x46\\xba\\xa4\\x40\\xd6\\x41\\x02\\xf9\\x7a\\xfa\\x38\\x82\\x55\\x41\\x81\\x27\\xb2\\x70\\x60\\x46\\x08\\xaf\\xb9\\x35\\xb2\\xcc\\xe8\\x24\\x9d\\xbe\\x3a\\xba\\xe3\\x73\\x22\\x7c\\xef\\x79\\x87\\x25\\xbc\\x4e\\x90\\x20\\xff\\xc1\\xb6\\xaa\\x77\\x4e\\x63\\x27\\xf4\\xa8\\x98\\x33\\xf2\\xd2\\xfc\\xf2\\x6f\\x7f\\xfd\\xeb\\xb7\\x7f\\x1d\\xe3\\xf0\\x3e\\x17\\x42\\x90\\x93\\x83\\xd3\\x83\\xdf\\xcf\\x7f\\x3e\\x84\\x12\\xdc\\xb6\\x54\\xed\\x28\\xd1\\xb3\\xeb\\x34\\xcf\\x4e\\x93\\x3c\\xbf\\x68\\x8a\\x27\\x14\\x96\\xb4\\xe6\\x22\\xd5\\x08\\x03\\x0c\\x19\\xa2\\x88\\x5a\\x0d\\x33\\x40\\xf3\\x43\\xa4\\xdb\\xd0\\x5d\\x6b\\x8e\\xda\\x56\\x9c\\x31\\x1d\\x65\\xe7\\x32\\xba\\xec\\xd0\\x7a\\x3a\\x62\\x59\\xce\\x22\\xf4\\xc6\\x5d\\x1c\\x4e\\x70\\x74\\x63\\xc5\\x9e\\xbe\\xbb\\x28\\x0b\\x1a\\x20\\xeb\\xa7\\x84\\xec\\xfb\\xd1\\xfa\\xeb\\x8c\\xe5\\x7b\\xc9\\x32\\xed\\x1d\\x04\\x53\\x1a\\x5d\\x5e\\xd1\\x3c\\x06\\xff\\x19\\xd5\\x1c\\x00\\x8a\\x11\\x61\\x30\\x67\\xb6\\x59\\x1c\\xa6\\x15\\x22\\x94\\x9a\\x6b\\xc6\\x8d\\xbc\\x1c\\xdd\\x14\\xce\\xe9\\x0a\\x8e\\x31\\x14\\x81\\x33\\xca\\x13\\xf0\\xd3\\xda\\x3e\\xd8\\x98\\x77\\x14\\x65\\xde\\x71\\x18\\x7a\\xce\\x7b\\x13\\xcf\\x5d\\x5b\\x6b\\xe2\\x05\\x7d\\xba\\xef\\x6b\\xed\\xb5\\xcd\\x7e\\xdc\\x62\\x51\\x67\\x45\\x5c\\x5e\\x69\\x99\\xdf\\x8b\\xba\\x0e\\xc6\\xdb\\x5e\\x51\\x97\\xe5\\xec\\x5c\\xcb\\x46\\x7d\\x37\\xc8\\x7a\\x2c\\x06\\x07\\xbb\\x21\\x12\\x33\\x65\\x33\\x69\\x98\\xf0\\x8d\\xa1\\x95\\xb8\\x80\\x43\\x48\\x05\\x94\\x20\\x3a\\xdf\\x99\\xac\\x84\\x4f\\x30\\xef\\xd3\\xa3\\xe4\\x5b\\x78\\xd6\\x7d\\x15\\x62\\xb2\\xba\\x8e\\xe3\\x43\\xf3\\x76\\x2c\\x85\\xd9\\x0d\\xcb\\x5a\\x0a\\xdb\\xef\\x1c\\x3e\\x64\\x3a\\x42\\xff\\x70\\xc0\\xc8\\x01\\x9f\\xd4\\x4e\\xbf\\x1e\\xac\\x89\\x72\\xaa\\x16\\xd8\\x0b\\x9c\\x5d\\x73\\x6d\\xd1\\x5f\\x27\\x32\\xae\\x77\\xf0\\x9f\\xe7\\x34\\x62\\x24\\x63\\x39\\x97\\x46\\x18\\x15\\x42\\xc7\\xf2\\x4a\\x90\\x29\\x9b\\x73\\xa1\\x1c\\x29\\x00\\xa2\\xdd\\xd2\\x0c\\xa2\\x3e\\x5c\\x79\\xf8\\xb9\\x31\\x39\\xab\\x40\\xaa\\xd8\\x62\\xa7\\x48\\x96\\x47\\xd3\\xce\\xb9\\x1e\\xaf\\x02\\x89\\x05\\x74\\x42\\x58\\x7d\\x4f\\xe1\\xb0\\x67\\xd8\\xe7\\xa6\\xbc\\x57\\x08\\x78\\x72\\xcc\\x12\\xba\\xc2\\x9c\\xd6\\x19\\x17\\x60\\x39\\xe6\\x6a\\xd0\\x41\\x5c\\x0b\\xbb\\xde\\xb9\\xef\\x6e\\x9c\\x07\\x57\\x24\\x67\\x34\\x5a\\xb4\\x0b\\x31\\xf7\\x81\\xb0\\x3b\\x5e\\x7d\\x20\\xac\\xcd\\x20\\x7d\\x20\\xac\\x0f\\x84\\x7d\\xe6\\xea\\x03\\x61\\x7d\\x20\\xac\\x76\\x6d\\xad\\x95\\xd4\\x07\\xc2\\x1a\\x5f\\x7d\\x20\\xec\\xf6\\xab\\x0f\\x84\\xdd\\xe1\\xea\\x03\\x61\\x77\\xbc\\xfa\\x40\\xd8\\xcd\\x57\\x1f\\x08\\x6b\\x37\\x99\\x3e\\x10\\xd6\\x07\\xc2\\xec\\xf5\\xc7\\xf3\\x0e\\xba\\xab\\x0f\\x84\\xad\\x0d\\xd2\\x07\\xc2\\xfa\\x40\\xd8\\x9d\\xaf\\xad\\x35\\xf1\\xfa\\x40\\x18\\x5e\\x7d\\x20\\xac\\x7a\\xfd\\xb1\\x44\\x9d\\x0b\\x23\\x4d\\x8c\\x41\\xd9\\xbe\\x3e\\x6f\\x02\\xa1\\x0b\\x1e\\xd9\\x68\\x94\\x9c\\x55\\x6a\\xba\\xf0\\x51\\xe3\\xb2\\xdf\\x46\\x00\\x71\\xe2\\xca\\x8a\\x6c\\xdc\\xa9\\x8c\\x66\\x6d\\xac\\xfd\\x6a\\xd9\\x13\\x2f\\x93\\x71\\x19\\x0e\\x09\\xe2\\x20\\x68\\x56\\x37\\xaf\\xbf\\x7b\\xb4\\xca\\xb2\\x36\\xc1\\x8f\\x87\\x09\\x7c\\x6c\\x49\\x94\\xa8\\x83\\x60\\x47\\x1f\\xe8\\x78\\x76\\x81\\x8e\\x6e\\x9c\\x84\\x1d\\x38\\x08\\x5b\\x8b\\x0a\\x1b\\xff\\xbf\\x58\\xe4\\x4c\\x2d\\x64\\xd2\\x78\\xa3\\x57\\x36\\xf9\\x5b\\x2e\\x78\\x5a\\xa4\\xd0\\xf5\\xd6\\xec\\x67\\xbe\\xf4\\x89\\x06\\xaa\\x6c\\xab\\x0f\\x1c\\x1b\\x7d\\x95\\x41\\x7b\\x5c\\xd7\\x16\\x17\\x6a\\x51\\x6d\\x9b\\x7b\\x55\\x44\\x11\\x63\\xd0\\x16\\x2e\\xb4\\x70\\xbe\\x1d\\xfb\\x27\\xf9\\x36\\x20\\x2f\\xdb\\xf1\\x9b\\x76\\x42\\x1c\\xa1\\x55\\x61\\x94\\x6f\\xbf\\x69\\x34\\xc6\\x3c\\xcf\\xba\\xe1\\xcb\\x3f\\x9c\\x4d\\x0e\\x03\\xbe\\x4c\\x85\\x63\\xcb\\x5c\\x2c\\x65\\x02\\x54\\xa5\\x78\\x93\\x51\\xd6\\x1e\\x91\\x49\\xb7\\x37\\x3b\\x5a\\x99\\x1c\\x5d\\xc8\\x88\\xb6\\x5a\\x75\\xd5\\x6f\\x66\\x74\\xe7\\xaa\\xe7\\x68\\x0e\\x6b\\x89\\x08\\xfe\\x77\\xd6\\x9d\\x5b\\x73\\xb7\\xf6\\xfa\\x6c\\xfb\\xe3\\x40\\x00\\x62\\x07\\x5e\\xbc\\x33\\x02\\xef\\x9c\\xdb\\xd6\\x55\\x56\\x04\\x87\\x86\\x8b\\xeb\\x6a\\xa5\\x25\\xc9\\x12\\x5a\\xf6\\xa5\\x82\\x15\\xf8\\x11\\xe4\\xc6\\xe1\\x82\\x45\\x97\\x67\\x36\\x46\\xbb\\xa7\\x18\\xf3\\xfa\\xe4\\x9c\\xeb\\x45\\x31\\x1d\\x47\\x32\\xdd\\x37\\xc7\\x18\\xff\\x6f\\x9a\\xc8\\xe9\\x7e\\x4a\\x95\\x66\\xb9\\x51\\x31\\xad\\x58\\x1a\\x45\\x66\\x14\\x2e\\xe6\\xe3\\x34\\x1e\\x8c\\xc9\\x47\\x81\\xd5\\xf5\\x65\\x1f\\xcc\\x00\\x5b\\xc2\\x3c\\xdf\\xe1\\x7c\\x4c\\x99\\xe1\\x88\\x12\\x7c\\x07\\x01\\x84\\x9e\\x99\\xde\\xb8\\x0d\\x50\\x73\\x6b\\x31\\xd2\\x32\\x3e\\xfe\\xf0\\xb1\\xf1\\x9e\\x73\\x91\\x0e\\x9c\\x24\\x4f\\x2d\\x06\\xde\\x59\\x2e\\x48\\x07\\xb1\\xef\\x2d\\x8a\\x7b\\x6f\\x8d\\x3a\\xbb\\x2d\\xb1\\xee\\x2d\\x44\\xbb\\xee\\x20\\xbe\\xdd\\x45\\x6c\\xbb\\xbb\\xb8\\xf6\\x17\\x00\\x85\\x7e\\xca\\xf1\\xec\\x0e\\x9d\\x7e\\x1d\\xc5\\xb1\\x1f\\x22\\x86\\xdd\\xc9\\x5b\\xb7\\x8d\\x5d\\x3f\\x5c\\xdc\\xba\\x9b\\xd7\\xed\\xd2\\xdc\\x78\\xaa\\xb1\\xea\\x0e\\x9c\\xf7\\x5d\\x3a\\xee\\x3b\\x73\\xda\\x7f\\xb1\\xd8\\x74\\xfb\\xb8\\xf4\\x16\\xc4\\xa4\\x5b\\x13\\x99\\x0b\\xae\\x39\\x4d\\x8e\\x58\\x42\\x57\\xe7\\x2c\\x92\\x22\\x6e\\x2c\\xc7\\x6a\\x58\\xa4\\xfe\\xfc\\x28\\x1c\\xd6\\x7a\\xb0\\xaa\\x85\\x1e\\x0b\\x6a\\x21\\xd7\\x8d\\xdd\\x86\\x85\\x2d\\x2e\\xca\\x61\\xd5\\x16\\x88\\x37\\xe3\\x2c\\xb7\\x32\\x6e\\x41\\xb6\\xc6\\x55\\x86\\x55\\x2f\\x5d\\x2e\\xe2\\x8f\\xf2\\x8a\\xc8\\x99\\x66\\x82\\xec\\x71\\xe1\\xd6\\x71\\x10\\x18\\x9b\\xa5\\xdf\\xd2\\x6f\\x6b\\xf3\\xed\\xcb\\x17\\xee\\xe6\\xe7\\xe7\\x90\\x04\\xd7\\xab\\x52\\x5f\\xde\\x3f\\x6c\\x1f\\xf4\\x79\\x07\\xb1\\xbd\\x71\\x56\\x24\\x55\\x27\\x31\\x3a\\x8e\\xab\\xfc\\xe6\\x65\\x09\\x1a\\xfd\\x12\\xc6\\xf5\\xa7\\x8d\\x8a\\x98\\xd8\\x4a\\xb8\\xe7\\xb7\\x68\\xad\\x33\\x6e\\xaa\\xaa\\x9f\\xcf\\xb0\\xf9\\x9c\\x3f\\xf9\\xe2\\x70\\xd2\\xbb\\x93\\xb7\\xcb\\x29\\xf3\\x48\\x59\\x2b\\x5b\\xa8\\xe8\\x3e\\xd1\\x4c\\x95\\x5e\\xd1\\xbd\\xc7\\x15\\xd4\\xc6\\xfe\\x90\\xd3\\x88\\x4d\\x3a\\xd7\\x11\\xdc\\x71\\x22\\x71\\x91\\x53\\xcb\\x00\\xbd\\xca\\xe7\\x0e\\x8f\\x60\\x2c\\xc6\\xd3\\xe4\\xeb\\x89\\xa1\\x52\\x77\\x56\\x24\\xc9\\x0a\\x7d\\x0e\\x95\\xea\\x6b\\x8c\\xc2\\xd7\\x8b\\x79\\xc1\\xf1\\xbf\\xe1\\x29\\xa5\\x62\\x99\\xe5\\xd2\\xca\\xcc\\xbc\\x10\\xc2\\xf0\\xe0\\xb2\\xf3\\x1b\\x28\\x92\\x00\\x46\\x4d\\x2b\\x25\\xc3\\x8a\\xcf\\xcd\\xf4\\x8d\\xfc\\x83\\x6a\\xe2\\x32\\x35\\xb1\\x32\\xa0\\xf9\\xf5\\x4c\\xe6\\x11\\x9f\\x26\\x2b\\xb2\\xa0\\x89\\x6f\\xf3\\x43\\xc9\\x25\\x4f\\x12\\x3b\\xcc\\x98\\x9c\\x33\\x8d\\x81\\x0b\\x94\\x9d\\x89\\x14\\x73\\x98\\x1c\\x15\\xae\\xbd\\x24\\x8b\\xcc\\x6f\\xa3\\x84\\x51\\x51\\x64\\xf8\\x3c\\x23\\x89\\x57\\xb2\\xc8\\xdd\\xf3\\xc6\\x3e\\xfc\\xe1\\x25\\xb0\\xe0\\xc9\\x30\\x68\\x62\\x77\\xeb\\xc2\\x96\\x2e\\x1a\\x65\\x14\\x80\\x77\\x0e\\x7c\\x7b\\x18\\x8e\\xe9\\xf0\\xd1\\x55\\xd0\\xc2\\x28\\xcb\\xe5\\x92\\xc7\\x18\\x43\\x71\\x64\\x83\\x76\\xd9\\xd8\\xa6\\xc8\\x9f\\x67\\x21\\xc5\\x48\\xb0\\x39\\x05\\x45\\xc5\\x9e\\x22\\x5c\\x33\\x1c\\x07\\x73\\x0b\\x44\\x0c\\x8d\\x8b\\x8c\\x86\\x2f\\xb3\\x4a\\x39\\xff\\x92\\x63\\xcb\\xe5\\x80\\x72\\x64\\x4f\\x48\\x22\\x21\\x53\\xb5\\x10\\x5c\\x63\\x1b\\xff\\x45\\xa1\\x49\\x2c\\xaf\\xc4\\xc0\\xfa\\xac\\xb8\\x22\\x94\\x4c\\x99\\xa6\\x41\\xae\\xa9\\x15\\x70\\x8a\\x30\\x41\\xa7\\x89\\x59\\x73\\x48\\xc5\\xba\\xd8\\x48\\x20\\x32\\x63\\x54\\x17\\x39\\x23\\x73\\xaa\\xd9\\x46\\x3d\\x07\\xdf\\xf7\\x76\\xf2\\x72\\x65\\x1d\\xac\\x33\\x52\\x08\\xc5\\x5a\\x8a\\xf7\\xce\\x94\\xa3\\xbf\\xfd\\xa5\\x19\\x8f\\xe0\\x29\\x93\\x85\\x7e\\x10\\xeb\\xef\\x6a\\xc1\\xa3\\x45\\xa8\\xcc\\xf2\\x94\\x29\\x22\\x8b\\x9a\\x59\\xfc\\xd2\\xfe\\x6c\\xf3\\x0a\\xf5\\x26\\xe0\\xa6\\xab\\xa9\\xfb\\x78\\x83\\xf7\\xab\\x0e\\xc7\\x50\\xf6\\xf7\\x86\\x0c\\xf2\\xa3\\xd3\\xf3\\xdf\\xdf\\x1c\\xfc\\xeb\\xf8\\xcd\\x98\\x1c\\xd3\\x68\\x11\\x62\\x72\\x08\\x42\\x81\\x69\\x00\\xa3\\x58\\xd0\\x25\\x23\\x94\\x14\\x82\\xff\\xbb\\xb0\\x61\\xe5\\x3d\\xff\\xdb\\x41\\xa7\\x88\\xf4\\x0d\\xa5\\xaf\\xe1\\x36\\x8d\\x76\\xfc\\xc6\\xa6\\x77\\x30\\x9a\\xcd\\xd8\\x92\\x8a\\x41\\x9b\\x9a\\x35\\xf5\\xc9\\xc7\\xb2\\x57\\x68\\x22\\x80\\xc2\\x05\\x89\\xf5\\x47\\xef\\x8e\\xcf\\x21\\x61\\x3f\\xcb\\x11\\xa9\\x04\\x32\\xbc\\xe0\\x7b\\x18\\x69\\xca\\xcc\\x2f\\x6c\\x7f\\xe2\\x31\\x39\\x10\\x2b\\xfc\\x12\\xcf\\x14\\x57\\x24\\xe1\\x4a\\x33\\x90\\x7a\\x56\\x6d\\x73\\x51\\xf2\\x9d\\x17\\x63\\xf8\\xdf\\x0e\\xa1\\x71\\x9c\\x1b\\xbd\\xce\\x27\\xae\\x45\\x6b\\x99\\xa4\\xa8\\xf9\\xf1\\x69\\x12\\xbc\\x80\\x60\\x1a\\xf3\\xd4\\xde\\xca\\xd8\\xce\\x1c\\x24\\x09\\x44\\xc8\\x50\\x0c\\x2a\\x9d\\x53\\xcd\\xe6\\x3c\\x22\\x29\\xcb\\xe7\\x8c\\x64\\x54\\x47\\x0b\\x92\\xd2\\x15\\x89\\x64\\x9e\\x17\\x19\\x76\\x33\\x88\\xa9\\xa6\\x63\\xf2\\x5a\\xe6\\x24\\x75\\x87\\xd8\\xec\\x79\\x23\\x87\\xcf\\x37\\x67\\x0e\\x94\\x27\\x3b\\xfc\\x27\\x57\\xaa\\x60\\x6a\\xff\\xe5\\x8b\\xbf\\x7f\\xf3\\xd7\\xbf\\x3e\\xab\\x06\\x78\\x3e\\xb5\\x17\\xf2\\x5e\\x82\\x06\\x78\\xd4\\xad\\x02\\xae\\x3a\\x36\\x44\\xe4\\x62\\x9e\\x84\\xfb\\xab\\x99\\x00\\x68\\x6b\\x65\\xb6\\xb5\\x31\\x47\\xe5\\x1b\\x4c\\x9a\\x9a\\x9a\\x9d\\x34\\xe2\\x2b\\xe7\\xd0\\x51\\xfb\\xaa\\x52\\x0e\\x3a\\xc3\\xca\\xf2\\x06\\x19\\x76\\x24\\x3e\\x99\\xb8\\x83\\x69\\xf5\\x9c\\xb4\\xd6\\xc6\\x36\\x2b\\x73\\xa0\\x86\\xe4\\x05\\xf9\\x8e\\x5c\\x93\\xef\\xc0\\xd0\\xfa\\x5b\\xdb\\x66\\x5f\\x6d\\x4d\\xa0\\x2e\\x52\\x9a\\x8c\\x7d\\x7f\\x32\\xe9\\x88\\xe2\\xbf\\x18\\xa6\\x69\\x46\\x34\\x54\\xd5\\x92\\x4c\\xb9\\x55\\xec\\xd9\\xb5\\x66\\xb9\\x51\\x34\\xed\\x4a\\x3c\\x6a\\x9b\\x34\\x33\\xc1\\x07\\xdc\\x66\\x18\\x78\\x38\\x99\\x55\\xd3\\xa8\\xee\\xb7\\xd1\\xcc\\xcf\\x7f\\x94\\x4a\\x9f\\x5a\\x2e\\x54\\x6d\\xf8\\x53\\x8e\\x96\\x02\\xe3\\xaf\\xb0\\x31\\x23\\x37\\x94\\x2e\\x0f\\x98\\x22\\xb1\\x84\\xac\\x2e\\x4c\\x71\\x5e\\xf0\\x16\\xc9\\x1a\\xdb\\xb3\\x8d\\xdb\\xc5\\xef\\x2b\\xeb\\x79\\xdb\\x4a\\xd5\\x5c\\x29\\x60\\x03\\x59\\x15\\x2b\\xc0\\xe8\\xca\\x64\\x6c\\xb5\\x33\\x33\\xad\\x38\\x90\\x19\\xb7\\xa8\\x67\\xd6\\x6b\\xe3\\xfd\\xcd\\xb0\\x97\\xcc\\x79\\x8a\\xa8\\xc0\\x22\\x93\\x19\\xcb\\x73\\xcc\\x4a\\x9f\\xae\\x5c\\x72\\x60\\xeb\\xc5\\x6b\\x75\\x92\\xb2\\x5c\\x6a\\x19\\xc9\\x16\\x9d\\xdc\\xaa\\xd1\\x6e\\x3b\\x1c\\x10\\x21\\xc3\\xbd\\x6b\\x29\\xff\\xfe\\x68\\x32\\x24\\x17\\x87\\x13\\xe8\\x6e\\x75\\x7e\\x78\\x31\\xa9\\xda\\x2c\\x3b\\x17\\x87\\x93\\x9d\\x47\\x25\\x05\\x71\\x0a\\x1f\\xb8\\xa8\\x1b\\x0c\\x52\\x71\\x41\\x19\\x6d\\x72\\x94\\xd2\\x6c\\x74\\xc9\\x56\\x0d\\x65\\x6a\\x17\\x72\\x7d\\xe4\\x57\\xb8\\x93\\x17\\x42\\x32\\xa7\\x34\\xbb\\xf7\\x68\\x39\\xa3\\x31\\x7f\\xa0\\x4a\\x2f\\x97\\x76\\xeb\\x9f\\xb9\\xb9\\xe4\\x2b\\x95\\x4b\\x16\\xa3\\x96\\xee\\x7e\\xc1\\x44\\x9c\\x49\\x6e\\xf4\\xc5\\xbe\\x0e\\xec\\xfe\\xbf\\xee\\xeb\\xc0\\xee\\x7c\\xf5\\x75\\x60\\x7d\\x1d\\xd8\\xfa\\xb5\\x35\\x89\\xb3\\x7d\\x1d\\xd8\\xf3\\x8a\\xe0\\xf7\\x75\\x60\\xf7\\xbf\\x1e\\x3d\\x70\\xdf\\xd7\\x81\\x6d\\xbe\\xfa\\x3a\\xb0\\xbe\\x0e\\xec\\x6e\\x57\\x5f\\x07\\x76\\xff\\x6b\\xeb\\x52\\x8e\\xfa\\x3a\\xb0\\x7b\\x5d\\x7d\\x1d\\xd8\\xfa\\xd5\\xd7\\x81\\xdd\\x70\\xf5\\x75\\x60\\x37\\x5c\\x7d\\x1d\\xd8\\xfa\\xd5\\xd7\\x81\\xdd\\xef\\xea\\xeb\\xc0\\xfa\\x3a\\xb0\\x67\\x9d\\x1e\\x4b\\xfa\\x3a\\x30\\x7b\\xf5\\x75\\x60\\xcf\\x22\\x09\\x90\\xf4\\x75\\x60\\x77\\xba\\xfa\\x3a\\xb0\\xbe\\x0e\\xac\\xc9\\xd5\\xd7\\x81\\x3d\\x17\\xa7\\x4c\\x5f\\x07\\xd6\\xd7\\x81\\xfd\\x71\\x14\\xdd\\xbe\\x0e\\xac\\xaf\\x03\\xeb\\xeb\\xc0\\xfa\\x3a\\xb0\\x5b\\x67\\xd1\\xd7\\x81\\x3d\\x07\\x13\\x30\\x67\\x8a\\xff\\x87\\x4d\\x64\\xc2\\xa3\\x55\\xeb\\x2c\\xc5\\x33\\xdb\\xf8\\x58\\xd9\\x61\\x49\\x06\\xe3\\x06\\xa9\\x55\\x2d\\x2a\\x4f\\xb6\\xac\\xe0\\xe6\\x2c\\x20\\x5c\\x58\\x78\\xe3\\x9b\\x3f\\x7f\\x01\\x12\\x6c\\x45\\xf1\\x8d\\x7b\\xc1\\xd3\\xe6\\x91\\x94\\x91\\x6b\\x40\\x80\\xe4\\x6b\\xe6\\xb7\\x68\\x6d\\x22\\x84\\x2f\\xd2\\x51\\x3e\\xf8\\x6e\\x58\\x11\\xe9\\x77\\x82\\x96\\x9e\\x83\\xf1\\x1b\\x37\\x08\\xcd\\xb2\\x84\\x33\\x35\\x26\\xe7\\xbe\\x01\\x0f\\x70\\x2f\\xf5\\x8a\\x44\\x59\\x31\\x24\\x29\\x4b\\x65\\xbe\\x6a\\x61\\x4d\\x74\\xa0\\x70\\x56\\x56\\xad\\x23\\x92\\x9d\\xe1\\x98\\x8e\\x0c\\xc6\\x88\\xc8\\xb2\\x64\\x85\\xca\\x54\\x59\\x4a\\xea\\xa9\\xc6\\x1d\\x73\\x89\\x41\\xdd\\xa9\\x65\\x79\\x70\\x5d\\x31\\xc3\\x4e\\xa5\\x3e\\xb3\\x1b\\xfe\\xd1\\x72\\xed\\x6f\\xca\\x2a\\xa7\\x5a\\xa6\\x3c\\x6a\\xc2\\xb0\\x91\\xc7\\xb6\\xcf\\x29\\x3f\\x94\\x69\\x56\\x68\\x56\\x61\\xdb\\x48\\x2c\\xd4\\xe4\\xb8\\x0a\\x4d\\xb8\\xf6\\xd9\\xe0\\x91\\x14\\x33\\x3e\\xb7\\xaa\\xf8\\x3e\\x76\\x74\\x1f\\xf9\\xf7\\x19\\x05\\x5d\\xd4\\x9f\\x60\\x2a\\x78\\x94\\x50\\xde\\x3c\\x6e\\x5f\\x4d\\xad\\x3a\\x84\\xb1\\xa0\\x42\\xb7\\x4c\\xae\\x82\\x1c\\x5d\\x4f\\xad\\xa1\\x4f\\x5c\\xe2\\x78\\x4c\\xc6\\xee\\x2b\\xfc\\xf1\\x10\\x33\\x7d\\x8d\\xfd\\x01\\x4a\\xe7\\x86\\x05\\xfd\\x28\\x4a\\xf5\\x58\\x10\\x9a\\x64\\x8b\\xdb\\x15\\x64\\x33\\x91\\xa3\\x95\\xa0\\x29\\x8f\\xdc\\x8e\\x39\\x48\\x12\\x19\\xa1\\x41\\x54\\x55\\x91\\xdd\\xd8\\x38\\x9e\\x79\\x48\\x9a\\x16\\x9a\\x4e\\x13\\x36\\x26\\x27\\x58\\x21\\x24\\x45\\xb2\\x32\\xbb\\x49\\x31\\xed\\x02\\x1f\\x76\\xf9\\x1b\\xe7\\x60\\xb5\\x4f\\xc0\\x68\\x99\\x7c\\xb1\\x51\\x1b\\x82\\x05\\xc1\\x6a\\x28\\x26\\xcc\\x29\\x93\\x82\\x11\\x26\\x74\\xbe\\x32\\x6b\\x37\\x91\\xf1\\xb9\\x59\\xbe\\xca\\xdd\\xad\\x8b\\xa4\\x5a\\xe6\\x5c\\x74\\x91\\x6f\\xd1\\x32\\xd7\\xa2\\x9b\\x0c\\x89\\xf6\\xd9\\x11\\xeb\\x61\\xde\\xa0\\x6e\\x31\\x4c\\x7c\\xac\\xac\\x6a\\x26\\xe3\\xf1\\x86\\x53\\xe9\\x54\\x83\\x89\\x8c\\x8d\\x80\\xcb\\x59\\xd8\\x0a\\xcf\\xda\\x87\\x70\\x40\\x52\\x7a\\x09\\x26\\x36\\xd5\\xa5\\xe4\\xa3\\x4b\\xca\\x13\\x73\\x84\\x36\\xd4\\xe3\\xb7\\x4b\\x9c\\xe8\\x40\\x35\\xe8\\xba\\x18\\x8c\\xb4\\xdd\\x41\\x5d\\x16\\x73\\x11\\xe8\\xdc\\x95\\xf2\\x66\\xe8\\x0f\\x64\\x4d\\xf0\\xbe\\x81\\xb1\\x82\\x74\\x2c\\xb3\\x27\\x52\\x7a\\x0d\\x36\\x2b\\x4d\\x65\\x21\\x34\\x56\\x78\\xa1\\x7c\\xf6\\x4c\\x1f\\x93\\xd6\\xb6\\x4e\\xf2\\x92\\x6e\\xd8\\x0e\\x8d\\x5d\\x09\\xcc\\xa4\\x8b\\x6c\\x72\\xaa\\x35\\xcb\\xc5\\x2b\\xf2\\x5f\\x7b\\x1f\\xbf\\xfe\\x34\\x1a\\x7c\\xbf\\xb7\\xf7\\xe1\\xc5\\xe8\\x1f\\xbf\\x7d\\xbd\\xf7\\x71\\x0c\\xff\\xf8\\xf3\\xe0\\xfb\\xc1\\x27\\xf7\\xc7\\xd7\\x83\\xc1\\xde\\xde\\x87\\x9f\\xde\\xfe\\x70\\x31\\x39\\xfe\\x8d\\x0f\\x3e\\x7d\\x10\\x45\\x7a\\x89\\x7f\\x7d\\xda\\xfb\\xc0\\x8e\\x7f\\xbb\\xe3\\x20\\x83\\xc1\\xf7\\x5f\\x35\\x9e\\x72\\x6b\\x1f\\x75\\x77\\x1e\\xea\\x8e\\xfc\\xd3\\x5f\\xc4\\x3b\\x6d\\xf3\\x38\\x3b\\x3a\\x8b\\x36\\x07\\x7d\\xed\\x34\\x5a\\x0f\\xd2\\x6d\\xa7\\xd1\\x49\\x49\\x30\\x44\\xfc\\x38\\x5c\\x11\\x99\\x72\\x6d\\x0c\\x38\\xa3\\xd6\\xd0\\xb0\\xf2\\xac\\x66\\x9e\\x58\\x3e\\x00\\xb5\\x97\\x14\\x4a\\xc4\\x82\\xaa\\xad\\xc0\\xaa\\x91\\xce\\x15\\x0b\\xe6\\x91\\x20\\x3c\\xcd\\x12\\x96\\x32\\xa1\\xe1\\x3c\\x8f\\x9c\\x26\\x08\\xf6\\xe2\\xb8\\x9c\\x49\\x84\\x1a\\x3b\\xbb\\x8e\\x18\\x8b\\xed\\xc3\\x7a\\xd6\\xf1\\xf9\\xab\\x67\\x1d\\xcf\\x91\\x75\\xb4\\x76\\x5e\\xd4\\xf9\\x46\\x30\\x9c\\x35\\xc6\\x94\\xf3\\xfb\\x80\\x47\\xc3\\x57\\x99\\xc8\\x19\\x44\\x35\\x96\\x3c\\x2e\\x68\\x12\\xe2\\x5a\\x38\\x84\\x85\\x71\\x68\\x2c\\xa5\\x74\\xb5\\x66\\x1b\\x71\\xc1\\x43\\x40\\x8c\\xa1\\x8f\\x3b\\xc1\\x8d\\x56\\x2b\\x28\\xbd\\xdd\\x3b\\x07\\xc9\\x15\\x5d\\xa9\\x1d\\xc4\\x4e\\x12\\x52\\x8c\\x6a\\x03\\x10\\x99\\xbb\\x68\\x55\\xa8\\x7e\\x6e\\x28\\x99\\x59\\x7b\\x99\\x6a\\xc9\\x8c\\x55\\x66\\x77\\x77\\x95\\xbf\\xd3\\xf9\\xb3\\xec\\x0c\\xcb\\xac\\x2d\\xb3\\x2d\\x20\\xd2\\xa5\\x9d\\x35\\x59\\xa5\\x21\\x2d\\x27\\xee\\xdd\\xa5\\xd5\\x79\\x63\\x84\\x0a\\x90\\x28\\xcc\\x97\\x33\\x69\\x5e\\x1c\\x60\\xae\\x66\\x33\\x16\\xe9\\x57\\xb6\\xf6\\x67\\xc3\\x6f\\x30\\xf7\\x45\\x73\\x51\\xd0\\x24\\x59\\x05\\xfd\\x4f\\xa5\\x20\\xec\\x9a\\x6b\\x52\\x08\\xcd\\x13\\x43\\x49\\x92\\xb3\\x79\\x91\\xd0\\xd0\\x1e\\xb5\\x4f\\x74\\x41\\xc8\\x78\\x4c\\xde\\x09\\xa3\\x8f\\xdf\\x72\\xb3\\x11\\x16\\x09\\xd3\\x86\\x8a\\x14\\x8a\\x79\\xab\\xe4\\x87\\x10\\x60\\x65\\x43\\x96\\xaf\\xee\\xe6\\xeb\\xc3\\x58\\x76\\x77\\x94\\x5d\\xb2\\x63\\x3e\\x9b\\x99\\x51\\xa0\\x94\\x5f\\xc8\\x3c\\xa5\\xeb\\x4f\\xb0\\x75\\xc8\\x98\\x87\\x15\\x22\\x71\\x00\\x26\\xdb\\x8e\\xb1\\x1f\\x22\\x9a\\xef\\x84\\xfe\\x80\\x83\\x44\\x2f\\x64\\x31\\x5f\\x6c\\xa4\\xa2\\xd2\\x10\\x74\\x33\\x13\\x56\\x2e\\x3c\\x5a\\xbf\\xc5\\xc8\\x1d\\x11\\x31\\x14\\x73\\x92\\xe1\\x7e\\xba\\xa2\\x5c\\xaf\\x7b\\xbf\\x31\\x77\\x02\\x69\\xe4\\x52\\xf8\\x20\\x8a\\xc9\\xe2\\x20\\xf3\\x51\\xb0\\x6b\\x5d\\x7b\\xca\\x98\\x9c\\x60\\xfd\\xca\\xf0\\xa6\\x3b\\xfc\\x24\\x83\\xc8\\xa1\\x8b\\xf5\\xae\\xbf\\x17\\xf7\\x99\\x84\\x00\\xd4\\x81\\x37\\x52\\xb1\\x72\\x59\\x4d\\x10\\x15\\xc4\\x84\\x43\\x9f\\x30\\x95\\xac\\xca\\xf5\\x6d\\xe4\\x90\\x6d\\xc5\\x20\\x15\\x8b\\x8a\\x9c\\xeb\\xd5\\xa1\\x14\\x9a\\x5d\\x37\\xca\\xec\\xa8\\x72\\xb2\\xf3\\xea\\x80\\x15\\x5e\\xe6\\x1e\\x46\\x64\\x86\\x95\\xe8\\x35\\xa8\\xbf\\x85\\x2c\\x92\\x18\\xe0\\x25\\x0a\\x01\\xbb\\x1a\\x71\\x83\\x98\\xc6\\xe5\\x01\\xce\\x02\\x56\\x6f\\xfd\\x21\\x2e\\x8e\\x8c\\xe1\\xed\\x7f\\x17\\x7c\\x49\\x13\\x26\\x74\\xf0\\x8b\\x09\\x44\\x4e\\xc3\\x1f\\xdd\\x55\\x77\\xd1\\x54\\x5d\\x96\\x8a\\x0b\\x1b\\x65\\x32\\x2e\\xf5\\x94\\x7d\\xf7\\x4a\\xf0\\x11\\xbb\\xd6\\x4f\\xd1\\xd9\\x08\\x1c\\x7f\\x92\\xf3\\x25\\x4f\\xd8\\x9c\\x1d\\xab\\x88\\x26\\xa0\\x9f\\x75\\xa3\\x12\\x1f\\xdc\\x30\\x3a\\x2c\\x7c\\x2e\\x13\\x65\\x64\\x87\\x51\\x49\\x8d\\xf4\\xc2\\xd4\\x03\\xf0\\xe8\\xcd\\x29\\x17\\x88\\xd4\\x97\\xb9\\x1f\\x2b\\xcc\\x61\\x30\\x5a\\x6e\\x46\\x73\\xb3\\xc0\\x3e\\x57\\x01\\x98\\xda\\x54\\xca\\xc4\\x62\\x30\\xc0\\xa9\\xb2\\xe3\\x5b\\x34\\x12\\x21\\x7f\\x17\\xec\\xea\\x77\\x33\\x9a\\x22\\xb3\\x84\\xce\\x4b\\xe6\\xc8\\xf4\\x5a\\x96\\x51\\x39\\xf4\\x8d\\x2f\\x00\\x00\\x07\\x85\\x61\\xdd\\x86\\xd7\\x96\\x09\\x1b\\x21\\x3f\\x78\\x45\\x5e\\x0e\\x60\\x3b\\x53\\x45\\xfc\\x18\\x31\\xf9\\x66\\x00\\x5c\\xe0\\xf0\\x60\\xf2\\xfb\\xf9\\xaf\\xe7\\xbf\\x1f\\x1c\\xbd\\x3d\\x39\\x25\\xa7\\x52\\x33\\xd4\\xdd\\x03\\x41\\x1a\\x79\\x47\\xb9\\x99\\xa5\\x8f\\x63\\x8c\\xa5\\x1a\\x83\\xaf\\x08\\xaa\\x68\\x44\\x2c\\xaf\\x54\\xe3\\x68\\x0e\\x6e\\x3f\\x43\\x3c\\x46\\x45\\x33\\x77\\x35\\xcd\\xe8\\x94\\x27\\xbc\\x8d\\xa6\\xbc\\x56\\xd9\\x12\\x0e\\x0a\\xb2\\x26\\x8e\\xf7\\xe3\\x5c\\x66\\x48\\x04\\x97\\x5c\\x13\\x38\\x7a\\x2b\\xe1\\xfb\\xb0\\x42\\x17\\xd6\\x77\\x56\\x1d\\x70\\x9e\\x53\\xa1\\x4b\\xb5\\xa3\\x5c\\xb3\\xdc\\x08\\x6f\\xc0\\xa3\\x6a\\xb9\\x1c\\x8f\\x67\\xc0\\x74\\xe1\\xed\\xa4\\x71\\x77\\xf8\\x2a\\x07\\x71\\xcc\\xe2\\x0a\\xf9\\x5b\\x67\\x31\\x6e\\x5b\\x5d\\xe4\\xa1\\x7b\\xb9\\x20\\x7c\\x4f\\x26\\xef\\xce\\x4f\\xfe\\x6f\\x6d\\x1f\\xaf\\xb2\\x76\\x05\\x5a\\xdd\\x60\\x75\\xe5\\x32\\xeb\\x6c\\x75\\xcf\\x2c\\x16\\x54\\xbf\\xbe\\x5b\\xb1\\xbe\\x5e\\x5a\\x76\\x53\\x16\\x70\\x56\\x88\\x2a\\xc8\\x72\\x39\\x3e\\x49\\x65\\xcc\\xc6\\x64\\xe2\\xf3\\x13\\xab\\xdf\\x86\\xf6\\x43\\xce\\x88\\xb9\\x45\\x68\\x0e\\x16\\x53\\xa0\\xa2\\x69\\x89\\xb8\\x48\\x15\\xb4\\xc8\\x90\\x91\\xcf\\x68\\xa2\\x1e\\x9b\\x1b\\xb7\\x91\\x8d\\x46\\x8f\\x78\\x2b\\x0b\\xd1\\x4d\\xde\\xbf\\x1f\\x8d\\xc4\\x4c\\x48\\x6d\\x15\\x6b\\x33\\x4b\\x40\\xe0\\xcc\\x65\\x44\\xd0\\xc7\\x18\\x14\\x81\\x55\\xe4\\x9b\\xc2\\x1c\\x49\\x27\\x1a\\xb9\\x72\\xc4\\x9e\\xf8\\x91\\x31\\xbd\\xa4\\x50\\xac\\xae\\xa0\\x5b\\xd1\\x58\\x7a\\x1d\\xcd\\xe8\\x39\\xa3\\x31\\x38\\x0e\\x32\\xaa\\x17\\x68\\x2a\\xa6\\x54\\x5d\\xb2\\x18\\x3f\\xb0\\xaa\\x99\\x0f\\x00\\x83\\x8d\\xef\\x1e\\x75\\x61\\xe6\\xed\\x62\\xbd\\xa0\\x92\\x61\\x65\\x09\\x44\\x89\\x8d\\x69\\xfc\\xa8\\xab\\xde\\xe2\\x10\\x1a\\xa2\\xbc\\x13\\xc9\\xea\\x4c\\x4a\\xfd\\xda\\x03\\x7b\\x75\\xb2\\x03\\x7e\\xb1\\xda\\x72\\x35\\x00\\x0f\\xea\\x24\\x85\\xe7\\x8e\\x60\\x35\\xe0\\x50\\x85\\x98\\x62\\x47\\xe5\\x8a\\x3f\\xf5\\x23\\x95\\x17\\xe2\\x40\\xfd\\x90\\xcb\\xa2\\xb1\\x10\\x5b\\x53\\x36\\x7f\\x38\\x39\\x02\\x56\\x54\\xd8\\x14\\x69\\xa1\\xf3\\x15\\x80\\x19\\xae\\x23\\xd2\\x7b\\xc3\\xe0\\xbd\\x4d\\xf2\\x0e\\xcf\\x44\\x99\\x8f\\x4b\\xde\\xd2\\x15\\xa1\\x89\\x92\\x8e\\x96\\x36\\x3c\\x5f\\xb7\\x42\\xad\\x89\\x6b\\xbe\\x9e\\x4a\\xbd\\x58\\xb3\\x6d\\xcd\\x81\\x5a\\xff\\xdd\\x30\\xc8\\x98\\x2e\\xf3\\x9a\\xb8\\x58\\xfb\\xb9\\x86\\xd8\\x6f\\x96\\xb3\\x88\\xc5\\x4c\\x44\\x8f\\xbd\\xec\\x8f\\x9d\\x68\\x0c\\x5b\\xe7\\x54\\x0a\\x73\\x30\\x3b\\xd9\\x3c\\x27\\x3e\\xc3\\xdc\\x92\\x34\\xdc\\x2a\\x10\\xdc\\xb7\\xd6\\x1f\\x05\\xd7\\x29\\x1c\\xcb\\x42\\x81\\xeb\\x69\\x06\\xe6\\x23\\xae\\xe4\\x4f\\xc5\\x94\\x25\\x86\\xf2\\xc6\\x24\\x05\\x3c\\x64\\xaa\\xd1\\x9d\\xc1\\x53\\x3a\\x67\\x84\\x6a\\xbf\\xd3\\xb4\\x24\\x4c\\xa8\\x22\\xb7\\x8b\\x18\\xba\\xc7\\xec\\xa3\\xde\\x9f\\x1c\\x91\\x17\\x64\\xcf\\x3c\\x6b\\x00\\xfb\\x67\\x46\\x79\\x02\\xc9\\xec\\xe0\\x53\\xad\\xd9\\xa8\\x33\\x37\\x04\\x4c\\x09\\x36\\x2f\\x91\\x39\\x32\\x89\\x21\\x11\\x92\\xa8\\x22\\x5a\\xb8\\x39\\x19\\xbb\\xd7\\x99\\xcd\\xb6\\x00\\x13\\x22\\xc8\\xdb\\xb9\\xd7\\x1f\\x97\\x43\\xbd\\x57\\x2c\\xef\\x8c\\x41\\xbd\\x6f\\xc0\\xa0\\x42\\x35\\xca\\xec\\xb9\\x2a\\xf5\\x70\\x63\\xa5\\x4c\\xd3\\x98\\x6a\\x6a\\x19\\x97\\xbb\\x61\\x6b\\x97\\xf4\\x8f\\xcd\\xbe\\x14\\x7b\\xc3\\x45\\x71\\x8d\\x05\\x4f\\xdd\\xb9\\x5a\\xce\\x8f\\x61\\x58\\x12\\x39\\xaa\\xc3\\xaa\\x63\\x12\\x71\\xec\\xbc\\x29\\xa1\\xd7\\xbc\\xb2\\x57\\x86\\x37\\xa8\\x89\\xc0\\x27\\x28\\x26\\xf5\\x31\\xa3\\x9c\\x50\\x11\\xcb\\x74\\xed\\x61\\x46\\x89\\x64\\x95\\x5e\\x2e\\x63\\xd2\\xef\\xbe\\xea\\xb5\\x25\\x4e\\xa1\\x84\\x2d\\x59\\x0b\\xb4\\xf3\\x7a\\xef\\x1a\\x33\\x9a\\x21\\x8e\\xdb\\x11\\x30\\x3c\\x49\\xe8\\x94\\x25\\x36\\xe1\\x14\\xd3\\xd8\\xd7\\x77\\xe0\\x63\\x57\\xc1\\xe6\\x32\\xe9\\x0e\\xb6\\xe3\\x4c\\x26\\x0c\\xcb\\xca\\x1c\\x21\\xcc\\xf0\\x4f\\x82\\x0e\\x30\\x48\\x57\\x74\\x00\\x6b\\xb0\\x42\\x07\\xb0\\x6b\\x9f\\x02\\x1d\\x8a\\x16\\xa2\\x9e\\xd4\\xe9\\x60\\xf4\\x86\\x2a\\x1d\\x40\\x78\\x6f\\x3b\\x1d\\x14\\x8b\\x22\\x99\\x66\\x93\\x5c\\x1a\\xb3\\xb3\\x33\\xd9\\x64\\x87\\x2d\\x63\\x86\\xe8\\xd8\\xd8\\x90\\x82\\x0e\\xb2\\xa0\\x7a\\x33\\xcd\\x83\\x82\\x52\\xaa\\x51\\x48\\xb8\\xaa\\xd2\\xff\\x15\\xc8\\x2c\\x60\\x3d\\x75\\x41\\xe6\\x46\\xa9\\x84\\x17\\xcd\\x2f\\xed\\x17\\x4f\\x59\\x1c\\x74\\x81\\xc9\\xd0\\xc2\\xd9\\xd9\\x89\\x34\\x92\\x11\\x4d\\xa0\\x9b\\x4d\\xbb\\x2d\\x47\\xea\\xdb\\xae\\x3e\\x70\\x50\\x46\\x0c\\x31\\x4a\\xf8\\x2c\\xa8\\x98\\xa0\\xe0\\x68\\x71\\x2e\\x4c\\x21\\x63\\x16\\xc4\\xb2\\x31\\x0b\\xfb\\x02\\xcb\\x4d\\xe1\\x3e\\x57\\xc1\\x6c\\xf4\\x0a\\x17\\x56\\x8e\\x2b\\xbf\\xd6\\xd2\\x62\\xb2\\xbf\\xf5\\x3d\\x72\\xcc\\x04\\x99\\x80\\x7c\\x86\\x8c\\xea\\xc5\\x90\\xe4\\x2c\\xc1\\xda\\x67\\xcb\\x04\\x2e\\xd1\\x82\\xdc\\x85\\x23\\xe1\\x06\\x75\\xe7\\xc1\\x3d\\xda\\x15\\x58\\x94\\x23\\x83\\xf6\\x34\\x43\\x4e\\xcb\\x15\\xd9\\x79\\xe3\\xde\\x7d\\xc7\\xde\\x73\\xfa\\xee\\x22\\x4c\\x1e\\xa2\\x62\\x85\\x19\\x84\\x98\\x81\\xf3\\xd8\\x8c\\xb7\\x53\\x01\\xb4\\x83\\x54\\xf0\\x8b\\x8d\\x8e\\xd0\\x4b\\x2e\\x62\\x5b\\x45\\x5c\\xa1\\xa5\\x6f\\x5a\\x87\\x6a\\x32\\xd4\\xa7\\xf3\\x38\\x64\\x3d\\xaf\\xc8\\x47\\x41\\x3c\\x41\\xc9\\xa8\\xf1\\xee\\x39\\x43\\x8d\\xda\\xb9\\xf0\\x46\\xb7\\xfb\\x65\\xfd\\x43\\xea\\xc3\\xbc\\x17\\xb0\\x35\\xcc\\x73\\x47\\xc6\\xb0\\x5f\\xbf\\xcf\\xbd\\xcb\\xa3\\xe2\\x16\\x5b\\xe6\\xd8\\xb5\\x91\\xf3\\x0b\\x0e\\xeb\\x34\\xfe\\xc8\\x6c\\x69\\xcd\\xc5\\x5c\\x85\\x86\\x0e\\x4d\\x92\\x8a\\xaf\\x7c\\x93\\xa5\\xe3\\x56\\xd8\\xb7\\x28\\x5c\\xb7\\x30\\x6a\\xe8\\x07\\x4f\\xc5\\x4a\\x49\\x8c\\xb6\\xf1\\xc4\\x6d\\x94\\x79\\xaa\\xe8\\x61\\x6e\\x28\\xa1\\x39\\x4d\\xce\\xb3\\xe6\\x3d\\x55\\xc8\\x1a\\x7e\\xff\\xdb\\xf3\\x83\\xea\\xd0\\x20\\xcb\\x6d\\xe9\\x0d\\x83\\xef\\x09\\x8d\\x53\\xae\\x14\\xf8\\xc9\\xd8\\x74\\x21\\xe5\\x25\\xd9\\xbb\\xb5\\xb5\\xe4\\x48\\xf1\\xb9\\xda\\xb7\\x7b\\x7e\\x64\\x66\\x3f\\x20\\x5c\\x24\\x3e\\x69\\x0a\\xcc\\x64\\xa1\\x7d\\xb5\\x0f\\x3c\\x24\\xf2\\xb3\\x80\\x35\\xb4\\x8d\\xb6\\x6c\\x2e\\xc3\\xfa\\x34\\xb1\\xb5\\x96\\xd9\\x05\\x8f\\xce\\xb0\\xd7\\x97\\xa7\\x5d\\xc5\\xf4\\x67\\x97\\xe8\\xd4\\xee\\xed\\x3a\\xac\\xfc\\x46\\x3a\\xa2\\x72\\xf9\\xe8\\x44\\xb2\\xba\\x47\\xc4\\x54\\x77\\x68\\xd6\\x3f\\x96\\x63\\x92\\x98\\x61\\xfe\\x29\\x83\\xe4\\x28\\x7a\\x63\\x0e\\x1e\\xb8\\xad\\x77\\x01\\xa3\\xca\\xfe\\x74\\xb7\\x9a\\xe3\\x99\\x18\\x6a\\x52\\x48\\xda\\x55\\x61\\xc0\\xb7\\x6c\\xf2\\xe6\\x31\\x79\\x31\\xab\\xd6\\x28\\x2c\\xe1\\x4c\\x90\\xbd\\xed\\x95\\x2d\\x6d\\x5c\\xfa\\xb1\\x96\\xae\\x49\\x5c\\xca\\xaf\\xcd\\x53\\xc2\\x5f\\xd5\\x52\\x53\\x85\\x14\\xa3\\xcd\\x5f\\x0f\\xc6\\xe4\\x44\\xf8\\x84\\xfe\\xa1\\x79\\xdb\\xf0\\x46\\x97\\xc1\\xa5\\x0d\\x33\\x0c\\x1b\\x0c\\xc2\\xfc\\x43\\xff\\x93\\x51\\xb2\\xf2\\xa2\\x83\\x9d\\xd1\\xc6\\xab\\x4c\\x42\\xcf\\x72\\xa7\\xc7\\x06\\x3c\\xcc\\x76\\x50\\x23\\x62\\x9c\\xac\\x6c\\xe3\\x71\\x36\\xb7\\x7c\\x29\\xaf\\xf3\\xd3\\x88\\x23\\x90\\xd6\\xd9\\xb9\\x41\\xda\\x70\\x07\\xa9\\xb9\\x61\\x12\\x32\\x5f\\x8f\\x5b\\x4d\\x64\\xbc\\x9e\\x9b\\x6c\\xc1\\x59\\x3d\\x44\\x42\\xa0\\x0b\\x09\\x69\\x2d\\x81\\x00\\x25\\xd5\\xf6\\xca\\x8a\\x6d\\x0a\\xbc\\x35\\xd1\\x31\\xbd\\xb9\\x3a\\x72\\x89\\x2f\\x15\\xb4\\x89\\x1b\\x96\\x05\\xad\\xbe\\xd3\\x9c\\xcf\\xa8\\xfe\\x1f\\x38\\x94\\x3e\\x9f\\xd3\\xc1\\x46\\x4e\\xfc\\xcf\\x99\\xab\\x7d\\xb0\\x3d\\x23\\xa1\\x56\\x5d\\x4b\\xe7\\x01\\xb0\\xa9\\xee\\x36\\x6f\\xd4\\x18\\x60\\x34\\xa7\\xa9\\x61\\x85\\x8a\\x58\\x12\\x4c\\xd9\\x9c\\x63\\x5e\\xa1\\xe7\\x6b\\xbb\\x41\\xb2\\xfc\\x10\\xd5\\x26\\xae\\x49\\xca\\xe7\\x0b\\xdc\\x28\\x84\\x02\\xc0\\x16\\x71\\xb1\\xb9\\x44\\xd2\\x18\\x7a\\x4d\\x43\\x59\\x04\\xcd\\x53\\xc3\\x5f\\x69\\xb4\\x80\\x40\\x1f\\x15\\x24\\x2e\\x72\\x68\\x9f\\xa4\\x19\\x8d\\x57\\x23\\xa5\\xa9\\x36\\x1a\\x25\\xcb\\xad\\x5d\\xe6\\xe6\\xdf\\xf7\\xca\\xbb\\xf5\\xea\\x7b\\xe5\\xdd\\xf1\\xea\\x7b\\xe5\\xf5\\xbd\\xf2\\xd6\\xaf\\xad\\x49\\xb2\\xec\\x7b\\xe5\\x3d\\x2f\\x94\\xe3\\xbe\\x57\\xde\\xfd\\xaf\\x47\\x07\\x37\\xee\\x7b\\xe5\\x6d\\xbe\\xfa\\x5e\\x79\\x7d\\xaf\\xbc\\xbb\\x5d\\x7d\\xaf\\xbc\\xfb\\x5f\\x5b\\x07\\xcb\\xde\\xf7\\xca\\xbb\\xd7\\xd5\\xf7\\xca\\x5b\\xbf\\xfa\\x5e\\x79\\x37\\x5c\\x7d\\xaf\\xbc\\x1b\\xae\\xbe\\x57\\xde\\xfa\\xd5\\xf7\\xca\\xbb\\xdf\\xd5\\xf7\\xca\\xeb\\x7b\\xe5\\x3d\\xeb\\x16\\x22\\xa4\\xef\\x95\\x67\\xaf\\xbe\\x57\\xde\\xb3\\x68\\x94\\x40\\xfa\\x5e\\x79\\x77\\xba\\xfa\\x5e\\x79\\x7d\\xaf\\xbc\\x26\\x57\\xdf\\x2b\\xef\\xb9\\x38\\x65\\xfa\\x5e\\x79\\x7d\\xaf\\xbc\\x3f\\x8e\\xa2\\xdb\\xf7\\xca\\xeb\\x7b\\xe5\\xf5\\xbd\\xf2\\xfa\\x5e\\x79\\xb7\\xce\\xa2\\xef\\x95\\xf7\\x1c\\x4c\\x40\\xa5\\x63\\xde\\x08\\x62\\xf3\\x2e\\x68\\x40\\x36\\x8d\\x3b\\x28\\xbe\\x9f\\x16\\xb3\\x19\\xcb\\x81\\x73\\xc1\\x93\\xd7\\xd2\\xaa\\x4a\\xe0\\xc3\\x7a\\x28\\x97\\xe9\\x21\\x00\\x0b\\xd9\\x8a\\x97\\x1b\\x7e\\x6e\\xab\\xfd\\x01\\x0a\\x33\\x67\\x0a\\xb0\\x70\\x04\\x39\\x7e\\xf7\\x7a\\x03\\xf4\\x50\\xe3\\x7c\\xc3\\xa6\\xd9\\xd3\\x30\\xe7\\x77\\xa2\\x59\\x14\\xfe\\x06\\x82\\x6f\\xaa\\xc0\\xb2\\x74\\x8f\\x12\\xa9\\x6c\\xea\\x3b\\x10\\x2b\\x5a\\x50\\x21\\x98\\xb3\\xf7\\xb8\\x06\\x3f\\xca\\x94\\x31\\x41\\x64\\xc6\\x6c\\x0c\\x9c\\x12\\xc5\\xc5\\x3c\\x61\\x84\\x6a\\x4d\\xa3\\xc5\\xd8\\x3c\\x49\\x38\\x62\\x97\\x79\\xea\\xf6\\x13\\xa5\\x73\\x46\\x53\\x24\\x7a\\xce\\x52\\xca\\x71\\x28\\x42\\xa3\\x5c\\x2a\\x45\\xd2\\x22\\xd1\\x3c\\xf3\\x83\\x11\\xc5\\xa0\\x24\\x05\\x05\\x95\\x27\\x06\\xe4\\xcb\\x95\\xc9\\xed\\xc3\\xf2\\x69\\x76\\x5a\\x52\\xd4\\x91\\x90\\x87\\xd0\\x57\\x20\\xcd\\xf4\\xca\\x67\\xf8\\x32\\x32\\xe3\\xb9\\xd2\\x24\\x4a\\x38\\x48\\x6b\\x78\\x22\\x16\\x27\\xc3\\x78\\x1e\\x5f\\x5c\\xd8\\x99\\x2a\\x3b\\x55\\x11\\x83\\xda\\x9a\\x69\\x85\\xf9\\xb2\\xe5\\x80\\x76\\xa8\\x98\\x2b\\xab\\xe6\\xab\\x21\\xa1\\x0e\\x98\\x0c\\x09\\xed\\x66\\x0a\\xa4\\x76\\x92\\x05\\x47\\xb7\\x1f\\x05\\xc3\\x85\\x00\\xcd\\x3e\\xa1\\xb8\\xdc\\xe8\\x80\\x3c\\xe6\\x36\\xe7\\xb0\\x52\\x0f\\x51\\x2a\\x14\\xb6\\x7d\\x4e\\xed\\x18\\xc0\\x02\\x08\\xb6\\x34\\x7b\\x80\\x45\\xcc\\xc8\\x57\\x7a\\xc3\\xae\\x7f\\xf0\\x4d\\x1f\\x08\\xc5\\xb7\\x4c\\x29\\x3a\\x67\\x93\\x86\\x81\\x86\\x9b\\x2c\\x32\\x88\\x35\\x94\\x0b\\x03\\x5b\\x21\\xa9\\xb4\\x28\\x0c\\xf3\\x36\\xab\\x6a\\x10\\x49\\x71\\x4e\\x5e\\xf9\\xb9\\xca\\xb9\\xd6\\x0c\\x16\\x15\\x20\\xec\\x20\\x22\\x5a\\xaf\\x70\\xdf\\xad\\x65\\x7f\\xbe\\x75\\x83\\x94\\x3f\\x36\\x4c\\x5d\\xc4\\x98\\x8b\\x39\\x65\\x64\\x9a\\x73\\x36\\x23\\x33\\x0e\\x09\\x9e\\x90\\x72\\x39\\x44\\x44\\x23\\x8a\\x5e\\x00\\xa5\\x8c\\xbd\\x2b\\x85\\xd3\\x65\\xdd\\xbc\\xc6\\xe4\\x17\\x3b\\x31\\x9d\\x17\\x22\\xa2\\x01\\x58\\x2c\\xd4\\x68\\xf2\\x19\\x99\\x43\\xca\\xa6\\xd5\\x16\\xff\\xf2\\xe2\\x1f\\x7f\\x23\\xd3\\x95\\x11\\x69\\xa0\\x59\\x69\\xa9\\x69\\xe2\\x5f\\x32\\x61\\x62\\x6e\\x68\\x85\\xc7\\xb3\\x5a\\x65\\xe8\\x29\\x00\\x5d\\x81\\x70\\xe2\\x2f\\xbf\\xb9\\x9c\\x56\\x65\\xec\\x7e\\xcc\\x96\\xfb\\x01\\xfd\\x46\\x89\\x9c\\x6f\\xea\\xa3\\xf7\\xe0\\x10\\xe2\\x1b\\xb6\\x59\\x37\\x5d\\x11\\x1c\\xb4\\x16\\x59\\xc8\\x2b\\xd4\\xf5\\x37\\xec\\x9e\\xb2\\x60\\x29\\x93\\x59\\x91\\xa0\\xd3\\xf9\\xb5\\xaf\\xcf\\x2d\\x14\\x5b\\xaf\\xa2\\xdb\\x78\\x2e\\xc0\\x4d\\x6a\\x87\\xa8\\x03\\x93\\x63\\xa6\\xae\\x7b\\xa4\\xb4\\x55\\x27\\xd6\\x91\\xe7\\x11\\xb6\\xc0\\x10\\x7a\\x4d\\x93\\x64\\x4a\\xa3\\xcb\\x0b\\xf9\\x46\\xce\\xd5\\x3b\\x71\\x9c\\xe7\\x32\\xaf\\xce\\x25\\xa1\\x86\\x5b\\x2e\\x0a\\x71\\x89\\x9d\\x60\\x3c\\x06\\x81\\x9c\\xdb\\x50\\xae\\x2b\\x71\\xd8\\xf4\\xc2\\x58\\x90\\xee\\x98\\xf0\\x7a\\x63\\x04\\x76\\xcd\\x4b\\x5b\\x47\\x10\\x66\\x9e\\x8f\\x3b\\x32\\x1c\\x5f\\x85\\x9b\\xed\\x9b\\x17\\x7f\\xf9\\x3b\\x6e\\x5d\\x22\\x73\\xf2\\xf7\\x17\\x90\\xcd\\xad\\x86\\x78\\x88\\x81\\xb7\\x19\\x41\\x91\\xd2\\x24\\x31\\x66\\x43\\xb8\\x29\\x0d\\xa1\\x37\\x6d\\xc2\\x07\\xdf\\x83\\xba\\xfd\\x76\\xbb\\xb3\\x2a\\x75\\x71\\xf1\\x2b\\xf6\\xd1\\xd0\\x8a\\x25\\xb3\\x21\\xd6\\x2b\\x79\\xb3\\x66\\x17\\x04\\xc3\\xae\\xe5\\x3e\\x50\\x34\\xb6\\x05\\x0a\\xd0\\x52\\x26\\x45\\xca\\x8e\\xd8\\x92\\x77\\xd1\\xec\\xb3\\x32\\x9a\\x33\\xf5\\x13\\xae\\xa0\\x34\\x6c\\x9a\\xc8\\xe8\\x92\\xc4\\xf6\\xcb\\x20\\xbf\\xa5\\x0e\\xb5\\xfd\\x74\\xfb\\x36\\x87\\xef\\x5f\\xc9\\xed\\x49\\x69\\x96\\xf9\\xea\\xa1\\x9c\\x5e\\x55\\x88\\x01\\x67\\x12\\x0a\\xfe\\x9f\\x7e\\xdf\\x66\\x7c\\x23\\xc3\\x37\\x1b\\x0f\\xd1\\x38\\x21\\xa8\\xbd\\x8f\\xba\\x9c\\x7d\\x47\\xdd\\x39\\xcb\\x01\\xdd\\x69\\xc8\\xe0\\xdf\\x58\\x6f\\xb2\\x56\\x2f\\xe9\\x4b\\xee\\xfc\\xc6\\x40\\x05\\xc0\\x6c\\x1f\\x60\\xc9\\x8f\\xd6\\x5f\\x98\\xb4\\x4e\\x6c\\xaa\\xd0\\x45\\xdc\\xd2\\xe2\\x92\\x92\\x8c\\xe5\\x8a\\x2b\\x23\\x97\\x7f\\x86\\x03\\x85\\xbd\\x4d\\x4b\\x17\\xe0\\xe3\\x10\\x01\\x0f\\x37\\xe0\\x13\\xb7\\xe7\\x94\\x13\\x19\\xdb\\x01\\x81\\x15\\x22\\x36\\xf3\\x06\\xb5\\xb6\\xaa\\xd5\\x76\\x28\\x50\\x1f\\x9b\\x55\\xfe\\x5c\\x52\\xb3\\xca\\x29\\xcd\\x27\\x9e\\x55\\xe2\\x5d\\xcf\\x89\\x41\\xc2\\xfb\\x3d\\x55\\xfe\\xe8\\x27\\xdf\\x11\\x1b\\x00\\xc6\\x68\\x17\\xb7\\xca\\x09\\x2b\\xc6\\x23\\x1e\\x94\\x40\\xa5\\xb7\\x76\\xe0\\x98\\x60\\x14\\xdc\\x9c\\x09\\xfb\\x53\\xb2\\xfb\\x6a\\xf7\\x51\\x99\\x24\\x92\\x28\\x97\\x19\\x9d\\xb7\\x6a\\x96\\x53\\xa3\\x54\\x7d\\xd8\\x10\\xaa\\xc1\\x98\\x41\\xf0\\xbd\\xc7\\x35\\x83\\xbb\\x58\\x5c\\x22\\xd1\\x00\\xce\\x10\\x46\\x47\\x1d\\x81\\x5d\\x6f\\x37\\xd0\\x6d\\xaf\\xe8\\x8a\\xd0\\x5c\\x16\\x22\\xb6\\xfe\\x25\\xef\\xe0\\x7b\\x5b\\x7b\\xf0\\xa9\\x14\\xac\\x6c\\x22\\x5c\\x6d\\xbf\\x0d\\x1e\\x7d\\x2e\\xc8\\xcb\\xf1\\xcb\\x17\\xcf\\x45\\x52\\xc1\\x1b\\xd6\\x24\\xd5\\xa9\\x97\\x54\\xc8\\x9f\\x1e\\xf5\\x5d\\x1d\\xa4\\x7c\\x47\\xef\\xfb\\xd6\\xba\\x58\\x4a\\xc4\\x78\\xee\\xf0\\xa8\\xe1\\xa3\\xab\\x9c\\x6b\\x16\\xf4\\x0a\\xdd\\x03\\xc3\\xc5\\xd8\\x87\\x01\\x5e\\xc3\\x60\\x53\\xab\\x86\\x96\\x44\\x6a\\x07\\x90\\xa1\\x8a\\xe9\\x17\\xe4\\x5b\\x96\\x41\\xc1\\x71\\xdb\\xe4\\xe1\\x52\\xb7\\xb0\\xb0\\x90\\x50\\x3b\\x3b\\x64\\x0f\\xef\\xdc\\xc5\\x52\\xe7\\xc1\\xa3\\x6e\\x2d\\x4b\\xb4\\xe3\\xeb\\xac\\x05\\x88\\x65\\xad\\xaa\\x3e\\xa3\\xe0\\x83\\xcb\\x3a\\xa4\\xe0\\xbf\\xd8\\x82\\x2e\\x19\\x94\\x78\\xf3\\x84\\xe6\\x09\\xc4\\x1c\\xcf\\x71\\xee\\x64\\x5a\\x68\\xc2\\xc4\\x92\\xe7\\x52\\xa4\\x4c\\x68\\x02\\x39\\xf0\\xd3\\x84\\x85\\xad\\xf2\\xbf\\xda\\xfb\\xf9\\xe0\\x0c\\x12\\x1a\\x06\\x16\\xac\\xc2\\xce\\xb2\\x50\\xae\\x89\\x64\\x38\\x93\\x60\\xb8\\xcf\\x2e\\x9f\\x9b\\x87\\xa1\\x21\\xf0\\x5c\\x37\\x2f\\xf3\\x9c\\xb4\\xd0\\xd8\\x29\\x92\\x5d\\x47\\x49\\xa1\\xf8\\xf2\\xb1\\x38\\x89\\xad\\xbd\\x3f\\xe2\\x8d\\xd6\\xb9\\x86\\x03\\x50\\x12\\x6a\\xad\\xa4\\x1f\\x5c\\xeb\\x1b\\xca\\x00\\xd7\\x02\\x26\\xbb\\xca\\x97\\x06\\x86\\x31\\x70\\xeb\\x7a\\xb2\\x28\\x1b\\x98\\x3e\\xe7\\x20\\x0d\\xd7\\x54\\x08\\x40\\x94\\x79\\x5c\\x27\\x94\\x90\\x31\\xbb\\x3f\\x1e\\x4f\\x35\\xbd\\xc7\\x0e\\x81\\x31\\xf3\\xa0\\x4e\\x50\\x45\\x0b\\x16\\x17\\x89\\x6d\\xee\\x0f\\xe8\\xa3\\xc6\\x7c\\xa0\\x25\\x8e\\x9d\\x80\\x36\\x3c\\x27\\x33\\x0f\\x76\\x20\\x46\\xe0\\x1c\\x44\\x9a\\xbb\\xdf\\xe7\\x0e\\x1a\\xc1\\x7d\\xa0\\x6a\\x23\\x82\\x51\\x6a\\xc6\\x1a\\x12\\xaa\\x54\\x91\\xe2\\x91\\xc0\\x0e\\x03\\x33\\xae\\x95\\xef\\x55\\xed\\xb4\\x63\\x73\\x30\\xee\\x59\\xb6\\xd5\\x82\\xbe\\xe7\\x2c\\x81\\xcd\\xd5\\x82\\xc6\\xbb\\xa7\\xc1\\x38\\x48\\x68\\xe5\\xfe\\xb2\\x1b\\xce\\x26\\x4c\\x40\\xb4\\xcd\\xe7\\x71\\x4a\\xf0\\x92\\xce\\x38\\x74\\x29\\xa2\\x96\\xde\\xe7\\x1b\\x7e\\x89\\xaa\\x03\\xde\\x01\\xc0\\x31\\x74\\xca\\x12\\x55\\x1f\\x68\\x5a\\x2e\\x8a\\x85\\xfd\\xb4\\x84\\x6f\\xd9\\x4e\\x9b\\x2a\\xc5\\xe7\\x02\\x1a\\x54\\x9a\\xd1\\xee\\xd9\\x8a\\xb2\\xb1\\xcd\\xd4\\x45\\xbb\\xec\\xc6\\x5c\\xad\\x92\\x85\\x95\\xd2\\x6c\\x64\\xad\\x5e\\x2d\\x53\\x1e\\xdd\\x63\\x24\\x79\\xcf\\x29\\xd7\\x2a\\xb2\\x2b\\x95\\xbe\\xef\\xce\\xd7\\x3c\\x3e\\x2a\\xf0\\x6a\\x8c\\xc9\\xb9\\x4c\\x6d\\x8a\\x93\\x08\\xda\\x64\\xb9\\x6e\\xa5\\x46\\x62\\xe4\\xcc\\xd0\\x02\\x12\\x8f\\x78\\x19\\x8d\\x87\\xb6\\x32\\xae\\xd6\\x1a\\x9e\\xe3\\x55\\x72\\x1b\\xc6\\x05\\x00\\x47\\xdb\\x2d\\xd5\\xf7\\x33\\xb6\\xe3\\xba\\xbd\\x0d\\x29\\x30\\xaf\\xc8\\xa8\\xd6\\xfa\\x75\\x5c\\x85\\xdd\\xbc\\xfd\\x39\\xf6\\xde\\xe1\\xe7\\x9f\\x82\\xf9\\x39\\x00\\x68\\x77\\x72\\x14\\xfe\\x79\\x32\\x39\\x0c\\xff\\x7c\\xaf\\x0c\\x95\\xec\\x07\\xf5\\xa9\\x55\\xdb\\x1e\\xdc\\x7c\\x57\\x08\\x40\\x7d\\xd3\\x5d\\x33\\xec\\x1c\\xf4\\x99\\xaf\\x0f\\x17\\x54\\xb8\\x40\\xd6\\x8d\\xcf\\x5b\\xa9\\x48\\x27\\xe5\\x74\\x16\\x34\\x67\\x16\\x59\\xce\\x70\\x72\\x95\\xd1\\xe8\\xc6\\x59\\x78\\x18\\xb7\\x5b\\x6f\\xb8\\x75\\xa6\\xaa\\xc8\\x5c\\xe3\\xfe\\x04\\x6e\\xf4\\x33\\x29\\xb7\\xdd\\x87\\x3f\\xff\\x76\\x47\\x62\\x7e\\xee\\x37\\x9b\\x48\\x7b\\xfb\\x6f\\x2a\\x7d\\xf1\\xee\\xf4\\x8b\\xcd\\x5d\\xb3\\xee\\xf6\\xdb\\xa0\\xf1\\xdc\\x9d\\xee\\xbf\\xa9\\xe9\\xed\\x5d\\x9f\\xe6\\x9a\\xa5\\xdd\\xed\\xc5\\xea\\xab\\x7d\\x87\\xdb\\x61\\x49\\xef\\x87\\x89\\xd0\\x98\\x85\\x37\\x75\\x77\\x35\\x70\\x52\\x35\\x77\\x4e\\x35\\x33\\xf6\\x6b\\x0a\\xc0\\x0d\\x60\\xa0\\x16\\x80\\x4d\\xcc\\x49\\x05\\x56\\xaa\\xc8\\x73\\x26\\xb4\\xd1\\x99\\x0a\\xc8\\x74\\x74\\x6d\\xf1\\x91\\x49\\x03\\xb3\\x05\\x1e\\xee\\xe0\\xdc\\xc9\\x81\\x97\\x85\\x36\\x03\\x2e\\xa5\\xd0\\x7a\\x3f\\x80\\x7b\\x9e\\x15\\x90\\xd0\\x08\\xac\\x1f\\x61\\xea\\xa4\\x30\\xf3\\x78\\xb5\\x09\\x87\\x43\\x66\\x4c\\x94\\x7b\\x65\\xdf\\x6a\\xcd\\x23\\xb3\\x87\\x2a\\xc8\\x1c\\xa8\\x08\\x8c\\xd3\\xf8\\x4f\\x59\\x42\\xf5\\x4c\\xe6\\xe9\\xc8\\xa9\\x87\\xa3\\x8a\\x92\\x40\\x0e\\x21\\xb5\\x46\\x39\\xfb\\x0a\\xf3\\x5b\\x11\\x6d\\x53\\xc4\\x09\\x0b\\xa4\\xb9\\x7f\\x55\\x11\\x23\\x38\\x15\\x29\\x44\\xce\\x22\\x39\\x17\\x50\\x79\\x6c\\xbf\\xe5\\x95\\xb6\\xff\\x54\\x19\\x49\\x4a\\x44\\x91\\x24\\xf7\\xcf\\x43\\x68\\xa8\\x04\\xc8\\x25\\xcb\\x17\\x8c\\xde\\x73\\xf3\\xd6\\x52\\x5a\\xec\\x18\\x65\\x73\\x4f\\x65\\x91\\x0b\\xac\\xca\\xeb\\x1e\\x62\\x54\\x63\\x19\\x41\\x6d\\x9b\\xed\\xbb\\x6f\\x13\\x97\\x29\\x08\\x74\\x40\\x48\\x27\\x73\\xbe\\x64\\xc2\\x81\\x76\\x1f\\x26\\xd4\\x37\\xa8\\x46\\x22\\x79\\xe0\\xf0\\x42\\x4b\\x9f\\xb4\\x40\\xa8\\x0e\\xa0\\x83\\x21\\xc7\\xc9\\xc6\\x4b\\xc3\\x71\\x82\\x5b\\x6c\\x7b\\xeb\\xc4\\xb5\\x12\\xbb\\xcb\\x9d\\x90\\x37\\x80\\xbd\\x15\\x87\\xe5\\x2b\\xa5\\xce\\xb7\\x5a\\xc1\\xdc\\x24\\x11\\x64\\xb7\\x38\\x53\\xc4\\x66\\xb5\\x7c\\xfe\\x11\\x36\\x25\\xcd\\xf0\\xa0\\x4d\\xc3\\x58\\x75\\xd9\\x63\\xc3\\x96\\x84\\x4d\\x0c\\xfb\\x5f\\xa1\\x92\\x73\\x32\\xab\\x3e\\x89\\x57\\x50\\xed\\xa1\\xf6\\x09\\xd4\\xef\\xd2\\x1e\\x9c\\xc8\\xd8\\x68\\x61\\x43\\xe2\\x97\\x32\\xec\\xee\\x6d\\xe3\\x2d\\x78\\x26\\x83\\xc3\\x88\\x4a\\x5a\\x9e\\x33\\x95\\x49\\x04\\xd7\\x0f\\x1f\\x3b\\x0c\\xfc\\x5f\\x5c\\x57\\x92\\xed\\xb0\\x4d\\x9a\\x3f\\x1a\\x88\\xdb\\xf6\\x1f\\x96\\xcb\\x8d\\x3a\\xfc\\x9c\\xeb\\xf1\\xe5\\xdf\\x41\\x81\\x67\\x62\\x41\\x45\\x84\\xb6\\xd3\\xfe\\x25\\xcb\\xd4\\xbe\\xe2\\x73\\xd4\\xd7\\xff\\xf6\\xf7\\xbf\\x83\\xf2\\xee\\x48\\xb2\\x7f\\x76\\x7c\\x70\\xf4\\xf6\\x78\\x9c\\xc6\\x4f\\x48\\x93\\xcf\\xa8\\xd6\\x2c\\x17\\xaf\\xc8\\x7f\\xed\\x7d\\xfc\\xfa\\xd3\\x68\\xf0\\xfd\\xde\\xde\\x87\\x17\\xa3\\x7f\\xfc\\xf6\\xf5\\xde\\xc7\\x31\\xfc\\xe3\\xcf\\x83\\xef\\x07\\x9f\\xdc\\x1f\\x5f\\x0f\\x06\\x7b\\x7b\\x1f\\x7e\\x7a\\xfb\\xc3\\xc5\\xe4\\xf8\\x37\\x3e\\xf8\\xf4\\x41\\x14\\xe9\\x25\\xfe\\xf5\\x69\\xef\\x03\\x3b\\xfe\\xed\\x8e\\x83\\x0c\\x06\\xdf\\x7f\\x75\\xcf\\x89\\x36\\xac\\x4b\\x69\\x5b\\x8b\\xd2\\xaa\\xfe\\xa4\\xc3\\x9a\\x93\\x2c\\x67\\x2c\\x05\\xf6\\xd7\\x24\\x5b\\xab\\xea\\x25\\xad\\x0d\\xe5\\x04\\xac\\xfd\\xcb\\xf0\\x44\\xf7\\x34\\x31\\x37\\x6c\\x52\\x21\\xeb\\x4c\\xe4\\x15\\x64\\x58\\x72\\x69\\x94\\x9f\\x31\\x79\\x07\\x72\\x90\\x9c\\xb2\\x25\\xcb\\x87\\x6e\\xd4\\x37\\xe6\\xa6\\x89\\xbf\\x27\\x74\\xc3\\x6d\\xba\\xa3\\x61\\x8e\\x7f\\xc3\\x35\\x71\\x73\\x6f\\x41\\x3c\\x6c\\x0c\\x62\\x27\\x0f\\xfc\\x69\\x4c\\x7e\\xa6\\x39\\x97\\x85\\xb2\\xba\\x08\\xe0\\xe7\\x4a\\x01\\x32\\x09\\x53\\xc8\\xbc\\x24\\x01\\xaf\\x84\\x0d\\xf0\\xf8\\x41\\x7c\\x65\\x98\\x8b\\xf1\\x78\\xda\\x1c\\x78\\x7e\\x7d\\xb8\\x59\\x24\\x70\\x6d\\x56\\x6a\\xe9\\x1e\\x95\\xbb\\x54\\x57\\x6c\\x94\\x10\\x3c\\x19\\x85\\xc1\\x46\\xfe\\xef\\x24\\x9a\\x0a\\x27\\x0a\\xc3\\xb8\\x79\\x00\\x6f\\x3d\\xb5\\xc8\\x26\\x8c\\x2c\\xf8\\xdc\\x25\\x54\\xc3\\xfb\\xa3\\xf9\\x1a\\x7c\\xea\\x77\\x48\\x83\\x25\\x6d\\x72\\x4c\\x9b\\xe6\\xf5\\x67\\xf5\\xf7\\x6b\\xb1\\x2d\\xaa\\x48\\xcb\\x21\\x58\\xb3\\xab\\x28\\x2a\\xcf\\xcd\\x0e\\xee\\x13\\x10\\x22\\xa3\\x28\\xe7\\x9a\\x47\\x34\\xd9\\x01\\xe1\\xe4\\xbe\\x8a\\x92\\xc2\\xe8\\x89\\xe1\\xb7\\x39\\x23\\xfa\\x4a\\xe2\\x53\\x68\\x42\\x2e\\xd9\\xea\\x4a\\xe6\\xb1\\x93\\xcf\\xee\\x89\\xe5\\x5a\\x28\\xed\\x1e\\xc9\\x99\\x3d\\xc0\\xe8\\x66\\xc8\\x53\\x96\\x93\\x29\\x73\\x1e\\xf4\\xda\\xcd\\xab\\x31\\x39\\xf0\\x2d\\x63\\x44\\x58\\x64\\x18\\xe0\\xbf\\x81\\x8e\\x80\\x5a\\x54\\x65\\x93\\x58\\x21\\xe6\\x9e\\x46\\xb5\\x05\\xc4\\xd9\\xec\\x5d\\x36\\x0a\\x98\\x3f\\x05\\x4e\\xfa\\x3b\\xf7\\xb2\\xcc\\x6d\\x95\\x13\\x9c\\x8e\\x1c\\x6b\\xb4\\xa4\\xfb\\xfa\\x41\\xb8\\x85\\xd1\\x6f\\xb8\\x60\\x4a\\xfd\\x60\\x96\\xb2\\x8d\\xba\\x5a\\xdd\\x1d\\x14\\xd4\\x12\\x3b\\x36\\x54\\x4a\\x95\\x29\\xc5\\xcc\\x1c\\x29\\x8c\\x11\\x1b\\x36\\x2c\\xe3\\xf2\\xce\\x31\\x39\\x80\\x0f\\x20\\x27\\xde\\x68\\x5e\\x50\\x45\\x67\\x06\\xe3\\x5a\\xd5\\xbb\\xb7\\xe3\\x1d\\x07\\xa7\\x47\\x2e\\x77\\x19\\x35\\x05\\x55\\x05\\x52\\x47\\x95\\xb9\\x3a\\x13\\xd0\\xf4\\x6c\\x06\\x2d\\xfb\\x77\\x41\\xa1\\x11\\xed\\xce\\x45\\x5e\\xb0\\x9d\\x66\\xaa\\x12\\x42\\xf4\\xef\\xff\\xf5\\xef\\x2f\\x40\\x5b\\xf2\\xcf\\x1b\\xc1\\xf3\\x9a\\xa8\\x4a\\xf7\\xcf\\x91\\x69\\x94\\x1d\\x53\\x4f\\x0c\\x3a\\x0b\\xf7\\x83\\x23\\xb8\\xb3\\x3b\\x6c\\xd0\\x0a\\x6a\\x7b\\x61\\x99\\x3c\\xcd\\x1b\\xb9\\x56\\x1b\\xe5\\xc2\\x34\\xcf\\x82\\x19\\x95\\xd3\\xbd\\xb8\\x7f\\x93\\xb0\\x36\\x09\\x2c\\x95\\xe7\\x76\\x11\\xe5\\x2a\\x47\\xc3\\x55\\x51\\xb8\\x24\\xfe\\x39\\x81\\x67\\x17\\x7b\\x60\\xd8\\x8f\\x21\\x1d\\x16\\x18\\x17\\x44\\x05\\x80\\x3d\\x36\\xec\\x98\\xd5\\x98\\xdf\\xa0\\xf1\\x0a\\x69\\x75\\xad\\xfc\\xdb\\x67\\x95\\x91\\x2c\\xe7\\x76\\xa2\\xa2\\xf6\\xa5\\xaf\\x21\\xb7\\x09\\xd3\\xae\\x36\\x07\\xc0\\xa7\\x3c\\x6a\\x8c\\x83\\xf9\\xe7\\x2a\\xec\\xf8\\x01\\x95\\x39\\xa8\\x15\\xb8\\xc9\\xab\\x20\\x39\\x32\\x66\\x84\\x2e\\x29\\x4f\\x20\\xae\\x0b\\x26\\x9d\\x54\\x15\\x27\\x3b\\x4e\\x28\\x92\\x42\\x15\\x29\\x3c\\x23\\x35\\xd2\\x05\\x65\\xc6\\x47\\x51\\xd6\\xa4\\x1a\\x36\\x97\\x2d\\x6e\\xaf\\x4a\\x35\\x33\\x3c\\x5a\\x09\\x9a\\xf2\\xc8\\xbd\\xe1\\x41\\xe2\\xfa\\xa7\\xd5\\xea\\x52\\xdd\\xd8\\xde\\x4d\\xce\\xd3\\xb4\\xd0\\x66\\x9a\\xf7\\x44\\x35\\x7d\\x64\\x7e\\x14\\x2c\\x64\\x18\\x37\\x67\\xd7\\x34\\xd2\\xc9\\x0a\\x1c\\x55\\xd5\\x9b\\xf4\\x22\\x97\\xc5\\x7c\\x41\\x28\\x81\\xbf\\xcf\\xe1\\xab\\x31\\x39\\xd1\\xc6\\x96\\x84\\x9e\\xe7\\x16\\xae\\x81\\x6b\\x94\\xdf\\x85\\xe0\\xff\\x2e\\x58\\xb2\\x22\\x1c\\xfa\\xee\\xf8\\x98\\x49\\x75\\xd8\\x00\\x3d\\x7e\\x62\\xd4\\xd8\\xc3\\x72\\x89\\x51\\x0b\\x60\\x2c\\x76\\x90\\x07\\xd6\\xb4\\xbf\\x61\\xf2\\x68\\xb7\\x83\\xf6\\x60\\x04\\x3e\\xbd\\x7f\\x12\\xcf\\x23\\xf1\\xcf\\x06\\xd9\\x7f\\x6d\\xd8\\x66\\xd3\\x4c\\xaa\\x75\\x2c\\xb6\\xcd\\x2b\\xcc\\x83\\xf0\\x71\\x54\\x5f\\x63\\x30\\x55\\xca\\x04\\x2c\\xe8\\x77\\x78\\x74\\x7a\\xfe\\xfb\\x9b\\x83\\x7f\\x1d\\xbf\\x79\\xf0\\x5a\\x12\\x9c\\x65\\x6b\\x62\\xe0\\x59\\x08\\x72\\x5e\\x6d\\x9f\\xb0\\xc0\\x64\\xab\\xec\\xd9\\xe6\\xef\\xf9\\x68\\x4d\\x38\\x2a\\x02\\xa6\\x4d\\x3f\\xa2\\x6a\\x3b\\xe4\\xfa\\xa8\\x75\\x87\\x3d\\xad\\x1d\\x76\\x6b\\x24\\x58\\x39\\x0c\\xa0\\x96\\xc2\\xc7\\xdf\\x68\\x99\\xe6\\xd0\\xae\\xec\\xbf\\x45\\x86\\x55\\x85\\x4e\\x17\\x2c\\xcd\\x8c\\x7d\\xdc\\x19\\xbd\\xaa\\xd2\\x39\\x1c\\xfe\\x33\\x84\\x73\\xb7\\xde\\x9d\\x80\\x28\\xe8\\x18\\xd1\\xee\\x97\\x61\\xd2\\x0e\\xe4\\x9d\\xa2\\xb3\\x97\\x12\\xc1\\xae\\xaa\\x0f\\x73\\x29\\x3d\\xee\\x17\\x53\\x59\\x08\\xdb\\x5a\\xde\\x0d\\xfe\\x0b\\xa2\\x78\\xd8\\x9c\\x14\\x40\\x08\\x4f\\x98\\x76\\xd6\\x5d\\x75\\xcd\\x6d\\xb5\\x39\\x36\\x8a\\xb2\\xf7\\xd9\\x2e\\xab\\x12\\x61\\x53\\x9d\\xda\\x81\\xc7\\xd0\\x7c\\x62\\x2c\\x25\\x29\\xe6\\x0e\\x06\\x64\\xce\\x04\\xcb\\x41\\x41\\xf1\\x0e\\x96\\xe1\\xda\\x0b\\x01\\x6a\\x1a\\xb5\\x4c\\x0d\\xc7\\x75\\xd9\\x1c\\xb7\\xbe\\x5e\\xce\\x22\\x99\\xc7\\x68\\x15\\x99\\x97\\x43\\x03\\x68\\x5c\\xd9\\x09\\xe7\\xf0\\x19\\x53\\xb7\\xe9\\x0f\\xb6\\xfd\\x07\\x54\\x90\\xcf\\xeb\\xca\\x90\\xaf\\x22\\xa8\\x38\\xb0\\x2b\\x74\\x0a\\x6a\\xae\\x72\\x99\\x90\\x2c\\xa1\\x82\\xd9\\x32\\x74\\x6f\\x74\\xaf\\xb3\\xa2\\xa6\\x50\\xec\\xdd\\xa4\\x71\\x18\\xcd\\x19\\x72\\x39\\x2e\\xd9\\xea\\xde\\x9c\\xa9\\x81\\xe4\\x5c\\x7f\\x38\\xbe\\x47\\x4a\\xb3\\xfb\\x69\\xdb\\x46\\x7b\\x6d\\xed\\x4d\\xdd\\x3d\\xc3\\x81\\x48\\x56\\xba\\x4f\\xd7\\xea\\x85\\x7d\\x3e\\x25\\x1c\\x1c\\xeb\\x38\\x3d\\x00\\xf0\\x85\\x21\\x79\\x27\\x5e\\x63\\x35\\xea\\x10\\x7d\\xa9\\xd0\\x03\\x4f\\xc9\\xd4\\x56\\xc1\\x5e\\x6b\\x35\\x24\\x90\\xf1\\x4b\\x89\\x2a\\xa6\\x8a\\xd9\\x86\\x6e\\x46\\x97\\xb6\\x41\\x3d\\x1b\\xb5\\xcc\\x58\\x9e\\x72\\x1d\\x66\\xaf\\x9a\\x2d\\x87\\x8f\\xe9\\x14\\xd6\\x63\\xff\\x4f\\x96\\x7a\\x23\\x7c\\xe9\\x26\\x46\\xfc\\xfd\\xcd\\xa3\\x20\\xd2\\xd3\\xd2\\x5b\\xb7\\x7b\\x56\\x1b\\xab\\x62\\x2a\\x56\\x22\\x59\\x55\\x5e\\x0b\\x59\\x5f\\xe8\\xee\\x20\\xf3\\x5c\\x16\\x99\\xe3\\x23\\xd5\\xd6\\xbd\\x65\\x1f\\x3e\\xc7\\x2b\\xd1\\x05\\x56\\x1d\\xda\\x33\\x3b\\x30\\x38\\x59\\xc9\\xfb\\x63\\xa3\\x72\\x29\\x55\\x7a\\xc9\\x10\\xb5\\x00\\x23\\x7e\\x79\\x21\\x5c\\x9b\\x5b\\x06\\x6e\\xb2\\x20\\x77\\x70\\x27\\x61\\x73\\x1a\\xad\\x76\\xaa\\xcf\\xd9\\x94\\xa9\\x89\\x56\\x15\\x4f\\xb1\\xf5\\x11\\x3e\\xaf\\xac\\x41\\x86\\x52\\x65\\xb0\\x1a\\xd1\\x36\\x46\\x53\\x40\\xd9\\x29\\x3a\\x17\\x9d\\x03\\xd1\\xc0\\x48\\x74\\xde\\x22\\x92\\xf6\\xd7\\xbf\\xff\\x75\\xe4\\x62\\xe5\\x30\\x95\\x07\\xd9\\x50\\x3e\\xd3\\xb2\\x53\\xdf\\x6f\\x65\\xcd\\x8c\\xb0\\xe3\\x2a\\x83\\xf5\\x05\\xcf\\x69\\xe9\\x7e\\xf3\\x4f\\xbf\\xcd\\x3d\\xba\\x79\\x10\\xb7\\x00\\xe5\\x10\\x0f\\x48\\x2e\\x2e\\xe6\\x6d\\xfd\\xa1\\x3b\\xe7\\xd5\\xa1\\xec\\x6e\\x94\\x19\\x35\\x42\\xdb\\xd5\\x25\\x5b\\xde\\x86\\x29\\xad\\x01\\x89\\x2d\\x51\\xa0\\x50\\xb7\\x9c\\x53\\xc9\\x5d\\xcd\\x72\\xac\\x8f\\x6f\\x08\\x1c\\x9c\\x14\\x4f\\x5c\\xa5\\xe9\\xca\\x9d\\xee\\xea\\xb4\\x00\\xaf\\x53\\x33\\x5f\\x91\\x53\\x26\\xe6\\xfa\\xe3\\x48\\xb5\\xd1\\xac\\xea\\x69\\xbf\\xcc\\xeb\\x5e\\xf5\\xf7\\x8c\\xcc\\x5b\\x1a\\x4e\\x6e\\xc3\\xdc\\x54\\xa3\\xab\\x10\\x24\\xbb\\x4d\\x23\\x40\\xf8\\x15\\x50\\x49\\x52\\xb9\\x84\\x8c\\x53\\xc3\\xfa\\x8d\\x0a\\x70\\x45\\xf3\\x58\\x55\\x3d\\x23\\x16\\xad\\xcb\\x7a\\x37\\x6c\\x60\\xc8\\x69\\x11\\x13\\x19\\x97\\x33\\xf0\\xde\\xcb\\xaa\\x2f\\xe4\\x09\\xf9\\x3b\\xaa\\xd4\\x84\\xd7\\x2f\\x93\\x3b\\x80\\x73\\x4f\\x30\\x61\\x77\\x5e\\xd0\\x3c\\x06\\xaf\\x78\\xb9\\x11\\x7a\\x37\\xc2\\xa6\\xab\\x3b\\x37\\x82\\x6b\\x68\\x54\\x1e\\x48\\x74\\xb5\\x1d\\x03\\x9c\\x51\\xf5\\xd3\\xa0\\xdd\\x70\\x4d\\x55\\x6f\\xda\\xf2\\xfa\\x8f\\xac\\xc8\\xd6\\xb2\\x11\\xdb\\xa8\\x45\\xf5\\xc6\\xba\\x0b\\x99\\xc4\\xa0\\xc0\\x8c\\x12\\xb6\\x64\\x89\\x7f\\x94\\x61\\x7c\\x39\\x9f\\x16\\xda\\xa6\\x9b\\x45\\x32\\x4d\\xab\\xd8\\x53\\xb6\\x55\\xff\\x98\\x94\\xe0\\x43\\x61\\x2a\\x00\\x70\\xe2\\x31\\x21\\xe7\\x8c\\xc1\\xda\\x85\\xf3\\x00\\x0d\\xda\\x89\\x38\\x2b\\x04\\xe4\\x8c\\x30\\xb3\\x91\\x70\\x83\\x3c\\x50\\x7a\\x4d\\xf3\\x83\\x65\\x93\\x92\\x5b\\x66\\x3f\\xee\\x1c\\xf8\\x68\\x6f\\x98\\x3b\\x8c\\x8a\\x27\\xca\\x45\\x9a\\x65\\x09\\xc7\\x52\\xf5\\x9a\\xcd\\x01\\x65\\xd9\\x65\\xf6\\xba\\xad\\xd2\\x32\\xb4\\xb0\\x1e\\x7c\\x38\\xae\\x3f\\x15\\x53\\x63\\x8b\\x83\\x2b\\x00\\x2c\\x56\\xcc\\xf1\\xba\\x32\\x43\\x2c\\x78\\x86\\xa7\\x9a\\x6a\\xff\\x73\\x30\\xdf\\xcd\\xd7\\x21\\x84\\xe5\\x2b\\x23\\x91\\x5e\\xa2\\x35\\x2f\\xaf\\x20\\xbb\\xee\\x87\\x93\\x23\\xaf\\xbb\\x98\\xbb\\x5e\\x9f\\x63\\x6a\\xf4\\x37\\x78\\x97\\x62\\x7a\\xce\\x63\\x32\\xc5\\x02\\x18\\x23\\x09\\xf7\\x04\\xbb\\xc2\\x92\\x7a\\xeb\\x93\\xf0\\xf1\\xc9\\xa5\\x2b\\x35\\xc7\\xd1\\xfc\\xc3\\xed\\x90\\x03\\xf2\\xad\\xf5\\x23\\x18\\xe3\\x07\\xb3\\x1b\\xa6\\xdc\\x96\\xdc\\xbe\\x3b\\xdb\\x75\\x69\\x7f\\x57\\xa3\\xfc\\x6a\\x34\\x1a\\x8d\\x6c\\x9e\\x3c\\x68\\xcf\\xc3\\x0a\\x0d\\xbc\\x54\\x4f\\x65\\xcc\\x67\\xab\\x1a\\x25\\xcc\\x36\\x2f\\x1f\\x01\\x3b\\x92\\x8a\\x95\\x9d\\xdd\\x98\\x9c\\x4a\\x88\\xbd\\x53\\x1d\\x66\\x51\\x94\\x6d\\x81\\xcd\\x2b\\x42\\xb8\\x16\\xb2\\x89\\xa5\\x1a\\x0b\\xeb\\xee\\x71\\x99\\xa8\\xf7\\xb7\\xe0\\xdb\\xa5\\x35\\xb5\\x81\\xb5\\xdc\\x90\\x72\\xdf\\x36\\xcf\\x77\\x53\\x16\\xbf\\x8b\\x5a\\xf9\\x1e\\x74\\x72\\x86\\x9b\\x14\\x50\\x08\\x6e\\x58\\x18\\x27\\x87\\xec\\xae\\xb1\\xd1\\x2b\\xcc\\x76\\x60\\xd7\\x99\\xc4\\xbe\\x4d\\xe0\\xc9\\x9e\\xc8\\x78\\x3d\\xcd\\x13\\x95\\xad\\x2c\\xc3\\x62\\xc5\\xca\\xa9\\xb1\\x86\\x1e\\x66\\x16\\x3b\\x22\\x90\\x29\\x35\\x43\\xfa\\xe9\\xec\\xd5\\xf6\\xc9\\x00\\x82\\x2b\\x30\\x34\\xc8\\x3b\\x21\\x6d\\x63\\x7d\\x22\\x05\\x61\\xd9\\x82\\xa5\\x2c\\xa7\\x49\\xf5\\x41\\x16\\xed\\xec\\x95\\x61\\xb7\\xb9\\xd9\\xa5\\x98\\x4a\\x99\\xd2\\x0c\\xb9\\x2d\\x30\\xcf\\x98\\xe7\\x80\\x1a\\xcb\\x2b\\x29\\xce\\x3b\\xef\\xc4\\x99\\x94\\xfa\\x2d\\x57\\x60\\x53\\xda\\xa4\\x12\\xf4\\x00\\xec\\x6c\\x32\\x34\\xdc\\x77\\x65\\xe9\\x78\\xdb\\x9d\\xfc\\x60\\x79\\xc4\\xc4\\x75\\xd7\\xef\\x82\\xd7\\x1a\\x0e\\x62\\x98\\xd6\\x7d\\x1b\\xe8\\xbf\\xb7\\x60\\xc8\\x60\\x08\\x3b\\xa1\\xe5\\x73\\xda\\x36\\xb5\\xc7\\x5f\\xeb\\x8d\\xff\\xc0\\xcd\\xf1\\xad\\x3f\\x94\\xea\\x0a\\xea\\x78\\xcb\\x45\\x7f\\x42\\xdc\\x0b\\xb6\\xcc\\xa9\\x84\\x73\\xd2\\x72\\xd3\\x9c\\xac\\xf7\\xe4\\x2f\\xb7\\x08\\xe8\\xb8\\x66\\x2f\\x51\\x88\\xab\\x4a\\x31\\x82\\x1e\\xd9\\x85\\x72\\x09\\xe0\\xb9\\x4b\\x9d\\xab\\x08\\xa0\\xa5\\x39\\xd2\\x2e\\x91\\x0b\\x4a\\x65\\x8d\\x95\\xe8\\x76\\x98\\x51\\x9d\\x84\\x2a\\x72\\xe6\\x2b\\x3d\\x63\\xc9\\xca\\x7e\\xd9\\x54\\x91\\xf7\\x27\\x47\\xe4\\x05\\xd9\\x83\\x2a\\x67\\x8f\\x74\\xe7\\x63\\xf5\\xf5\\x52\\xdc\\x99\\x1b\\xa2\\xea\\x52\\xb2\\xc0\\x9a\\x42\\x22\\x2f\\xb2\\x73\\x32\\xec\\xd5\\x89\\x61\\xdb\\xa0\\x04\\x3a\\xc6\\x6c\\xdf\\x1e\\x6f\\xba\\x1f\\x9b\\x61\\x19\\xf8\\x6a\\xa1\\x0e\\x78\\xd0\\xfb\\x06\\x3c\\x28\\x54\\xac\\xcd\\xf6\\xaa\\xd2\\x0a\\xf7\\x50\\xca\\x34\\x05\\xd0\\x56\\xe4\\x4d\\xee\\x86\\xad\\x5c\\xbd\\x3f\\x3a\\x87\\xaa\\x16\\xfc\\x75\\xb0\\xa9\\xce\\x8f\\x61\\x40\\x17\\x4e\\xb0\\x6a\\x3c\\xda\\x0e\\xf1\\xba\\xed\\xe0\\x78\\xc1\\x67\\xb0\\x00\\x5c\\x4c\\xcf\\xe3\\x2c\\xe6\\x54\\xc4\\x32\\x5d\\x7b\\x9a\\x59\\x4d\\x30\\xde\\x82\\xd5\\xec\\xb7\\xdd\\x4d\\x57\\xab\\x14\\x81\\x76\\x09\\x02\\x60\\xe3\\x77\\x00\\x21\\xf6\\x06\\x7c\\x05\\x5c\\xf9\\x9d\\x80\\xce\\x03\\x28\\xae\\x5f\\x33\\x5b\\x5b\\x23\\x4c\\xb6\\x8e\\xf7\\xe7\\x32\\x69\\x18\\xd8\\xaf\\xa6\\x41\\xc8\\xc4\\x82\\x41\\xb8\\xd7\\x36\\x03\\x6f\\xed\\x5b\\xeb\\x86\\xe9\\x96\\x75\\xf6\\xb2\\xca\\x6a\\x6f\\x0d\\xee\\x9c\\x6d\\x7d\\xeb\\xa2\\x91\\x94\\x26\\xf5\\xb7\\x86\\xd2\\xe0\\xca\\x5b\\x83\\xdc\\xdd\\xc6\\xb7\\xae\\x56\\x82\\x77\\x20\\x4c\\xec\\x80\\x44\\xda\\x7a\\x74\\xdb\\x91\\xb1\\x0e\\x16\\x5b\\x56\\x9a\\x82\\x13\\xea\\x69\\xf1\\xd1\\x36\\x70\\x82\\x58\\x30\\xf6\\xd0\\xac\\x5b\\x46\\x34\\x01\\xd0\\x86\\xa6\\xeb\\x4c\\xea\\x6b\\x5d\\x1f\\x32\\x28\\x6a\\xa1\\x66\\xb6\\xf0\\x59\\x50\\x9a\\x49\\x11\\xe9\\x5a\\x96\\x81\\xf2\\x5a\\x50\\xdc\\xba\\xe9\\xec\\x2f\\x5d\\xe6\\xa0\\x91\\xbf\\x65\\xa5\\x68\\xf8\\x6b\\x2d\\x01\\xa8\\xa8\\xec\\xa8\\x47\\x61\\x82\\x0c\\xd3\\x66\\x32\\xaa\\x17\\x43\\x92\\xb3\\x04\\x9b\\xe4\\xd8\\x73\\x76\\x89\\xa6\\xd4\\x6e\\xa5\\xfc\\xd4\\xed\\x58\\xf7\\x68\\x97\\x14\\x5c\\x8e\\x0c\\x5a\\xc6\\x0c\\x59\\x17\\x57\\x64\\xe7\\x8d\\x7b\\xf7\\x1d\\x7b\\xcf\\xe9\\xbb\\x0b\\x77\\x1f\\xe4\\x77\\xf8\\x0a\\x99\\xa6\\x29\\xe2\\xdb\\xc2\\xbf\\x77\\xf0\\x9d\\xfd\\xd2\\xa2\\x93\\xeb\\x92\\x8b\\xd8\\x36\\x97\\xa9\\x50\\xce\\x57\\x42\\xa3\\xea\\xe8\\x1c\\x50\\x8e\\x15\\xd0\\x9c\\x81\\x2f\\xd8\\x93\\x8f\\x8c\\x1a\\xef\\x15\\x9b\\xc1\\xe0\\xf2\\x58\\x46\\x37\\xe8\\xa0\\xce\\xe5\\xe2\\x1e\\x52\\x1f\\xe6\\xbd\\x80\\x8d\\x20\\x00\\x66\\x42\\xc8\\x0d\\xf7\\xb9\\x77\\x69\\x96\\x43\\xd5\\x86\\x33\\xaf\\xe1\\x81\\xb4\\xe4\\xce\\x07\\x3e\\x74\\x3e\\x47\\x78\\x91\\x40\\xc3\\x2f\\xdb\\x7e\\x58\\xb3\\x11\\x4c\\x4c\\x2e\\x6a\\x9a\\xf9\\x10\\x56\\xc7\\x96\\x15\\xaf\\x09\\x2f\\xac\\x62\\x4b\\x69\\xbe\\x22\\x3f\\x9c\\x1c\\x59\\xd8\\x1a\\xeb\\x07\\xdd\\x0b\\x43\\xf4\\x03\\x0c\\x62\\x63\\xa0\\x22\\x65\\xe9\\x14\\x9d\\xa3\\x6a\\xbd\\x94\\xbb\\x02\\x0a\\xe6\\x53\\xf5\\x0a\\x1e\\xdf\\x62\\xef\\xd6\\xad\\x13\\x21\\x43\\x14\\x04\\xf7\\xee\\x39\\x60\\x23\\x58\\xfb\\x46\\xac\\x36\\x2b\\xf5\\x5f\\x64\\x86\\xd8\\x09\\x4d\\x9b\\xb3\\x82\\xbe\\x5e\\xbe\\x64\\x43\\xc2\\x96\\x4c\\xd8\\x6a\\xb6\\x15\\xdc\\x61\\x44\\x1f\\x17\\x51\\x52\\xc4\\xee\\x71\\x80\\xf2\\xaf\\xf4\\xa3\\x49\\xcb\\x66\\xd8\\xc3\\x8d\\x91\\x87\\xdb\\xf6\\x74\\x6a\\x65\\x63\\x23\\x16\\x50\\xcb\\x13\\x77\\x6e\\x11\\x85\\x16\\x32\\x89\\x09\\xf5\\xc7\\xcf\\x27\\xe3\\xc6\\xee\\x39\\x98\\x15\\x16\\xe0\\x8a\\x8d\\x8d\\xe5\\x6a\\x33\\xae\\x0a\\x51\\xc2\\x95\\xb8\\xfb\\xf7\\xea\\xfa\\x94\\xe3\\x78\\x03\\x0b\\xb2\\xe7\\xdc\\x7a\\x09\\x2d\\x44\\xb4\\xf8\\xa3\\x6c\\x99\\x0d\\xd4\\xf7\\x71\\x22\\x4a\\x2e\\x59\\x2e\\x58\\x42\\x32\\x9a\\xd3\\x94\\x41\\xa3\\x17\\xe7\\x5f\\x78\\xf8\\x5c\\xfd\\x76\\x88\\xd4\\x2d\\xd0\\xa4\\x47\\xe8\\xfb\\x78\\x84\\xf2\\x82\\x36\\xe8\\xbe\\x1b\\x13\\x4a\\xa8\\x9b\\x12\\x76\\x2b\\x6c\\xb4\\x8c\\xa4\\x8b\\x82\\x00\\xa0\\x68\\x27\\xaf\\x86\\x7d\\x1e\\xb7\\xe3\\xdd\\xaa\\x00\\x72\\x1d\\x98\\x86\\xbf\\xe0\\x80\\x25\\xd2\\xa5\\x4b\\x03\\xb9\\xaf\\xaf\\xd1\\x29\\x94\\xeb\\xf8\\xf2\\xbb\\x6a\\xcd\\x8f\\x57\\x6d\\xc6\\xf9\\xc0\\x81\\x86\\xc6\\x7c\\x17\\xc0\\xa8\\x9e\\x94\\x7b\\x70\\x9e\\x2a\\x7a\\x98\\x33\\xa8\\x12\\xa3\\xc9\\x79\\xc6\\xa2\\x0e\\xec\\x8f\\x1f\\xde\\x9e\\x1f\\x54\\x07\\x05\\xa1\\x84\\xa5\\x57\\x0b\\x06\\xdf\\x07\\xb8\\x15\\x57\\x6c\\xba\\x90\\xf2\\x92\\xec\\x6d\\xc0\\xde\\x0a\\x72\\xa9\\x14\\x9f\\xab\\x7d\\xbb\\xbd\\x47\\x66\\xde\\x03\\xc2\\x05\\x34\\x49\\xf2\\x42\\xd5\\x37\\x97\\x72\\x0f\\x89\\xfc\\x2c\\x60\\xad\\x6c\\x22\\xb6\\x15\\xc3\\xeb\\xd3\\x3c\\x6d\\x95\\xaf\\xd6\\x9a\\x27\\xad\\x2f\\x46\\xf3\\xfa\\xa4\\xcf\\x2c\\xc8\\x4d\\x18\\x6c\\x1b\\xa9\\x86\\xde\\xa0\\x47\\x21\\x89\\xf5\\x55\\x18\\x0d\\xbc\\x03\\x3a\\xfc\\x58\\x8e\\x16\\x62\\xfa\\xf3\\x59\\xa5\\xdd\\x60\\x69\\x46\\xfa\\x48\\xef\\x2e\\xb4\\x3d\\xb7\\x3f\\xdd\\x0d\\xcd\\x8e\\x83\\x24\\x41\\xce\\x3f\\x71\\xa5\\xe7\\xce\\x55\\x56\\xe6\\x43\\xfa\\x82\\x2e\\x6f\\x39\\x54\\x66\\x82\\x2c\\x6a\\xcf\\x01\\x07\\xeb\\xb0\\x18\\xdb\\xe6\\x53\\xa6\\xfc\\xda\\x3c\\x25\\xfc\\x55\\x88\\x0d\\x01\\xe5\\x49\\x62\\xb4\\xf9\\xeb\\x01\\x94\\x9e\\x38\\x63\\x6a\\x68\\xde\\x36\\xbc\\x31\\x68\\x6b\\x29\\xe0\\x8b\\x53\\xc4\\x76\\xc0\\xf9\\x87\\xe1\\x1c\\xdb\\xa1\\xb2\\xcd\\x3e\\x68\\x8e\\x2b\\xef\\xe3\\xb1\\x1d\\x1d\\x09\\x88\\xcb\\xda\\xe1\\x8c\\x50\\x70\\x62\\xae\\x4d\\x9c\\x16\\x6c\\xc8\\x0e\\x62\\xb5\\xeb\\xb2\\xec\\xc1\\x45\\xe0\\x43\\x9e\\x75\\xc5\\xf2\\x25\\x8f\\xd8\\x41\\x14\\xc9\\x42\\xb4\\x4a\\x75\\x3d\\x62\\xe6\\x15\\xa8\\x66\\xf1\\x79\\x65\\x4c\\x74\\xeb\\xc7\\xf0\\x2d\\x66\\x96\\xd3\\x84\\x53\\xc4\\x84\\xae\\xde\\x89\\x88\\x48\\xe5\\x38\\x10\\x16\\xa8\\xcd\\xd0\\x6e\\x19\\xa5\\x19\\x6d\\x96\\xb6\\xda\\x92\\x42\\x6d\\xeb\\xa4\\xd6\\xdf\\x78\\x93\\x24\\xa8\\x51\\xd0\\x46\\x04\\xd6\\x6a\\xa0\\xee\\x56\\x80\\xa6\\xa9\\xba\\x2c\\x91\\xb2\\x19\\x60\\xc6\\xf8\\xc3\\x14\\x7c\\x6e\\x5f\\x74\\x44\\xf1\\xa9\\x8d\\xd0\\xb3\\x1b\\x50\\x57\\x1b\\xbe\\x67\\x5e\\xfe\\x40\\xbd\\xfe\\x3f\\x47\\xa7\\xed\\xca\\x86\\x7c\\x93\\x60\\x04\\x23\\x59\\xd8\\xa1\\xbd\\x4a\\x1b\\x62\\x28\\x86\\x58\\x52\\xe6\\xc9\\x43\\x92\\x53\\xdb\\xff\\xd0\\xf6\\xbe\\x4f\\x18\\x45\\xdf\\x03\\xd9\\x0b\\xca\\xb4\\x90\\xa7\\x97\\x21\\x79\\xe4\\xf4\\xb6\\x55\\x7d\\xca\\xa8\\x50\\x01\\x5e\\x18\\x83\\xa1\\x9d\\xf3\\xcb\\xcf\\x07\\xb5\\x5a\\xbb\\xda\\xd6\\xca\\xde\\x73\\xae\\xdb\\xea\\x1d\\x4a\\xe7\\x45\\xa4\\x49\\xa1\\x95\\xf9\\x1c\\x1f\\xee\\x18\\xe6\\x1d\\x1e\\x9f\\xb3\\x39\\x57\\x3a\\x5f\\xb9\\x26\\xfa\\xb3\\x60\\x12\\xd6\\x7b\\xe2\\x6f\\xb9\\x64\\x2b\\xf2\\xe3\\x4f\\xc7\\xbf\\xfe\\xfe\\xe6\\xdd\\xe1\\xc1\\x9b\\xdf\\xdf\\x1e\\x1c\\xfe\\x78\\x72\\x7a\\xfc\\xf1\\xe3\\xf9\\xaf\\xe7\\x17\\xc7\\x6f\\x3f\\x7e\\x3c\\x44\\x38\\x58\\x8b\\x9d\\x76\\xce\\xf4\\xc7\\x8f\\x76\\xa7\\xaa\\x8f\\x1f\\x2f\\xa2\\x8c\\x67\\x1f\\x3f\\x4e\\x9c\\xaf\\x00\\xdb\\x63\\xfe\\x9f\\xa3\\x53\\xe0\\x9f\\x08\\xe1\\xe3\\x73\\xab\\x40\\xb4\\x22\\xd1\\x61\\xde\\x0b\\xaa\\xca\\x4c\\xce\\x4a\\xb1\\x65\\x83\\x96\\x2a\\x4d\\xc5\\xdd\\x46\\xfc\\xea\\x56\\x87\\x7d\\x01\\x4e\\x53\\xd7\\xd7\\xda\\x79\\x33\\xcb\\xd2\\xf2\\x29\\xd3\\x57\\xcc\\x62\\x4e\\x6d\\x44\\x4c\\xa7\\xf5\\xc2\\x70\\x9b\\xdd\\xbd\\xa1\\x77\\xae\\xc3\\x84\\x59\\x72\\x76\\x85\\x00\\xa1\\x7c\\x2e\\x68\\x12\\x34\\x70\\x06\\x0c\\x3a\\x8c\\xb2\\xac\\xe3\\xb2\\x83\\x8e\\x94\\xc9\\xd8\\x37\\xab\\xae\\x79\\xb7\\xd7\\x3c\\xdb\\x95\\x1a\\x4a\\x44\\xde\\x67\\x31\\x99\\x9c\\x1c\\x91\\x97\\x63\\x54\\x72\\x4e\\x8e\\xb0\\x11\\xc8\\x46\\x58\\x70\\x67\\xd1\\x19\\x81\\x8a\\xd2\\x77\\x43\\x69\\x43\\xb9\\x01\\x9a\\x30\\xa3\\x06\\x3b\\xa0\\x98\\xc6\\x32\\xa5\\xf7\\x6d\\x4b\\xff\\x99\\xe2\\xc5\\x59\\x91\\x24\\x2b\\xf2\\xef\\x82\\x26\\xa8\\x03\\x4c\\x64\\xbc\\xce\\x99\\x76\\xbe\\x73\\x1f\\xfd\\x73\\xfc\\x9d\\x9f\\xc7\\x3f\\xc7\\xdf\\xb9\\x72\\x7e\\x20\\xdb\\x3f\\xc7\\x6a\\x19\\x8d\\xbf\\xb3\\x68\\x76\\xc4\\xde\\xb4\\x31\\x11\\x79\\xad\\xd4\\xd5\\xaa\\xb3\\xf8\\x1b\\x04\\x08\\x00\\x75\\xf7\\x41\\x6a\\x1d\\x83\\x46\\xbe\\x3f\\xe4\\x34\\x62\\x13\\x96\\x73\\x50\\x99\\xa4\\x88\\xdb\\x54\\x3e\\xba\\x2d\\x43\\x62\\x87\\xef\\xcc\\x05\\x51\\x38\\xac\\x27\\x81\\x60\\x2c\\x46\\x25\\xd1\\xce\\x82\\x91\\xb9\\x99\\x04\\x2c\\x0c\\x6a\\x81\\x00\\xa2\\x10\\xe5\\x8c\\x62\\x3e\\xbb\\x45\\x54\\x70\\xa0\\xbd\\x63\\xeb\\x66\\x72\\x31\\x56\\xa3\\xf0\\x0b\\x36\\xc7\\x48\\xa9\\xf5\\xb7\\x63\\x34\\x16\\xb9\\x2c\\x02\\xed\\xf9\\x18\\xa0\\xd2\\x32\\x23\\x3c\\x4d\\x59\\x6c\\x14\\xa0\\x64\\x45\\x96\\x9c\\x22\\xe7\\x87\\x82\\x49\\x3c\\xa7\\x7b\\x42\\x12\\x09\\x5e\\xeb\\x42\\x70\\xeb\\xc4\\x5a\\x14\\x9a\\xc4\\xf2\\x4a\\x0c\\xca\\x56\\xed\\xf8\\x00\\x63\\xac\\xf0\\x64\\x58\\xa9\\x1e\\x86\\x57\\x22\\x19\\x10\\xb6\\x0a\\xe3\\xe0\\xf4\\x25\\x98\\x61\\xe5\\x36\\xab\\x7b\\x6c\\x22\\x1e\\x62\\x24\\x20\\xfc\\xa4\\xe3\\x20\\x0e\\xeb\\xb9\\xac\\xbd\\xc7\\xd0\\x0c\\xb4\\xbd\\xaf\\x34\\x6b\\xb6\\x2f\\xe5\\x78\\x09\\xa6\\xb7\\x21\\x17\\x0b\\x07\\x34\\xbf\\x9e\\xc9\\x3c\\xe2\\xd3\\x64\\x45\\x16\\x34\\x29\\x1b\\x37\\x87\\xb4\\x19\\x93\\x73\\xa6\\xc3\\xd7\\x4f\\xa4\\x98\\x87\\x82\\x1a\\x41\\xbc\\xa1\\xcc\\x9b\\x51\\x51\\x64\\xf8\\x3c\\x23\\xdf\\x56\\xb2\\xb8\\xc1\\x60\\xf8\\xf6\\x85\\x7b\\xd5\\x47\\x80\\xd5\\xbc\\x57\\x78\\x45\\xcb\\x84\\xe1\\xfa\\xb4\\x39\\x29\\x1b\\x8b\\xaa\\x77\\x55\\x38\\x7a\\x13\\x42\\x3c\\x46\\xe9\\xaa\\x43\\x39\\x81\\x1d\\x71\\xe1\\xe7\\x0f\\x96\\x86\\xd6\\x14\\xaa\\xba\\xcd\\x69\\xc7\\x6f\\xa0\\xa4\\x6e\\x45\\x8c\\xd4\\xb2\\x18\\x5c\\x21\\x3c\\x80\\xce\\x79\\x96\\x30\\xf2\\xdd\\x25\\x5b\\x0d\\x11\\x7d\\x15\\x95\\x90\\x7f\\x06\\x3d\\xb1\\x3c\\x7e\\x1d\\xa2\\xe4\\xcb\\x9c\\x7c\\xe7\\xfe\\xf5\\xcf\\x07\\x2c\\x83\\x6d\\xe3\\x6d\\xc4\\x97\\x6a\\x1d\\x21\\x3a\\xc6\\x52\\x9b\\x2a\\x1c\\x2b\\x52\\xd6\\x56\\xe1\\x68\\x89\\xe4\\x1a\\x93\\x63\\x00\\x3d\\x40\\x8d\\xd4\\xf6\\x05\\x4a\\x92\\xca\\xcd\\xca\\x6a\\x36\\x55\\x28\\x4f\\x70\\xbf\\x04\\x25\\x38\\xa7\\xd2\\xd6\\x29\\x33\\xc0\\x44\\x9e\\xb1\\xbc\\xfc\\x04\\x18\\xcc\\xa9\\x3c\\xbe\\x66\\x51\\xa1\\x1f\\x12\\x5a\\x10\\xaf\\x4b\\xd6\\xbe\\xeb\\xfa\\x4f\\xcc\\xe3\\x45\\x23\\x6d\\x8c\\x16\\xee\\xcb\\x1f\\xca\\xd3\\x19\\x64\\xc0\\xdd\\x4e\\xdb\\x4b\\xb6\\x52\\x1e\\x11\\xff\\x12\\x47\\xb7\\x85\\xfa\\x7e\\xff\\x3a\\x41\\x76\\x7c\\xcd\\x95\\x56\\xff\\xdb\\xb5\\x7c\\x4f\\xa7\\x65\\xb3\\x7d\\x8a\\xa9\\x68\\xe5\\xe8\\x41\\x37\\x04\\xf3\\x27\\x3c\\xe6\\xa1\\x09\\xee\\x5e\\xa0\\x35\\xd5\\xdf\\x39\\x4a\\x04\\xfd\\x0e\\xa8\\x79\\xa7\\x5d\\x65\\x73\\xa0\\xa4\\x80\\x6a\\xb8\\x10\\x38\\xbf\\x4c\\xcf\\xc1\\x1f\\xe3\\xfe\\x44\\x1a\\x02\\x5d\\x8e\\x8d\\x92\\x57\\x15\\x33\\xf6\\x23\\x7b\\x13\\x07\\x08\\x58\\xbe\\xa4\\x09\\x13\\xb6\\x8f\\x50\\x12\\x47\\x34\\xc7\\x50\\xb6\\x45\\x7f\\x56\\xb6\\x15\\x99\\x85\\x3d\\x35\\x32\\xce\\x72\\xb2\\x72\\x95\\x95\\x0d\\x79\\xd1\\x5c\\xf3\\xa8\\x48\\x68\\x4e\\xcc\\x79\\x9c\\xcb\\xfc\\x9e\\x20\\xd1\\x78\\xb5\\x5a\\x93\\x72\\x8b\\x36\\x52\\xe7\\xf0\\xaa\\xf2\\xf7\\xfa\\x88\\xf5\\xae\\x14\\x56\\x7b\\x31\\x26\\x13\\x47\\x9c\\xcb\\xf0\\xa0\\xec\\x55\\x5b\\x99\\xc9\\x99\\xe3\\x4d\\x9e\\x51\\x84\\x7d\\x0d\\x74\\x15\\x77\\x6a\\x2e\\x64\\xce\\xe2\\x41\\x20\\x3c\\xfc\\xc9\\x1c\\x93\\x7f\\x79\\xa8\\x90\\x21\\x29\\x5d\\xc6\\x50\\xf8\\x6a\\x9f\\x69\\x8f\\x8d\\x5d\\xae\\xf2\\x50\\xcf\\x64\\xce\\x96\\x2c\\x27\\x7b\\xb1\\x44\\xe4\\x8c\\x25\\x8f\\xf4\\x60\\x4c\\xfe\\xff\\x46\\x53\\x04\\x1f\\xb2\\x53\\x27\\xed\\x31\\xf3\\xc5\\xbe\\x65\\x77\\x85\\x17\\x64\\x0f\\x7e\\x16\\xaa\\x92\\x03\\x17\\x50\\xb1\\x6d\\x5b\\x9e\\x58\\xd6\\x48\\x8b\\x48\\xf0\\x86\\x28\\x70\\x85\\x8d\\xa2\\xa6\\x58\\xdb\\x1a\\x5e\\xf2\\x4b\\xcf\\x21\\x3d\\x4f\\xe4\\xca\\x9e\\xd2\\x8a\\xe7\\xd6\\xc7\\x23\\x1c\\x0b\\xf5\\x1b\\xe7\\x7f\\xc0\\x47\\x4f\\x72\\x36\\x87\\xf3\\x87\\xa7\\xe7\\x01\\x4f\\x9f\\x96\\x99\\x4c\\xe4\\x7c\\x75\\x9e\\xe5\\x8c\\xc6\\x87\\x52\\x28\\x9d\\x03\\x6b\\x68\\x03\\xc6\\x7f\\xd3\\x98\\x01\\x8c\\xe3\\x42\\x5e\\x11\\x6a\\x13\\xbd\\xe4\\x0c\\xdb\\x19\\xc8\\x62\\xbe\\x40\\xd4\\x16\\xf8\\x21\\xa1\\x51\\x2e\\x01\\x9a\\x14\\x87\\xb3\\x46\\xa7\\x1a\\x3b\\x00\\x17\\xe7\\x3e\\xf0\\x20\\x2f\\x30\\x0a\\x38\\x3c\\xae\\xe8\\xca\\x1e\\x26\\x3a\\xe5\\x31\\x53\\x41\\x22\\xb4\\x9b\\x0c\\x46\\x7e\\x6e\\x7c\\x7f\\xe0\\xca\\x07\\xa7\\x47\\xf7\\xed\\x80\\xf9\\x88\\x0a\\xed\\x0d\\xaf\\xe2\\x35\\x23\\xa4\\x7a\\x49\\x5f\\xaf\\x91\\x02\\xdd\\x68\\x2a\\xad\\xa6\\x8a\\x8d\\x77\\x1c\\x65\\x9e\\x08\\x44\\x4b\\x4a\\xaf\\xcf\\x2f\\xd9\\x55\\x83\\x5f\\xba\\x17\\xfd\\x89\\xdd\\x3f\\x65\\x6a\\x04\\xf6\\xe8\\x7b\\xa1\\xa8\\xe6\\x6a\\x06\\xad\\x72\\x1f\\x50\\x1f\\x87\\xca\\x86\\x66\\x1d\\x3d\\xf1\\xaa\\x16\\x08\\x85\\xa3\\xb9\\xca\\x73\\x8f\\xb4\\x5a\\xd9\\x2c\\x36\\x4f\\xae\\xb4\\x83\\x6c\\x9a\\x24\\x54\\x5a\\xf8\\x66\\xa0\\xe6\\x04\\x45\\xb6\\x41\\xb6\\x96\\x65\\xbc\\x16\\x23\\x15\\x45\\x3a\\x65\\xb9\\x3f\\xfb\\xe8\\x0c\\xe0\\x79\\x0d\\x86\\xb1\\x76\\xf6\\x9f\\x20\\xba\\x2b\\x90\\xe7\\xf8\\xda\\x68\\x1e\\xaa\\x59\\x42\\x0f\\x5e\\xd5\\xfe\\xf6\\xb5\\x41\\x31\\x3c\\xe6\\x12\\x1d\\x6b\\xcb\\x50\\xe9\\x33\\x6b\\x51\\xc1\\xcb\\x4f\\x9a\\xf2\\xb9\\xf2\\x6a\\x93\\x72\\x88\\x57\\xe3\\xc4\\x43\\xbc\\xea\\xe9\\xd6\\x37\\xbe\\x7e\\xad\\x59\\x6d\\x58\\x55\\x68\\x9d\\x42\\x6a\\x88\\x0a\\x3c\\x3a\\xb0\\x01\\xfd\\xcc\\x0a\\x76\\xb8\\x19\\x94\\x7a\\xab\\xcd\\x19\\xa3\\xc8\\xdc\\x84\\xbf\\x6b\\xdb\\x8a\\xba\\xf1\\xfe\\xc4\\xab\\x5d\\x5e\\x23\\x5e\\x23\\xf3\\x4a\\xad\\x7e\\xef\\x88\\xd5\\x78\\x90\\xb6\\x87\\x0d\\xaf\\x86\\x06\\x75\\x79\\x55\\x36\\xd4\\x65\\x69\\x5a\\xe3\\xce\\xaa\\x98\\xd6\\x25\\xb3\\x2b\\x0d\\xeb\\x56\\xcf\\xee\\xa0\\x11\\x3d\\x69\\x69\\xe3\\x96\\x57\\x85\\x10\\xf2\\x1e\\xd6\\x2e\\x25\\x16\\x10\\xd5\\x9e\\x8e\\x8d\\x36\\xef\\x89\\x18\\x92\\x53\\xa9\\xcd\\x7f\\x02\\xf3\\xf7\\x48\\x32\\x75\\x2a\\x35\\x7c\\xb2\\x15\\xa4\\xc4\\x57\\xe8\\x90\\x90\\xae\\xe7\\x23\\xb6\\x50\\x30\\x7c\\xd3\\x86\\x68\\x8d\\xc4\\x73\\x04\\xdb\\x60\\x58\\x9c\\x08\\x22\\x73\\x47\\x31\\x6f\\x5d\\x28\\x3b\\x44\\x18\\x56\\xb0\\x40\\x5e\\x37\\x1a\\x27\\x66\\x9c\\x90\\xce\\xb7\\x0c\\x67\\x87\\x02\\x44\\x1e\\xfc\\x06\\x40\\xe8\\xb3\\x04\\x12\\xe9\\xe3\\x22\\xc7\\x86\\x43\\x46\\xd7\\xd4\\x6c\\xce\\x23\\x92\\xb2\\x7c\\xce\\x08\\xe0\\x62\\x76\\xb1\\x7c\\x6d\\xe4\\x0a\\x5e\\x2d\\xa5\\x4b\\x38\\x99\\x16\\x7b\\x09\\x44\\x36\\xa8\\x58\\x1d\\xaa\\x00\\x38\\x1e\\x8a\\xb5\\x94\\x82\\x25\\xf5\\xff\\x78\\x1f\\xf4\\xff\\x4b\\x32\\xca\\x73\\x68\\x50\\x64\\x63\\xc7\\xe1\\x77\\x36\\xfa\\x12\\x0e\\x63\\x46\\x58\\xf3\\x2d\\x51\\x41\\x18\\xd6\\x43\\x99\\xd1\\xeb\\x8a\\xc7\\x90\\x5c\\x01\\xe2\\xb1\\xe1\\x89\\xde\\xfd\\xb1\\x73\\xc9\\x56\\x3b\\xc3\\xb5\\xad\\xb7\\x73\\x22\\x76\\xca\\xc0\\x70\\x65\\xb3\\x79\\x21\\x0c\\x40\\x4f\\x3b\\xf0\\xdd\\xce\\x97\\xd3\\x55\\x5a\\x09\\xdb\\x2e\\xda\\x3b\\xd6\\x27\\xd4\\x70\\x5f\\x95\\x8b\\xf7\\x53\\x03\\x68\\x44\\xb2\\x56\\x75\\xf8\\xb6\\x32\\x9e\\xd3\\x96\\xb4\\x55\\xd2\\x4b\\xf1\\xa7\\x30\\x39\\x3e\\x01\\x57\\xfd\\xc2\\xda\\xdd\\x72\\xc9\\x5c\\x17\\x7f\\xb4\\x2f\\x39\\x80\\xc4\\xdb\\x94\\x19\\x9a\\x44\\xd8\\xa1\\x15\\x57\\x15\\x06\\x31\\xab\\xe9\\x6c\\x8c\\x44\\xca\\xcb\\x22\\x73\\xbb\\x02\\x92\\x0c\\x00\\x6a\\x47\\x44\\x32\\xb5\\x56\\x07\\x3e\\x1f\\x1c\\x2b\\x76\\xcb\\x8d\\x6c\\x20\\x0f\\xb7\\xaf\\xdf\\x1c\\xb6\\x2f\\x62\\xc5\\x9c\\xa9\\x4e\\xd8\\xfb\\x1d\\x98\\xe1\\x7e\\xde\\x04\\xbe\\xe3\\x2b\\xf8\\x9c\\x97\\x70\\x76\\x16\\x42\\x8f\\xa6\\xde\\x5d\\x3e\\x93\\xf9\\x94\\xc7\\x31\\x98\\xd2\\xf8\\x20\\x9f\\xfc\\x57\\x23\\xb4\\x39\\x13\\x15\\xeb\\x6b\\x5c\\xbf\\x63\\x43\\xea\\x7a\\xdd\\x5c\\x13\\xbb\\x1a\\x13\\x20\\xe0\\x07\\xa0\\xa0\\xc4\\xd2\\x7c\\xe8\\x1f\\x7d\\x03\\x41\\xfd\\x1b\\x5a\\xb7\\xa5\\x61\\x18\\xa2\\x48\\x12\\x8f\\x62\\x8d\\x86\\x05\\x7a\\x25\\xe1\\x80\\x5a\\x77\\xfe\\xdc\\x1c\\x59\\x5d\\x25\\xf4\\x46\\x1c\\xdc\\xf5\\xfe\\x40\\x66\\x2a\\xd5\\x57\\x3c\\x11\\x13\\x19\\x57\\x5d\\x18\\x15\\x48\\x5c\\x5b\\x35\\xe4\\xb0\\x74\\xf7\\x02\\x50\\x5d\\x9f\\x52\\xd5\\xa4\\x58\\xb4\\x9d\\x94\\x69\\x21\\x5b\\x5a\\x4a\\x94\\x9b\\x50\\x4a\\xa9\\x96\\x29\\x8f\\x1a\\xb0\\x12\\x70\\x9f\\xb4\\xe6\\x21\\xbb\\x6f\\x71\\xa0\\xc0\\xd5\\x87\\xe9\\x05\\xf3\\x9c\\x61\\xf1\\x38\\x1c\\x2f\\x38\\x6e\\x16\\x1f\\xbf\\x10\\x6c\\xc9\\xcc\\xb6\\x8a\\xb9\\xb2\\xf8\\xa5\\x2e\\x5b\\xe9\\xbf\\xd7\\xbc\\x2b\\xff\\xbf\\x23\\x79\\x2a\\xb5\\x73\\x00\\xfe\\xb7\\xf3\\xa0\\xa3\\x28\\xbb\\xe6\\x69\\x91\\x96\\x78\\xfb\\x24\\xe6\\x33\\xd7\\xc0\\xc8\\x25\\x49\\x55\\x5d\\x0f\\x55\\x0f\\x98\\x3d\\x22\\x9a\\xe6\\x73\\x48\\x96\\xb6\\xae\\x07\\x27\\xb1\\xe6\\x89\\x9c\\xd2\\x84\\xa4\\x5c\\x98\\xc7\\xd8\\x3c\\x88\\xca\\x67\\x7e\\x26\\xf6\\xcf\\x5b\\x1e\\x04\\x62\\x95\\xcf\\xf9\\x34\\x61\\xd6\\xb7\\x51\\xeb\\xad\\x18\\xfc\\xb8\\x76\\x23\\x1c\\xad\\x04\\x9a\\x36\\x2d\\xa8\\x20\\x6f\\xb9\\x38\\x72\\x8e\\xd1\\xd7\\xe6\\xc8\\x5e\\xd3\\x34\\x4b\\x18\\xd6\\x0c\\x93\\x6f\\x47\\xff\\x91\\x82\\x11\\x9b\\xeb\\x33\\x24\\x6e\\x79\\x6c\\x0a\\x98\\x96\\xe4\\x25\\xca\\xe4\\xb2\\xa1\\xac\\x4f\\xe4\\xaa\\x72\\x50\\xe7\\x94\\x55\\xe4\\x9b\\xfd\\x6f\\xf6\\x5f\\xbe\\x32\\xea\\x28\\x46\\xfc\\xa8\\xb2\\x90\\x69\\xeb\\xd4\\x78\\x39\\x26\\x9f\\x88\\x99\\xc1\\x4b\\xfb\\xdf\\x6f\\xec\\x7f\\xbf\\x25\\x9f\\xc8\\x27\\x42\\x26\\x64\\x42\\xc2\\xff\\x9a\\xff\\x90\\x4f\\x64\\x64\\x88\\x10\\x4c\\xf5\\xe5\\xb0\\xca\\xb8\\x2a\\x88\\xdd\\x76\\x2f\\x80\\x18\\xc1\\xa1\\x81\\x55\\x44\\x32\\x65\\x30\\xd5\\x6f\\xfe\\x77\\x88\\x74\\xcc\\x35\\x91\\xc2\\xde\\xf9\\x72\\x0f\\xa6\\x34\\x20\\x57\\xe0\\x9f\\x4f\\xe9\\x25\\xfa\\xa6\\x0e\\x22\\x5d\\xd0\\xc4\\x3c\\x7c\\xef\\xdb\\xd1\\xcb\\x01\\x91\\xa2\\x7a\\xfb\\x92\\x4b\\xe8\\xdb\\x62\\x67\\xb8\\xf7\\x72\\x30\\x5e\\x9b\\xf2\\x37\\x1b\\xa6\\x5c\\x99\\x2d\\xcc\\x82\\x8a\\x15\\x0c\\x7d\\xf3\\x7e\\x77\\x5b\\xfd\\x40\\xac\\xae\\xe8\\xca\\x6f\\x78\\x27\\x37\\xe7\\x7c\\xe9\\xbb\\xbc\\x06\\xa0\\x49\\x90\\xb8\\x00\\xfb\\x97\\x3b\\x1c\\x3c\\x1c\\x74\\x45\\xb8\\x1e\\x93\\x13\\xbd\\xbb\\xab\\x20\\xec\\x80\\x6e\\x03\\xd7\\x8e\\xf6\\x28\\xc4\\xf7\\x05\\xc2\\xc3\\xde\\x78\\x51\\xab\\x6b\\x68\\x80\\x26\\xd9\\x69\\x84\\xe8\\x5e\\xfd\\x64\\xf1\\x4a\\xfd\\x29\\xe9\\x40\\x4d\\xf2\\x63\\x55\\xd0\\x37\\xd6\\x4f\\x7d\\xfd\\xe0\\xfa\\x1c\\xcc\\x5b\\x4f\\x77\\xad\\xdb\\xa1\\x63\\x43\\x97\\x56\\x25\\x2b\\x4f\\x7e\\xf9\\x4e\\x43\\x48\\x07\\x74\\xd2\\x93\\x58\\xf1\\x09\\x51\\x3f\\x45\\x3e\\xee\\x54\\xcf\\xe5\\xc7\\x1d\\x88\\x03\\x7a\\x55\\xdc\\x96\\xd4\\x5b\\xf5\\xc6\\xa2\\xb5\\xba\\x6d\\x1c\\x20\\x0a\\x1e\\x88\\xb8\\xcc\\xbe\\x6a\\x38\\x7f\\x68\\x5d\\x0a\\xe6\\xe7\\x1c\\x42\\x92\\xf9\\xfa\\x9b\\x04\\x19\\x5a\\x95\\x84\\x5e\\x73\\x0a\\x03\\xe0\\x78\\x72\\x80\\x1b\\x58\\x41\\x1c\\xf5\\x2e\\xf3\\xba\\x91\\x76\\x41\\x0b\\x01\\x50\\x98\\x7c\\x3c\\x29\\xc5\\x1e\\x8b\\xe6\\x76\\x7b\\xb0\\xd1\\xed\\xed\\x7a\\x26\\xfa\\x65\\x3d\\x99\\x6d\\x48\\xa9\\x2b\\x63\\x4d\\x08\\x96\\x6b\\x36\\x09\\x94\\x2a\\x85\\xfb\\x27\\xe8\\xe6\\xfa\\x72\\x03\\x72\\xac\\x3d\\x2e\\xaa\\x4a\\xae\\x17\\x76\\x23\\x95\\xcf\\x94\\x1a\\x9f\\xfb\\x4b\\x9d\\x7f\\x78\\x3b\\xbe\\x22\\x37\\x41\\x4b\\x6b\\x22\\x2c\\xbe\\x19\\xd6\\x66\\x6f\\x3f\\xff\\x6b\\x13\\x19\\xf2\\xcd\\xab\\xfb\\x09\\x07\\xfb\\xdf\\x8b\\xca\\x32\\x6f\\x5c\\xdd\\xbf\\xee\\x95\\xb3\\x1c\\x40\\x2e\\xc4\\x86\\x43\\x00\\x75\\x53\\x65\\x5c\\x7c\\xec\\x05\\x9a\\xe2\\xba\\xa0\\x58\\x6a\\x25\\xd8\\x95\\xcd\\x7f\\xbd\\xf9\\xa5\\x02\\xdd\\xdc\\x31\\xf7\\xa1\\x91\\x3f\\xb4\\x80\\xb6\\x9a\\x69\\x56\\x00\\x84\\x80\\x21\\xa4\\xd3\\xb4\\xbf\\xdd\\xfb\\x96\\x8c\\xc8\\x8b\\x81\\xd9\\x0d\\x02\\xb7\\x15\\x10\\x33\\x14\\x65\\x80\\x66\\x83\\xaa\\x80\\x5e\\x18\\xe5\\xc9\\x50\\x46\\x0d\\xb1\\x15\\x63\\x92\\xd4\\x85\\xd0\\x7d\\x14\\x6f\\x4f\\x9b\\xc7\\x55\\xba\\x1f\\x4b\\x16\\x08\\x19\\xb3\\x83\\x19\\xb4\\xd1\\x59\\x35\\x05\\xca\\xae\\xcb\\x84\\xd3\\xb5\\x31\\x03\\xd9\\xb0\\x90\\x57\\xe4\\xca\\x66\\x69\\xc3\\x96\\xb3\\xb5\\x86\\xe1\\x44\\xf6\\xcd\\x1f\\x7e\\x4f\\x01\\x3f\\xf3\\x2c\\xd9\\xaa\\x10\\x9e\\x95\\xda\\x63\\xa4\\x60\\xd9\\xdf\\x85\\x30\\x3f\\x23\\xf2\\xa3\\x14\\x32\\x7f\\x85\\xda\\x91\\x19\\x52\\x95\\xac\\xf8\\xe6\\xc7\\x21\\xab\\x09\\x41\\x4f\\x2a\\x02\\x41\\x19\\xf5\\xe6\\x04\\xac\\xc3\\x57\\x9f\\x1b\\xc5\\xdb\\x90\\x90\\x30\\x1e\\x7b\\x3e\\x76\\xdb\\xe0\\x08\\xfe\\x7e\\x43\\x66\\xb2\\x07\\x1a\\x5f\\x73\\x4d\\x99\\x6f\\xe1\\x75\\x6d\\x93\\xaf\\x71\\x6d\\xff\\xdb\\xf6\\x08\\x6e\\x43\\xbb\\x14\\xe7\\x5a\\x3b\\x16\\xb3\\x72\\x27\\x66\\x7a\\x8a\\x4b\\x81\\x4b\\x77\\xdb\\xb1\\x98\\x25\\x74\\xde\\x62\\xcf\\x37\\xb4\\xf7\\x0c\\x25\\x2f\\x20\\x2f\\xa1\\xcb\\x0d\\x1b\\x8e\\x78\\xeb\\x76\\x45\\xe4\\x2f\\xcc\\x8b\\x68\\xbd\\x35\\x71\\x57\\x18\\x8e\\x2a\\x0b\\x6d\\x47\\xad\\x34\\x15\\x84\\x8f\\x58\\x6c\\x6f\\x9c\\x49\\xe7\\x93\\x59\\xf3\\x5f\\x2c\\xa0\\xb4\\xb7\\xcc\\xcc\\x19\\x56\\xf6\\x5a\\x7d\\xd3\\xba\\x17\\xb8\\xc3\\x36\\x6d\\xb5\\x25\\xf1\\x99\\xcf\\x7f\\x4f\\x06\\x79\\x13\\x1d\\x24\\xeb\\xf9\\xb1\\x9c\\x11\\x7d\\xc9\\x40\\xfe\\xc1\\xca\\xa1\\xa3\\x6a\\x0c\\x74\\xb1\\xe6\\x8c\\x2d\\x44\\x41\\x9f\\x64\\xd9\\x9b\\xd8\\x45\\x65\\xb1\\x6d\\x6e\\x44\\x93\\x50\\x9b\\x32\\x1a\\x19\\x8f\\x59\\x8e\\x02\\x76\\xca\\x2a\\x65\\x4b\\x3e\\xdf\\x85\\xfc\\x52\\xde\\x89\\xe5\\x4a\\x90\\xd7\\x8d\\x03\\xfd\\x13\\xcb\\xc9\\x77\\xa6\\x45\\x74\\xc9\\xb4\\xf3\\x67\\xe7\\x50\\x69\\x91\\x15\\x9a\\x4c\\x69\\x42\\x45\\x64\\x36\\x6f\\x3d\\xbf\\x41\\x4b\\x1c\\x0c\\x7f\\x09\\x4f\\x41\\x8c\\x1c\\x5f\\x4e\\x83\\x43\\x07\\xd9\\x98\\x5c\\x28\\x6d\\x46\\xc3\\x34\\xcd\\x72\\x82\\x07\\x89\\x92\\x43\\x73\\x44\\xdd\\x00\\xeb\\xce\\x04\\x18\\xca\\xfe\\x1b\\x5d\\xf4\\x56\\x18\\x30\\xa6\\x6d\\xbd\\x5e\\xe0\\x57\\xb7\\x74\\xae\\x09\\x30\\xac\\x4a\\xaf\\xb2\\x89\\x31\\x61\\xe3\\x39\\x28\\xbc\\xb5\\x25\\xdb\\xa9\\x16\\x8d\\xba\\x3a\\xa4\\x9d\\x21\\xbe\\xb5\\x59\\x39\\x5b\\xc4\\x6b\\xbd\\x1d\\xb6\\x87\\x49\\xf0\\x56\\x22\\x86\\xda\\xf6\\xfa\\xc0\\xfe\\x8e\\xea\\x13\\x8c\\x3a\\xe4\\x46\\x07\\xb5\\xf5\\xf6\\xd1\\x4f\\xf4\\x26\\x8b\\xf7\\xa1\\xcf\\xcc\\x9a\\x7d\\xdf\\xde\\xe1\\xb6\\xae\\xf2\\x57\\x39\\x39\\x64\\xde\\xd0\\xc4\\x55\\xc4\\x40\\x53\\x58\\x0f\\x30\\x2f\\x76\\x77\\x4b\\xcf\\x00\\x1c\\x05\\xe4\\x2c\\xa5\\xed\\x62\\xb8\\x68\\xc5\\x76\\x20\\x7b\\x4e\\xf5\\x23\\x9a\\x25\\x09\\x1e\\xd6\\xd2\\x84\\x32\\xaa\\x70\\xd8\\x78\\x8d\\xc3\\x08\\x55\\x2f\\xc6\\xc6\\x1f\\x6e\\xe8\\xd6\\x86\\x8e\\xb2\\x95\\x87\\x86\\x1c\\x92\\x69\\xa1\\xc9\\x9c\\x2f\\x8d\\x00\\xb8\\x93\\xd3\\x03\\x1d\\x3b\\x0b\\x96\\x64\\x24\\x67\\x71\\x11\\x59\\x28\\x07\\x90\\x4e\\x07\\xa1\\x85\\x06\\x99\\xeb\\x9e\\x3b\\xec\\x54\\x08\\xba\\x63\\xd1\\x25\\xab\\xc2\\x87\\xcf\\xe0\\x80\\x80\\xa2\\xc5\\x67\\x84\\x2d\\x59\\xbe\\x22\\x99\\x54\\x0a\\x8e\\x21\\xb0\\x2d\\x2c\\x68\\x84\\xd8\\x99\\x47\\xb1\\x06\\x6b\\x02\\x66\\xe5\\x14\\xf8\\x1d\\xab\\xc1\\xef\\x80\\x85\\x2b\\x2b\\xac\\xe8\\x61\\x1c\\x7a\\xdf\\xee\\xbf\\xdc\\x7f\\x79\\xbb\\x31\\x36\\x81\\xff\\x95\\x1e\\x3a\\xf7\\xdf\\x93\\xd9\\x06\\x9b\\xb3\\x9c\\x4b\\x65\\xe7\\xdc\\xc7\\x89\\xf7\\x0d\\xf8\\xda\\xbe\\x1d\\x04\\xbe\\xbc\\x6f\\xf7\\xbf\\xd9\\x7f\\xb9\\x67\\xe6\\xfa\\xcd\\xc0\\xcc\\x3a\\xf0\\xd2\\x7d\\x13\\x78\\xe9\\xfc\\x2f\\xed\\x8c\\x98\\xaa\\xf8\\xe9\\x4e\\x84\\xad\\x5e\\xbd\\x92\\x79\\x6c\\xb3\\x74\\x5d\\x25\\xa4\\x99\\x11\\x22\\x04\\x1a\\xd9\\x90\\x3a\\x5e\\x8e\\xdb\\xae\\xea\\x25\\xd8\\xd5\\xe8\\x2e\\xe4\\x9a\\xfc\\x39\\x95\\x39\\xfb\\x73\\x70\\xff\\x8d\\xfe\\xb5\\xe6\\x6e\\xb3\\x47\\xee\\xa1\\xd6\\x3c\\x45\\xb2\\x6d\\x82\\x64\\x37\\xcd\\xd8\\xb0\\x91\\x4f\\x9b\\x9c\\xe6\\xdd\\x37\\xae\\xff\\x25\\x0e\\x65\\x93\\xc7\\xd0\\xa9\\x9b\\xda\\x24\\xc7\\xe9\\x2a\\xac\\x89\\x9e\\x32\\xa3\\xd2\\xa2\\x0f\\xac\\x04\\x18\\xbc\\x67\\xbf\\x5f\\xa5\\x65\\x4e\\xe7\\x6c\\xdf\\x3e\\xb6\\x49\\x05\\xf3\\x63\\xe4\\x22\\xff\\x8c\\x9d\\x93\\x2a\\x99\\x42\\x08\\xdd\\x64\\x7b\\x2a\\xb9\\xb2\\x74\\x97\\x43\\x0a\\x5c\\x80\\x46\\x50\\xd1\\x09\\x84\\xac\\x80\\x83\\x06\\xb5\\xa2\\x4f\\x24\\x1d\\xf9\\x81\\x3b\\x46\\xd2\\x2b\\x75\\x9c\\x50\\xa5\\x79\\xf4\\xaf\\x44\\x46\\x97\\xe7\\xda\\x58\\x3d\\xad\\x55\\x8b\\x4d\\xa3\\x56\\xd6\\x54\\x90\\x83\\x5f\\xce\\xc9\\x11\\x57\\x97\\x65\\xdb\\x64\\x6c\\x81\\x53\\x2d\\xa2\\xa4\\x1e\\x02\\xda\\xe2\\x69\\x90\\x94\\x46\\x0b\\x54\\x5d\\xad\\x0f\\xda\\xb5\\x01\\xeb\\xee\\xac\\xfc\\x89\\x5e\\x29\\x86\\xd3\\x87\\xb6\\xb4\\xe6\\x6b\\xd6\\x9c\\x05\\x3f\\x1a\\xe6\\x24\\xbe\\xce\\xc9\\xd1\\x23\\x24\\x2f\\xcf\\xd4\\x45\\x63\\x40\\xeb\\xf5\\x66\\x72\\xae\\x2b\\x01\\xe2\\x42\\x24\\x0c\\xab\\x8d\\x10\\xdf\\xbb\\xda\\x20\\x0e\\xf6\\xd0\\x4a\\x16\\xe4\\x8a\\xa2\\x5d\\x0d\\x1c\\x76\\x4c\\x2e\\x78\\xf6\\x8a\\x1c\\x07\\xad\\x96\\x36\\x0d\\x65\\xb4\\x0f\\x8f\\xdc\\x6a\\x0d\\x6a\\xd8\\x73\\x98\\x8c\\x64\\x18\\xb2\\xad\\x73\\x22\\xc7\\xa8\\x5a\\xa9\\x57\\x64\\x87\\x5d\\xeb\\xbf\\xec\\x0c\\xc9\\xce\\xf5\\x4c\\x99\\xff\\x08\\x3d\\x83\\xd6\\x6c\\xb6\\x15\\xb7\\xd1\\xf1\\xc4\\x8c\\xe5\\xa5\\xe9\\x88\\x3f\\x58\\x07\\x83\\xea\\x7e\\xcb\\x92\\x8b\\x77\\x47\\xef\\x5e\\x81\\x2e\\x1f\\x4b\\x63\\xf5\\x65\\x39\\x5b\\x1a\\x9d\\x92\\xe5\\xb9\\x2c\\xb1\\x37\\x02\\x32\\x40\\xfa\\x4c\\x24\\xd3\\x2c\\x97\\x29\\x0f\\x0a\\x90\\xe1\\xc8\\x35\\x39\\x01\\xa4\\x8b\\x0c\\x38\\x30\\x6c\\x61\\x33\\x74\\xb2\\x9f\\xfc\\x70\\x6e\\x4b\\x05\\x1f\\x88\\xbb\\x6c\\xa6\\x93\\x19\\x91\\x98\\x28\\x50\\x85\\x40\\xe0\\xca\\xdf\\x64\\xb6\\x8f\\x1d\\x45\\x00\\xae\\x54\\xb9\\x61\\x8c\\x66\\x6e\\xbf\\xda\\x8f\\xd9\\x72\\x5f\\xc5\\xf4\\xe5\\x10\\x1e\\x83\\xbb\\x61\\x55\\x9b\\x13\\x55\\x64\\xe7\\xe5\\xce\\x98\\x9c\\xf3\\x94\\x27\\x34\\x4f\\x6c\\xc7\\x6b\\x3b\\x44\\x79\\x9f\\x31\\x14\\xdc\\x80\\x60\\xfe\\xbe\\xd8\\x21\\x7b\\x88\\x41\\x00\\xea\\x46\\xc2\\x1c\\x20\\x9d\\x47\\x2a\\x85\\x24\\x9d\\x41\\x23\\xed\\x92\\x74\\xe0\\x8c\\x27\\xad\\x1d\\xf2\\x04\\xb8\\x24\\x8d\\xdf\\x89\\xa4\\x71\\xe6\\x76\\x75\\x73\\xb8\\xd1\\x5c\\x01\\x5f\\x5e\\x58\\x7f\\xe6\\x4c\\xe6\\xd6\\x08\\xf4\\xb7\\x38\\xa0\\x23\\x2e\\xac\\xda\\xf2\\xd6\\x2c\\xbd\\xda\\x1a\\xf1\\x43\\x3a\\x00\\xdf\\x23\\x5e\\x8a\\x74\\x43\\x5f\\x37\\x1a\\xa4\\x22\\x60\\xab\\xe8\\x93\\x23\\xc7\\xc4\\x33\\x96\\x2b\\xae\\xb4\\x61\\x51\\x71\\x45\\x35\\xe0\\xa8\\x2f\\xec\\x1d\\xa4\\xf4\\x3f\\x52\\x90\\xe3\\x7f\\x9d\\xdb\\x69\\x0d\\xb6\\x90\\xd8\\x0d\\x39\\x1d\\xfd\\x4f\\x91\\x33\\xa3\\x11\\xb5\\x56\\xbf\\xfc\\x48\\x75\\x95\\xcb\\x7c\\x4e\\x8e\\xa8\\xa6\\xa8\\x79\\x21\\xa7\\x92\\x25\\x38\\x18\\xb6\\xaa\\x87\\xa2\\x2d\\x87\\xfc\\xd6\\x50\\x79\\x26\\x8f\\xaf\\xfd\\x98\\x1d\\x74\\xda\\x1c\\x75\\xdb\\xfc\\xfc\\xfd\\xd9\\xc9\\x23\\xe8\\x4e\\x11\\x88\\xdb\\xf9\\x5b\\x19\\x77\\xa4\\x40\\x05\\x03\\x3a\\x91\\x07\\xa0\\xa6\\x87\\xf8\\x39\\x49\\xcd\\x93\\xc8\\xa9\\x14\\x6c\\x48\\xce\\x18\\x8d\\x89\\xe1\\x6e\\xf6\\x9f\\xbf\\xe4\\x5c\\xdf\\x17\\xff\\xaa\\xbc\\x5a\\x8b\\x7e\\xb7\\x88\\x9d\\x10\\xc2\\x0d\\xe6\\x88\\x10\\x36\\xba\\x07\\x80\\x4e\\x60\\x3a\\x56\\x07\\x98\\x26\\x72\\x4a\\x2c\\xb3\\x78\\xcc\\xb7\\x7f\\x7f\\x76\\xd2\\xd9\\xcb\\xbf\\x3f\\x3b\\x71\\xef\\x6e\\xfe\\x29\\x67\\xdb\\xf9\\xda\\x1d\\x1a\\x0f\\xa5\\xed\\xf0\\xba\\xa6\\xec\\x97\\xea\\x5c\\xd9\\x8f\\xa8\\x6e\\x10\\xdc\\xdd\\x1a\\x18\\x77\\x65\\x07\\x3c\\x16\\xcd\\x2f\\xb9\\x68\\x5c\\x03\\x58\\xe5\\x36\\xd0\\x6c\\xc8\\x43\\x62\\x05\\x41\\x34\\x40\\xe2\\x8b\\x5f\\x91\\xb4\\x48\\x34\\xa0\\x1e\\xc1\\x5e\\x33\\x9b\\x0f\\xb2\\xc5\\xdc\\xae\\x23\\x16\\x01\\x94\\x90\\x23\\x86\\xe1\\x88\\xf8\\x95\\xab\\x43\\xf1\\xbf\\xd8\\xfc\\x83\\xb7\\x54\\xd0\\xb9\\xb9\\x1d\\x24\\x20\\x49\\xf1\\xcf\\x60\\x93\\xef\\xa1\\xd3\\x5d\\xf8\\xaf\\xe8\\x92\\xf2\\x84\\x4e\\x79\\xc2\\x35\\xe8\\x73\\x83\\xb1\\xd3\\xe6\\xb1\\x54\\x01\\xa6\\xfc\\x68\\xdc\\xaf\\x53\\xd5\\xd6\\xab\\xad\\x21\\x3e\\x0c\\xc0\\x1b\\x92\\x3d\\xf3\\xdd\\xfe\\x95\\x61\\xf5\\x83\\x31\\xf0\\x7d\\xb8\\x11\\x50\\xdb\\x6b\\xca\\xef\\xd9\\xe7\\x94\\xdf\\x47\\xd1\\x53\\x61\\xbd\\x5f\\x37\\x6c\\x94\\xb6\\xae\\x3b\\x99\\x91\\x36\\xea\\x4e\\xf0\\x85\\x05\\x1d\\x7d\\xe6\\xea\\x13\\x36\\xab\\x6f\\xa1\\x40\\xc1\\xd9\\x69\\xf8\\xfb\\xb6\\x2a\\xd4\\x97\\x39\\x38\\xf1\\xf3\\x3b\\x38\\x04\\x5b\\x4a\\xda\\x95\\xee\\x84\\x5c\\xe5\\x70\\x4e\\xd7\\xf0\\xe0\\xd2\\xf8\\x55\\xad\\x7c\\x1e\\x4f\\xd6\\xb9\\xe5\\xe5\\x0e\\x74\\x1a\\x7e\\x6f\\xce\\x53\\x13\\x70\\x0d\\xbc\\x5a\\xb3\\x5f\\xbf\\x83\\xbb\\xa1\\x8b\\x1b\\xcd\\x91\\x05\\x85\\x14\\x7c\\x4c\\x1a\\x9f\\xb3\\x96\\xaf\\x19\\xb1\\x6c\\x31\\x6b\\x9f\\xd9\\x6e\\x86\\x79\\x7d\\x5e\\x8d\\xda\\x1c\\xb2\\x6c\\x41\\x5e\\x9f\\x6f\\x60\\x93\\x58\\x55\\x60\\xde\\x5b\\x61\\x2c\\x67\\x57\\x91\\x84\\xcf\\x98\\xe6\\x8d\\x88\\xf0\\xc8\\x8c\\x32\\x95\\x82\\x6b\\x99\\xab\\x47\\x60\\x73\\xee\\xd1\\xdd\\x28\\x6e\\x6e\\x34\\xb3\\x3f\\xcf\\x1c\\x51\\xc8\\xdb\\xe0\\x53\\x4a\\x22\\x99\\x24\\x2c\\x72\\xb9\\xfe\\xb0\\xc4\\xfe\\x67\\x1b\\x1c\\x31\\x36\\x03\\x41\\x8d\\x2f\\xff\\x0e\\xae\\x18\\xeb\\x74\\xd9\\xc7\\x6d\\xb7\\x7f\\x76\\x7c\\x70\\xf4\\xf6\\x78\\x9c\\xc6\\x7f\\x5a\\xc8\\xab\\x91\\x96\\xa3\\xff\\x8f\\xbd\\x77\\xed\\x6e\\x1b\\xb7\\x16\\x86\\xbf\\xf7\\x57\\x60\\xf9\\x74\\x2d\\xdb\\x53\\x49\\x4e\\xa6\\x3d\\xed\\x69\\x9e\\x9e\\xce\\x72\\xed\\x64\\x1e\\x9f\\xc9\\xc5\\x8f\\x9d\\x99\\x59\\xe7\\x4d\\x72\\xce\\x40\\x24\\x24\\xa1\\x26\\x01\\x0e\\x01\\xca\\x51\\x3b\\xfd\\xef\\xef\\xc2\\xde\\x00\\x08\\xe8\\x4a\\x49\\xf4\\x2d\\x43\\x7e\\x49\\x4c\\x91\\x20\\xb0\\xb1\\xb1\\xef\\x97\\x4a\\xb1\\x3e\\xd7\\xfb\\xc9\\x5b\\x0f\\x58\\x4f\\xa4\\x05\\x4b\\xb7\\x9e\\xb4\\x65\\xe4\\xd6\\x13\\xb3\\x65\\x75\\x51\\xeb\\xef\\x55\\x5d\\x76\\xde\\xf9\\x9d\\x4b\\x29\\xf5\\x62\\xe1\\xf9\\x51\\x95\\x65\\xb8\\xb7\\xba\\x64\\xac\\x17\\xda\\xb7\\xb7\\x2c\\xcb\\x5f\\x5f\\x8f\\x4b\\x16\\xae\\xcd\\xbc\\x11\\x88\\xee\\x56\\x32\\x7e\\x2c\\x07\\x64\\x7f\\x59\\x61\\x57\\x49\\x9b\\x2c\\xec\\x43\\x3d\\x5e\\xbc\\x13\\xd7\\xd1\\x7d\\x74\\x88\\xe8\\x89\\xd9\\x97\\x1b\\x36\\x23\\x50\\x3a\\x62\\x24\\x4b\\x68\\xe3\\x12\\xe3\\x27\\xd3\\x09\\x00\\xef\\xa4\\x52\\xac\\x1c\\x58\\x81\\xe3\\x91\\x00\\x7e\\x1f\\x51\\x04\\x16\\x72\\xc5\\x46\\x6d\\x82\\xfd\\x8a\\x8d\\x96\\x41\\xdd\\xde\\x86\\x5a\\xb7\\x3e\\x3c\\xce\\xc8\\x2b\\x95\\x9e\\x60\\x6c\\x2c\\xd6\\xd8\\x46\\xd8\\x2e\\xdd\\x06\\x5b\\xfb\\xe3\\x91\\xc0\\x7d\\xaf\\xaa\\x0d\\x6d\\x54\\x16\\xda\\xa7\\x93\\x22\\x59\\xd8\\xbc\\xd0\\x6c\\x69\\x37\\x49\\x6f\\xed\\x06\\x91\\x53\\xa3\\xc5\\xb2\\xdb\\x93\\x5b\\x59\\xde\\x70\\x31\\xee\\xdf\\x72\\x3d\\xe9\\x23\\xa4\\xd4\\x09\\x54\\xfc\\x3f\\xf9\\x37\\xf8\\xc7\\x7a\\x91\\x4f\\xd3\\xd4\\xc6\\xbf\\x55\\x8a\\x8d\\xaa\\x0c\\x23\\xd3\\xd4\\x80\\xd0\\x82\\xff\\xc0\\x4a\\x05\\x51\\x96\\x37\\x5c\\xa4\\x3d\\x52\\xf1\\xf4\\x9b\\x5d\\x77\\x8c\\xb4\\x71\\x5a\\xcc\\xd9\\x6f\\xe7\\xa0\\x40\\x4f\\x27\\xae\\x6c\\x07\\x43\\xcb\\x46\\x4b\\x47\\x93\\x4a\\x9a\\x4a\\x85\\x7d\\x9f\\x0c\\xa8\\xa2\\x23\\x40\\xd3\\x9c\\x8b\\xc7\\x72\\x02\\x76\\xd5\\x0e\\xb8\\x48\\x77\\x83\\xe4\\x9c\\x03\\x02\\xc6\\x89\\xd5\\x03\\x7b\\xcf\\xba\\xb1\\x7d\\xcc\\x0f\\x75\\xd6\\x13\\xec\\x1e\\x6f\\xa3\\x7f\\xe2\\xd8\\x9f\\x46\\x84\\x25\\x9f\\xa9\\x9f\\xb3\\x3e\\x7e\\xa5\\x5f\\xa4\\x35\\x5c\\xbb\\x40\\x9e\\x6d\\xae\\xfb\\x0b\\xe4\\x69\\xd7\\x20\\x7f\\x0f\\xe1\\x39\\x77\\x8a\\x71\\xe4\\x11\\xcb\\xcc\\x77\\x6b\\x07\\x7b\\x40\\x50\\xef\\x2f\\x19\\xdf\\x8d\\x84\\x56\\x73\\x1f\\xe8\\x49\\xa8\\x5c\\xa1\\x3c\\x10\\xc0\\x90\\x2a\\x39\\x7b\\x1a\\xc4\\xc8\\xd7\\x4d\\xb0\\x5c\\xb5\\x87\\x44\\x0a\\x61\\xfb\\x23\\xbc\\x2b\\x98\\xb8\\xd6\\x34\\xb9\\xd9\\xd3\\xab\\xdb\\x49\\x55\\xbf\\x32\\xa9\\xea\\x8e\\x02\\x81\\x1c\\x8a\\x62\\xe2\\x9d\\x0d\\x7f\\xab\\x83\\xbd\\xf1\\x90\\x3f\\x41\\x02\\x8c\\xcd\\xfe\\xde\\xd0\\x62\\x7f\\xeb\\xaa\\x1b\\x69\\x4e\\x82\\xf2\\xb7\\xad\\x41\\x15\\x92\\x83\\x0a\\x59\\x40\\xb1\\x31\\x9b\\x82\\x0a\\x70\\xbc\\x7f\\x89\\x67\\xdf\\xf3\\x6d\\x59\\x4c\\x7b\\x31\\x30\\xc1\\x80\\x31\\x45\\xcd\\xcd\\x9d\\x21\\xd7\\x35\\xad\\x54\\x4c\\x63\\x29\\x28\\x5b\\x22\\x59\\x0a\\x92\\xd8\\x72\\x0f\\x20\\x8f\\x04\\x45\\x0c\\x02\\x59\\x45\\x10\\x99\\x68\\x97\\x35\\xea\\xab\\x46\\x3d\\x7b\\xf6\\xec\\x19\\x56\\xc2\\xf9\\xd3\\x9f\\xfe\\x44\\x64\\x09\\xbd\\x48\\x13\\x9e\\x2f\\x3e\\x08\\x4f\\xfd\\xfb\\xf3\\xe7\\x03\\xf2\\xdf\\xa7\\x6f\\x5e\\x43\\x46\\x43\\xa1\\x15\\x56\\x7d\\xc3\\x91\\xcd\\x03\\xd1\\xcb\\xaa\\x47\\xfe\\xeb\\xfa\\xdd\\xdb\\xba\\x46\\x43\\xfc\\x2b\\xa8\\xe6\\x7e\\x79\\x71\\x5f\\x90\\x67\\x7f\\xfc\\xc3\\x1f\\x06\\xe4\\x9c\\x97\\x90\\xd1\\xc5\\x99\\xef\\xcd\\xee\\x4d\\x2d\\xb4\\x64\\x58\\xb9\\x07\\x6a\\xa8\\x38\\x89\\x8b\\xfb\\xf6\\x8e\\x36\\x3f\\x39\\xe7\\xe3\\x89\\xb6\\x19\\xb1\\x06\\x21\\x33\\x9e\\x68\\x4c\\x1e\\x43\\xb2\\xe6\\x5a\\xbf\\x63\\x4b\\x11\\xdb\\xa4\\xc7\\x4a\\x7f\\x30\\xb9\\x1e\\xc9\\xf8\\x0d\\x23\\x23\\xf5\\x6d\\x29\\xab\\xa2\\x2e\\xf3\\x88\\x05\\x5a\\x5c\\xa2\\x0c\\x0e\\x56\\xef\\x95\\x62\\xfa\\x89\\x87\\xad\\xee\\x65\\x6a\\x8e\\x70\\x1b\\x46\\x9a\\x13\\x58\\x6d\\x7a\\x6b\\x5d\\xea\\xb0\\xa0\\xdc\\x27\\xc3\\x40\\x04\\x60\\xd4\\x03\\xd4\\xdb\\x7a\\x52\\x72\\xe6\\xa9\\x8a\\xab\\x39\\x52\\x94\\xf2\\xef\\x88\\x02\\x90\\x8b\\x1c\\x90\\x67\\xc8\\x15\\x86\\x9d\\xb4\\x99\\xc2\\x81\\x77\\xcb\\xe5\\x53\\xdb\\xe6\\xec\\xee\\xb6\\xed\\x64\\xb3\\xd8\\x0e\\x2c\\xe3\\xca\\x7c\\x02\\x8a\\xfd\\xac\\xf9\\x72\\xdd\\xcb\\xd8\\x60\\xa9\\x42\\x7c\\xa9\\xc4\\xc2\\xdb\\xb6\\xb0\\x8a\\x25\\x97\\xb6\\x09\\xa8\\xad\\xaf\\x58\\x8f\\x81\\xe5\\x01\\x6c\\x1d\\x1c\\xfb\\xac\\x83\\x92\\x07\\x44\\x14\\x6f\\xad\\x98\\xae\\x2c\\x68\\x20\\x8a\\xde\\x7c\\x1b\\x1a\\x54\\xc2\\x0a\\x73\\x5a\\xde\\x18\\xc5\\xd5\\x52\\x97\\x01\\xb9\\x34\\x93\\xf4\\xa5\\x74\\xb0\\xd8\\xf1\\x14\\x1d\\x9b\\x39\\x9d\\xc1\\x67\\xad\\xe0\\x06\\x1f\\x39\\x1c\\x0c\\x0e\\xf1\\xf8\\xc9\\x92\\x28\\x4d\\x4b\\x7b\\x96\\xcc\\xfd\\x2f\\xa3\\xca\\xfa\\x1b\\x5a\\x28\\xac\\xfa\\x6b\\x24\\x55\\xa8\\x88\\x2d\\x21\\x77\\x5d\\x4f\\x1c\\x09\\xa2\\x16\\xd6\\x5d\\x65\\x74\\xd2\\x07\\xc0\\xec\\x3c\\xc0\\x23\\xaf\\x8a\\x6e\\x77\\xdf\\x9e\\xf2\\x47\\x51\\xb2\\x3b\\xdf\\x43\\xe0\\xc0\\x6b\\xde\\xa7\\x9a\\xce\\x79\\x36\\x1a\\xc9\\x1b\\xb6\\x2b\\x54\\xc6\\x9e\\x94\\x80\\xb1\\xbc\\x0b\\xac\\x25\\x9c\\xa1\\x00\\x16\\xb6\\x07\\x7d\\xba\\x72\\x04\\x5e\\x6d\\x48\\x13\\x78\\xed\\x2f\\x53\\xe0\\xb5\\x8f\\x13\\x19\\xaf\\x08\\x87\\x9d\\x27\\x19\\x81\\x69\\x19\\x18\\xf2\\xa8\\x51\\xbd\\x05\\xd0\\xab\\xaf\\x08\\x8e\\x35\\x36\\xb6\\x75\\x0d\\x9a\\x05\\xa1\\x43\\x25\\xb3\\x4a\\xe3\\xab\\xf5\\x8f\\x21\\xf7\\x83\\x41\\x5d\\xcd\\x70\\x60\\x79\\xfe\\xb1\\x80\\x17\\x82\\x14\\x80\\xec\\x63\\x1f\\xb6\\x88\\xd7\\xde\\x64\\x63\\x1f\\x23\\xc4\\xaf\\xc8\\x00\\xb1\\x37\\x9c\\xbd\\xc2\\xd6\\x06\\xac\\xdd\\x60\\x3e\\xe3\\xee\\x76\\xc2\\x6c\\x08\\x44\\x20\\xf7\\x19\\x6a\\x6a\\x68\\x04\\x08\\x95\\x4e\\x84\\xc3\\xc2\\x39\\xe9\\x83\\x98\\x19\\x13\\xc5\\xf7\\xb7\\x25\\x28\\x4e\\x8e\\xce\\x7c\\x7a\\xbc\\x0b\\xbb\\xbb\\x10\\x9a\\x95\\x23\\x9a\\xb0\\xe3\\xd0\\xc6\\xc0\\x8a\\x09\\xcb\\x59\\x69\\x00\\x65\\x9f\\x73\\x39\\xda\\x13\\x2a\\x52\\x5b\\x76\\x2a\\x61\\x25\\x9c\\x60\\xf6\\x59\\xb3\\xd2\\x00\\xf5\\xec\\xfa\\x82\\xa4\\x25\\x9f\\xb2\\x52\\x91\\xa3\\xbf\\x41\\x39\\x41\\x2c\\x37\\x75\\xfc\\x04\\xc3\\x60\\x71\\x21\\x0f\\x61\\x01\\x81\\x0f\\xb7\\x93\\xfa\\x01\\x43\\x39\\x1a\\x2e\\x02\\x3a\\x53\\x6f\\x95\\xab\\x8d\\x65\\xb6\\x55\\x85\\xb6\\xa3\\x81\\x39\\x10\\xc0\\x42\\x81\\xfa\\x42\\x47\\x6b\\xf4\\x6d\\xba\\x62\\xf6\\xd0\\x78\\x2b\\xd1\\x38\\x30\\x55\\xa4\\x64\\x63\\xa3\\x8d\\x95\\x41\\xd1\\x3e\\x2c\\x93\\xf2\\x60\\xc9\\x0d\\xed\\x27\\x94\\xd4\\xce\\xaa\\x75\\xb9\\x1f\\x23\\xab\\x57\\xca\\x29\\x4f\\x9d\\x38\\x84\\x85\\xf1\\x7d\\x69\\xb8\\x82\\xaa\\xa0\\x78\\x01\\x55\\x4a\\x26\\x1c\\x4c\\x4d\\xc1\\xd6\\xa0\\x96\\x0a\\x42\\x53\\xdc\\x0a\\xcd\\xb9\\x9b\\x43\\x37\\x99\\x84\\x86\\x42\\x3b\\xf5\\x61\\x25\\xad\\x30\\x44\\x99\\xb2\\xcb\\x6a\\x98\\x71\\x35\\xb9\\x6e\\xd5\\x25\\xb2\\x6c\\x60\\x0c\\x4a\\x5c\\x88\\x54\\x59\\xe9\\x19\\x51\\x4c\\x28\\x6e\\xdb\\xe6\\xa3\\xb8\\xc5\\x25\\x74\\x59\\x30\\xdb\\xe0\\xde\\x0e\\x0f\\x85\\x84\\x6c\\x78\\x68\\xc6\\xef\\x7e\\x7a\\x5b\\xcf\\xc3\\x16\\x2b\\xc1\\x2e\\xd0\\x29\\xfb\\x5e\\x14\\xd1\\xfd\\x84\\x66\\x99\\xb2\\xf2\\xad\\xef\\x71\\xe2\\x78\\x0f\\x4a\\xa8\\xae\\x80\\x09\\x62\\x05\\x37\\x08\\xe3\\x66\\x0f\\x21\\x38\\x48\\xbc\\x7c\\x43\\x9e\\xa5\\x0b\\x53\\x41\\xb9\\x61\\x29\\xdc\\x43\\xd0\\xcc\\xda\\xbd\\xe0\\x21\\x84\\x99\\x38\\x88\\x74\\x0f\\xd8\\x0a\\xa5\\x73\\xff\\x3c\\x3d\\xf7\\xcf\\xdd\\xe4\\x54\\xd4\\x2d\\x46\\x29\\xdc\\xec\\x43\\x86\\x16\\xba\\x36\\x2a\\xdb\\x36\\xd7\\x31\\x1a\\xc7\\x90\\x36\\x84\\x69\\x3e\\x98\\x0b\\x18\\xe7\\x77\\xaa\\x6d\\x2f\\x8a\\x76\\xac\\xbb\\xf3\\x83\\x82\\x28\\x66\\x54\\x71\\xa0\\x50\\x7d\\x0b\\xbf\\x24\\x38\\x52\\x56\\x47\\xf6\\xe7\\x7c\\x91\\xae\\xd5\\x3c\\x1d\\xd8\\x39\\xde\\x3c\\x54\\x24\\x95\\x49\\x65\\x94\\xaf\\x1a\\xec\\x75\\xc0\\xc5\\x7e\\xdd\\x0a\\xbf\\xac\\xf6\\x49\\xa9\\xbc\\x15\\xb7\\xb4\\x4c\\x4f\\x2f\\x77\\xca\\xcd\\x8d\\x85\\xb3\\x7a\\xac\\x50\\xf4\\x76\\xb7\\x89\\xb9\\x4f\\x87\\x50\\xf0\\xd6\\xd6\\x36\\xec\\xbc\\x7d\\x4b\\x87\\x08\\xa9\\xf9\\x32\\x73\\x9b\\x96\\x86\\xc8\\x36\\xf4\\xe6\\x6d\\x6b\\xb0\\xeb\\x1c\\x84\\x9d\\x83\\x30\\xba\\x1e\\x93\\x83\\xf0\\x02\\x1d\\x84\\x61\\xa7\\xdf\\x88\\xbc\\x58\\x0b\\xad\\x81\\xf8\\x17\\xe1\\x63\\x3a\\xaf\\x49\\x2a\\x4a\\xe2\\xf3\\xf9\\xbc\\x73\\xc2\\x3f\\x1e\\xde\\x1a\\xeb\\x02\\x85\\xc1\\xd1\\x5c\\x90\\xcb\\xbe\\x04\\x7f\\xd4\\x23\\xf0\\x27\\x01\\x2c\\xf7\\xd0\\x0a\\xf1\\x8a\\x09\\x7e\\x9d\\xaf\\x86\\x55\\x6a\\xd1\\x31\\x1d\\x78\\xb8\\x0b\\x99\\xda\\xde\\x06\\xd0\\x74\\x03\\x1b\\x08\\xf4\\x7c\\x67\\x40\\xe1\\xd2\\x4d\\x41\\x3a\\x2f\\x68\\xc2\\x80\\xbe\\x79\\xf1\\xa7\\x15\\x27\\xc1\\x9e\\x08\\x40\\x5a\\x42\\x02\\x02\\x88\\x00\\xd0\\xb9\\xdc\\x07\\x1b\\x48\\x6b\\x18\\x61\\xae\\x5a\\xe3\\xd9\\x77\\xa4\\xf9\\x8a\\xa2\\x38\\xaa\\x43\\x04\\x95\\x4c\\x58\\x4e\\xe1\\xbf\\xaf\\x1c\\x08\\x0c\\x6d\\x34\\xca\\x83\\x66\\x58\\x02\\x8e\\x95\\xb9\\x22\\x72\\xd4\\x8b\\x22\\x5d\\x0f\\xa6\\xcf\\x0f\\xf6\\x73\\x36\\x90\\xf6\\xfc\\x94\\xc4\\x9d\\xa3\\xcb\\xbd\\x9d\\x3d\\x64\\x1e\\x60\\x97\\x91\\x6f\\xc7\\x9c\\xa1\\xba\\x07\\xa6\\xab\\x7b\\xef\\x23\\x28\\x80\\x7f\\x20\\x84\\x1f\\x0d\\x70\\xda\\x76\\xe2\\xee\\xea\\xbc\\xed\\x79\\xaf\\xc1\\x13\\x10\\xfe\\x3a\\xe7\\xed\\x97\\xe8\\xbc\\x0d\\x18\\xa3\\x23\\x74\\x4b\\x1c\\xb9\\xa1\\x4b\\xc0\\x79\\x73\\x87\\xcc\\x29\\x35\\x56\\x87\\x71\\xae\\x5c\\xe7\\xc7\\x95\\x65\\x1c\\xba\\x74\\x38\\x18\\x1c\\x1e\\x3a\\xef\\xae\\xc5\\xfb\\x4a\\x8f\\xfa\\xff\\x41\\x98\\x48\\x64\\xea\\x1a\\xf8\\x8e\\x78\\xa9\\x34\\x88\\x7b\\xb5\\xb9\\x2d\\x9c\\x4b\\xee\\xbe\\x15\\x86\\x3f\\xc1\\xd8\\x6d\\x6c\\xf5\\xde\\xb4\\xc5\\x95\\x24\\x7c\\x75\\x07\\x42\\x4c\\x2d\\xba\\xf8\\xc2\\x87\\x16\\x44\\xbe\\x9e\\xb5\\x95\\x61\\xdc\\xef\\x8a\\x64\\x3c\\xe7\\xb6\\xff\\xbd\\x39\\xe8\\x4c\\x69\\x45\\x8e\\xf0\\xe6\\x20\\x29\\xaa\\x9e\\x7d\\x60\\x90\\xb3\\x5c\\x96\\xb3\\x9e\\x7f\\xc8\\xfc\\x18\\xbd\\x65\\x9f\\x38\\xc6\\x7e\\x27\\x55\\x59\\x32\\xa1\\xb3\\xd9\\x97\\x2c\\x01\\x39\\x20\\x3e\\x12\\x01\\xc8\\xef\\xf1\\x3e\\x15\\x47\\xea\\x2b\\x46\\xad\\xda\\xe3\\x0b\\x66\\xf3\\xa0\\xbf\\x80\\xaf\\x46\\xab\\x7a\\xb5\\x5f\\xdc\\xdc\\x65\\x62\\x4a\\xa6\\xb4\\xdc\\xb2\\x72\\xfc\\xb2\\xab\\x45\\x99\\x27\\xe5\\x53\\xae\\xe4\\xce\\x6e\\xd1\\x60\\xa0\\x10\\x3c\\xd7\\xde\\x08\\x6d\\x0e\\x9b\\xac\\x74\\x51\\x69\\x4b\\xd1\\xdd\\x09\\x74\\x55\\xc6\\xfd\\xc9\\x9b\\x13\\x0e\\x9f\\xef\\xd2\\x45\\x29\\xbe\\x0a\\xaa\\x35\\x2b\\xc5\\x0b\\xf2\\x3f\\x47\\x1f\\x7f\\xf7\\x4b\\xff\\xf8\\x9b\\xa3\\xa3\\x0f\\xcf\\xfa\\x7f\\xfe\\xf4\\xbb\\xa3\\x8f\\x03\\xf8\\xcf\\x57\\xc7\\xdf\\x1c\\xff\\xe2\\xfe\\xf8\\xdd\\xf1\\xf1\\xd1\\xd1\\x87\\xef\\xde\\x7c\\xfb\\xfe\\xf2\\xe5\\x27\\x7e\\xfc\\xcb\\x07\\x51\\xe5\\x37\\xf8\\xd7\\x2f\\x47\\x1f\\xd8\\xcb\\x4f\\x0d\\x07\\x39\\x3e\\xfe\\xe6\\xb7\\x7b\\x4f\\x9d\\x8a\\xd9\\xbb\\x3d\\x49\\x21\\x5e\\xfd\\x16\\x59\\x72\\x3c\\x62\\x2b\\xe8\\x37\\xd7\\x56\\x82\\x0b\\xdd\\x97\\x65\\x1f\\x87\\x7e\\x01\\xc5\\x82\\xf7\\xfc\\x80\\x43\\xaf\\xb6\\xcf\\x7f\\x2d\\x06\\xd4\\xe5\\xf6\\x9d\\x50\\xff\\xc0\\x07\\x1c\\x5c\\x9f\\xe7\\xbc\\x85\\x34\\x63\\x37\\x52\\x9c\\x26\\xa3\\x59\\x5e\\xc8\\x92\\x96\\x33\\x92\\x5a\\x6b\\xe6\\x6c\\x49\\x05\\xa2\\xa0\\x04\\xd1\\xde\\x25\\x85\\x61\\x1e\\x29\\x2f\\x1f\\x20\\xd3\\x78\\xef\\x8a\\x42\\x2c\\xe5\\x55\\xde\\x52\\x3d\\x21\\x18\\x2b\\xdc\\x8c\\x5b\\xa8\\xbc\\x6f\\xab\\xf6\\xbb\\x90\\x22\\xfb\\x98\\x75\\x68\\x0c\\x69\\x72\\x83\\x1a\\x94\\xdf\\x2d\\x94\\x1b\\x83\\xd4\\xfa\\x83\\x03\\x1b\\x12\\x91\\x33\\x2a\\xbc\\x61\\x1f\\x62\\x5b\\x64\\xca\\xcc\\x56\\xba\\x87\\x71\\xec\\xc8\\x08\\x8f\\x9e\\x76\\x1b\\x40\\x58\\x77\\xa4\\x92\\x25\\x79\\x03\\x02\\xd0\\x83\\xee\\x3e\\x69\\xa5\\x56\\x08\\xff\\x07\\x7b\\x6d\\xa4\\xbe\\x96\\x32\\x51\\xdd\\x70\\x2e\\x80\\x48\\x4b\\xd0\\x37\\x6d\\x5d\\xaf\\x11\\x34\\xd9\\xaa\\x23\\xc4\\x22\\xc9\\x02\\x36\\xf2\\xa5\\x3b\\x96\\xce\\x7f\\x6b\\xb6\\xd3\\x8c\\x8a\\xb2\\x29\\x18\\xa6\\x33\\x85\\x71\\x2b\\x3c\\x81\\x3e\\x50\\xa0\\x9b\\xc2\\x76\\xf8\\x2d\\x7c\\x1f\\x34\\xea\\xaf\\x94\\xf9\\x92\\x14\\xf1\\x33\\xf5\\x87\\xb0\\x4d\\xd6\\x10\\x71\\xc2\\x75\\xd7\\x8e\\x35\\x6a\\xf3\\xcb\\xb5\\x5f\\x59\\x6d\\xcf\\x80\\x94\\x65\\xa7\\x7e\\xaa\\x0a\\x94\\x14\\xfb\\x15\\x2b\\x6a\\xcb\\x11\\x44\\x56\\x04\\xfd\\x7a\\x5c\\x4b\\x9a\\x05\\x44\\x15\\x3c\\x8b\\x31\\xd5\\x75\\x9e\\xf0\\x0b\\xaf\\x84\\x0d\\x28\\x7c\\x70\\xb4\\x7b\\x72\\xd2\\xc7\\x9e\\x32\\x47\\x5b\\x92\\x46\\x2b\\xf2\\x45\\xeb\\x52\\x85\\x8f\\xdc\\xdc\\xbf\\xdf\\x6b\\x1d\\x04\\x1a\\xb1\\xd5\\xb0\\x47\\x46\\x1c\\x10\\x4a\\x7d\\x5b\\x34\\x47\\x13\\x5c\\xd4\\xc1\\x7b\\x6f\\x51\\xb2\\xec\\x36\\x99\\x25\\xb6\\xc2\\x13\\x8f\\x3a\\xf8\\xe0\\xb0\\x78\\x34\\x20\\xb7\\xaa\\xef\\xbb\\x57\\xd7\\x76\\x09\\x32\\x64\\x23\\x0c\\x7c\\xc2\\x77\\xc0\\x60\\x60\\x33\\xc2\\x52\\x96\\x31\\xcd\\x82\\xb6\\xf3\\x05\\x36\\xca\\x2e\\x59\\x2e\\xa7\\xb6\\x4d\\xeb\\xf7\\xca\\xba\\xcd\\xf9\\xe8\\x05\\xa1\\xc7\\x51\\xde\\xb1\\xb2\\x7d\\x90\\x19\\x4b\\x31\\x4d\\x2c\\xe8\\x2d\\x58\\x56\\x42\\xf5\\xc8\\xf0\\xd8\\x85\\xb5\\xda\\x2e\\x98\\x25\\xd8\\xd6\\x6c\\x93\\x2f\\x30\\x67\\x95\\xcc\\x00\\x00\\x6a\\x55\\x95\\x32\\x27\\x4a\\xd0\\x42\\x4d\\xa4\\x06\\xcb\\x09\\x2d\\x68\\xc2\\xf5\\x8c\\xe8\\x92\\x26\\x37\\xe6\\x11\\x70\\xa7\\xc2\\xe7\\x7a\\x24\\x39\\xb6\\x51\\xee\\x21\\xf8\\xe2\\xcc\\x35\\x3d\\x29\\x65\\x35\\x9e\\x40\\x2a\\x15\\x3e\\x95\\x64\\x54\\xb9\\xd5\\x2f\\x7d\\xdf\\xaa\\xf2\\x8a\\xa4\\x33\\x41\\x73\\x9e\\xf8\\x16\\x22\\xa5\\x9c\\x72\\xc5\\xa5\\x75\\x78\\xb9\\x71\\x2f\\x7d\\x33\\x06\\x74\\xa2\\x9d\\x65\\x94\\xe7\\xe4\\x48\\x31\\x46\\x5e\\x3a\\x94\\xc0\\x5f\\xae\\x51\\xa0\\x44\\x83\\x62\\x19\\xc7\\xd6\\xd9\\xba\\x8f\\xb6\\xfe\\x80\\xb9\\x53\\x53\\x60\\x1f\\xb1\\x80\\x32\\x81\\x99\\xf9\\xd2\\x8f\\x1e\\xfb\\xed\\x5a\\x3e\\x27\\x59\\x42\\xdc\\x9b\\xeb\\x04\\xc4\\x44\\x2a\\x83\\xc0\\x98\\xd3\\xcb\\x0b\\x15\\xaa\\xb9\\xb6\\x9b\\x22\\x8e\\x04\\x3f\\x64\\x52\\x8c\\xc3\\xfa\\x77\\x35\\x66\\x1a\\x5a\\x2f\\xa0\\x2d\\xe6\\x94\\xa7\\x15\\xcd\\x90\\xca\\xdb\\xc9\\x9c\\x5d\\x5f\\xe0\\xeb\\x7c\\x3c\\xd1\\xfd\\x5b\\x06\\x46\\x50\\x64\\x86\\xf5\\x99\\x71\\x1f\\xe5\\x0b\\x01\\xb7\\x5c\\x01\\x57\\xd0\\xd6\\xd8\\x86\\x06\\x65\\x68\\x3d\\x49\\x67\\x50\\x7f\\xd7\\xc6\\x78\\x46\\x31\\x39\\xae\\x5a\\x3d\\x0e\\xb1\\x0c\\xe2\\x30\\xbd\\x53\\xdf\\x27\\xd1\\x48\\x46\\x60\\x25\\x36\\x20\\x06\\x4c\\x5d\\x9c\\x1b\\x34\\x7d\\xac\\x5b\\x6f\\xf8\\xdb\\xba\\x6e\\x00\\x09\\x72\\xf1\\xee\\x8d\\x82\\x1f\\x4c\\x9e\\x9d\\xd6\\x68\\xf2\\x9e\\xe5\\x45\\x46\\x75\\x3b\\x11\\x26\\x07\\x3f\\x06\\x56\\xf0\\xc0\\x87\\x6c\\x8e\\x23\\x15\\x69\\x9f\\x66\\x06\\x23\\x2f\\x7f\\x38\\xb3\\x09\\x6e\\x78\\xc0\\xa2\\x28\\xb6\\xf7\\x75\\xab\\x52\\xd7\\xa5\\xda\\x08\\x4b\\x4b\\x8f\\x16\\x94\\x54\\x1b\\xb2\\x14\\x88\\x91\\xfd\\x32\\x98\\x2a\\x6e\\x05\\xb6\\x0a\\x36\\x7f\\x5c\\xfe\\x70\\xd6\\x23\\x7c\\xc0\\x06\\xee\\x2f\\xff\\xa8\\xa3\\x86\\x5a\\x8e\\x31\\xcf\\xc1\\x27\\xd2\\x00\\x3e\\xc3\\x54\\x42\\x1b\\x70\\xf8\\xee\\x4f\\x7f\\x31\\x93\\x34\\xbf\\xfe\\xb5\\xff\\x97\\xa0\\xa5\\xd1\\x5f\\x7f\\x32\\xc4\\xb5\\x34\\x0f\\xc4\\x77\\xc3\\x30\\x73\\xa0\\x7b\\xe6\\xaf\\x9f\\x2e\\x65\\x7a\\x5d\\xb0\\x64\\x80\\xcb\\x52\\x3f\\x61\\xb0\\x00\\x61\\x42\\x1b\\x91\\xfb\\x52\\x42\\x80\\x19\\x4f\\x11\\xcb\\xe1\\xdb\\x25\\xfb\\xbb\\xf3\\x13\\xd8\\xae\\xa9\\x96\\x90\\x24\\x54\\x33\\x01\\x0c\\xc0\\xe5\\x1b\\x0b\\xa9\\xf1\\x75\\xec\\xb7\\x0a\\xf3\\x3f\\x1a\\x85\\x1d\\x50\\xb5\\x94\\x70\\xcc\\x91\\x94\\x9c\\x0a\\xc2\\x3e\\x73\\x05\\xe5\\x67\\x70\\xad\\x00\\x0e\\x6a\\x63\\xd8\\x1d\\x4f\\x33\\xc3\\x1a\\x08\\xfb\\x6a\\x43\\xd0\\x82\\xd5\\xcc\\xed\\x2b\\x21\\xf5\\x57\\x7e\\xfb\\x5d\\x7c\\x22\\xf6\\x33\\x27\\x74\\x2a\\x79\\x4a\\x2a\\x68\\x9f\\x65\\x4e\\xa0\\x00\\x03\\x77\\xdd\\xc1\\x70\\x38\\x23\\x39\\x57\\x9a\\xde\\xb0\\x01\\xb9\\x36\\x3c\\x2b\\x0c\\x34\\x40\\xe8\\x09\\x02\\xcd\\x68\\x58\\x4a\\x2a\\xa1\\x79\\x06\\xbf\\xd6\\xe3\\x98\\x29\\x87\\xbc\\xec\\x62\\x44\\x54\\x95\\x40\\x8f\\xde\\x92\\xf5\\x1d\\x77\\xb4\\x4f\\x2d\\xd0\\x98\\x7a\\x2d\\x3d\\xbf\\xd9\\x13\\x8a\\x6a\\x54\\x91\\xc2\\xab\\xd8\\xf1\\x57\\x58\\xf4\\x5a\\x08\\xaf\\x36\\xf3\\x94\\x22\\xa9\\x39\\x22\\x00\\x13\\xba\\x6c\\x1b\\x26\\x98\\xb9\\x38\\x20\\xd4\\xe8\\xac\\xdf\\x40\\xb0\\x84\\x29\\x45\\xcb\\x19\\x36\\x45\\xe5\\xbe\\x77\\xa3\\x8d\\x7c\\x05\\x4e\\x9d\\x53\\x51\\xc1\\x00\\x25\\xc3\\x16\\xbb\\x55\\x02\\xd0\\xa1\\x64\\x58\\xca\\x1b\\x26\\x7c\\x26\\x81\\xd9\\xc5\\x38\\xae\\xba\\x0e\\x1e\\xc5\\xee\\xd3\\x24\\x99\\x50\\x31\\x66\\x75\\x32\\x79\\x4e\\x53\\x80\\xfd\\x77\\x5e\\xd2\\x72\\xeb\\x31\\x10\\xa0\\x23\\x23\\xb0\\x70\\x0d\\xa0\\x18\\x1a\\xfe\\xe4\\xbd\\x1f\\x1f\\x85\\x2f\\x87\\xdb\\xab\\xdd\\x13\\x66\\x49\\x3c\\xdb\\x89\\x26\\x92\\x76\\xec\\xe1\\xfb\\x5b\\xc2\\xfb\\x20\\x50\\x3c\\x60\\x0c\\x77\\xce\\x34\\x4d\\xa9\\xa6\\xad\\xc5\\x71\\xbf\\xa1\\xbe\\xf9\\xa7\\x8d\\xed\\x00\\x74\\x08\\x62\\x3e\\x2c\\x8f\\x75\\xa2\\xa4\\x2c\\x78\\x58\\x5e\\x00\\xa8\\xc1\\xc4\\xed\\x3e\\x94\\xa7\\xd2\\x06\\xaf\\xad\\xef\\x11\\xc3\\xb3\\x41\\x56\\xa3\\x59\\x26\\x6f\\x6d\\xc1\\x3a\\x37\\x1a\\x92\\x2c\\x96\\x92\\xb4\\x02\\xb1\\xaf\\x26\\x69\\xfb\\xf8\\xc6\\x5b\\x71\\x9d\\x98\\x8d\\x6e\\x0d\\xca\\xef\\xeb\\x10\\x80\\x24\\x0e\\xd1\\x5e\\x2a\\xa0\\x21\\xaf\\x63\\x42\\x73\\x6c\\xa5\\xef\\xea\\x41\\x58\\xe0\\x57\\x02\\x8f\\xea\\xdc\\x36\\xc0\\x3e\\x8d\\x99\\x56\\x75\\x70\\x25\\x72\\x13\\x43\\x22\\x2d\\x2f\\xb7\\xb6\\x04\\x60\\x35\\x76\\x6b\\xac\\x3a\\xbe\\x5c\\x52\\xc4\\x8d\\x53\\xd2\\x72\\x0b\\xc3\\xbf\\x1e\\x7c\\x67\\xda\\xf3\\x21\\x61\\x17\\xdc\\x37\\x32\\xdd\\xdf\\x19\\x35\\xd7\\xce\\xb5\\x1e\\xb8\\x4e\\x3a\\xc1\\x04\\x24\\x05\\xb6\\x1e\\x7c\\x00\\x5c\\xf3\\x2a\\xaa\\x96\\x81\\x2c\\x60\\x42\\xa7\\xbb\\x5b\\x55\\x6b\\xc9\\xb4\\xef\\x7b\\xb6\\xc1\\xe7\\xfa\\xf0\\xb9\\xfe\\xf3\\x7d\\xed\\xd7\\xfb\\x07\\x2f\\xba\\x6b\\xcf\\x20\\xc6\\x78\\x42\\x2d\\x38\\x2c\\x0c\\x69\\xbd\\x6e\\xc5\\x9f\\x30\\x57\\x4c\\xc9\\x8f\\x6b\\xf9\\xaf\\x0d\\xd0\\xf0\\x41\\x31\\x36\\xad\\x96\\x71\\x43\\x35\\x5f\\x90\\xaf\\x22\\x89\\xcb\\x4a\\xb6\\x5e\\x1b\\xc6\\x64\\xa6\\x23\\xa7\\x1e\\x0f\\xec\\xc6\\xbb\\xaa\\x5e\\xf1\\xe3\\xc7\\x73\\x83\\x81\\xa8\\xb7\\x5c\\x6b\\x74\\x49\\x53\\x5e\\xfc\\x36\\xa2\\x32\\xb4\\xe3\\xf7\\xa9\\xaa\\x06\\x99\\x4b\\x99\\x65\\xae\\x85\\x3b\\x6a\\xc8\\x73\\x21\\x4e\\xd0\\x3e\\x08\\x9d\\x26\\x3d\\x6f\\x86\\xf0\\xf2\\xbe\\x60\\xb7\\x5e\\xb0\\xa3\\x0a\\xab\\x96\\x3a\\x97\\x3d\\x98\\x4a\\x5c\\xdc\\xd9\\xb2\\xf1\\x06\\xd0\\x03\\x1f\\x7e\\x3f\\x15\\x33\\x9c\\xfc\\x79\\x00\\x5c\\x34\\x30\\x90\\xb1\\xf9\\x94\\xd1\\x01\\x04\\x1d\\x66\\x46\\x0a\\x09\\x36\\xc0\\x7f\\x67\\x8e\\xa5\\x69\\x19\\x3c\\x75\\xc5\\x46\\xd6\\x32\\x10\\xde\\x6a\\xf6\\x2e\\xf2\\xc3\\xe8\\xc5\\x41\\x1d\\x25\\x69\\xc5\\xe4\\xa0\\x52\\xa6\\x85\\x7a\\xf4\\x48\\x1c\\x55\\x34\\x37\\x5a\\x54\\xb0\\x67\\xd9\\x0c\\xf6\\x0c\\x3d\\x68\\x31\\xf8\\xa0\\xbd\\xf0\\x03\\xa8\\x0d\\xc3\\xc5\\xee\\x31\\xc5\\xf5\\x30\\x3b\\x74\\x0c\\x9f\\xbf\\xda\\x8b\\x62\\x80\\x40\\x4e\\x88\\xe2\\x6a\\xc3\\x1d\\x1c\\x91\\x9d\\xd3\\xcb\\x0b\\x18\\xd8\\x69\\x98\\x63\\xf8\\xc3\\x49\\x1e\\xde\\xaf\\x39\\x64\\x86\\x2e\\xd4\\x15\\xad\\x00\\x23\\xc3\\x77\\x97\\x84\\xb9\\xd5\\x87\\xf3\\x3b\\x68\\xdf\\x64\\xdd\\x45\\x2e\\x7d\\xd9\\x30\\xae\\xd3\\xcb\\x0b\\xfc\\xe2\\x00\\x3a\\xf8\\x52\\x31\\xb3\\x32\\xa1\\x9e\\xf0\\x32\\xed\\x17\\xb4\\xd4\\x33\\x34\\xb2\\xf4\\xa2\\xaf\\xf9\\x1c\\xce\\x16\\xc0\\xd1\\xaa\\x27\\x7b\\x9f\\x8e\\x6f\\xe1\\x15\\xed\\x11\\x80\\xcf\\xf9\\x89\\xac\\xa3\\x6f\\xe5\\xce\\x3c\\x36\\x88\\xec\\x9b\\x51\\xea\\xae\\x08\\x22\\x61\\xc7\\x1f\\x67\\x63\\x79\\x12\\x10\\x89\\x68\\xf4\\x5d\\xc9\\x0f\\x86\\xfc\\xab\\x38\\xfa\\x06\\xc5\\x01\\x90\\xf5\\xad\\x5d\\x4c\\x86\\x69\\x6e\\x5e\\xb6\\x04\\x23\\x85\\x19\\xa9\\x47\\xf8\\xc8\\x30\\x62\\x29\\xfa\\x36\\xb9\\xde\\x1b\\xf1\\xad\\x7c\\xea\\xc2\\x54\\xd1\\xe0\\x00\\x47\\x37\\xf8\\x4a\\xf8\\xaa\\x3f\\xe5\\xe4\\x48\\x48\\x81\\x27\\x1f\\x9f\\x3d\\xc6\\xf8\\xdc\\x15\\x16\\x68\\x78\\xc4\\x73\\xf3\\xd0\\x2e\\x11\\x50\\x1a\\x27\\x26\\x70\\x91\\x9a\\x6d\\x07\\xb6\\x07\\x16\\x0b\\x55\\x25\\x09\\x63\\xde\\xc6\\x15\\xf6\\xb5\\xaf\\x29\\x93\\x9d\\x72\\x4e\\x75\\x32\\x61\\x8a\\x28\\x09\\xf5\\x51\\x95\\xa6\\x59\\x56\\xdb\\x96\\x2c\\xa0\\x24\\x48\\x3a\\xce\\xce\\x1f\\x08\\x40\\x51\\x36\\xba\\x35\\xb3\\x15\\x19\\xb5\\xb6\\x9c\\x51\\x25\\x12\\x8c\\x00\\xe3\\x7a\\x16\\x76\\x46\\x8d\\x84\\x3d\\x50\\xa8\\x15\\x9a\\x9c\\xf8\\x08\\xad\\xcb\\x81\\x62\\xec\\x81\\x09\\xa4\\x75\\x86\\xc4\\x74\\xe2\\x7a\\x8f\\x83\\xae\\x66\\x8b\\x00\\x1a\\x3a\\x3a\\xa4\\xc9\\xcd\\x2d\\x2d\\x53\\x05\\x89\\xf6\\x54\\x73\\xec\\xc5\\xd8\\x43\\xa9\\x23\\x14\\x22\\xc4\\xe1\\x61\\xe8\\xa8\\xe5\\x62\\x5e\\xbe\\x09\\x27\\x72\\x14\\xcc\\x7a\\x41\\xee\\x39\\xf6\\xf2\\x8e\\x62\\xbe\\x4b\\x5f\\x3d\\x31\\x42\\x2b\\x2d\\x73\\xaa\\x79\\x02\\xa6\\x28\\x3e\\x0a\\xbc\\x0b\\xb9\\xef\\x6e\\xe1\\x9d\\xc4\\xc8\\x05\\x80\\xaf\\xd8\\x85\\x5b\\x3c\\x58\\x2e\\x01\\x2d\\x99\\x78\\x30\\x57\\xb7\\xcc\\xe5\\xf3\\x0a\\x58\\x93\\xfd\\xd0\\x7b\\xf4\\x57\\x83\\x17\\xac\\x64\\x8c\\xf0\\xdc\\x08\\xb0\\x14\\x1a\\x68\\x8f\\x7c\\xce\\xbf\\x73\\xb9\\xac\\x03\\x8a\\x91\\xd2\\x7f\\x04\\x3f\\x57\\xf0\\x14\\xda\\xd3\\xb2\\x4c\\xde\\x2a\\xa2\\x6f\\xa5\\x57\\xfa\\x6b\\x6f\\x82\\x4d\\x6e\\xef\\xcd\\x89\\x74\\xf6\\x1d\\x73\\xd4\\x0c\\x58\\x82\\x73\\xd4\\x33\\xb8\\x73\\xcb\\xb2\\xcc\\xfc\\xbb\\xee\\x34\\xa9\\xc1\\xb2\\x19\\xf1\\xb1\\xc0\\xf4\\x67\\xae\\x9c\\x05\\xc6\\xc6\\xb3\\x1f\\xa5\\xa5\\x2c\\x0a\\x6b\\x4b\\xcd\\x8f\\xe7\\x67\\x04\\xae\\xcb\\x72\\xca\\x14\\x78\\xef\\x5d\\x84\\xbc\\x01\\xc3\\x98\\x09\\x56\\x52\\x0d\\x8e\\x10\\x5b\\xd4\\x11\\x08\\xca\\xfc\\x27\\xa2\\x6d\\x5c\\x3a\\xb9\\x10\\x5c\\xe8\\x08\\x5a\\x0f\\x1e\\xfb\\x2b\\x58\\x2c\\x0c\\xa4\\x1c\\xc2\\xa8\\x01\\x16\\xce\\x39\\x26\\xdf\\x2b\\x5c\\x90\\x3f\\xb3\\x3e\\x9a\\xbf\\x91\\xce\\x80\\x66\\x5f\\xab\\x36\\x0c\\xc8\\xd1\\x69\\x56\\x4c\\x82\\x51\\x43\\x29\\xdd\\x67\\x4b\\xc5\\x33\\x8d\\xbe\\x77\\x56\\x4a\\xa5\\xde\\xba\\x57\\xb6\\xf9\\x74\\x27\\xc1\\xaf\\x1b\\xa6\\x93\\xe0\\x3b\\x09\\x7e\\x87\\xab\\x93\\xe0\\xe7\\xaf\\x4e\\x82\\x9f\\xbf\\x3c\\x81\\xbf\\x13\\xb0\\x78\\xf1\\x26\\xe6\\x25\\xeb\\x00\\x44\\xde\\x4a\\x6d\\x5d\\xac\\x20\\xe2\\xd1\\x95\\x96\\x22\\x0a\\x8c\\xe4\\x96\\xce\\x06\\x82\\x69\\x5b\\x51\\xc7\\x19\\x05\\xaf\\xdc\\x78\\xdf\\x96\\x46\\xd8\\xb1\\xb2\\x71\\x70\\x58\\xdd\\xc9\\x77\\xb5\\x7c\\x82\\xaf\\x68\\x89\\xfc\\xb7\\xf6\\xf8\\xc2\\xfd\\x43\\x65\\xfd\\x9d\\xe6\\x77\\xc8\\xaf\\x0b\\x07\\x48\\xd8\\x80\\x5c\\x33\\xd7\\xc2\\x24\\xfa\\xf8\\x62\\xd5\\x94\\x94\\x69\\xca\\x33\\x55\\x33\\xdc\\xf7\\x2b\\x18\\xf8\\xee\\x0c\\xf5\\x31\\xe1\\x99\\xcf\\x89\\x68\\x57\\x4b\\xac\\x93\\x9c\\x82\\xc0\\xb3\\x30\\xa2\\xb3\\x7e\\x60\\x95\\xcb\\xe1\\x62\\x44\\xae\\x58\\x22\\xa7\\xac\\x44\\xd8\\xbe\\xfc\\x5c\\x50\\x61\\x34\\xa1\\x57\\x94\\x67\\x06\\xb2\\x0e\\xc2\\xb5\\x71\\x15\\xda\\x79\\xc5\\x2e\\xbe\\xc0\\xa2\\xed\\xd1\\xda\\x6e\\x63\\x6e\\x27\\x65\\x0b\\xee\\x98\\xe7\\x6d\\x20\\x51\\x51\\xb2\\x29\\x97\\x95\\x72\\x71\\xa7\\x95\\x46\\xa6\\xa4\\xb4\\xd5\\x3d\\x26\\x7c\\xec\\xbb\\x6e\\xfa\\x70\\xb0\\x92\\x25\\xb2\\x4c\\x6b\\xf4\\x55\\x9a\\xea\\x4a\\xc5\\xa9\\xec\\x09\\xfa\\xd4\\xda\\x73\\xa7\\x78\\x38\\x3e\\x22\\x29\\xad\\x4d\\x79\\x06\\x00\\xd6\\xc2\\x38\\xf3\\x31\\x40\\xa0\\xad\\x28\\xa8\\xa9\\x11\\x50\\xc0\\x90\\xfa\\x61\\x96\\x10\\x17\\xb8\\xa1\\x06\\x89\\x06\\xee\\x27\\x7c\\xb9\\x57\\xe3\\x4e\\x1d\\x9c\\xc1\\x55\\x1d\\x5d\\x5c\\x47\\x3a\\x70\\xd0\\x4f\\xa8\\x21\\x28\\x81\\x22\\xee\\xc9\\x09\\xa0\\xaf\\x13\\xeb\\xcf\\x51\\xf3\\xbf\\xb2\\xdf\\x3a\\xcd\\x8c\\x36\\x82\\xe4\\x29\\x20\\x29\\x4b\\xa2\\x28\\x78\\x9e\\x57\\xda\\x9c\\x83\\x01\\xb9\\xc0\\xbc\\x5b\\xd0\\x69\\xac\\xaa\\x3c\\xaa\\x73\\x3e\\x59\\xa9\\x76\\x8e\\x7d\\x08\\xaf\\xf6\\x9c\\x6f\\xa4\\x3d\\x07\\x1c\\x99\\xdf\\xea\\xab\\x70\\xd3\\xc2\\x6a\\x7a\\x52\\x30\\x8c\\x61\\x32\\xfb\\xeb\\x62\\x9c\\xa2\\xa7\\x77\\x2e\\x99\\x15\\x5f\\x2d\\x1e\\x2d\\xbc\\xda\\x53\\x83\\xf0\\x6a\\x45\\x8b\\xc1\\xab\\xcd\\xb3\\x8f\\x57\\x5b\\x72\\x21\\x5e\\x8b\\xd2\\x21\\x50\\x76\\xb0\\xcc\\x45\\x52\\x62\\x84\\x1d\\x85\\x4c\\x07\\x4b\\x28\\x80\\x8f\\xb9\\x93\\xa9\\x0d\\xa8\\x8b\\xed\\x87\\x98\\x66\\x7f\\x61\\x86\\xbf\\x71\\xc1\\xab\\x9e\\x0b\\xd1\\x29\\xe5\\x19\\x64\\x4c\\x70\\xa1\\x78\\xca\\xb0\\x2b\\x90\\xa5\\x1c\\xad\\xad\\xb7\\x55\\x81\\x74\\x2e\\xd8\\xdd\\x10\\xcf\\x7e\\x4e\\x8b\\xfe\\x0d\\x9b\\xb5\\xb4\\xdd\\xad\\x61\\xe2\\xe2\\x44\\x11\\x12\\x39\\x2d\\xf6\\x1e\\x1d\\x93\\x49\\x5a\\xe7\\x49\\x87\\xaf\\x31\\x49\\x05\\x6f\\x0e\\xad\\x68\\xe4\\xf2\\x66\\xea\\x9c\\x9d\\x44\\xe6\\x45\\xa5\\x59\\x20\\x42\\x59\\x61\\x67\\x6b\\xb9\\x22\\x2a\\xd5\\x78\\x92\\x53\\x41\\xc7\\xac\\xef\\x87\\xed\\xd7\\xec\\x62\\xe7\\xd6\\xe1\\xe1\\xd5\\x32\\x19\\x6c\\xb7\\xa6\\x60\\x78\\x3d\\xb9\\x74\\x9a\\xf8\\x6a\\x2d\\xa1\\x97\\xdc\\x49\\x52\\x2f\\x69\\x3f\\xb1\\x97\\xdc\\x7d\\x72\\x2f\\xf1\\xc5\\x16\\xda\\x3f\\xf7\\x57\\xae\\xf8\\xc3\\xdc\\xc9\\xb7\\xaa\\xd2\\xba\\x93\\x1f\\x55\\x19\\xf6\\xe3\\x70\\x45\\x64\\xce\\xb5\\x66\\x2e\\xa8\\xda\\x9f\\x64\\x08\\x82\\x09\\x93\\xdf\\x2d\\xcd\\x01\\xef\\x15\\x46\\x4e\\xb3\\xcf\\xbe\\xbd\\x6a\\xa0\\xd0\\x83\\xb5\\xed\\x96\\x2b\\x54\\xc1\\x05\\xe1\\x79\\x81\\xcd\\x1e\\x80\\x76\\xf4\\x9d\\xa4\\x6c\\xbd\\x43\\x7e\\x26\\x09\\x44\\x6f\\x12\\xf6\\x19\\x7c\\x64\\xf8\\xb1\\x8e\\x4c\\x75\\x64\\xaa\\x23\\x53\\x77\\x41\\xa6\\xb0\\x26\\xc0\\xfe\\x25\\x36\\x22\\xf2\\xe4\\x06\\xb5\\x45\\x28\\xe9\\x90\\x65\\xe4\\xe7\\x8a\\x95\\x33\\x22\\xa7\\x2c\\xc8\\xcc\\x82\\x46\\xb5\\x46\\x90\\xc5\\xdc\\x26\\xeb\\x29\\xdf\\x57\\x92\\x7d\\xa4\\x66\\x09\\xd0\\x17\\x5e\\x7e\\x2e\\x4a\\x86\\xb5\\xc3\\x5a\\x67\\x0a\\xf3\\x1f\\x88\\x4b\\x80\\xe2\\x2e\\xf8\\x9d\\x09\\x0d\\x5a\\x18\\x56\\x1d\\x99\\xb8\\x68\\xc9\\xc8\\xe9\\xdb\\xf3\\x36\\x2d\\x8f\\x8f\\x5d\\xe9\\x3f\\x5d\\x03\\x22\\x04\\xa5\\xff\\x05\\xf8\\x9e\\x8f\\x8c\\xf6\\xce\\x65\\x72\\xc3\\x66\\x3d\\x9b\\x80\\x60\\xbb\\x94\\xbb\\x87\\x31\\x97\\x27\\x6e\\x95\\xb8\\x5f\\x89\\xed\\xf8\\x7a\\x02\\xf6\\x82\\xfd\\x5a\\xe3\\xc5\\x63\\x39\\xe0\\x3e\\x52\\xfb\\xc3\\xde\\x2d\\xf4\\xc2\\x6b\\x55\\x3b\\x3d\\xc4\\x56\\xe8\\xbe\\xe5\\xea\\x0c\\x78\\x04\\x85\\xda\\x0a\\x40\\x61\\x1f\\xad\\x59\\x80\\x40\\x97\\x27\\xdc\\xc6\\x3b\\x02\\x96\\x3f\\x82\\x51\\x26\\xfb\\x0d\\x9b\\x1d\\x2a\\x5b\\x85\\x4e\\x0a\\x35\\xe1\\x85\\xeb\\xaf\\x0e\\x74\\xd2\\x9e\\x4a\\xf2\\x03\\xa4\\x8c\\xb8\\x21\\x90\\x22\\x5e\\x88\\x1e\\x79\\x2b\\xb5\\xf9\\xe7\\x25\\xe4\\xc0\\xc1\\x39\\x3e\\x97\\x4c\\xbd\\x95\\x1a\\xee\\x3c\\x6a\\x70\\xe3\\xd2\\xee\\x08\\xd8\\x36\\x2c\\xc7\\x9a\\xad\\x21\\xdb\\x13\\xaa\\xbe\\xb8\\xcc\\x28\\x00\\xaa\\x0d\\x16\\xf7\\x1b\\xc3\\x15\\xb9\\x10\\x44\\x96\\x0e\\xaa\\xda\\xb5\\x8c\\x55\\x76\\x08\\xe7\\xd8\\x0f\\x82\\xad\\x96\\x8c\\x61\\x37\\x43\\x96\\xd1\\x5e\\xac\\x19\\xce\\x87\\x53\\x71\\xf7\\x0b\\xf8\\x12\\x21\\x34\\xce\\xa7\\x73\\x41\\xdb\\x52\\xaa\\xd9\\x98\\x27\\x24\\x67\\xe5\\x18\\x2a\\x16\\x26\\x93\\xb6\\xb7\\xb8\\x2d\\xbe\\x88\\x57\\x8b\\xdc\\x11\\xaf\\x56\\xf1\\x10\\x44\\x94\\xd7\\x90\\xa8\\x77\\x37\\xe2\\x0f\\x8e\\x8d\\xec\\x3a\\xa7\\x85\\x41\\xc1\\x7f\\x1a\\xae\\x0c\\x58\\xf0\\x2f\\x68\\x8b\\xac\\x06\\xe4\\x94\\x28\\x2e\\xc6\\x19\\x8b\\x7e\\xb3\\x2e\\xb8\\x70\\x18\\x33\\x82\\x51\\x6f\\x7f\\xae\\xf8\\x94\\x66\\x0c\\x13\\x6b\\xa9\\xf0\\x4d\\x0b\\xe5\\x68\\x41\\xe8\\xea\\xd9\\xde\\xc8\\x86\\x2e\\x7b\\xa3\\xee\\xc1\\x0d\\x9b\\x1d\\xf4\\x16\\xd0\\xf6\\xe0\\x42\\x1c\\xd4\\xc5\\x4f\\x23\\x44\\xf5\\xc2\\x05\\xf8\\x63\\x0e\\xe0\\xb7\\x83\\xfb\\x91\\xd3\\x9e\\x80\\x1a\\xdb\\x1a\\x4e\\x5a\\x2f\\xe9\\x59\\x46\\xd1\\x2f\\xdf\\xae\\x47\\x7b\\x7e\\xf4\\x65\\x2d\\xd9\\xae\\x83\\x67\\xea\\x68\\x06\\x9b\\xb4\\xdd\\xba\\xeb\\x17\\x8a\\x86\\xb4\\x95\\x42\\xd7\\x02\\xfc\\x71\\x5e\\xfb\\x34\\x02\\x71\\xd7\\x92\\x26\\x3a\\x50\\xbe\\xd8\\x15\\x95\\x89\\x6a\\x91\\xd5\\x11\\xe3\\x2b\\x20\\xfe\\x03\\x38\\xf1\\xe5\\x88\\xbc\\xaa\\x5b\\xad\\x81\\xbb\\xd4\\x88\\x55\\xb6\\xcc\\x8c\\x90\\x9a\\x70\\x91\\x64\\x95\\xf5\\xdf\\xc3\\xab\\xe8\\xf4\\x7d\\x5c\\xe0\\x6d\\x1d\\xb1\\xeb\\x61\\x1d\\x46\\xbb\\x18\\xf7\\x85\\xda\\x01\\xf3\\x11\\xbf\\x10\\x00\\xee\\x63\\x5c\\x11\\xda\\x0f\\x09\\xad\\xd1\\x4e\\x59\\xd2\\x71\\x8b\\xc0\\x24\\x96\\x2f\\x5f\\xf1\\x61\\xc9\\xc8\\xd9\\x84\\x0a\\xc1\\xb2\\xa0\\xfe\\xa2\\xb5\\x95\\x52\\xad\\x69\\x32\\xc1\\x30\\x13\\x4a\\xcc\\x39\\xce\\x98\\x3e\\x54\\x64\\x22\\xc1\\xa7\\x98\\x4c\\xb8\\xf0\\x15\\xc9\\x84\\xaf\\x43\\x5a\\x97\\x62\\x78\\x80\\xa6\\x9a\\xfb\\x2a\\x48\\x2d\\xf6\\x63\\x3c\\xb4\\x0d\\x19\\x2d\\xde\\x85\\x9d\\x10\\xe3\\x3e\\x8d\\x75\\x6b\\x9f\\xf9\\x67\\xea\\x1e\\x57\\xf6\\xcc\\x03\\xe4\\x91\\x2f\\x43\\xd3\\x40\\x78\\x76\\x7d\\xa7\\xc7\\xdc\\xdb\\xbb\\xb9\\x18\\xb1\\xb2\\xc4\\x1d\\x1a\\x32\\xfb\\x02\\xe1\\x23\\x52\\x89\\x20\\x78\\x1c\\xdb\\xbf\\x4d\\xe4\\x2d\\x49\\x25\\xb9\\x65\\x10\\x2d\\x64\\x04\\x08\\x08\\x3f\\x57\\x4e\\xf4\\x08\\x66\\x0a\\x99\\x2a\\x89\\xcc\\x8b\\x52\\xe6\\xdc\\x87\\x6f\\x5b\\xf4\\x78\\xb0\\x52\\x83\\x59\\xb5\\x73\\xb7\\x86\\x78\\x17\\xb3\\x4a\\xc4\\x6d\\xd2\\x5f\\x9d\\x11\\x4d\\xcb\\x31\\xd3\\xe6\\x1b\\x44\\x54\\xf9\\x90\\xed\\x59\\x51\\xf1\\xa1\\xfb\\xf9\\xb4\\xda\\x3f\\xef\\xd0\\x37\\xd0\\x8b\\xa0\\xb6\\xa1\\x33\\x1e\\xb9\\x72\\x6f\\x41\\xa0\\x01\\x64\\xc1\\x8c\\x64\\x99\\xb8\\xb0\\x46\\xd7\\x93\\x0f\\x1b\\x38\\x19\\x2c\\xfc\\xc1\\x32\\xce\\x4a\\x68\\xb5\\x67\\x3f\\xa5\\x7d\\x3a\\xeb\\x21\\x2a\\xfc\\xf8\\xe3\\xdb\\x76\\x1a\\x22\\x1d\\xd6\\xe3\\xad\\xc2\\xba\\x5b\\x59\\x66\\xe9\\x2d\\x4f\\x5d\\x50\\xd7\\x91\\x79\\xf8\\x78\\x3f\\x08\\x3c\\x60\\x7f\\xa4\\xbd\\x4f\\xfa\\xed\\x2d\\x4f\\x5b\\x02\\x3e\\x0c\\x15\\x03\\xdd\\xa5\\xf4\\x19\\xa0\\x13\\x80\\x3a\\x4f\\x99\\xd0\\x86\\x58\\x96\\x8a\\x1c\\xc1\\x1b\\xc7\\xe4\\x25\\xc7\\xe2\\x55\\xf0\\x3e\\x84\\xa2\\xe5\\x43\\x2e\\xea\\xc2\\x68\\xf5\\xa6\\x1a\\x76\\x69\\xe8\\x86\\x53\\xef\\x15\\xd3\\x58\\x76\\x08\\xb2\\xcc\\xa5\\x9e\\x10\\xc5\\xf3\\x2a\\xd3\\x54\\x30\\x59\\xa9\\x6c\\xb6\\x27\\x6a\\x3f\\xd5\\x8d\\x1d\\x65\\xec\\x33\\x9e\\xf0\\xfd\\x85\\x1e\\x3f\\x54\\x2c\\xfc\\x40\\x72\\x55\\x5d\\x6b\\x70\\x41\\xfa\\xa9\\x73\\x13\\xd3\\x13\\x2f\\x09\\xf9\\xda\\x59\\xec\\x33\\x4b\\x6c\\x59\\x85\\x22\\xab\\xc6\\x7c\\xa7\\x3a\\x3a\\x5d\\x07\\xf1\\x9d\\xde\\x6e\\xd6\\x41\\xbc\\x6e\\x94\\x5c\\x29\\x56\\xd7\\xfc\\xb5\\x45\\xee\\x1e\\x4a\\x2e\\x69\\xbf\\xe1\\xf7\\xc3\\xca\\x97\\xef\\x97\\x37\\xfb\\x4e\\x59\\xc1\\x44\\x0a\\x4d\\x87\\x5e\\xd5\\xe7\\x0f\\x27\\xff\\x60\\xb0\\xb7\\xcd\\x7e\\xda\\xe1\\x15\\xae\\x73\\x50\\xc4\\xa5\\x83\\x00\\xc9\\x89\\xcc\\x52\\x45\\xd8\\x67\\x5d\\x52\\xc3\\x0e\\x72\\x43\\xf8\\xfd\\x3b\\x23\\x42\\xc5\\xbe\\xa4\\xfd\\x4b\\x69\\x59\\x4b\\xee\\x49\\x02\\x4d\\xbf\\x50\\x09\\x54\\xb5\\xda\\xcb\\xfe\\x50\\x85\\x1d\\xec\\x6b\\xe8\\x45\\xb7\\x5b\\x6e\\x6b\\x8f\\x0c\\xd4\\x52\\x07\\x15\\x97\\x44\\x58\\xd2\\x7e\\xbe\\x4e\\xa9\\x5a\\xac\\xed\\xb3\\x63\\x1b\\x7a\\xb5\\xa4\\x29\\xf5\\xdc\\xac\\x1e\\xf0\\xb0\\x76\\x3d\\xe9\\x9f\\x56\\x4f\\xfa\\x11\\x54\\x48\\xdd\\xbf\\x6d\\x88\\x1d\\x67\\xce\\x66\\x67\\x6f\\x5a\\xb1\\xb5\\x89\\x8d\\xce\\x9e\\xa8\\x80\\x27\\x9b\\x7d\\x73\\x03\\xd9\\x4a\\x63\\x44\\x99\\xdd\\xa8\\xd3\\x22\\x2b\\x21\\x76\\xa3\\xe6\\x0f\\xdd\\xb1\\x9b\\x6a\\xaa\\x98\\xde\\xc7\\x92\\x1c\\x0b\\x98\\xf5\\x78\\x86\\xe4\\x84\\x98\\x6f\\x7f\\xc2\\xbe\\xf7\\x50\\x79\\xc4\\x55\\x0d\\x25\\xfd\\xbf\\x5a\\x59\\x54\\x44\\x4f\\x1a\\x29\\xd4\\xc1\\xdd\\xb5\\x15\\x61\\x3e\\xb2\\x0c\\xc7\\x48\\xcd\\x6e\\x27\\x54\\xef\\x9c\\xb1\\xbb\\x37\\x37\\xb6\\xb3\\xfd\\xfe\\xfb\\x8b\\xf3\\x36\\x41\\x68\\xc6\\x73\\xd2\\x2a\\xfc\\x3f\\x06\\xe3\\xc0\\x27\\x93\\x55\\x82\\xff\\x5c\\x85\\x8a\\x36\\x54\\x3b\\xf7\\x80\\xb3\\xcf\\x3f\\x04\\x74\\xc6\\x09\\xab\\xdd\\x04\\xe7\\x5c\\xdd\\xec\\xdf\\x1a\\x68\\x61\\xc8\\xf8\\xb8\\x7f\\x7b\\xf6\\x92\\xd8\\xbb\\x8d\\xac\\xf3\\xdb\\x98\\xe7\\xf7\\x6d\\xec\\x31\\x4e\\x58\\xed\\xb8\\x4b\\xb9\\xba\\x79\\x80\\xb6\\x42\\xfb\\xea\\xc0\\x45\\xfa\\x76\\xb7\\x94\\x9c\\xc7\\xe9\\x69\\x98\\xd7\\xf0\\x5c\\xe7\\x81\\xa0\\x25\\xc6\\x4c\\x56\\xe4\\xd6\\x56\\xde\\xb6\\x1a\\xe2\\x7b\\x5e\\xbc\\x20\\x2f\\x85\\xaa\\x4a\\x56\\x47\\x68\\xcd\\x0f\\x65\\xe4\\xad\\xc6\\xfa\\x22\\x14\\x37\\x57\\x2f\\x5a\\xf3\\x4a\\xb4\\x8d\\xa9\\x5f\\x8a\\x9b\\xa3\\xa0\\xa5\\x06\\x45\\xae\\x1d\\x44\\xf2\\xc3\\x39\\x3a\\x1d\\xdc\\x10\\x4d\\x30\\xe9\\x62\\xe4\\x72\\x33\\x7a\\xb6\\x0c\\xaf\\x6f\\x39\\xe4\\x1e\\x32\\xb8\\x13\\xd4\\xe5\\x0f\\xb1\\xe5\\x95\\xef\\x85\\x41\\x4e\\x52\\x36\\x3d\\x51\\x29\\x7d\\xde\\x83\\xcf\\xb8\\x2c\\xf7\\x78\\x4e\\x54\\x91\\x83\\xe7\\x07\\x03\\x72\\xcd\\x73\\x9e\\xd1\\x32\\x9b\\x45\\xad\\x81\\xeb\\xe7\\x0c\\xdb\\x75\\x03\\x42\\x34\\xcb\\xb3\\x03\\x72\\x24\\x4b\\x18\\x39\\xa1\\x82\\x64\\xcc\\x15\\x01\\xb3\\xa7\\x7a\\x86\\x7a\\xc7\\xf1\\xe3\\x20\\x91\\xe4\\xd1\\x78\\x8a\\x90\\x5a\\xb6\\x84\\x6b\\xa9\\x93\\xa9\\x2c\\xbf\\x8f\\xfa\\x3c\\x9c\\xd7\\x0c\\x8f\\x0b\\xc3\\x05\\x07\\xe4\\x7b\\xcb\\xbe\\xac\\x5c\\x80\\xc8\\x00\\x87\\xd9\\x3d\\xf1\\xb8\\x36\\xeb\\xf1\\xd9\\x43\\x76\\xb2\\x6c\\x2c\\xba\\xee\\x1e\\x1b\\xa0\\x77\\xb5\\x9e\\x8c\\xb9\\xbe\\x62\\x85\\x6c\\x41\\x86\\xc3\\x81\\xe6\\xfc\\x0b\\x5c\\x9b\\x1b\\x52\\x71\\x68\\xec\\x48\\x35\\xa1\\x48\\x92\\x92\\x2a\\xa3\\x46\\xa9\\x43\\xef\\xc2\\x80\\x9c\\xbf\\xbc\\xbc\\x7a\\x79\\x76\\xfa\\xfe\\xe5\\xf9\\x0b\\xf2\\xad\\x1d\\x89\\x87\\x7a\\xc0\\x80\\xbc\\x0f\\x5b\\xb5\\x04\\x09\\x6f\\xb6\\x1f\\x86\\xff\\x56\\xcf\\x92\\x58\\x2a\\xea\\x96\\x73\\x50\\xba\\x9e\\x0a\\x72\\x21\\xb8\\xae\\x9b\\xed\\x62\\x5e\\x40\\x26\\x85\\x8d\\xf4\\x37\\x6f\\x5b\\xef\\xc6\\x98\\x6b\\x5b\\x0c\\x19\\x07\\x33\\x3f\\xc7\\xa3\\xd9\\xac\\x70\\x23\\x6c\\xd6\\x49\\xdd\\x4f\\x50\\xf8\\xab\\xb7\\xe7\\x21\\x14\\x55\\xd7\\x45\\xb2\\x1d\\x1d\\xcb\\x77\\x10\\x75\\x15\\xb2\\xd0\\x5b\\x5c\\xdf\\x47\\x66\\xeb\\x1b\\xa6\\xbb\\x5e\\x14\\xb2\\x8c\\xfa\\x99\\x0f\\x06\\x87\\x03\\x62\\xd8\\xf8\\xe1\\xe0\\xd0\\x89\\x7c\\xd9\\x42\\xd3\\x7d\\x3f\\x68\\xd8\\xf2\\x27\\x46\\xf8\\x01\\x21\\xef\\x5c\\x56\\x25\\xd4\\x41\\x5d\\xde\\xbf\\x1f\\x4b\\x96\\x07\\xdd\\xda\\xe7\\x8e\\x8d\\xab\\x36\\x53\\x0d\\xc3\\x8f\\xda\\x1e\\x41\\x63\\x3e\\xb5\\xd5\\x2c\\x1f\\xcc\\xa7\\x50\\x4f\\xb5\\x95\\x6d\\x0c\\x57\\x6e\\x35\\xe5\\xab\\xd7\\x0f\\xb7\\x36\\xa4\\x38\\x2d\\xad\\xcc\\x92\\x2f\\xbb\\xae\\x44\\xe6\\x39\\x36\\xb5\\x99\\xf8\\x3a\\x7b\\x75\\xa9\\x3c\\x4f\\x1d\\x1f\\x44\\xcb\\xc7\\x56\\x3e\\xa3\\x9d\\x0e\\xf6\\x1c\\x67\\x70\\x43\\xcd\\x69\\xf5\\xfe\\xb6\\xcd\\x7e\\x16\\xb5\\x3a\\xb5\\x7d\\x07\\x60\\xdb\\x4b\\x4a\\xb9\\x12\\x64\\x96\\xcd\\x9e\\xf8\\x8f\\x9f\\x5c\\xbd\\x3c\\x3d\\x7f\\xf3\\x72\\x90\\xa7\\x4f\\x90\\x48\\x33\\x91\\x16\\x92\\x0b\\xad\\x76\\xd5\\xf0\\xa9\\x9e\\x3c\\x00\\x79\\xf7\\xd3\\x6e\\x47\\x86\\xf3\\xc3\\xb9\\xf3\\xe3\\x6e\\x04\\x8d\\xc1\\x6c\\x71\\xb7\\x00\\xbb\\xb4\\x2c\\x64\\x26\\xc7\\xcb\\x5b\\x07\\x6f\\x81\\x36\\xff\\x86\\x4d\\x25\\xfa\\xb4\\x6f\\xf0\\xf1\\xe1\\x94\\x5d\\x3d\\x69\\x4b\\xcf\\xd5\\x13\\x07\\xc8\\x1a\\x5a\\x5e\\x6f\\xd4\\x93\\x2f\\x03\\x60\\xf7\\xa8\\x46\\x2c\\x40\\x11\\xcd\\x39\\x40\\xde\\x5c\\xdf\\xb6\\xba\\x11\\x5a\\xc1\\xca\\x9c\\x63\\x16\\x4a\\x53\\xfd\\xe2\\x61\\x80\\xbf\\xab\\x6a\\x61\\x28\\xf9\\xe5\\x8e\\xe8\\x1a\\x43\\xdd\\x8d\\x14\\x33\\x90\\xa2\\x64\\x7d\\xdf\\x69\\x66\\xc4\\x33\\x06\\x55\\xd5\\xbd\\x84\\x14\\xf2\\x13\\x67\\x09\\x76\\x76\\x63\\x7c\\x2a\\x9b\\xcd\\x5b\\x84\\x83\\xc2\\x6e\\xce\\x10\\x8f\\xf5\\xa7\\xb3\\x6c\\x56\\x77\\x13\\xb4\\xd6\\x30\\x3a\\xc6\\x0e\\x32\\xa5\\x75\\xc8\\x15\\x25\\x9f\\xf2\\x8c\\x8d\\xa1\\x53\\x28\\x17\\xe3\\xa0\\xf2\\x60\\x58\\xab\\xd0\\x96\\xa9\\x8c\\x9d\\x53\\x6f\\xcc\\x5f\\x41\\xd3\\x6a\\xc0\\xac\\xb7\\xef\\xde\\x43\\xd3\\x59\\x08\\xa9\\xd8\\x5b\\xe1\\x34\\x1f\\x84\\x33\\xdf\\xef\\xf7\\xc1\\xf4\\x77\\xf4\\x77\\xa3\\xf9\\xa4\\xd9\\x31\\xf9\\x91\\xd9\\xef\\x48\\xe8\\x8a\\x5b\\xf2\\x44\\x93\\xdb\\x89\\xf4\\x2d\\x4a\\x61\\xae\\x35\\x64\\x01\\xa1\\x31\\x8c\\xcf\\x3e\\x75\\x62\\x9e\\x34\\x12\\x35\\xb2\\xf2\\xe8\\x79\\xce\\xa0\\xef\\x57\\x1d\\x67\\xf0\\x14\\xb5\\xa4\\x07\\x62\\xa0\\x2d\\x53\\x7b\\xe7\\x6c\\x5a\\x76\\x46\\x7c\\xf8\\x80\\xe3\\x0b\\x94\\xa8\\x59\\x9e\\x71\\x71\\x53\\xb7\\x55\\x1a\\x49\\x5b\\x99\\x95\\x11\\xf3\\x83\\x3b\\x35\\x25\\xa3\\xd9\\x6a\\x8e\\xb1\\x0b\\x8e\\x3e\\x18\\xb7\\xd0\\xad\\xf9\\x23\\xc0\\x5f\\x60\\xa8\\xc5\\xff\\x75\\xc4\\xcb\\x06\\x80\\x85\\xa4\\xfe\\xe0\\xe0\\x49\\x43\\x8c\\xab\\x44\\xf1\\xfd\\xc9\\x3b\\x0c\\x13\\xd1\\x76\\x41\\x2e\\xae\\xcf\\xae\\x2f\\xee\\xd5\\xeb\\xb7\\x8a\\xb9\\xc2\\xec\\x9e\\xb4\\xf6\\xc0\\x7f\\xde\\x2d\\xaa\\xaa\\x4f\\xb2\\x6a\\xd7\\x37\\xd1\\xf4\\x72\\x29\\x4b\\x4d\\xb3\\x07\\x20\\x9c\\xc9\\x84\\x16\\xa7\\x95\\x9e\\x9c\\x73\\x05\\x05\\x86\\xdb\\x11\\xff\\x16\\x46\\x0d\\xf2\\x15\\xb1\\x75\\xb3\\xeb\\x51\\xc7\\x1d\\xfa\\xda\\xe7\\xce\\xfe\\xef\\xe9\\x25\\xa1\\x95\\xc1\\x47\\x6d\\xbb\\x72\\x3e\\x58\\xb0\\x9c\\x5b\\xc5\\x35\\xe6\\x40\\xb7\\x0a\\x19\\x3b\\xe6\\x06\\xb8\\xb8\\xa7\\x1e\\x13\\x54\\xee\\x2f\\xeb\\xad\\xf3\\x47\\x03\\xe7\\x42\\xaa\\xff\\x85\\xf8\\xa0\\xb9\\xe0\\x9a\\x53\\x2d\\xcb\\xd6\\x7c\\x83\\xd1\\x88\\xde\\x60\\x58\\x29\\x2d\\x73\\x7b\\x8a\\x2e\\xdc\\x13\\x10\\x90\\x05\\xf2\\xdb\\xc2\\x4b\\xb5\\x35\\x11\\xb4\\x4f\\x80\\xf9\\x85\\x30\\xba\\x22\\x4d\\xd8\\x5c\\x9a\\x4d\\x0f\\xba\\x65\\xe2\\xd8\\xdc\\x3f\\xf3\\x17\\x6b\\x44\\x87\\xce\\x45\\xd9\\x5f\\x5f\\x44\\xfd\\xe4\\xeb\\xd6\\x94\\xae\\x09\\xb0\\xb5\\x62\\x26\\x52\\x08\\x96\\xec\\xd3\\x5b\\x79\\xff\\x2d\\xf9\\xb9\\x1d\\xd2\\xc6\\x7f\\x16\\x73\\xfe\\x04\\x04\\xd1\\xff\\xab\\x68\\x86\\xa0\\x7d\\xfb\\x90\\xc6\\xf7\\x78\\x4b\\xdb\\x59\\x71\\x8c\\x25\\x76\\xf1\\x35\\x4a\\xbc\\xf5\\xd6\\xb6\\x4a\\x61\\x5f\\x26\\x84\\x88\\x2e\\xa9\\x50\\x06\\x4f\\x62\\x7b\\xc6\\xa1\\x0d\\x80\\x38\\x24\\x47\\x3a\\x29\\x8e\\x1f\\x0c\\x52\\x6d\\xa5\\xc3\\x66\\x95\\x08\\x85\\x55\\x5c\\xfb\\x7b\\x44\\x8d\\xd7\\x3e\\x1d\\x76\\xbf\\x65\\x3e\\x78\\x90\\x03\\x9c\\xf6\\x76\\xec\\xb6\\x76\\x2c\\x8f\\x47\\x21\\xbc\\x50\\x40\\x24\\xaf\\xb9\\xd2\\x98\\x47\\x83\\x0f\\x43\\x19\\x17\\xcc\\x27\\x34\\xba\\xc0\\x25\\x91\\x25\\xe1\\xc5\\xff\\xd2\\x34\\x2d\\x5f\\xa0\\x1c\\x61\\x75\\x55\\xf8\\xbf\\xf2\\x9d\\x82\\xa8\\xf0\\xd1\\x36\\x47\\x7a\\x56\\xd8\\x1e\\x71\\xef\\xcf\\x2e\\xe1\\x49\\x45\\xfe\\xe3\\x8f\\xcf\\x40\\x2f\\xf8\\xfd\\xd7\\x7f\\x7c\\xb6\\x27\\x22\\x3e\\xd5\\xac\\x42\\xd2\\xb6\\x4d\\xb4\\xf5\\xc8\\x8a\\x2f\\x24\\x8b\\x24\\xca\\x16\\x81\\x76\\x32\\x46\\xda\\xbd\\xc6\\xe4\\x0c\\xc3\\x27\\x2d\\xd1\\xc4\\x83\\x60\\xb0\\xd2\\x73\\xef\\x36\\x65\\xe2\\x2e\\xeb\\xe2\\x57\\x94\\x75\\x41\\x7c\\x36\\x3e\\x12\\xd6\\x56\\x10\\x39\\x1c\\x10\\xca\\xea\\x2c\\x12\\x70\\xa4\\xdd\\x97\\x4f\\x85\\x76\\xef\\x08\\xdd\\x5d\\x31\\x39\\xc6\\xe0\\x30\\xc4\\xcf\\x26\\xe2\\x06\\xe9\\xa9\\xe7\\x6f\\xaf\\xff\\xf7\\xf5\\xe9\\xdf\\x5e\\xbe\\x86\\xb5\\xda\\xa8\\x40\\x83\\x9e\\x56\\x13\\xda\\x25\\x66\\xbd\\x39\\xba\\xef\\x6e\\xdc\\xda\\x15\\xa4\\x6d\\x04\\x18\\x88\\xb9\\xd0\\x02\\x41\\xde\\xbe\\xba\\xde\\x36\\xaa\\x60\\x5f\\x75\\x56\\x8c\\xf6\\x80\\xde\\x53\\xf3\\x6b\\x98\\x57\\xa1\\x5f\\xeb\\x43\\x64\\xce\\xb7\\xec\\x14\\x09\\xaa\\xe2\\x47\\x76\\x14\\x83\\x43\\xb8\\xc6\\xbd\\x4d\\x1d\\x3b\\xe2\\x06\\x79\\x74\\xb2\\xde\\x7a\\xff\\xb7\\x81\\x18\\x42\\xb1\\x75\\xcf\\xf7\\xbd\\x42\\x7b\\x3f\\x19\\xb2\\x6c\\xab\\xac\\xc3\\x21\\x8e\\xe5\\xc4\\x47\\x43\\xc2\\x90\\x77\\x94\\x86\\xab\\x1a\\x7e\\xca\\x94\\x6f\\x50\\xf4\\x05\\x60\\x6b\\xb1\\xac\\xdd\\xf4\\xfe\\xdc\\x61\\xe9\\xb0\\xf8\\xdf\\x6b\\xd7\\x2d\\x30\\x88\\x2a\\x88\\xf2\\xba\\x57\\x75\\x94\\x77\\x11\\x99\\x34\\x0f\\x1a\\x6b\\xb6\\x59\\xf9\\xb1\\xbe\\x85\\x77\\xb0\\x49\\xde\\x13\\x64\\x30\\x30\\xf1\\x07\\x4a\\x2f\\xf3\\xdf\\x6e\\xe7\\x38\\xfa\\xe1\\xe6\\x2b\\xad\\x6c\\x85\\x25\\x84\\x2a\\x27\\xc8\\xd9\\x58\\xf3\\xb0\\x24\\xcb\\xa3\\x44\\x21\\xf2\\xe8\\xf8\\x90\\x67\\x43\\x3f\\xee\\x68\\x6e\\x78\\x48\\x53\\x43\\x31\\x91\\x5a\\x8a\\x96\\x73\\x68\\x97\\x0d\\x1a\\x13\\xb6\\x4b\\x78\\xe2\\x0c\\x33\\xdd\\x33\\x56\\x06\\xf4\\x16\\x33\\x88\\xbc\\x5b\\xdd\\x68\\x1e\\x8e\\x75\\x4b\\xe1\\x1c\\xec\\xb1\\x7b\\xfd\\xe9\\x51\\xa2\\x22\\xbd\\x38\\x7f\\x00\\x22\\xf4\\xa5\\x15\\x3b\\xda\\xd6\\x4d\\xf8\\x60\\x81\\xb2\\x69\\x4b\\x99\\xfb\\x66\\x20\\x07\\xf3\\x8b\\x73\\xab\\x2e\\xb8\\xb4\\x7c\\x65\\x8f\\x15\\x59\\x7d\\xae\\x1e\\x44\\x94\\x92\\xa5\\xbe\\x95\\x65\\x5b\\xe5\\xe3\\xe2\\xe1\\xe6\\xa2\\x30\\xed\\x6f\\x0b\\xc5\\x38\\xbe\\x4c\\x2a\\x82\\xab\\x7c\\xf2\\x94\\xe4\\x1a\\x28\\xc9\\x5c\\xe7\\xee\\x55\\x14\\xe5\\x2e\\x08\\xca\\xd3\\x21\\x24\\x77\\x23\\xb8\\xdc\\x6d\\x25\\xae\\x07\\x53\\x7f\\xdd\\xf1\\x68\\x05\\x58\\x6e\\x30\\x6b\\x06\\x35\\x88\\x52\\xd3\\x5d\\x0a\\xe6\\xe6\\x80\\xf2\\x3c\\x08\\x9d\\x2d\\xa5\\xa1\\x43\\xbb\\x91\\x93\\x98\\xc4\\xba\\x91\\xd0\\x39\\x88\\x5d\\x1d\\xb3\\xcc\\xec\\xac\\x14\\x61\\x3f\\x48\\x5b\\xac\\xab\\x47\\xb0\\x67\\x62\\x4e\\x0b\\x85\\x4d\\x29\\x52\\x79\\x2b\\x6e\\x69\\x99\\x92\\xd3\\xcb\\x8b\\xfb\\xa7\\xab\\x7b\\x67\\x82\\xe2\\x79\\xd8\\xa7\\xb7\\x40\\x9c\\x0b\\x5a\\x8f\\x07\\x11\\xf8\\x10\\x24\\x64\\xfe\\x18\\x72\\x8d\\x6d\\x9b\\x31\\x18\\x5f\\x87\\xd6\\x28\\xc3\\xa7\\x7c\\x24\\x8b\\xa1\\x74\\x86\\xaa\\xd9\\x91\\x02\\xb1\\x4a\\x10\\x99\\x68\\x9a\\x61\\x0b\\x10\\x32\\x64\\xfa\\x96\\x31\\x41\\x9e\\x3d\\x7b\\x86\\x0e\\x8a\\x67\\x7f\\xfa\\xd3\\x9f\\x08\\x34\\xe5\\x4c\\x59\\xc2\\xf3\\xc5\\x07\\xe1\\xa9\\x7f\\x7f\\xfe\\x7c\\x40\\xfe\\xfb\\xf4\\xcd\\x6b\\x42\\x13\\xd0\\xe5\\xb0\\xf2\\x2d\\x8e\\x0c\\xfb\\x19\\xbe\\xac\\x7a\\xe4\\xbf\\xae\\xdf\\xbd\\xad\\x1b\\xca\\xc7\\xbf\\x02\\xba\\xf8\\xe5\\x0d\\xc8\\x79\\x10\\x7b\\x1f\\x3a\\x0f\\xa8\\x9e\\x00\\x34\\x84\\xd4\\x84\\x8e\\x46\\x88\\x70\\xae\\xab\\xbd\\x25\\x26\\xae\\xf6\\x1c\\x1f\\x4f\\x60\\xb9\\x5c\\x00\\xaa\\x65\\x90\\x14\\xc0\\xcd\\x14\\xc1\\x61\\xe3\\xea\\x38\\x62\\x8e\\x03\\x8c\\xe5\\x99\\x08\\x4c\\xa5\\x47\\x32\\x7e\\xc3\\xc8\\x48\\x7d\\x5b\\xca\\xaa\\xa8\\x1b\\xa7\\x94\\x4c\\x19\\x05\\x2c\\xa1\\xc2\\x8c\\x8e\\x83\\xd5\\x3b\\xa3\\xd8\\x9e\\xb5\\x31\\x1f\\x3a\\x72\\xc2\\x9e\\xd3\\x76\\x5c\\xc8\\xf6\\xcc\\xbb\\x16\\x62\\xb6\\x37\\xa0\\xcb\\xd1\\x42\\x92\\x61\\x76\\xe1\\xa9\\x46\\x32\\x44\\xab\\xbd\\xf4\\xeb\\x41\\xa4\\xb2\\xd5\\x0f\\x6b\\xca\\x48\\x33\\x29\\xc6\\x21\\x0e\\xd6\\xd2\\x87\\x0b\\xa6\\x9c\\x15\\x6c\\x57\\x60\\xb4\\xd4\\x50\\xa7\\x9d\\xf6\\x74\\x48\\xdc\\xdf\\xd0\\x62\\xbf\\x4e\\x20\\x71\\x8c\\xae\\x1b\\x33\\xaa\\x43\\x49\\x87\\xb2\\xd2\\x2e\\x66\\xcf\\xfe\\x0e\\xe5\\xdb\\xb4\\x74\\xa0\\xdf\\x6b\\x0a\\xad\\x75\\x29\\x6a\\xaf\\xef\\x5f\\x4b\\x4d\\xb7\\xe2\\x98\\x39\\xe0\\xda\\xb1\\xc8\\xda\\x23\\x8c\\x26\\x13\\x72\\xc3\\x66\\x7d\\xe4\\x00\\x05\\x85\\xea\\x11\\x00\\xed\\x73\\x03\\x63\\x2c\\x93\\x1b\\x87\\x33\\x24\\x2c\\x35\\xda\\xa4\\xdd\\x0a\\x17\\x60\\x19\\xc8\\x07\\xae\\xfa\\x84\\x53\\xb8\\x94\\x95\\xcb\\x6d\\x2b\\x2b\\x11\\x58\\x28\\x5d\\xef\\xca\\x44\\x0a\\x6d\\xfb\\x62\\xfa\\xde\\x55\\x10\\x30\\x3a\\x57\\x90\\xc0\\x50\\x18\\x96\\x9a\\xd7\\xd4\\xba\\x2f\\xd7\\x51\\xa5\\x86\\xa3\\x58\\xf9\\xa3\\x12\\x0b\\x6f\\x43\\x3d\\x77\\x88\\xe9\\x55\\xcc\\x56\\x46\\xa2\\xae\\x27\\x62\\x10\\x99\\x3a\\xe1\\x09\\x64\\x1c\\x99\\xc7\\xed\\xb3\\x0e\\x4a\\x1e\\x10\\x51\\xc1\\x04\\xc5\\x74\\x65\\x41\\x03\\x71\\xc2\\xe6\\xdb\\x4c\\x29\\xc2\\x61\\x85\\x39\\x2d\\x6f\\x98\\x2b\\x34\\x4c\\xb3\\x01\\xb9\\x34\\x93\\xf4\\xd5\\xe6\\xb1\\x95\\xe0\\x14\\x13\\x44\\x0c\\x8d\\x09\\x2b\\x41\\x98\\x8f\\x1c\\x0e\\x06\\x87\\xc8\\x2a\\x97\\xd4\\x85\\xd8\\x1b\\x6b\\xda\\xec\\x22\\xd7\\x5a\\xf7\\xb8\\x08\\x95\\xdf\\xd0\\x42\\x61\\x37\\x3d\\xa3\\x5a\\x40\\xc7\\x4a\\x09\\x75\\x5b\\xf4\\xc4\\x09\\x13\\x74\\xcf\\x12\\xe2\\xe1\\xd5\\x72\\x1b\\xb3\\x76\\x3b\\xa1\\xb6\\xd7\\x07\\x75\\x0f\\x5f\\x7b\\x7c\\xb5\\xdd\\xff\\xb4\\xc5\\xee\\xa7\\xab\\x7a\\x9f\\x5a\\x1c\\xb2\\x94\\xa4\\xad\\x8e\\x8c\\xad\\xb7\\xdc\\xcc\\x5b\\x68\\x6c\\xe6\\xae\\xd8\\x75\\x04\\xf2\\x6d\\x54\\x4b\\xba\\x91\\x2e\\x62\\x4b\\xa9\\x67\\xec\\x49\\x29\\x1f\\x17\\x23\\x20\\xa9\\xcb\\x6b\\xdd\\x84\\x7a\\x99\\xe3\\x30\\x06\\x02\\x0f\\xaf\\x75\\xec\\xdb\\x65\\xcf\\x5d\\x77\\xd1\\xa6\\x7e\\x7f\\xb5\\x64\\xfe\\xda\\x27\\x88\\x66\\xfe\\x8a\\x0d\\x19\\x41\\x59\\x09\\xcf\\x6a\\xc3\\xec\\x63\\xd8\\x2a\\x2d\\xa1\\x5b\\x67\\x4d\\x1c\\x06\\xe4\\x8d\\x65\\xc5\\x88\\xe4\\x74\\xa8\\x64\\x56\\x69\\x5f\\x89\\x62\\x09\\x9f\\x86\\x41\\x5d\\x6f\\x4f\\x2c\\xda\\xe4\\x1e\\x0b\\xb8\\x36\\xc8\\x2b\\xc8\\xca\\xda\\x61\\xe0\\x78\\xb5\\x48\\x7c\\xf6\\x0d\\x90\\xc5\\xeb\\x57\\x16\\x26\\x8b\\x57\\x8b\\xbb\\xe0\\xc4\\xc5\\x96\\x77\\xc2\\x0d\\xeb\\xab\\x77\\xba\\x8c\\xc8\\x48\\xba\\x85\\x18\\x59\\xad\\x50\\x74\\x76\\x82\\x2a\\xe6\\x50\\xee\\x5a\\x01\\xbb\\xbe\\xf6\\xb7\\xea\\xda\\x75\\x59\\x03\\xe3\\xe9\\xe5\\x45\\x8b\\x5a\\x69\\x30\\xea\\x0a\\xbd\\x34\\x7c\\xa2\\xd3\\x4c\\x9b\\x5c\\x11\\x80\\x2f\\x50\\x33\\x35\\x22\\xbd\\x33\\x20\\x9d\\xd7\\x10\\xb5\\x2e\\x3d\\x43\\x94\\x7f\\x05\\xaa\\xcd\\xc2\\xc2\\x5f\\x19\\x66\\x14\\x26\\x73\\xc5\\x1d\\x3a\\xd0\\x18\\x5c\\xb3\\xad\\xa0\\xab\\x87\\x8b\\xe1\\x01\\x12\\xf7\\xe5\\xab\\x41\\x8f\\x54\\x79\\x01\\xe8\\xef\\x91\\xb1\\x33\\x7f\\xc5\\x5c\\xf4\\xca\\x01\\x91\\x5c\\xb3\\xcc\\x30\\x3d\\x32\\x67\\xb2\\x29\\x64\\xfa\\x02\\x7b\\x7e\\x53\\x21\\xa4\\x06\\xbc\\x51\\x3d\\x92\\x41\\x3f\\xf2\\x1e\\x9a\\x62\\x8c\\x04\\x1a\\x44\\x7f\\x95\\x81\\xd3\\xb4\\x65\\x99\\xb3\\x35\\xe4\\x21\\xad\\x23\\x10\\x01\\x24\\x02\\xd8\\x5d\\xb6\\x83\\x49\\xe4\\x0e\\xb0\\xc9\\x5c\\xb5\\xa8\\xd2\\x66\\x5b\\xfe\\x08\\xaf\\xec\\xf8\\x0e\\x89\\x54\\x32\\x61\\x39\\xc5\\x7e\\x24\\x0e\\x40\\x86\\x5e\\xdf\\x96\\x5c\\x6b\\x86\\x55\\xc7\\x59\\x99\\x2b\\x22\\x47\\xbd\\xc8\\x6f\\x7c\\x30\\x7d\\x7e\\xd0\\x96\\x3c\\x4b\\xee\\x42\\xa1\\x26\\xee\\x84\\xee\\x5a\\x06\\x6c\\xd5\\x15\\xfb\\x0d\\x22\\xe5\\xc2\\x9c\\x4e\\xd0\\xa6\\x33\\x68\\x90\\x24\\xe6\\x0c\\x96\\x46\\x88\\x98\\x22\\xfc\\x1f\\x35\\xe8\\xee\\xce\\x16\\xb1\\xab\\x0d\\xa2\\xe7\\x05\\xd3\\xce\\x06\\xd1\\xd9\\x20\\xda\\x18\\xf1\\xce\\x6c\\x10\\x01\\xe3\\x76\\xc4\\x74\\x89\\x3d\\x22\\x4c\\xc4\\x73\\x46\\x89\\xba\\x94\\x45\\x50\\x26\\xda\\xa0\\xbc\\x33\\x47\\xc8\\x32\\xf6\\x15\\x1c\\x0e\\x06\\x87\\x87\\xce\\x48\\x61\\xcf\\x47\\xa5\\x47\\xfd\\xff\\x20\\x4c\\x24\\x32\\x45\\xa4\\x32\\xe3\\x97\\x4a\\x83\\x50\\x5b\\x6b\\xe5\\xe1\\x5c\\x72\\xf7\\xad\\xd0\\xdf\\x00\\x63\\xb7\\x8b\\x12\\x2d\\x52\\x28\\x17\\x92\\xf2\\xea\\x4e\\x45\\xb0\\x5a\\xf0\\xf2\\x65\\xc0\\x2c\\x00\\x7d\\xb5\\x44\\x2b\\x81\\xd5\\x21\\x32\\x19\\xcf\\xb9\\xad\\x4f\\x68\\xc8\\x05\\x53\\x5a\\x91\\x23\\xbc\\x39\\x48\\x8a\\xaa\\x67\\x1f\\x18\\xe4\\x2c\\x97\\xe5\\xac\\xe7\\x1f\\x32\\x3f\\x46\\x6f\\xd9\\x27\\x8e\\x41\\x6a\\x4b\\xaa\\xb2\\x64\\x42\\x67\\xb3\\x5f\\xaf\\xfc\\xe6\\x40\\xfc\\x88\\xc5\\x37\\x8f\\x15\\xfb\\xe4\\x7d\\x2c\\xbb\\x62\\xb4\\xac\\x9b\\x08\\x80\\xf5\\xce\\x43\\x1b\\xf8\\x90\\xcd\\xc0\\xe8\\xd5\\xc6\\x1f\\x73\\x97\\x89\\x29\\x99\\xd2\\x72\\xe7\\x0c\\x8c\\x65\\xd7\\x9d\\x48\\x6c\\x29\\x9f\\x72\\x25\\x77\\xce\\x61\\x5b\\x3a\\x64\\x08\\xbc\\x6b\\xcb\\x94\\xd1\\x46\\x2c\\x2b\\x5d\\x54\\xda\\x72\\x17\\x77\\xb6\\x5d\\xc9\\x3e\\x7f\\xa6\\xe7\\x04\\xdf\\xe7\\x07\\x2d\\x4e\\xae\\xa0\\x5a\\xb3\\x52\\xbc\\x20\\xff\\x73\\xf4\\xf1\\x77\\xbf\\xf4\\x8f\\xbf\\x39\\x3a\\xfa\\xf0\\xac\\xff\\xe7\\x4f\\xbf\\x3b\\xfa\\x38\\x80\\xff\\x7c\\x75\\xfc\\xcd\\xf1\\x2f\\xee\\x8f\\xdf\\x1d\\x1f\\x1f\\x1d\\x7d\\xf8\\xee\\xcd\\xb7\\xef\\x2f\\x5f\\x7e\\xe2\\xc7\\xbf\\x7c\\x10\\x55\\x7e\\x83\\x7f\\xfd\\x72\\xf4\\x81\\xbd\\xfc\\xd4\\x70\\x90\\xe3\\xe3\\x6f\\x7e\\xdb\\xe2\\x22\\xa8\\x98\\xbd\\x6b\\x8d\\x04\\xe3\\xd5\\xbf\\x13\\x31\\x22\\x1e\\xbb\\x65\\xd4\\x25\\xe4\\x73\\xbf\\xb6\\x68\\xf7\\xb9\\xd0\\x7d\\x59\\xf6\\xf1\\x23\\x2f\\x88\\x2e\\xab\\xb6\\x48\\x57\\xcd\\xfe\\xee\\x8e\\xc6\\xd4\\x42\\x4c\\x5d\\x01\\xd3\\x29\\x36\\x8f\\x90\\x88\\x60\\x60\\x6a\\x8b\\x96\\x61\\xdb\\xc7\\x76\\xb9\\x51\\xd8\\xfe\\xd8\\xd9\\x83\\x9b\\x5c\\x77\\x18\\xa9\\x64\\xeb\\xd9\\xfc\\xca\\xc3\\x94\\xae\\x6d\\x37\\xe5\\x2e\\x46\\x69\\xe1\\xea\\x62\\x94\\x16\\xaf\\x2e\\x46\\x69\\xcb\\xab\\x8b\\x51\\x72\\x57\\x17\\xa3\\xd4\\xd9\\x07\\xf7\\xbf\\x7e\\xe5\\xf6\\xc1\\x2e\\x46\\x69\\xdb\\xab\\x8b\\x51\\xda\\xf9\\x7a\\x42\\x31\\x4a\\x28\\xe4\\x2f\\x8b\\x54\\xb2\\x62\\x7e\\x1d\\xa6\\xf4\\x68\\xa3\\x94\\x94\\xc1\\x87\\x84\\x9d\\x26\\x89\\xac\\x84\\x7e\\x2f\\x6f\\xd8\\x9e\\x8e\\xdc\\x39\\x9d\\x74\\x61\\x74\\x28\\x89\\xb8\\x42\\x47\\x5d\\x7c\\xf8\\x51\\x2a\\xac\\x6d\\xc9\\xa3\\x2d\\xc8\\x8f\\xed\\x49\\x8e\\xb4\\x4a\\xb9\\xd1\\x51\\x5b\\x3e\\x2c\\x6e\\xd8\\xb0\\x2c\\xb6\\x48\\x59\\x5a\\xff\\x60\\x49\\x9a\\x36\\xfb\\x3d\\x20\\xa7\\xa4\\x64\\x09\\x2f\\xb8\\x61\\x00\\x50\\x2b\\x08\\xee\\xe3\\xf1\\xf1\\x5d\\x9c\\xb9\\x56\\x2c\\x1b\\xd9\\x4e\\xb6\\xa2\\x4e\\x73\\x2e\\x03\\xfd\\xd3\\x72\\x94\\xa5\\x9f\\x41\\x19\\x42\\xba\\x5e\\xa3\\x44\\x4d\\x64\\x95\\xa5\\xa4\\x64\\x7f\\x77\\xc2\\x87\\x9d\\xcd\\xfb\\x70\\x84\\xd0\\xa4\\x0a\\x4b\\xa9\\x3f\\x6b\\x07\\xa7\\x05\\xb7\\x45\\xc5\\x1e\\x13\\x19\\x64\\x9f\\x0b\\x5e\\xc2\\x61\\xbb\\x66\\x89\\x14\\x69\\xdb\\x16\\x92\\x85\\xf1\\x6b\\x59\\x01\\xfc\\x42\\x2c\\x25\\x69\\x85\\x0f\\x40\\x3a\\x26\\xcd\\x78\\xca\\xf5\\xcc\\xc7\\x73\\xe0\\xb1\\x37\\x62\\x2b\\xf6\\x0e\\xb6\\x88\\xa0\\xea\\x8d\\x20\\xb4\\x28\\x4a\\x49\\x93\\x09\\x53\\xc1\\xd7\\x50\\x08\\xb5\\x85\\x32\\x7c\\x96\\x67\\x56\\x8d\\xb9\\x40\\x39\\x14\\xde\\x31\\xc2\\x4a\\x36\\x23\\xa5\\xd4\\x2e\\x34\\x6d\\xc5\\x07\\xdf\\x07\\x83\\xc1\\xeb\\x28\\x71\\xe8\\x72\\x06\\xf1\\x6b\\x32\\x1c\\x02\\x67\\xc5\\x47\\xe1\\x1f\\x8a\\xc8\\x2c\\x75\\xa5\\x59\\xff\\xe3\\x99\\x11\\xfc\\x13\\x8b\\xc5\\x86\\x09\\x40\\xd1\\x4c\\x2d\\x49\\x66\\x84\\x27\\xc3\\x18\\x56\\xbf\\xfc\\xf5\\x1f\\xc8\\x44\\x56\\xa5\\x1a\\x84\\xc5\\xfe\\x9e\\xc3\\x3d\\xb4\\x70\\x38\\xc5\\x41\\x93\\x8c\\x51\\xa5\\xc9\\xf3\\x67\\x24\\xe7\\xa2\\x32\\x1c\\xbf\\x25\\xc4\\x6b\\x4b\\xd6\\x0d\\xa4\\xdc\\x3f\\xfe\\x61\\xcf\\xd1\\xda\\x91\\x6f\\x57\\x4a\\xb6\\x05\\x76\\xcc\\xb3\\xe2\\xad\\x3d\\xe3\\x58\\xd0\\x03\\xbb\\x66\\xce\\x09\\xbb\\x96\\x25\\x85\\xbb\\x28\\xb4\\x7c\\xe0\\x93\\xff\\x73\\x25\\x87\\x33\\xbd\\x7f\\x09\\x1b\\x3b\\x4e\\x5c\\xbb\\xe6\\xff\\xd9\\x9b\\x4d\\x4a\\xc5\\xd6\\x95\\x62\\x77\\x98\\xca\\x83\\xf7\\xf8\\x1e\\x73\\xa5\\x77\\xea\\xf0\\x5d\\xd7\\xbc\\xd9\\xe1\\xe5\\x7d\\x99\\xf9\\xd8\\xe8\\xc7\\xad\\x64\\xd2\\xc3\\x48\\x4e\\xa3\\x73\\x16\\xe9\\x24\\x61\\x0a\\x48\\x91\\x2b\\x0a\\x07\\xc6\\x5d\\x7c\\x76\\xc7\\x8f\\x3e\\xd2\\x6a\\x33\\xcb\\x8a\\xc8\\x38\\xe4\\x6f\\xa1\\x57\\xe9\\x5e\\xc0\\xda\\x47\\xe4\\x77\\x88\\xdd\\x12\\xb4\\x70\\xb0\\x98\\x46\\x28\\x2e\\xc6\\xd8\\x5a\\x34\\xaf\\x32\\xcd\\x8b\\xac\\x86\\xdc\\x95\\x7b\\xc1\\x32\\xe0\\xd0\\x5b\\x40\\x03\\xf3\\x34\\xc5\\xa2\\x57\\x58\\xfd\\x1c\\x3c\\x2b\\x47\\x7e\\x2c\\x26\\x34\\x76\\xc8\\x2c\\x0d\\x1f\\x2f\\x68\\x49\\x3d\\xf8\\x13\\x99\\xe7\\x54\\x1d\\x5b\\xc7\\x03\\x85\\x28\\x18\\xdb\\x06\\xc8\\xbc\\x45\\xb3\\x7a\\xc6\\x41\\xd4\\xc1\\x43\\x21\\xae\\x66\\x82\\x8a\\x9d\\xdd\\x7f\\x71\\xc1\\x79\\x18\\x8a\\xc8\\x5b\\x1f\\x68\\x8f\\x4d\\xee\\xe7\\x30\\xd6\\x0a\\xc4\\x7f\\xa3\\xc9\\x0d\\x13\\x29\\xf9\\x5e\\x39\\xc0\\xa5\\x33\\x41\\x73\\x5b\\x3f\\xbe\\x28\\x25\\x76\\x51\\x67\\xe9\\xdc\\xfb\\xaa\\x67\\xcd\\x8e\\x58\\xfa\\xc4\\x15\\xb0\\x42\\x79\\xeb\\xa1\\xa0\\x58\\xa9\\x96\\x8a\\x07\\x9b\\x81\\x36\\xd1\\x3b\\x85\\x26\\xdd\\x92\\x4f\\x13\\xe6\\x64\\x47\\xf3\\xde\\x43\\x2d\\x7e\\xba\\x73\\xb5\\x3a\\xb2\\xbc\\x74\\x94\\x6d\\x63\\x8a\\xa7\\x10\\x58\\xba\\xf7\\x5c\\x42\\x99\\x78\\x9a\\x19\\x12\\x37\\xf3\\x35\\x7f\\xe6\\x10\\x6c\\x38\\x03\\xbb\\xd7\\x83\\x54\\x1e\\x2b\\x87\\xfb\\xd7\\x94\\x3a\\x2c\\x87\\x69\\x4c\\xcc\\xae\\x68\\x2a\\x15\\xf9\\x5b\\x26\\x93\\x1b\\x72\\xce\\x40\\x69\\xb8\\xcb\\xe6\\xfb\\xe5\\x30\\x7d\\xda\\x8d\\x33\\x73\\x3a\\xde\\x2d\\x62\\xa4\\x4f\\x72\\x29\\xb8\\x96\\xe5\\x2e\\xf4\\xf8\\x11\\x15\\x0a\\xec\\x5a\\x19\\x36\\xa9\\x98\\x6e\\xce\\xd9\\x97\\xd2\\xc8\\xd0\\xa0\\x7c\\x3b\\xa8\\x03\\x43\\x79\\xd3\\x09\\x50\\x1e\\xbc\\x05\\x44\\x75\\x67\\x3a\\xf2\\x6f\\x13\\x79\\xdb\\xd7\\xb2\\x5f\\x29\\xd6\\xe7\\x3b\\x07\\x42\\xed\\x0d\\xa8\\x1b\\x36\\x83\\xa8\\xb2\\x56\\x40\\x65\\x07\\x8b\\x34\\x77\\x2d\\xc1\\xce\\x0e\\xf7\\x8d\\x7c\\x77\\xf5\\xb7\\xf3\\xef\\x15\\x2b\\x07\\xa1\\xb6\\x72\\xc2\\x74\\x72\\x92\\xb0\\x62\\x72\\x62\\x47\\x78\\xf2\\x60\\x75\\x64\\xb3\\x1d\\xb8\\xba\\xd1\\x50\\x10\\x48\\x64\\x96\\xd9\\x02\\x63\\x72\\x44\\xce\\x58\\x31\\xf1\\x9f\\x7b\\x1c\\x70\\x7b\\xca\\x3d\\xe5\\x0a\\x29\\xdb\\x69\\x37\\x75\\x68\\x46\\x8a\\xc9\\x06\\xdc\\x41\\xaa\\x11\\x20\\x7f\\x39\\xdc\\xae\\x91\\xf7\\x63\\x44\\xf7\\x7b\\xec\\xce\\xb2\\x4b\\x2b\\xbe\\x47\\x01\\xde\\xc7\\xd3\\xd2\\xef\\x30\\xea\\xe9\\x17\\xe6\\x0f\\xc5\\x0d\\xfb\\x5c\\x74\\x6a\\x44\\xb6\\x2f\\x46\\xa8\\x8c\\xa6\\x2c\\x25\\x72\\xca\\xca\\x92\\xa7\\x4c\\x11\\x4f\\xb7\\x43\\x1b\\x14\\xcf\\x1e\\x07\\xe4\\xbb\\xde\\x81\\x4f\\x2b\\xe0\\xe0\\xf1\\x98\\x1f\\x0e\\xc1\\xfe\\x10\\x11\\x71\\xb8\\xb3\\x40\\xc4\\x69\\x9a\\x73\\xf1\\x38\\xb0\\x7d\\x47\\xb8\\xa9\\x84\\x66\\xec\\xe2\\xdd\\xde\\xda\\xba\\x1d\\x27\\x56\\xd8\\xaf\\xed\\xcd\\xa0\\xa7\\xc0\\x86\\x3a\\xfb\\xdf\\x79\\xdc\\x25\\x42\\xa6\\xbb\\x39\\xd0\\x1e\\x58\\xed\\x1e\\x53\\xcd\\x6e\\x77\\x14\\x84\\xfa\\x35\\xc9\\xdf\\xf5\\x7d\\x50\\xcf\\x9e\\xb6\\xda\\xfe\\x28\\x3a\\x85\\x04\\xa7\\x1c\\x4b\\xfe\\x3f\\x94\\x90\\x65\\xf1\\xa9\\x1d\\x47\\x12\\x8e\\x15\\x36\\x65\\x9b\\x6f\\xc5\\xe6\\xce\\xec\\xe9\\xe5\\x05\\xf9\\x16\\x1f\\x7f\\xb8\\x2e\\x28\\xa5\\xd4\\xa8\\xf2\\x9c\\xcb\\x9c\\xf2\\x76\\x1a\\xa0\\xcf\\x0f\\x3a\\xdf\\x0f\\x2b\\x04\\xc2\\xa5\\x7f\\x96\\xd8\\x87\\x8d\\x50\\x54\\x97\\x1b\\xae\\x4a\\x96\\x12\\x6b\\x4f\\xf9\\xc2\\x5a\\x3c\\x2c\\x88\\xd3\\x5f\\x46\\x8b\\x87\\xbb\\xea\\x92\\x1d\\x98\\xe6\\x5d\\xfe\\x4e\\x2d\\x45\\x3b\\x74\\x02\\x21\\xc2\\xc7\\x3a\\x11\\xc5\\x84\\xe2\\x10\\xde\\x10\\x44\\xe0\\x81\\xa8\\x0d\\x61\\xe9\\x3e\\x59\\x07\\xc5\\xee\\x1e\\x79\\x2d\\xc7\\x5c\\x38\\x2a\\x26\\x6d\\x54\\xcd\\x88\\xf2\\x6c\\x3f\\x70\\x76\\x72\\xf2\\xaf\\x4c\\x4e\\x56\\x2a\\x7b\\x29\\xe8\\x30\\xdb\\x3d\\x64\\x32\\x3e\\x04\\x7e\\x38\\xf2\\x2a\\xa3\\x63\\xc2\\xe0\\x8f\\x93\\x94\\x2b\\xf3\\x2f\\xb9\\xbe\\x7e\\x0d\\xce\\xe0\\x4a\\x38\\xfd\\x12\\xdc\\x9c\\x96\\xb7\\xf8\\xd4\\x68\\x24\\x32\\x0f\\x47\\x17\\x90\\x88\\xb7\\xd6\\xc1\\x23\\x18\\x8f\\x70\\x91\\x9a\\xa5\\x33\\x15\\x05\\x25\\xdb\\x27\\xb0\\x57\\x8a\\xcf\\xbb\\xc3\\xd0\\xc7\\x21\\x23\\xef\\x27\\x3c\\xb9\\xb9\\x0c\\xfc\\xbf\\xb2\\x34\\xf7\\x44\\x70\\x2b\\x12\\x52\\xe6\\x7f\\x7b\\x28\\x6e\\x64\\x97\\x75\\xd9\\x96\\x41\\x2d\\x18\\xcf\\x71\\x6a\\x47\\x4e\\xaf\\x2d\\x04\\xe1\\x37\\xaa\\x94\\x4c\\x78\\x1d\\x7f\\x00\\x96\\xe8\\x9a\\x7d\\xa7\\xc0\\xbe\\x1f\\x0e\\x2a\\x20\\x70\\xb6\\x03\\x10\\x94\\x73\\x97\\x48\\x2d\\x0e\\xa3\\xec\\x13\\x54\\x85\\x52\\x0a\\x17\\x0e\\x6e\\x0f\\x06\\x04\\xc4\\xf1\\xd6\\x5a\\x9a\\xd6\\xc3\\x2d\\xb6\\x34\\x75\\x6a\\xe6\\x9c\\x8b\\xdc\\x25\\xbc\\x5a\\x04\\x72\\x2a\\x83\\xed\\xa1\\xbd\\x88\\x42\\xbe\\xb5\\xa9\\x6d\\x66\\xf2\\x20\\xa0\\xdb\\x3d\\x35\\x7d\\x99\\xf9\\x6f\\x2e\\x3e\\x08\\xef\\x59\\xa7\\x39\\xd0\\x9e\\x42\\x16\\x55\\x86\\x91\\xb5\\xfb\\x77\\x76\\x75\\x3e\\x46\\xfc\\xce\\x03\\x38\\xd1\\x1f\\x5b\\x67\\xa7\\xc3\\x30\\x3d\\x6f\\xfb\\x7c\\xc5\\x2f\\xa3\\xbf\\x53\\xa0\\x5a\\x3c\\xfb\\xe3\\x1f\\xfe\\xf0\\xd4\\x3b\\x3e\\xed\\x67\\xb8\\x7b\\xe8\\x96\\x4f\\x7b\\xb9\\xde\\x96\\xd4\\x66\\xb8\\xe8\\x6a\\x33\\x74\\xb5\\x19\\xe2\\xeb\\xc1\\xfd\\xc3\\xf7\\x5f\\x7d\\xa1\\x95\\xec\\xb6\\x36\\x32\\xdb\\xf6\\xad\\xaf\\xb0\\x67\\x56\\x5c\\x3b\\x19\\x71\\x7b\\x57\\x50\\xb8\\x8f\\xba\\x09\\x2d\\xe5\\x88\\xed\\x5f\\x23\\xa1\\xab\\x8c\\xf0\\xeb\\xaa\\x8c\\xd0\\x5e\\x8e\\x58\\x5b\\x55\\x10\\xf6\\xcf\\x0d\\xfb\\xf5\\x54\\x3c\\xd8\\x9b\\x6c\\xec\\x9b\\x57\\xbf\\x77\\x36\\x7d\\x5b\\x4d\\x3f\\xda\\xb2\\xee\\xb7\\x66\\x61\\x38\\xac\\xc7\\x5b\\x6a\\x6f\\x71\\x25\\xde\\x5c\\x35\\xfd\\xc3\\x43\\x15\\x14\\xcb\\xd7\\xd2\\x50\\x97\\x07\\x54\\x9d\\xc9\\xde\\x96\\x07\\x9c\\x8a\\xdc\\x89\\x77\\x2f\\xb3\\xe2\\xbd\\xbb\\x9e\\x0b\\x10\\xf0\\xb7\\x1f\\x7f\\x5c\\x40\\xe7\\x20\\xdf\\x2f\\x4c\\xfd\\xcb\\x72\\x8f\\x7e\\xa1\\x1d\\xf0\\xef\\xca\\x3d\\xaa\\xa2\\xaa\\xb9\\xce\\xea\\x08\\x04\\x12\\x44\\x38\\x39\\x0c\\x3b\\xd3\\xd4\\x64\\xe1\\xf4\\xf2\\x82\\x24\\x25\\x83\\xd2\\x0e\\x34\\x53\\x03\\xb2\\x44\\xc2\\x73\\x0e\\x24\\x2b\\x11\\x3a\\xc9\\x8e\\x6a\\xcd\\xf2\\x42\\xef\\x8b\\x79\\x9d\\x77\\xf4\\x57\\xe6\\x1d\\xbd\\x73\\x2f\\xc5\\xa4\\xca\\xa9\\xe8\\x1b\\x6a\\x01\\xfe\\xd1\\x28\\xee\\x64\\x8e\\x1f\\x0e\\x88\\xa5\\x0b\\x28\\x56\\x80\\x2d\\x14\\x52\\x9a\\x2b\\xc1\\x7f\\xae\\x58\\x6d\\xae\\xf0\\x52\\xc7\\x23\\x70\\xee\\xc0\\x3c\\x5a\\x86\\x1d\\x4a\\x54\\x73\\x54\\x24\\x91\\x0b\\x49\\x5c\\x16\\x20\\x1e\\x8e\\x8e\\x60\\x04\\x62\\x59\\x64\\x7a\\xd3\\x13\\x86\\xd2\\xdb\\x25\\x14\\x49\\xa8\\x9f\\x8a\\xf5\\x43\\x54\\x10\\x69\\x96\\xc9\\x5b\\xfc\\x76\\x28\\x8f\\x98\\xfd\\x33\\x73\\xb1\\x75\\x49\\x86\\x8c\\xe4\\xbc\\x2c\\x65\\x69\\xdd\\x48\\xe1\\x74\\x30\\x7c\\xc8\\xe8\\x99\\xac\\x44\\x85\\xad\\xb4\\x41\\x1f\\xd7\\x4c\\xdb\\xad\\x06\\x54\\xd1\\x92\\x50\\x81\\x09\\x9c\\xe6\\xff\\x2e\\xe2\\x1a\\xbe\\xed\\xe8\\xdd\\x90\\x4d\\xe8\\x94\\xcb\\xaa\\xc4\\xb7\\xb5\\x24\\x07\\xf6\\x27\\xe0\\xbd\\x33\\x59\\x79\\xdb\\x79\\x05\\x19\\x5a\\x7e\\x75\\x6a\\x09\\x9c\\xde\\xd6\\x3f\\x82\\x82\\x9b\\x4a\\x67\\x8e\\xec\\xb3\\xcf\\x5c\\xe9\\xc5\\xb5\\x38\\x10\\xb9\\x96\\x13\\x0f\\x81\\x79\\x53\\x55\\x18\\x06\\xfb\\xc3\\xce\\xb9\\xb7\\x31\\xbe\\x85\\xa3\\xc5\\x92\\xea\\xf4\\x1a\\x7e\\xda\\x24\\xa7\\xda\\x8a\\x35\\x98\\x32\\xef\\xd2\\xe1\\x9e\\x5e\\x0c\\x2b\\xae\\x72\\xc7\\x5e\\x57\\x8f\\x52\\x50\\xee\\x84\\xe4\\xb5\\x97\\x8f\\xb2\\xc8\\x78\\x32\\xbb\\x38\\x6f\\x37\\x72\\x03\\xc7\\x74\\xec\\x4f\\xf9\\xa8\\x0d\\x73\\x9f\\xfc\\x8d\\x2a\\x96\\x92\\x37\\x54\\xd0\\x31\\x5a\\x5d\\x8e\\xae\\x2f\\xff\\xf6\\xe6\\xd8\\x60\\x11\\x58\\x75\\x2e\\xce\\x97\\x86\\x76\\x5c\\x87\\x83\\xbf\\x7d\\xa8\\x3c\\x77\\x32\\x0f\\xba\\xd6\\xc4\\x86\\x85\\x51\\x77\\x04\\xdf\\x83\\x95\\x00\\x20\\x5e\\x26\\xd8\\xa7\\x7d\\xda\\x12\\x71\\xe0\\x72\\xbe\\x48\\x14\\x86\\x6f\\xb8\\xea\\x6f\\x6a\\x9e\\x54\\x4f\\xf3\\xf4\\xe6\\x2e\\x01\\x10\\xd8\\xcd\\xd7\\xad\\xb2\\x99\\x0f\\xac\\x81\\x9f\\x2b\\xee\\x46\\xa2\\x4b\\xaa\\xd9\\x78\\x76\\xce\\x8a\\x4c\\xce\\x0c\\x02\\x5c\\x06\\x66\\x7c\\x7c\\x74\\x88\\x62\\x43\\x39\\xa4\\x09\\x29\\xab\\x8c\\x61\\x6f\\xa1\\xf9\\xb2\\x6b\\x82\\xb1\\xb4\\xa6\\x74\\x5c\\x28\\x4d\\xa1\\xe8\\x1a\\x8e\\xbf\\x76\\x46\\x8d\\x99\\x55\\x53\\xb6\\xd4\\xc7\\x79\\x6e\\x7c\\x2a\\x2e\\x51\\x69\\x4e\\xc9\\xda\\x57\\x9a\\x33\\x26\\xf8\\xfc\\x66\\x9c\\xdd\\xc6\\xaf\\xd9\\xd8\\x83\\x19\\x77\\x07\\x84\\x53\\x7e\\x55\\x65\\x86\\xf9\\x64\\xe9\\x5c\\x8b\\x57\\x90\\xd3\\xec\\x1e\\x63\\xb5\\x0b\\xa0\\x09\\x66\\xf6\\x3d\\x32\\xac\\x8c\\x10\\xc7\\x54\\x64\\xe3\\x5e\\x2c\\xf5\\x79\\x3b\\x41\\x97\\xb6\\x79\\x89\\xd0\\xa2\\xc8\\x38\\x86\\x30\\xcb\\xd2\\xfa\\xa5\\x03\\x83\\xe6\\xe2\\x63\\x4d\\x48\\xcb\\x96\\xb2\\xcc\\x76\\xb2\\x4b\\x9f\\x4c\\x59\\x39\\x6c\\x52\\xa7\\x62\\x5b\\xb1\\x84\\x16\\x1c\\xfc\\x38\\x8d\\xa5\\x98\\x68\\xe3\\x4e\\x2f\\x2f\\xf0\\xed\\x65\\x86\\x63\\xf7\\x23\\xee\\xa0\\xdd\\x1b\\xe7\\xde\\xb0\\x3d\\x83\\x50\\x73\\xf1\\x95\\x96\\x4e\\x2f\\x2f\\xb0\\xb4\\x97\\x2d\\xb6\\x54\\x9b\\x3f\\x8c\\x9e\\x40\\x31\\xc8\\xb1\\xae\\xf0\\x48\\xc7\\x66\\x44\\x4d\\xa4\\xf0\\x1f\\x65\\xa2\\xca\\x19\\x16\\x68\\xaa\\x9b\\x8d\\x19\\xe5\\x51\\xcc\\xea\\xd1\\x6b\\xeb\\x89\\xd1\\x75\\x8c\\xea\\x73\\x70\\x10\\x0a\\xc2\\x98\\xfa\\x50\\x06\\xf3\\x01\\x62\\x72\\xf0\\x55\\xf4\\x94\\xa1\\x1c\\xf5\\x84\\x9b\\xb2\\x9f\\xed\\xa3\\x04\\xb6\\x8c\\x0a\\xd8\\x9a\\x9f\\x09\\x29\\xae\\x2c\\xa8\\xbe\\xbf\\x7a\\xbd\\x1b\\x22\\xbc\\x8d\\xc7\\xb0\\x45\\x7d\\x18\\xd4\\x2f\\x2c\\x68\\xa9\\x39\\xcd\\x48\\x55\\x66\\xce\\xad\\x88\\x39\\x02\\x36\\x14\\x6f\\x42\\xa7\\x41\\xe1\\xa3\\x01\\x21\\x5f\\xe1\\xee\\xdb\\xcd\\xc1\\x33\\x8e\\x0d\\x7c\\xad\\x29\\xb8\\xca\\xb2\\x1e\\x19\\x71\\x68\\xd9\\xae\\x59\\x41\\x42\\xb7\\xd6\\x35\\x17\\x89\\x51\\x07\\x45\\xdf\\x77\\xe4\\x81\\x19\\x39\\x25\\xd1\\x1f\\x74\\xf0\\x9a\\x82\\xcc\\xcc\\xb2\\x14\\x8a\\x61\\xc2\\x27\\xcc\\xa1\\x4f\\xc0\\x64\\x61\\xb4\\xd8\\xb3\\xac\\x52\\x9a\\x95\\x57\\xd2\\x30\\x94\\x20\\x6c\\x07\\x0a\\x83\\xd0\\xf0\\xe7\\xbf\\x71\\x91\\x42\\x9c\\xd6\\x15\\x30\\x9f\\x84\\x0a\\xc2\\x38\\x18\\x83\\xcc\\x90\\xe0\\x7f\\x37\\xc8\\x52\\x23\\xe5\\x91\\xaa\\x92\\x89\\x59\\xd2\\x41\\x21\\x53\\x75\\x60\\x48\\xd1\\x01\\x9a\\x0c\\xd5\\xc1\\xb1\\xf9\\x6b\\x7e\\x0d\\x18\\x85\\x13\\xbc\\x77\\x42\\x0b\\x7e\\x70\\xdc\\x23\\x00\\x20\\x70\\x00\\x4a\\x3d\\x79\\xba\\x78\\xe8\\xd6\\x0a\\x3a\\xfa\\x4e\\x58\\x78\\x15\\x8e\\x00\\x38\\x28\\x6a\\x57\\xdf\\xed\\x84\\x6b\\xe6\\xdb\\xab\\xa3\\xa5\\xc9\\x57\\xba\\x99\\x27\\xf8\\x84\\x9c\\x0a\\xc2\\xf2\\x42\\x83\\xf5\\x9a\\xe4\\x8c\\x3a\\x97\\x38\\x9b\\xb2\\x72\\xa6\\x27\\xb6\\x12\\x88\\x23\\x20\\x4f\\x1e\\xe8\\xfb\\x01\\x7c\\xae\\x77\\x7d\\x8d\\xe4\\x70\\xc2\\x16\\x80\\x7b\\xf8\\xd5\\xe1\\x3c\\x21\\xad\\x39\\xc2\\x93\\x05\\x25\\xb0\\xe8\\x9d\\xc0\\xf8\\x83\\x79\\x33\\x06\\x21\\xde\\x42\\x6a\\xe9\\xe9\\xc7\\xeb\\xd7\\xd6\\xb1\\x82\\xb0\\xfa\\x8e\\x8b\\x54\\xf9\\x6e\\x8a\\x36\\xee\\xdb\\xc2\\x7b\\x29\\x90\\x61\\x86\\x4f\\x11\\xc0\\x8b\\x22\\x70\\x53\\xb1\\x75\\xcd\\xf0\\x4e\\xea\\x5f\\x35\\xd4\\xda\\x01\\xac\\xea\\xf0\\x46\\xa6\\xcb\\x8f\\x4e\\xb4\\xbf\\x17\\xc1\\xc3\\x3e\\xd8\\xa0\\xb6\\xbb\\xd8\\xb1\\xac\\xb8\\x3b\\x2b\\x96\\xea\\x04\\xeb\\xb7\\x63\\x0d\\xe8\\x57\\xcd\\xa4\\x36\\x38\\x00\\x9d\\x0c\\x7e\\x01\\x6b\\x12\\xd6\\x39\\x27\\xa3\\x8c\\x8e\\x6b\\x34\\x02\\xaa\\x87\\x82\\xd6\\xd9\\xf5\\x0f\\x6e\\x09\\x8a\\xf0\\xe5\\x22\\xef\\x46\\x99\\x78\\x93\\x14\\xdc\\xaf\\xa1\\xb4\\xf2\\x09\\xf3\\x91\\xa5\\x3f\\x6e\\x16\\x85\\xfd\\xe0\\xab\\xb1\\xa9\\x89\\xb3\\x51\\xaf\\x35\\xe4\\xad\\x82\\xbf\\xb3\\xd9\\xd1\\x00\\x13\\x5c\\xc1\\x36\\xa7\\x98\\x42\\xfc\\x14\\xc8\\x21\\xd7\\x3f\\x44\\x68\\xb2\\x61\\xbe\\x2b\\x90\\xf6\\x86\\xcd\\x6e\\x65\\xb9\\xbc\\x16\\x7b\\x2c\\xd7\\x7b\\x3a\\xe4\\x5e\\x71\\x1a\\x98\\x73\\x5e\\xa2\\x7d\\x50\\x2e\\x2d\\x3a\\xbf\\x33\\xaa\\xae\\x9d\\x7c\\x46\\x87\\x2c\\xdb\\x3c\\xf5\\x37\\xb4\\x30\\xf3\\xae\\xe3\\x5e\\xd1\\x10\\x60\\xdd\\xa6\\xa8\\x8a\\x60\\x88\\x9a\\x0b\\x0b\\x94\\xe5\\x98\\x0a\\xfe\\x0f\\x0c\\x16\\x4e\\x0c\\x49\\x90\\xa5\\xf9\\xf3\\x08\\x5d\\x2f\\x68\\x46\\xc8\\x58\\xa2\\x8f\\x2d\\x2a\\x2f\\x25\\xa1\\x1b\\x70\\x9d\\xa6\\x29\\x47\\x41\\xe4\\x72\\x03\\x5a\\xae\\x07\\x02\\x17\\x37\\xdb\\x6c\\x1f\\x3c\\x8f\\xd1\\x64\\xb8\\xd8\\x3b\\xde\\xbb\\x35\\x67\\x7d\\xf3\\x71\\x5c\\xef\\x03\\x6e\\xc0\\x2e\\xaa\\x72\\x4d\\x78\\xd8\\xda\\xf7\\x73\\xca\\x6d\\xb3\\xe0\\x6d\\xa0\\x6b\\x31\\x87\\x5a\\x09\\xd3\\x10\\x48\\xb3\\x3e\\x3f\\xda\\x3d\\x1c\\x96\\xbd\\x00\\xce\\x72\\xca\\x77\\x85\\x18\\x5e\\x7b\\x6c\\x59\\x4e\\x75\\x55\\x72\\xbd\\x94\\xfd\\xae\\x7f\\x91\\x8b\\xef\\xaa\\x21\\xb3\\x1e\\xf5\\xad\\x5f\\x17\\x10\\x58\\x79\\x7a\\x79\\xb1\\x14\\x2c\\xed\\xb0\\x59\\xb0\\x7b\\xd8\\x09\\x1a\\x29\\x8d\\x54\\x82\\xe6\\x43\\x3e\\xae\\x64\\xa5\\xb2\\x59\\x68\\xc6\\xa5\\x10\\x10\\x30\\x20\\xe4\\x02\\xed\\x58\\xe2\\x50\\x13\\x2a\\xa4\\x98\\xe5\\xf6\\x51\\x91\\x64\\x55\\xca\\xa2\\x11\\xc1\\x6f\\x3a\\x95\\x3c\\x25\\xb4\\xd2\\x32\\xa7\\x9a\\x27\\x24\\x91\\xac\\x4c\\xc0\\xc7\\x1a\\x8e\\x54\\x29\\x46\\xe8\\x8a\\x77\\x93\\x4a\\x69\\x99\\x93\\x9c\\x96\\x6a\\x42\\xb3\\x6c\\xd5\\x1e\\xb7\\xc0\\xc3\\xd7\\x15\\x6b\\xef\\xc3\\xfa\\x57\\xfe\\x38\\xc5\\x59\\xef\\x88\\xdf\\x1b\\x6a\\xd3\\x37\\xc0\\x6f\\x33\\xb9\\xbd\\x06\\x98\\xae\\xc6\\xd2\\x06\\x63\\xd8\\xaa\\x08\\x4b\\xeb\\x3d\\x45\\x08\\xf7\\x7e\\xc2\\x48\\x51\\x0d\\x33\\xae\\x40\\x33\\x05\\x4a\\x34\\x23\\x43\\x36\\xe1\\x36\\x3a\\x7b\\x33\\x09\\x5a\\xb9\\xc5\\x9b\\xe0\\xbc\\x8e\\x06\\x6c\\x84\\xd0\\x1a\\x92\\xbd\\xf6\\x5d\\xcb\\xd2\\x2e\\x72\\x3a\\x6e\\x20\\x80\\xbf\\x36\\x04\\x9b\\x8a\\x99\\xe7\\x84\\x50\\xe4\\x54\\xf5\\x88\\x2c\\x6d\\xc4\\x8e\\xef\\x49\\x6f\\x7f\\xf2\\x85\\x72\\x4b\\xf2\\xce\\x82\\xce\\x86\\xce\\x5b\\x7c\\x87\\x84\\x0a\\x56\\x8e\\x64\\x99\\x1b\\x00\\xf3\\x92\\x8c\\x2a\\x01\\x06\\x4a\\x65\\x23\\xed\\x81\\x4b\\x58\\x1b\\x17\\xcd\\x94\\xf4\\x67\\x19\\xf6\\x42\\xb8\\x49\\x10\\xaa\\xc8\\x2d\\xcb\\xb2\\x01\\x39\\xcd\\x32\\x5b\\x7d\\x35\\xa8\\xb3\\x51\\xe7\\xca\\xd7\\xf1\\x1c\\xc3\\x19\\x49\\xf9\\x98\\x29\\x4d\\x8e\\xae\\xff\\xef\\xe9\\x31\\x88\\x28\\x60\\xff\\x99\\x11\\x4d\\x5d\\xaa\\x60\\x6c\\xd7\\x02\\x61\\x27\\xad\\x40\\x28\\x4a\\xa8\\xa6\\x99\\x1c\\x63\\x48\\x03\\xd8\\xc8\\x45\\x4a\\x8a\\x8c\\xce\\xa0\\xb5\\x42\\x41\\x4b\\x88\\xf6\\x4d\\xd0\\xb6\\x45\\xca\\x4a\\x40\\x51\\xe9\\x7b\\xe5\\x5d\\x9b\\x89\\xca\\xba\\xba\\xcf\\x7d\\xc0\\xc9\\x1d\\x89\\xc6\\x86\\xea\\xba\\x77\\xcb\\x14\\x4b\\x56\\x64\\x74\\x85\\x35\\x66\\xe1\\xc0\\xd7\\x89\\xe0\\x46\\x3d\\x00\\xd5\\x5f\\x0a\\xe6\\xc7\\x18\\x90\\x6b\\xc4\\x9d\\x9c\\xea\\x04\\xfd\\xc9\\x3f\\xe5\\x4c\\xd3\\x94\\x6a\\x3a\\x30\\x3a\\xf4\\x4f\\x71\\x56\\xa2\\xcc\\x52\\x33\\xd0\\xea\\x8d\\x5e\\x31\\x67\\x14\\x8e\\xe5\\x66\\x22\\xf5\\xda\\x48\\xf0\\xfe\\x71\\xd0\\x6b\\xdc\\x79\\x5c\\x6b\\xfe\\xd9\\x93\\x3e\\xc1\\xf2\\x5f\\x7e\\x36\\x2a\\xec\\x5a\\xff\\x65\\x34\\xd7\\xf9\\x97\\x62\\xeb\\x4c\\x16\\xaf\\xc4\\x62\\x6b\\xce\\xa0\\x44\\xe7\\x7b\\xdb\\x85\\xca\\xdd\\x01\\xd3\\xf3\\xe9\\xdb\\xf3\\xd5\\x66\\xc2\\xcd\\xa6\\x96\\x0d\\xa6\\x95\\x79\\xf9\\x74\\xe5\\xf4\\x9c\\x61\\xde\\xfe\\x12\\x7b\\x66\\x5c\\x2a\\x12\\x24\\x6f\\x62\\x62\\x0f\\x15\\x9e\\x73\\xb8\\xe2\\xfc\\x19\\x58\\x0c\\xc2\\xb4\\x53\\x7c\\x6f\\xb5\\x5d\\xa9\\x91\\x6b\\xac\\x89\\x43\\x6c\\x53\\x96\\x5f\\xdf\\x4f\\x76\\xe5\\x43\\xcd\\xfc\\x63\\x1b\\x33\\xf1\\x56\\x65\\xda\\x21\\xe4\\x21\\x31\\xc7\\x99\\x96\\x3d\\xb0\\x9b\\xfa\\x13\\x1b\\xda\\xc5\\xdc\\x52\\xb7\\x98\\xa8\\xdf\\xca\\x28\\xe8\\xeb\\x86\\xcd\\x0e\\xad\\x8e\\x68\\x30\\x7d\\xc2\\x0b\\x4c\\x15\\xb5\\xee\\x1b\\xbb\\xbb\\xe4\\x07\\x9a\\xf1\\xd4\\x0f\\x81\\x58\\x7d\\x21\\x7a\\xe4\\xad\\xd4\\xe6\\x9f\\x97\\x9f\\xb9\\xd2\\xa8\\x6b\\x9f\\x4b\\xa6\\xde\\x4a\\x0d\\x77\\x5a\\x59\\x2a\\x4e\\x61\\x8b\\x85\\x5a\\x6d\\x1f\\x3d\\x00\\x70\\xae\\x02\\x9b\\x80\\x5b\\xd0\\xc5\\x28\\x92\\x8c\\xcc\\xd3\\x17\\xc2\\x48\\x04\\x76\\x45\\x3e\\x85\\x5a\\xd9\\x21\\x5c\\xfe\\x8f\\x90\\xa2\\x0f\\xbe\\x81\\xa5\\x63\\x58\\x40\\xc8\\x32\\x82\\xc3\\x9a\\xe1\\xec\\x50\\x18\\x7c\\x09\\xbf\\x70\\xe5\\x88\\xb8\\xe7\\xd9\\xd4\\x99\\x2b\\x79\\x42\\x72\\x56\\x8e\\xc1\\xdb\\x95\\x6c\\xf0\\xf6\\x34\\x35\\xe1\\x36\\x32\\xdc\\x6e\\xdc\\x2b\\x20\\x99\\xaf\\x57\\x5a\\x69\\x16\\x36\\x29\\x78\\x1e\\xc9\\x52\\x8e\\xa6\\x9b\\x7f\\x1a\\xea\\x03\\x90\\xfa\\x17\\xe4\\xd1\\xab\\x01\\x39\\x75\\x2d\\x7e\\xc2\\xdf\\xac\\xd7\\x2f\\x1c\\xc6\\x8c\\xc0\\x15\\x31\\xa4\\x64\\x4a\\x33\\x86\\x1d\\x0e\\xa8\\xf0\\xb9\\x6e\\x72\\xb4\\x40\\xd8\\x7b\\x36\\x9f\\xde\\x9c\\x59\\x2f\\x32\\x1d\\xdc\\xb0\\xd9\\x41\\x6f\\x61\\x6b\\x0f\\x2e\\xc4\\x41\\x9d\\xf0\\x18\\x6d\\xa6\\x27\\xa2\\x20\\x6d\\x1d\\xc0\\x6f\\x07\\xbb\\xf3\\x82\\xb5\\xc4\\xb2\\xb9\\x2d\\x69\\xe3\\xbe\\xa9\\x1b\\xbe\\xdc\\xf5\\xbf\\x54\\xd8\\x38\\x52\\xc7\\x60\\xf6\\x10\\xd8\\x6b\\x49\\x96\\x60\\x06\\x36\\x77\\xc3\\xd2\\x2a\\x46\\x54\\xbd\\xe1\\x45\\x51\\x57\\xa2\\xa9\\x8a\\x71\\x49\\x53\\x46\\xc6\\x25\\x2d\\x26\\xdb\\x8a\\x25\\x28\\xdb\\x2c\\x1b\\xfe\\xc9\\x08\\xba\\x2b\\x80\\xbf\\x46\\x37\\x5c\\xfb\\xde\\x2d\\x1b\\x4e\\xa4\\xbc\\x81\\x34\\x44\\x40\\x84\\x3b\\xb4\\x64\\xfc\\x88\\xdf\\x3a\\xaf\\xef\\x39\\xa5\\x54\\x91\\x94\\x69\\xca\\x33\\x88\\xa3\\x79\\xf7\\xfa\\x8d\\x8d\\xb4\\x71\\x7c\\xdc\\xcd\\x72\\x79\\xd0\\x4a\\x0b\\x0a\\x00\\x4d\\x6d\\x04\\xd8\\x15\\x9b\\x72\\x76\\x6b\\xed\\x1b\\xab\\x62\\x64\\xfa\\x64\\xcc\\x04\\x04\\x86\\xac\\x09\\xa0\\xea\\x13\\xc5\\x53\\xf6\\x12\\x92\\x9e\\x57\\x0f\\xb4\\x87\\xc3\\x61\\xc5\\x9c\\x37\\x1d\\xde\\xf5\\x14\\x7c\\x23\\xf5\\x6e\\xc0\\x65\\xbd\\xfa\\x7b\\x29\\xcb\\x35\\x45\\x98\\x9a\\xe5\\x60\\x37\\xcb\\xaf\\xb6\\x51\\xfc\\x2f\\xc8\\x1f\\xfe\\xf0\\xfb\\x95\\x0f\\xe5\\xf4\\x33\\xcf\\xab\\xfc\\x05\\xf9\\xe3\\xbf\\xff\\xfb\\xef\\xff\\x7d\\xf5\\x63\\x5c\\xe0\\x63\\xcf\\x57\\xaf\\xcf\\x9e\\xb6\\xb3\\xab\\xf3\\x47\\x00\\xef\\xd4\\x47\\x32\\xae\\x77\\x66\\x36\\x18\\x6a\\x44\\x79\\x56\\x95\\x36\\x86\\xb6\\xa1\\x8a\\xf0\\x2a\\x7c\\x07\\x1c\\x51\\x75\\xd2\\x09\\x75\\x23\\xba\\x40\\x3b\\x1b\\x80\\x37\\xe2\\x82\\x29\\x68\\x9e\\x53\\x89\\x92\\x25\\x72\\x2c\\xf8\\x3f\\x58\\xea\\x7a\\xe7\\x40\\x40\\x0c\\x54\\xd9\\x77\\x28\\x4e\\x98\\x48\\xb1\\x87\\xa9\\xe1\\x79\\x13\\x2a\\xd2\\x6c\\x5d\\xa0\\x44\\x83\\x95\\x86\\x27\\x78\\x2f\\x90\\x01\\xe7\\xd9\\x0a\\x60\\x6f\\xea\\x37\\xe6\\xc0\\x05\\x9d\\x58\\xad\\xdb\\x0e\\x39\\x1a\\x82\\x6d\\xaf\\x95\\x22\\x61\\xbc\\x5e\\xa3\\x58\\x2f\\x99\\xe3\\x82\\xde\\x87\\x2a\\x2b\\xdc\\xfb\\xb9\\x62\\xe5\\x0c\\x12\\x6c\\x6a\\xc1\\x3e\\x08\\xc2\\x7b\\x5f\\xd7\\x6f\\x70\\xcb\\xb0\\x12\\x15\\x16\\xd0\\x99\\xd3\\x85\\x6b\\x21\\xa6\\x0e\\x93\\x99\\xfb\\x36\\xbc\\xc3\\x30\\xec\\xc0\\x79\\xcd\\xc8\\x29\\x11\\x55\\x96\\xad\\x7a\\x54\\xc8\\x75\\xfe\\xb5\\x10\\x76\\x1b\\x54\\xc9\\x66\\x3a\\x5e\\x53\\xb3\\xc0\\x12\\x48\\xdf\\xab\\x71\\x20\\x5c\\x78\\x4b\\xa2\\xfc\\xe3\\x36\\x17\\x84\\x0b\\x6e\\x14\\x4f\\xdb\\x3c\\x96\\xb6\\x59\\x99\\xa0\\x06\\x66\\x04\\xbc\\xb6\\x09\\xb6\\x6d\\x58\\xdc\\xe7\\x2e\\x0d\\x0b\\x78\\x6d\\x15\\xd7\\xd4\\xcc\\xc8\\xb0\\x64\\xea\\x8f\\xce\\xd4\\xb0\\xc3\\xe2\\x9b\\x98\\x1d\\x96\\x2c\\xbd\\x33\\x3e\\x2c\\x00\\xbc\\x69\\x14\\xd9\\x16\\x11\\x64\\x0d\\x77\\xb2\\x81\\x51\\x02\\xaf\\xce\\x34\\xb1\\x15\\x27\\x6a\\x40\\x98\\xb7\\x33\\x53\\x34\\xde\\xd5\\x92\\x71\\x31\\x95\\x58\\x64\\x7b\\x2b\\x19\\xee\\x6a\\xe1\\xc5\\x39\\x51\\xee\\x16\\x28\\xab\\x95\\xe5\\xbc\\xf0\\x1b\\x8a\\xb4\\x46\\xa1\\x25\\x95\\xda\\x6c\\xec\\x5e\\xbf\\x82\\xf5\\x79\\x37\\xad\\xe8\\x20\\xf1\\xca\\xab\\x8c\\xfd\\xc8\\xf5\\xe4\\x9d\\x2b\\xaa\\x6f\\xb1\\x5a\\x57\\x45\\x06\\x8b\\x0d\\x7e\\x30\\x28\\x74\\x55\\x4b\\x86\\x17\\xd8\\xc6\\x8d\\x25\\x32\\xcf\\x99\\x48\\x31\\x88\\x28\\xa7\\x37\\x8c\\xd4\\xad\\x42\\x8d\\x8c\\x07\\x62\\x30\\x0c\\xc7\\x3e\\x17\\x54\\xd4\\x72\\xe2\\xd4\\xd0\\xf2\\x75\\x18\\xd5\\x10\\x9f\\x9a\\xf2\\xda\\xc6\\x09\\x2d\\xeb\\x13\\x59\\x82\\x4c\\x94\\x28\\x61\\x85\\x0c\\x59\\x26\\x21\\x05\\x1e\\x23\\x6c\\x31\\x06\\xdc\\xe5\\x80\\x18\\x92\\x6c\\xef\\x5a\\xae\\x67\\x0b\\x6e\\x32\\x31\\xae\\xeb\\x78\\xa9\\x0c\\x9a\\xfa\\x5a\\x0a\\x2c\\x05\\x1b\\x90\\x2b\\x2b\\xc2\\x34\\x93\\x8a\\x9a\\x90\\xd3\\x86\\xa4\\x74\\x0b\\x86\\xf8\\xb9\\x5f\\x57\\xcb\\xe8\\x1b\\x61\\xb7\\x6f\\x67\\xa3\\x65\\xce\\x93\\x4d\\x9b\\xb2\\xd9\\xd6\\x81\\xd7\\xfc\\xb6\\xb8\\xf7\\xc2\\x8d\\x99\\xba\\x7b\\x4d\\xb6\\xc6\\x3d\\xdc\\x6d\\xce\\x8a\\xcb\\xb7\\xda\\xd8\\x6e\\x6f\\x62\\x62\\x52\\xf3\\x23\\xbf\\x31\\x73\\x64\\x33\\xc1\\x66\\xd5\\x60\\x24\\xec\\x93\\xb3\\xab\\x97\\xa7\\xef\\x5f\\xf6\\xc8\\xf7\\x97\\xe7\\xf0\\xef\\xf9\\xcb\\xd7\\x2f\\xcd\\xbf\\x67\\xef\\xde\\xbe\\x7d\\x79\\xf6\\xde\\x48\\x30\\x5f\\x61\\xd3\\x00\\xa3\\x40\\x9a\\xad\\x31\\x9c\\x50\\xc6\\x74\\x8a\\x8a\\x19\\x19\\x55\\xda\\x10\\xa2\\xfa\\x63\\xd1\\x2c\\x28\\x5a\\x1f\\x68\\x9a\\x1a\\x65\\xf5\\xc9\\x21\\xc0\\x72\\x80\\xcf\\x1b\\x6c\\xc2\\x6e\\x29\\xd8\\x67\\xc1\\xa6\\xc8\\x6d\\x16\\xd0\\xee\\x07\\xc3\\x1a\\x27\\x99\\x44\\xeb\\x3d\\xd8\\x31\\xbb\\xe4\\xa3\\x20\\xaf\\x64\\x49\\x6c\\x6f\\x3a\\x68\\x56\\x9a\\xaa\\x43\\x9b\\xc3\\x63\\xfe\\x3f\\xc0\\x5b\\x27\\x99\\x1c\\x1f\\xfa\\xd4\\x1e\\x46\\x32\\x39\\x26\\xaa\\x1a\\xfa\\x94\\x2b\\x10\\x02\\xe0\\xe9\\xaf\\xdc\\x63\\x51\\xa6\\x4a\\xcf\\xe7\\x5d\\x05\\x6f\\xf9\\xc1\\xa3\\x77\\xc2\\x07\\xc2\\x71\\x4f\\xa0\\xa1\\x5c\\xf4\\xa4\\xb9\\x31\\x3f\\xe0\\x57\\x27\\xcb\\x67\\xe0\\xe4\\x3d\\x5e\\xce\\xbd\\xf1\\x51\\x18\\x5c\\xbf\\xe5\\x59\\x9a\\xd0\\x32\\x5d\\x40\\x78\\xe0\\xc9\\x88\\x2f\\x00\\x3d\\xac\\xb2\\x8c\\xcd\\xbf\\xeb\\xc1\\x6d\\x6d\\x14\\x39\\x65\\x65\\x46\\x0b\\x4c\\x08\\x80\\x32\\xd7\\x10\\x31\\x05\\x1f\\x39\\x67\\x05\\x83\\xb4\\x37\\xd7\\x9c\\x9e\\x89\\x24\\x93\\x50\\x86\\x05\\x19\\x7a\\x2f\\x5e\\x3a\\x46\\x50\\xb9\\x5a\\x95\\x2e\\xf9\\xd2\\x1f\\xaf\\x83\\x2f\\x93\\xc0\\x42\\x1c\\xf9\\x56\\xa8\\x8f\\x91\\xe7\\x2b\\x0b\\x01\\xf9\\x1c\\x1f\\x54\\x94\\xbd\\xb4\\xcf\\xc8\\x81\\xcd\\x48\\x3c\\xe8\\x91\\x03\\x5f\\xeb\\x26\\xb5\\x9a\\xc1\\xc1\\x57\\x07\\xf5\\x03\\x61\\x4e\\x1b\\x28\\x06\\xd6\\x0d\\xd6\\x87\\xef\\x84\\xd9\\xb3\\x80\\x1d\\xce\\x59\\xe7\\x3f\\x5d\\xd7\\x2b\\x32\\x1c\\xd9\\x1a\\xee\\x60\\x0e\\xf1\\x40\\x83\\x68\\x22\\x0b\\x5f\\xad\\xd3\\x31\\x37\\x7e\\xd1\\x4c\\x3f\\x78\\x5d\\x43\\xf9\\x03\\x4c\\xeb\\xb4\\xc0\\x29\\x99\\xd9\\x4a\\x17\\x84\\x77\\x1d\\x61\\x9e\\x77\\x36\\x86\\x05\\x95\\x78\\x49\\x0a\\x5a\\x1a\\xf5\\xcb\\x3d\\x19\\xb7\\xc4\\xfb\\x6a\\x63\\x43\\xbc\\x06\\x18\\x14\\xf8\\x94\\x1a\\x6a\\x2a\\xd7\\xfe\\x8d\\xb3\\x8c\\x2a\\xb5\\xc4\\xda\\x0c\\x54\\xc4\\x0c\\x4c\\x18\\x8e\\x4c\\xa8\\x73\\xb8\\x41\\xbd\\xf3\\x09\\x9d\\xae\\x29\\x88\\xd1\\x60\\xd2\\x9a\\x96\\x63\\xa6\\xd7\\x7b\\x83\\xa8\\x98\\xbd\\x5b\\x5b\\x42\\xaf\\xdf\\xb8\\x68\\x6f\\xbf\\xd9\\x51\\x8c\\x0e\\x21\\x17\\xba\\x2f\\xcb\\x3e\\xbe\\xf2\\x82\\xe8\\xb2\\x5a\\xe5\\xd7\\xd3\\x3c\\x67\\xb2\\xd2\\xd7\\x2c\\x91\\x62\\x79\\xf6\\x8b\\x7d\\xae\\x35\\xf7\\xd6\\x16\\x29\\x41\\xd6\\xc3\\x7a\\xea\\x04\\x98\\xb0\\xe8\\xa5\\x53\\x46\\x6b\\xe9\\xc6\\x79\\x55\\xe3\\xb2\\x3d\\xef\\x5e\\xbf\\xd9\\x67\\xb3\\x09\\xa4\\xcd\\xaf\\xdf\\xc9\\x1f\\x2c\\xcf\\x10\\x63\\x3f\\x53\\x3b\\xf3\\xb5\\xaf\\xbd\\xa9\\xf4\\xf6\\x2f\\x9d\\x79\\x6f\\xdd\\xfa\\xa7\\x2d\\x30\\xd6\\x97\\x5e\\x59\\xb9\\x7e\\xa5\\xa9\\xae\\x16\\xb0\\x21\\xda\\x1b\\x4b\\x2c\\xaf\\x31\\xfd\\xd0\\xaa\\x22\\xd7\\xf0\\x5e\\x68\\xd8\\x5c\\xac\\x37\\x81\\x35\\x6c\\xe0\\x39\\x17\\xa0\\x39\\x20\\xf6\\x45\\x73\\x3e\\x75\\x49\\x39\\x2a\\xcd\\x34\\xd1\\x15\\xe4\\xb1\\x53\\x6d\\x83\\x39\\x6d\\xc1\\xa5\\xdf\\x2c\\x5b\\xc6\\x52\\x35\\x79\\x9d\\x6a\\x9c\\xb0\\x52\\xab\\xd7\\x54\\xe9\\xef\\x8b\\x94\\xae\\xc8\\x74\\x9b\\x0b\\xd2\\x54\\x1a\\x0e\\x0c\\x8a\\xf4\\xb7\\x82\\xa5\\x86\\xc2\\x5b\\x10\\xe0\\x78\\xe4\\xd6\\x90\\xde\\x0a\\x47\\x5c\\x19\\x7a\\xb0\\x12\\xe5\\xdc\\x01\\x32\\xaf\\xf7\\xcd\\xa7\\x96\\xcf\\xfa\\x4a\\x1a\\x98\\x9c\\x2e\\x25\\x40\\x71\\x78\\xca\\xa6\\xd9\\x1a\\x76\\x52\\xc2\\x68\\x44\\xb0\\xcf\\xcb\\xac\\x0c\\xfb\\xcf\\x38\\x63\\x54\\x2c\\x4f\\x36\\x98\\xc3\\x28\\x78\\x6e\\x7b\\x1c\\xb2\\x1f\\x20\\xb7\\x13\\x6e\\xe4\\x5d\\xcc\\x08\\x54\\xc4\\xc9\\x5f\\x29\\xcb\\xd8\\x8a\\xc4\\xc0\\x3d\\xc3\\x67\\xed\\x17\\xce\\xed\\x07\\x1a\\x85\\x76\\x5d\\xc6\\xef\\x78\\x27\\x86\\x95\\xe0\\x6d\\xea\\x49\\x2d\\x69\\x5b\\xe9\\xc1\\xeb\\x6b\\xf3\\xab\\x02\\xf1\\x65\\x98\\xc9\\xe4\\x06\\x0b\\xd0\\x41\\xed\\x07\\xfe\\x0f\\x56\\xba\\x58\\xfb\\xba\\xf9\\x9c\\xed\\x88\\x36\\x76\\xdd\\x5e\\x1d\\xdc\\x5c\\xfb\\x2b\\x18\\xc5\\x8c\\x6d\\x00\\xe8\\xc7\\x97\\x65\\x6d\\x4d\\xad\\x84\\xcd\\xb4\\xbc\\x9f\\x70\\x5d\\xa7\\xe5\\x40\\x8e\\x42\\xe4\\x2d\\x59\\x54\\x78\\xb0\\x56\\x0d\\xd4\\xc7\\xb4\\xca\\x2a\\xcd\\x6d\\x6e\\xd0\\xc9\\x77\\xab\\xf3\\x68\\x5a\\x0d\\xc1\\x5d\\x97\\xcd\\x83\\x4f\\x00\\xf8\\x44\\xb2\\xb6\\xb4\\xd1\\xda\\xbc\\x9f\\xa6\\xd6\\xbe\\x0d\\xf9\\x3d\\xa4\\xb9\\x84\\xef\\xa7\\xdc\\x64\\xb4\\x56\\x03\\x2a\\x5b\\xf7\\x70\\xae\\x4c\\x7d\\xa8\\xaf\\x6d\\xfc\\x96\\x4d\\x0b\\xf3\\x6e\\xe5\\x59\\x13\\xdb\\x14\\x50\\x8d\\x0b\\xcd\\x78\\xb5\\xc3\\x66\\xf1\\x62\\xf4\\xc1\\x48\\x96\\x2b\\x15\\x98\\xf6\\x26\\xbf\\x3e\\x1b\\x6c\\xe3\\x40\\x46\\xfa\\x5c\\x1d\\xaf\\xb7\\x98\\xb0\\x64\\xa8\\x97\\x7f\\xa5\\x47\\x28\\x99\\x70\\xa5\\x65\\x69\\xdd\\x89\\xd0\\xbc\\xae\\xa4\\xd0\\x5c\\x77\\x79\\xdc\\x5b\\x3b\\x11\\x80\\x67\\x7e\\x0a\\x84\\x16\\x05\\xa3\\xbe\\xaf\\x95\\xe5\\x4d\\xd0\\x98\\xaa\\x64\\x89\\x2c\\xd3\\xa5\\x13\\x73\\xa6\\x81\\xa5\\xb2\\xd4\\xd2\\xcf\\xb7\\x90\\xd9\\x9a\\x51\\xa5\\xdf\\xfb\\x39\\x18\\x01\\xa1\\x21\\x35\\x8e\\xc5\\x1f\\xbb\\xc4\\x7a\\x35\\xae\\xf4\\x8f\\x14\\xf5\\x8f\\x92\\x50\\x81\\x26\\x91\\xfd\\x64\\xf0\\xcd\\x42\\x46\\xbd\\x36\\x94\\xe6\\x76\\x5a\\xd7\\xad\\x97\\xdc\\x82\\x25\\xde\\xcf\\xcc\\x73\\xa6\\xd4\\xda\\xe4\\xaa\\xb9\\xc0\\x14\\xa8\\x21\\x4d\\x7c\\x0d\\x69\\xfb\\xba\\x63\\xf6\\x28\\x20\\x60\\x08\\xaa\\xab\\xf2\\x36\\x5b\\x8d\\x6a\\x04\\xc4\\x04\\x34\\x28\\xf8\\x63\\xb5\\xd7\\x96\\x15\\x13\\xaa\\x9a\\x2e\\xc6\\x9f\\x22\\x1f\\xd6\\xdc\\xf8\\x38\\x34\\x9c\\x4d\\xc9\\xa8\\x5a\\x97\\x68\\x3a\\x07\\xdb\\x61\\xc9\\xd9\\x88\\x9c\\xd1\\x9c\\x65\\x67\\x54\\xb5\\x09\\x5c\\xa0\\x00\\x03\\xc2\\x06\\xe3\\x01\\x39\\xbc\\x0a\\x3c\\xcc\\x6f\\xa5\\x7e\\xb3\\xae\\xc7\\xc7\\x86\\xf2\\x0f\\x4d\\x4e\\xf4\\x9d\\x9e\\xe5\\xbd\\x95\\x84\\xcd\\x27\\x77\\xcf\\x33\\xbb\\xf7\\x0c\\xd7\\x9c\\xd0\\x47\\x71\\x36\\xd7\\x67\\x4b\\xaf\\x3a\\x8f\\xf1\\x49\\xac\\x4a\\xb0\\xf8\\x25\\xbb\\x9e\\xc8\\x0d\\x09\\x9c\\xab\\x4e\\xe1\\x63\\x3e\\x7f\\x1b\\x96\\xe4\\x87\\xb8\\x5e\\x6a\\x32\\x59\\x58\\xdd\\xfb\\x48\\x73\\x05\\x9f\\x41\\x18\\x54\\x08\\xe5\\xe1\\xcd\\x4c\\xcf\\xae\\x7f\\x68\\x53\\x6c\\x79\\xd8\\x52\\x05\\x76\\x03\\x57\\xfe\\xbe\\x46\\x2e\\xef\\xaf\\xe7\\xc2\\xfb\\x96\\x41\\x48\\xc1\\x4b\\x63\\x30\\xe0\\x3e\\x83\\x4e\\xce\\xdd\\x57\\xad\\xad\\xc3\\x57\\x76\\x86\\xbf\\x46\\xb6\\x83\\x9e\\x7d\\x26\\xc2\\x8f\\x23\\xe8\\x55\\xc8\\xa6\\xd8\\x20\\x14\\x92\\x5c\\x18\\x11\\x4c\\x99\\x43\\x71\\xbc\\xe6\\xf3\\x0d\\x15\\xaa\\x66\\xca\\xd4\\x66\\x45\\x77\\xa3\\x12\\x4b\\x36\\x6f\\xad\\x7b\\x68\\xdd\\x06\\xe3\\xd5\\x54\\x67\\x6b\\xa0\\x13\\x6f\\xa1\\xac\\x6d\\xd6\\x78\\xb6\\x18\\x6c\\xa3\\xf8\\xb7\\xe5\\x78\\xcb\\x0d\\xb8\\xf3\\xd7\\x5c\\x25\\x69\\xf3\\xca\\x15\\x10\\x69\\xf4\\x2a\\x27\\x86\\x02\\x27\\x50\\x5f\\x1c\\x69\\xb7\\x25\\x4f\\xb1\\xfd\\xf6\\x6a\\x9e\\x06\\x42\\x88\\x65\\x8c\\xe1\\x6d\\x2d\\xab\\xaa\\x78\\x7b\\x30\\xdf\\x58\\x7f\\xa4\\xf1\\x78\\x8f\\xa0\\x98\\xca\\x46\\x04\\xba\\xdb\\xe2\\x0c\\x78\\x6d\\xc2\\xba\\x87\\xc7\\xb7\\x26\\x95\\xb2\\xd6\\xe2\\xd8\\x1d\\xd5\\xb5\\x51\\xac\\x9c\\xb2\\x34\\xf2\\xd4\\xd9\\x3a\\xff\\xf1\\xbd\\xc0\\x6f\\x5b\\x8f\\x6f\\xc1\\x4e\\xfe\\xf9\\xaf\\xdf\\xfc\\xa6\\xdf\\xef\\xff\\xa6\\x0e\\x29\\x7b\\x41\\x68\\xc1\\xd9\\x67\\xcd\\x30\\xea\\x70\\x70\\xf3\\x1f\\xd0\\xcc\\x69\\xfa\\xfc\\x37\\x80\\x70\\xe4\\x0c\\xac\\xcd\\xce\\xcc\\x7a\\xee\\xb3\\x26\\x7f\\xe3\\xb2\\x4e\\xcd\\x47\\xa8\\x10\\x52\\x87\\x51\\x50\\x89\\x14\\xba\\x94\\x59\\xc6\\xca\\xfe\\x98\\x89\\xc1\\x4d\\x35\\x64\\xc3\\x8a\\x67\\x29\\x2b\\x61\\x70\\xf7\\xe9\\xe9\\xb3\\xc1\\x9f\\x07\\xcf\\x7e\\x43\\x7c\\x8e\\xa9\\x91\\xec\\x95\\xa6\\x79\\xf1\\x02\\x92\\x5d\\x7e\\x63\\x31\\xce\\x55\\xef\\x2b\\x32\\x2a\\xd4\\xc0\\x87\\xb6\\x0f\\x12\\x59\\x32\\x69\\xfe\\xc9\\x7f\\xa3\\x0a\\x96\\x98\\x6f\\xe3\\x41\\x23\\x4b\\x9f\\xb1\\xa6\\x33\\x3b\\x45\\x5b\\xab\\xae\\x06\\x53\\x9f\\xc8\\x2c\\x87\\xff\\xe3\\xd2\\x6d\\xb9\\xc1\\xcb\\xcc\\xd6\\x2e\\xcc\\xb8\\xd2\\xdf\\xcd\\xff\\xf2\\x9a\\x2b\\x64\\x97\\x45\\x56\\x95\\x34\\x8b\\xa7\\x0a\\x3f\\xa8\\x89\\x2c\\x75\\x54\\x96\\xb7\\x4f\\x38\\xb2\\x46\\xc5\\xc5\\xb8\\xca\\x68\\x19\\xbd\\xf5\\x1b\\x17\\xf3\\x50\\x9b\\xeb\\x0c\\x97\\x9c\\x46\\x21\\x80\\xfd\\x28\\x40\\x98\\x0b\\xcd\\xca\\x33\\x99\\x55\\x79\\x68\\x1d\\xeb\\x2f\\xca\\x95\\x23\\x5e\\x2a\\x6d\\xeb\\x21\\xc6\\x4e\\x85\\x65\\x72\\x31\\x7c\\x3f\\xc0\\xd1\\xbf\\x2b\\x29\\xc0\\x5d\\x48\\x06\\x06\\xdc\\x83\\xd5\\x2f\\x7d\\x78\\xf6\\x29\\x78\\x0f\\xf7\\x30\\x96\\x57\\x97\\x9e\\x92\\x25\\x33\\xa6\\x45\\x51\\xca\\x29\\xc5\\x6a\\x8e\\x6b\\xe6\\xe2\\x9e\\x5b\\xf8\\xec\\xe9\\xe2\\x0f\\x2b\\xbe\\xbd\\x7c\\xc8\\xc8\\x47\\x17\\x0e\\x19\\xfd\\xa0\\x97\\x54\\xba\\xc4\\x87\\xa7\\xcf\\x69\\x56\\x4c\\xa8\\xcb\\xad\\x54\\xc9\\x84\\xe5\\xb4\\xde\\x24\\x59\\x30\\x71\\x7a\\x79\\xf1\\xc3\\xef\\xaf\\xe7\\x7e\\x58\\x5e\\xfb\\xd2\\xa0\\x9c\\x4f\\x27\\x0c\\xba\\x30\\x50\\xa7\\x8b\\xf9\\x74\\x90\\xfa\\x04\\x2c\\x4c\\x73\\x41\\xc8\\x5b\\x2e\\xd4\\x19\\xa9\\x1c\\xcf\\xf8\\xdc\\x6d\\x03\\x9d\\xe0\\xd6\\x2a\\xe1\\x2a\\x20\\x32\\x73\\x84\\x2e\\xee\\x37\\x57\\xc7\\xa9\\x46\\x2b\\xb3\\x08\\xcf\\x52\\x0b\\xb3\\x3a\\x7a\\xc7\\xb9\\x79\\xea\\x45\\x0b\\xbb\\xa6\\x01\\x31\\xc8\\xc8\\x4a\\x5f\\xf9\\x09\\x53\\x57\\x35\\x09\\x72\\x2e\\x71\\x34\\xe5\\xea\\x39\\x42\\x8a\\x95\\x86\\xb8\\x85\\x52\\xb8\\xa6\\xd1\\x3d\\xdf\\xfb\\xbe\\x64\\x66\\xdc\\x38\\x6b\\xd3\\xa5\\xa1\\x2c\\x69\\x89\\x37\\xe6\\xda\\x91\\xd0\\x44\\xe6\\x79\\x25\\xb8\\x9e\\x9d\\x00\\x35\\xe4\\xc3\\xca\\xec\\xc6\\x49\\xca\\xa6\\x2c\\x3b\\x51\\x7c\\xdc\\xa7\\x65\\x32\\xe1\\x9a\\x25\\xba\\x2a\\xd9\\x09\\x2d\\x78\\x1f\\x26\\x2b\\x30\\x00\\x27\\x4f\\xff\\xcd\\xd3\\xf1\\x79\\xa5\\x73\\x25\\x87\\x59\\x26\\x23\\xc4\\xb0\\x86\\x7a\\x7a\\x3c\\xe8\\x6d\\x8f\\xed\\xb7\\xa3\\x1a\\xb5\\x50\\x25\\xf9\\xe5\\xf5\\xfb\\xda\\xc5\\x88\\xd5\\x91\\x00\\xc2\\x81\\x93\\xad\\x06\\xb6\\x01\\x14\\xf4\\x2e\\xb2\\x45\\xe1\\x5d\\x3a\\xab\\x4f\\x62\\x85\\x9e\\x00\\x19\\x37\\x3a\\x89\\xaa\\x86\\x39\\xd7\\xca\\x45\\x59\\x62\\xd4\\xe1\\x19\\x70\\x10\\xa8\\x2b\\x8a\\x96\\x9a\\x01\\xb9\\x10\\xb5\\x7e\\x7f\\xe7\\xa0\\x86\\xa8\\xa0\\xbe\\x01\\x5f\\x73\\x60\\x87\\x0c\\x70\\xf1\\x85\\x25\\x8a\\x94\\x63\\x51\\x2b\\x77\\x27\\x38\\xe3\\xd7\\x05\\x4b\\xfc\\x69\\xf0\\x67\\xfa\\x14\\xeb\\xeb\\xdb\\x46\\x0e\\x3e\\x90\\x53\\x62\\x47\\x72\\x78\\x79\\x21\\xa4\\x60\\x8d\\x5e\\xb7\\x5a\\x97\\xeb\\x93\\x25\\xf4\\x34\\xfe\\x69\\x49\\xec\\x42\\xbf\\x19\\x1b\\x21\\x1b\\x14\\x32\\xf7\\xe9\\xcd\\x76\\x20\\xc7\\x1b\\xac\\x76\\x0c\\x7d\\x11\\x3c\\xc3\\xb0\\x39\\x28\\xa0\\x2b\\x8b\\x10\\xb6\\x90\\x97\\x11\\x84\\x28\\x1b\\xc8\\x1e\\x9c\\xba\\x62\\x90\\xd8\\x4b\\xe0\\x0d\\x15\\x15\\xcd\\x96\\x06\\xb0\\xad\\x95\\xef\\x1c\\x6c\\x56\\xd7\\x94\\x58\\x55\\x0d\\x79\\x35\\xe8\\x5a\\xad\\x4f\\xb1\\x76\\xf6\\x36\\x47\\x7c\\x6d\\x59\\x8d\\x55\\x01\\x5e\\x88\\x8d\\x5b\\x97\\xe3\\x08\\x7a\\x0e\\xac\\x72\\x69\\xee\\x13\\x83\\x74\\x10\\x9e\\xa9\\x85\\xb0\\x11\\x64\\xa0\\xeb\\x43\\x47\\x94\\x66\\x85\\xaa\\x0b\\x73\\x68\\x49\\x12\\x99\\x17\\x19\\xd3\\x31\\xef\\x85\\x88\\xde\\xed\\x62\\x94\\xe6\\x03\\x76\\x77\\x3c\\xa9\\xb6\\x4e\\xcb\\xf5\\x0a\\x7f\\x6d\\x1f\\x2d\\xbb\\xdb\\x9c\\x3f\\xad\\x99\\xa8\\x0c\\x15\\xbe\\x8e\\x2a\\xc7\\xaf\\x68\\xf9\\x1b\\x1f\\xc9\\xd5\\xef\\x86\\x75\\x19\\x31\\x03\\x37\\xee\\x2e\\xe5\\x62\\x4c\\x5c\\x65\\xe9\\xd4\\x06\\xa6\\xa6\\x41\\xaa\\xde\\xea\\xd0\\x92\\x3d\\xe3\\x74\\x56\\xcb\\x2a\\xcb\\x97\\x59\\xe7\\xd1\\x2c\\x74\\xca\\x5d\\xf1\\xfe\\x46\\xb5\\x10\\x92\\x14\\xd7\\x45\\xe3\\xc5\\x9c\\xfc\\xc2\\x02\\xb4\\xb4\\x3d\\x45\\x29\\x29\\x38\\xc3\\xc0\\x7b\\x2f\\x0e\\x01\\xc0\\x18\\x4d\\xed\\x4d\\xc3\\xf0\\x4a\\xe6\\x83\\xcb\\xad\\xbd\\x1b\\x06\\xa8\\xc5\\x25\\xe8\\x01\\x45\\x31\\xca\\x9d\\xfc\\xd7\\xf5\\xbb\\xb7\\x27\\xdf\\x4a\\x9b\\x40\\x69\\xdb\\xcc\\x00\\x26\\xe7\\x10\\x0f\\xef\\xba\\xa9\\xa4\\x4c\\x19\\xf4\\xbc\\x06\\xe3\\x79\\x4e\\x05\\x1f\\x31\\xa5\\x07\\xbe\\x2e\\x8a\\xfa\\xf0\\xf5\\xa7\\x41\\x98\\x57\\xd0\\x73\\x85\\xf0\\xbd\\x50\\x61\\x51\\x03\\x48\\xb9\\x59\\x4c\\x5d\\x52\\xd4\\x37\\xb0\\x2d\\xa4\\xeb\\x3a\\x73\\x0b\\x93\\xd5\\xf4\\xc6\\xd0\\x6f\\x9c\\x6c\\x65\\x74\\x99\\x1b\\xf6\\x82\\x1c\\xa0\\x6a\\xe2\\x3f\\xfd\\x4f\\x23\\x86\\xff\\xeb\\x80\\x1c\\xdd\\x42\\xc8\\xf3\\x81\\xf9\\xf3\\x00\\x3f\\xe8\\x65\\xc0\\xb0\\xf1\\x52\\xfd\\x61\\x0c\\x94\\x2e\\xf9\\x78\\xcc\\x4a\\xeb\\x3b\\x02\\xb3\\x2a\\xf4\\x97\\xe1\\xd0\\x32\\xb6\\x7e\\x58\\xd8\\xfe\\x7b\\x75\\x9d\\xd1\\xf9\\x89\\x7c\\xf8\\xfa\\xd3\\x01\\x39\\x8a\\xd7\\x45\\xb8\\x48\\xd9\\x67\\xf2\\xb5\\x77\\x3f\\x14\\x32\\x3d\\xb6\\x51\\x59\\x6a\\x26\\x34\\xfd\\x6c\\xc6\\x4c\\x26\\x52\\x31\\x81\\x21\\xdf\\x5a\\x62\\xcb\\x1f\\x25\\xc1\\xb3\\x95\\x65\\x7d\\x94\\x12\\x52\\x72\\x8b\\xa9\\xd2\\x0e\\x94\\x98\\x7a\\x0c\\x65\\x9a\\x62\\x09\\x19\\xdb\\x2d\\xc3\\xd7\\xcc\\xb6\\x8d\\xc1\\xb4\\x62\\xa4\\x2f\\xec\\x09\\x84\\x59\\x11\\x61\\x65\\x28\\x55\\xe1\\x26\\x19\\xd2\\x37\\xa1\\x02\\xdc\\x2c\\xb6\\x95\\x90\\x91\\xa7\\x06\\xab\\x7c\\x92\\x1b\\x31\\x7e\\x9d\\x49\\x6b\\x89\\xd8\\xda\\xa4\\x25\\xf5\\x3d\\x09\\x85\\x8d\\x97\\xb8\\xce\\x60\\xf6\\xa0\\x5d\\xb7\\xf7\\x5a\\xd1\\xda\\xe8\\xa3\\xc5\\x65\\x61\\xc8\\xd1\\x3d\\xac\\x0d\\x7a\\x13\\x9f\\xec\\xbc\\x34\\x27\\x52\\x6f\\xc3\\x09\\x0e\\xaf\\xf1\\xc0\\x27\\xf3\\x6f\\x9b\\xe3\\x82\\x11\\x87\\x56\\x69\\x0d\\x28\\x5c\\x4e\\x53\\x24\\x81\\x54\\xcc\\xee\\x1c\\x8d\\x0d\\x00\\xc1\\x6b\\x9b\\xcc\\xfa\\xd6\\x2e\\xd7\\xa7\\x22\\x35\\xff\\x57\\x5c\\x69\\x73\\x7f\\x67\\x88\\xad\\x31\\x84\\xc6\\x50\\xfa\\xfe\\xe2\\xfc\\x7e\\x90\\xbb\\xe2\\x3b\\x9e\\xd6\\x61\\x25\\xd2\\x8c\\xbd\\x96\\xf2\\x66\\x45\\xfa\\x73\\xb4\\xa0\\xbf\\x85\\x4f\\x7b\\xef\\x1c\\x6a\\x69\\x5c\\xf4\\x7d\\x0c\\x6d\\xa0\\xe5\\x92\\xa2\\xca\\x90\\xbc\\x56\\xa2\\xa0\\xc9\\x0d\\x1d\\x33\\xfb\\x51\\x60\\x23\\xb6\\xa8\\x01\\x6a\\xca\\xa0\\x0a\\xb4\\x5a\\x4b\\x6f\\xe5\\xec\\xd1\\x1a\\x60\\xe7\\xb9\\x62\\x9a\\x8e\\x2f\\xda\\x52\\x0b\\xd4\\xcd\\x7b\\xf3\\x7c\\x5b\\xf1\\x2b\\x47\\x12\\xee\\x15\\x1b\\xad\\x7c\\xd0\\xb7\\x06\\x58\\x95\\x7f\\xd2\\x87\\x36\\x70\\x2b\\x7f\\x74\\xc5\\x9f\\x97\\x3e\\xb0\\xd9\\x87\\x38\\x3f\\xcf\\xa6\\xd1\\x4d\\x73\\xaf\\xb9\\x1d\\x71\\x04\\xc3\\x42\\x39\\x7a\\x0c\\xee\\xd8\\x5d\\x80\\xce\\x7d\\xb7\\x54\\x01\\x05\\xca\\xa6\\x36\\x32\\xe7\\x5e\\xca\\x40\\x6d\\x16\\x9b\\x97\\xac\\x77\\x07\\xe1\\x39\\x9c\\xf8\\x46\\xbf\\xdd\\x46\\x41\\x7a\\xc9\\x9c\\x3a\\x71\\xba\\x13\\xa7\\x1f\\xb9\\x38\\xbd\\xd5\\x19\\xd8\\x1c\\x7a\\xf0\\x34\\x04\\xec\\xad\\x16\\xbd\\x39\\xda\\xfe\\x51\\x8a\\xdc\\x5b\\xaf\\xb1\\x41\\xf0\\xff\\xa3\\x15\\xc2\\xb7\\x5a\\x6c\\x43\\x81\\x7c\\xd9\\x92\\xbf\\x64\\xb1\\x7c\\x2b\\x18\\x6e\\x8c\\x87\\x79\\x84\\x82\\x7a\\xe3\\x05\\xae\\x4f\\x0a\\x59\\xb2\\xbe\\x20\\x1f\\x63\\xce\\x0e\\x6c\\x26\\x8d\\xed\\xec\\xbd\\x9d\\x36\\x14\\x93\\x37\\x89\\x53\\xad\\x54\\xbd\\x6d\\x2d\\xfa\\xae\\x51\\xd8\\xdc\\xca\\x52\\xcc\\x78\\x35\\x8d\\x99\\xdb\\x26\\x5b\\x04\\xaf\\x35\\x71\\xe6\\x75\\x5c\\xf1\\xde\\x69\\x23\\x78\\x6d\\x91\\x59\\xd5\\x34\\x11\\xa3\\x5e\\x76\\x93\\x44\\x92\\x2d\\x96\\x6c\\x64\\xf8\\xa2\\x94\\xc3\\xa6\\xb5\\x72\\xee\\x60\\x55\\x0d\\xa3\\x0c\\xf7\\x0c\\x67\\x87\\xec\\x7c\\xbf\\xbf\\xad\\x2d\\x76\\x53\\x12\\xc7\\x92\\xb9\\x63\\x1d\\xbf\\x28\\x92\\xcc\\xef\\xc7\\xa1\\x82\\x4d\\xbe\\x8b\\x99\\xee\\x1c\\x7c\\x19\\x88\\xd5\\x38\\xc9\\x9e\\xf3\\x60\\xbe\\x2f\\x2b\\xd6\\x23\\xaf\\x68\\xa6\\x58\\x8f\\x7c\\x2f\\x6e\\x84\\xbc\\x6d\\x6f\\xbe\\xeb\\x2b\\x32\\x2c\\x99\\xed\\x7b\\x5b\\x7b\\xa1\\x41\\xae\\x50\\xe3\\xa9\\xd4\\xda\\x7d\\x43\\x62\\x7f\\xe1\\x5f\\x70\\x16\\x1a\\xab\\xa1\\xf7\\x2b\\xc1\\x7f\\xae\\x62\\x45\\xc5\\x3b\\x99\\x8e\\xe6\\x55\\x98\\xb3\\xeb\\x1f\\x00\\x39\\x50\\xdd\\x56\\x51\\x21\\x5f\\xf3\\xa3\\x5a\\x1d\\x56\\xdd\\x24\\x0f\\x6a\\xad\\xa2\\x1a\\x27\\x86\\x1b\\x45\\x3f\\x56\\xb5\\x32\\x5b\\x92\\x71\\xde\\x2c\\x53\\x54\\x59\\x36\\x20\\x17\\xfa\\x50\\x99\\x39\\xf0\\x84\\x66\\xd9\\xcc\\x68\\x2d\\x73\\x1d\\xd2\\xf6\\xcb\\xe0\\x6a\\xc0\\x20\\x16\\x0e\\x1b\\x56\\x5c\\xe1\\x53\\x16\\xbc\\xee\\x00\\x8d\\x06\\x27\\x96\\xda\\x75\\xec\\x57\\x26\\x72\\x4d\\x2f\\xb0\\x25\\x53\\xbb\\xb2\\x8f\\x3b\\x44\\x09\\xf7\\xbf\\x86\\xaa\\x1d\\x14\\x75\\x4d\\x40\\x1a\\xc1\\xc8\\x48\\x56\\x22\\x25\\x54\\xc3\\xf6\\xec\\x38\\xe7\\xd8\\x87\\x7b\\x7f\\x0e\\xff\\xf5\\xf2\\x53\\x3b\\xc6\\xc6\\xc0\\x03\\x5f\\xe7\\xf1\\xad\\x11\\xbe\\x6a\\x22\\xc7\\x3e\\xb3\\xa4\\x0a\\x62\\xbc\\xc2\\x18\\x8e\\xdd\\x6c\\x8d\\xed\\xe6\\xbe\\x3e\\x48\\x62\\xea\\xfd\\xe6\\x94\\xb6\\x9d\\x3a\\xe9\\x31\\xa0\\x79\\x54\\x77\\x33\\x51\\xa1\\x85\\xd8\\xf3\\x26\\x85\\x9d\\x9a\\x57\\x26\\x5a\\x86\\xf6\\xc0\\x15\\x6d\\x2f\\x70\\xa6\\x82\\x15\\x2e\\xe0\\xb7\\xa1\\x27\\x14\\x2a\\xb0\\x18\\x26\\x63\\x3b\\x41\\x40\\x9d\\xaa\\x89\\xdc\\x99\\x32\\x36\\xcd\\x4f\\x7c\\xe3\\xe4\\x37\\xf3\\x41\\x90\\xed\\xfa\\x0b\\xb2\\x9d\\xe5\\x7f\\xb5\\x6c\\x07\\x0d\\x8b\\xea\\x50\\x1a\\x60\\x92\\x39\\x9d\\x41\\x68\\x5a\\x5e\\xc8\\x52\\x53\\x74\\x70\\x54\\x22\\x65\\xa5\\xd2\\x14\\x6b\\x94\\xb8\\xbc\\xbc\\xc2\\xac\\x79\\x42\\x15\\xe1\\x5a\\x91\\xc4\\x26\\x19\\xe2\\x86\\xdd\\x51\\x26\\x63\\x00\\xec\\x4b\\xf3\\x82\\x17\\x11\\xa2\\x8f\\x23\\x5f\\x8d\\x36\\x66\\xed\\x2e\\xac\\x9f\\x58\\x46\\xd7\\x04\\x56\\xed\\x4b\\x67\\xaf\\x35\\x2b\\xe6\\xe9\\x6a\\xb0\\x08\\x01\\xe2\\xf8\\x94\\xa7\\x18\\x8c\\xc4\\x0a\\xc2\\x45\\x3b\\x44\\x75\\xb3\\x03\\x07\\x1d\\x13\\xab\\x8f\\x55\\xdf\\x5b\\x69\\x56\\x3e\\xb0\\x46\\xa3\\xdd\\x4c\\xd4\\x65\\x81\\x91\\xf2\\x9b\\xce\\xfe\\xaa\\xd8\\x3c\\xbc\\xfc\\x2a\\xf6\\x24\\x97\\xab\\x23\\xe5\\xf0\\x5a\\xd8\\x55\\x97\\x7d\\xb1\\x66\\x77\\x83\\x58\\x5d\\x88\\x06\\xd5\\xa5\\x95\\xa4\\x66\\x8d\\xf6\\x98\\xdc\\x77\\x95\\x9b\\x0d\\xa9\\x7f\\x1b\\x0b\\xb1\\xf4\\x83\\xc0\\xc1\\x86\\x8f\\x81\\x61\\x72\\xed\\xb3\\x9b\\xf2\\x08\\xef\\xbb\\xae\\xce\\x9e\\x15\\x53\\xea\\xcb\\xb9\\x90\\x5a\\x19\\x6c\\xb3\\x95\\xbd\\xe1\\x40\\xf5\\xd6\\xb4\\x3c\\x5c\\x03\\xfb\\x78\\xc3\\x31\\x1b\\x25\\x00\\xb6\\x9f\\xf6\\xc6\\x8a\\x38\\xed\\x77\\x19\\x4f\\x2a\\x68\\xa9\\x79\\x52\\x65\\xb4\\xac\\xcf\\x3e\\x10\\xf9\\x85\\xbc\\xa5\\xad\\xe7\\xac\\x34\\x2d\\x75\\xa3\\x22\\x0b\\xd7\\xee\\x49\\x5f\\x73\\x11\\x0a\\x2e\\x4c\\x98\\xf0\\xce\\x3f\\x4c\\x03\\x23\\x43\\x36\\x36\\xcc\\xb3\\x28\\xb2\\x99\\xcb\\x31\\xa8\\x23\\xd8\\x33\\xae\\x74\\xdd\\xf0\\x10\\x64\\x81\\xa6\\xa1\\x10\\x5b\\x97\\x6b\\xf8\\x55\\xe7\\xd1\\xc9\\x2c\\x4f\\xa4\\x18\\xf1\\xf1\\xfd\\x65\\xd1\\xbd\\x7b\\xfd\\xe6\\x0c\\x3e\\x09\\xf7\\xea\\x1c\\x3a\\x7f\\x7f\\x21\\x83\\xae\\x9e\\x24\\xdc\\xae\\x93\\xe4\\xfc\\x0f\\x75\\x8a\\x9c\\xad\\xe7\\xb0\\x24\\x3f\\xce\\x65\\x5f\\xb9\\xfd\\xdc\\x31\\xef\\xca\\x4f\\xd3\\x45\\x65\\x78\\x56\\xac\\x0a\\x29\\x14\\x37\\x32\\x31\\xd4\\xcf\\x82\\x87\\xb0\\xe3\\xcb\\xbb\\xd7\\x6f\\xda\\x4d\\xba\\xea\\x32\\xac\\xba\\x0c\\xab\\x2e\\xc3\\x6a\\xd3\\x81\\x6a\\x90\\x61\\xe5\\x4f\\x33\\xe4\\x57\\xb9\\xb0\\x3d\\xf3\\x7f\\x9b\\x26\\x54\\x1f\\x77\\x5f\\xd3\\xba\\xe9\\xc7\\xd7\\xcb\\x87\\x23\\x46\\x0d\\x68\\x36\\x47\\x16\\xbe\\xb2\\x0f\\xd6\\x9d\\x87\\xa2\\x3c\\x5d\\x4b\\x66\\x40\\x17\\x7f\\xf7\\xfa\\x8d\\x1f\\xf7\\x0e\\x72\\x22\\x52\\xae\\xcc\\x67\\xce\\x64\\xc1\\x59\\x7a\\x76\\xfd\\x43\\xb3\\xc6\\xd4\\xe7\\xf3\\x6f\\x45\\x39\\x1d\\xf8\\xa3\\x99\\xf9\\xa1\\x22\\x07\\xf8\\x10\\x39\\xbb\\xfe\\xe1\\xc0\\x2d\\x04\\x36\\xa2\\x6e\\x5e\\xe6\\xb3\\xda\\x08\\xd5\\xa1\\x40\\x80\\xf4\\xbf\\x47\\x30\\x0a\\x89\\xc6\\xb7\\xd3\\xa8\\xb9\\x93\\x14\\xb6\\xd3\\xce\\x84\\x2a\\x32\\x64\\x4c\\x04\\x83\\xa2\\x0a\\xfc\\xce\\x3e\\x0d\\xa5\\x40\\x6d\\x9c\\x12\\x54\\xf0\\xc6\\x8e\\x01\\x75\\x54\\xc3\\x80\\xfc\\x68\\x44\\x9b\\x92\\x31\\x61\\x96\\x91\\xf6\\x60\\x0b\\xb0\\x42\\x2e\\x03\\xde\\x8b\\x2e\\xbd\\x60\\x61\\xea\\x00\\x56\\x04\\x65\\x7c\\x56\\x4c\\x72\\x7d\\xc6\\xc8\\x3a\\x9d\\xd4\\xc6\\x67\\x22\\x91\\xb8\\x9e\\x89\\xe4\\xc2\\xd0\\xd8\\x15\\xa9\\x73\\x0b\\x3b\\x75\\xb9\\xea\\xed\\x68\\xc7\\x80\\x5f\\xe0\\x39\\x99\\x89\\x04\\xa9\\xb8\\x79\\xc6\\xac\\xca\\x7e\\xbf\\x04\\x99\\xaa\\xb4\\x8d\\x19\\xec\\xb0\\xc1\\x3d\\x52\\xb0\\x92\\xcb\\xd4\\x7a\\x21\\x92\\x09\\x4b\\x6e\\xe6\\xf4\\xd7\\x28\\xb6\\x51\\xfd\\x1f\\x1b\\x4b\\x17\\x15\\x6e\\xc7\\x31\\x48\\x05\\xfd\\x11\\xd2\\xaa\\xee\\xd8\\x91\\x53\\x4d\\x8e\\xa0\\x5e\\xd3\\xc1\\x1f\\x9f\\xe5\\x07\\xc7\\x18\\x19\\x87\\xe1\\x5f\\xb4\\xa4\\x39\\xd3\\xac\\xec\\x61\\xb4\\xd7\\x44\\x56\\xa5\\x22\\x47\\x07\\x93\\x83\\xe3\\x1e\\xc9\\xb9\\xa8\\x34\\x33\\x7f\\xe6\\xe6\\x4f\\xc3\\x8e\\x14\\xd6\\x38\\x27\\x47\\x07\\xea\\xe0\\xd8\\x59\\xaf\\x7c\\x08\\x9a\\xdd\\x7d\\xe8\\x59\\xe1\\xee\\xf5\\xc2\\xb9\\xd9\\xa6\\xbc\\x9e\\xf1\\x21\\xe5\\xaf\\x43\\xd8\\x6c\\xe8\\x1d\\xbc\\x11\\x02\\x69\\xe7\\x94\\x21\\xf0\\x1e\\x19\\xae\\xfa\\x82\\xfc\\xcf\\xd1\\x87\\x67\\xfd\\x3f\\x7f\\xfa\\xdd\\xd1\\xc7\\x01\\xfe\\xe7\\xf8\\x9b\\x23\\xf5\\x4b\\xfe\\xcb\\xe4\\xf8\\xf8\\x77\\xbf\\x8d\\x89\\xe4\\xe6\\xac\\xb9\\x9a\\x4c\\xae\\xac\\x3e\\x74\\x87\\xa4\\xf2\\x3e\\x9c\\x12\\x07\\xb5\\x2b\\xc2\\xd3\\x59\\xe7\\xa3\\x06\\x0a\\x24\\x18\\xa1\\x66\\xe7\\xb4\\xf7\\xb8\\x06\\x3a\\x58\\xdd\\x49\\xe2\\xf4\\xf2\\xc2\\xd7\\x20\\x1e\\x90\\x7e\\xbf\\x6f\\x83\\x0d\\x75\\x59\\x25\\x1a\\xeb\\x8a\\x69\\xec\\xfc\\x65\\x46\\x4d\\x79\\x09\\xa2\\x8e\\x62\\x60\\x46\\x74\\x0d\\x0e\\x2d\\x69\\xc3\\x08\\x41\\x88\\xe6\\x1d\\x58\\xd3\\x67\\x0d\\x8a\\x01\\x89\\x03\\x3e\\x3f\\x0a\\x80\\x04\\x79\\x25\\xa5\\xdd\\x24\\xfc\\xe6\\x3f\\xc9\\xc9\\x09\\xb9\\x9a\\xf3\\xae\\x0c\\x0d\\x9e\\xd9\\xb6\\x3e\\xa0\\x3c\\x8e\\xa4\\x3c\\x8c\\xed\\xac\\x6c\\x60\\x5e\\xfc\\x4e\\xc8\\x5b\\xb1\\xec\\xeb\\xf0\\x2d\\x5a\\xb2\\x17\\xe4\\xe3\\xc1\\xe9\\x94\\xf2\\xcc\\xd0\\xbf\\x8f\\x07\\x3d\\xf2\\xf1\\xe0\\xd2\\xc6\\xba\\x73\\x31\\xfe\\x68\\x7b\\x65\\x7c\\x3c\\x38\\x67\\xd0\\xb4\\x3e\\xfd\\x78\\x60\\x86\\xfd\\x1d\\x74\\x3c\\x7c\\xc3\\xca\\x31\\xfb\\x8e\\xcd\\xfe\\x13\\x06\\xf3\\xb7\\xaf\\xb1\\x3b\\xe2\\xec\\x3f\\xb1\\x39\\xa2\\xb9\\x6f\\xb8\\xdd\\xfb\\x59\\xc1\\xfe\\x33\\xa7\\x85\\xbf\\xf1\\x86\\x16\\xfe\\xe5\\x20\\x8c\\xe7\\xc3\\x27\\x23\\x26\\x4c\\x9f\\x0f\\xea\\x1d\\xfd\\xe9\\xef\\x4a\\x8a\\x17\\x1f\\x0f\\x82\\xfa\\xaf\\x32\\x37\\x98\\x51\\xe8\\xd9\\xc7\\x03\\x12\\x7d\\xf5\\xc5\\xc7\\x03\\xf8\\xae\\xbb\\xef\\x26\\xf9\\xe2\\xe3\\x81\\xf9\\x92\\xb9\\x5d\\x4a\\x2d\\x87\\xd5\\xe8\\xc5\\xc7\\x83\\xe1\\x4c\\x33\\xd5\\x7b\\xde\\x2b\\x59\\xd1\\x33\\x5c\\xe1\\x3f\\xeb\\x2f\\x7c\\x3c\\xf8\\xc9\\xec\\xc9\\xc9\\x09\\x36\\x78\\xc1\\xcd\\x54\\xe4\\x5f\\xcb\\xbb\\xb2\\xb4\\x60\\x53\\x5d\\x74\\x54\\xad\\x7c\\x74\\x53\\x71\\x35\\x74\\xba\\xec\\x62\\x7a\\xdd\\xb3\\xa3\\xfb\\xce\\x85\\x66\\x17\\x5f\\xac\\x5b\\xbd\\xee\\x17\\x4e\\x64\\xcf\\x2f\\xea\\x36\\xc3\\xc0\\x96\\x01\\x7e\\x0b\\x34\\x5e\\xd4\\xa3\\x62\\x00\\x6f\\x3a\\x20\\xd8\\x4e\\x14\\x13\\x58\\x0d\\x83\\x80\\xf0\\x0b\\x60\\x0e\\xc2\\xb2\\xac\\x45\\xeb\\x88\\xa1\\x1d\\x78\\xe6\\xed\\x30\\xa0\\x36\\x24\\x09\\x2b\\xb4\\x39\\x5d\\xf7\\x54\\x10\\x77\\xbb\\xb2\\xb2\\xf9\\x82\\x6b\\x68\\xf7\\xb0\\x1f\\x04\\xb5\\xe5\\xb2\\xd4\\xb5\\xc2\\xc6\\x65\\xed\\xb9\\xf8\\x9c\\x7e\\x7e\\x0d\\x7d\\xc9\\x5e\\x90\\xdf\\x7f\\xfd\\xa7\\x3f\\xfe\\xc7\\x2a\\xbf\\xc0\\x10\\xad\\x41\\xdf\\xae\\xcd\\x7b\\x5f\\x02\\x86\\xc5\\x17\\xe7\\x6d\\xf3\\x03\\xa7\\xbc\\x0c\\xea\\xa4\\xfa\\xba\\xfb\\x70\\x1c\\xf3\\xa5\\x98\\x26\\x43\\x70\\x7f\\x56\\x85\\x81\\xcb\\x2b\\x97\\xea\\x2c\\x12\\x8c\\x47\\x5d\\x3a\\x18\\xf7\\x04\\x3c\\x9b\\x91\\xe7\\x5f\\x63\\x43\\x2d\\xf8\\xf4\\x02\\xf9\\xfe\\xf0\\xf9\\xd3\\x60\\xc9\\x94\\xb9\\x22\\x7f\\xee\\xcd\\xcd\\xc7\\x08\\xcc\\x15\\x30\\x3d\\x83\\x38\\x18\\xe9\\x50\\x32\\xe4\\x84\\xce\\x26\\xb7\\xc8\\x09\\x99\\x9f\\xef\\xa6\\x8d\\xdb\\xa2\\x3f\\xcc\\x1f\\xff\\xb0\\x7a\\x7f\\xb9\\xe0\\x79\\x95\\xbf\\x20\\xcf\\x56\\x7a\\x59\\xb6\\x70\\x4a\\x5b\\xa7\\xb3\\x17\\x04\\x28\\xf6\\x40\\xa0\\x39\\x14\\x84\\x08\\xe2\\x8e\\x42\\xd4\\xd6\\xdb\\x45\\x8e\\x91\\xcb\\x52\\xa6\\x55\\x62\\x74\\x79\\x39\\x72\\x32\\x61\\x12\\x12\\x28\\x68\\x4c\\x64\\x4e\\x83\\x15\\xb9\\xd9\\x67\\x03\\x74\\x56\\x77\\xa8\\x12\\x29\\x74\\x70\\xe2\\x62\\xac\\xea\\x2a\\xa0\\x40\\x40\\x90\\xeb\\xde\\x4e\\x18\\xb0\\x1e\\x1d\\xf6\\xb0\\x85\\x59\\x29\\x9e\\x42\\xce\\x05\\x25\\xe3\\x8a\\x96\\x54\\x68\\x86\\x9d\\x3e\\xb0\\x8f\\xad\\x15\\x53\\x3d\\xc9\\xa3\\x41\\x61\\x55\\x7b\\x1a\\xf1\\xa8\\x22\\xb1\\x32\\x53\\xb4\\xa6\\x04\\xec\\x7f\\xdc\\xda\\x51\\x7d\\xfe\\xec\\xeb\\xb5\\x5b\\xee\\x9f\\x5b\\xed\\xa1\\xf1\\xe2\\xf0\\x87\\xd3\\xfe\\xff\\x47\\xfb\\xff\\xf8\\x74\\x64\\xff\\xf3\\xac\\xff\\xe7\\xff\\xed\\xbd\\xf8\\xf4\\x55\\xf0\\xe7\\xa7\\xe3\\x6f\\x7e\\xdb\\x86\\xbd\\x5e\\xb5\\x1a\\x99\\xd7\\x08\\x68\\x9b\\x3b\\x0e\\x1d\\x98\\xaf\\xae\\x6b\\x09\\xd7\\x27\\x07\\x30\\xa5\\xf5\\xcf\\xd8\\xe9\\xae\\x53\\x50\\x9a\\x01\\x49\\xcf\\x07\\x04\\x1a\\xdd\\xbb\\xc6\\x33\\xa0\\x78\\x46\\x2c\\x1d\\x58\\x09\\x77\\x90\\xc8\\xfc\\x24\\x30\\x4f\\x19\\xd1\\xfa\\x0d\\x15\\x33\\x52\\x93\\x35\\x14\\x4a\\xe7\\x31\\x5d\\x41\\x96\\x22\\x4d\\x4a\\xa9\\x54\\xe4\\x62\\xb8\\x61\\xc4\\x4b\\xae\\x48\\x2c\\x87\\x2c\\xa1\\x20\\x8b\\x97\\x43\\xae\\x4b\\x5a\\xce\\x02\\xd5\\xc3\\x75\\x48\\xa8\\x14\\x1b\\x55\\x19\\x39\\x52\\x8c\\x91\\x81\\x90\\x29\\x5b\\xa4\\xae\\xc7\\x48\\x43\\xe9\\x90\\x67\\x5c\\xcf\\x50\\x69\\x4e\\xa4\\x18\\x65\\xdc\\xaa\\x00\\x2e\\xfc\\xc1\\xb5\\x8d\\x1e\\xb3\\xcf\\x84\\x6b\\xec\\xaa\\x86\\x21\\x67\\x47\\xa9\\x50\\xcf\\x9f\\x7f\\xfd\\xfb\\xeb\\x6a\\x98\\xca\\x9c\\x72\\xf1\\x2a\\xd7\\x27\\xc7\\xdf\\x1c\\xfd\\x5c\\xd1\\x0c\\x74\\xc7\\xb7\\x34\\x67\\xaf\\x72\\xbd\\x57\\xa4\\x61\\xcc\\x16\\x9f\\xff\\xb1\\xc1\\x29\\x3a\\xfa\\x80\\x67\\xe5\\xd3\\xd1\\x87\\xbe\\xfd\\xdf\\x57\\xee\\xd6\\xf1\\x37\\x46\\xd7\\x5c\\xf7\\xfb\\xf1\\x57\\x66\\x0d\\xc1\\x09\\xfc\\xf4\\xa1\\x5f\\x1f\\xbf\\xc1\\xa7\\xaf\\x8e\\xbf\\x09\\x7e\\x3b\\xfe\\x6d\\xe7\\xa1\\xa9\\x5d\\x2e\\x81\\xee\\x75\\x6f\\x9e\\x1a\\x3b\\x86\\x57\\xa4\\xe6\\x3d\\x36\\xf3\\xbf\\x2f\\x7a\\x6e\\x16\\x26\\x8f\\x1e\\x9c\\x25\\x15\\x10\\x93\\xe8\\x23\\x81\\x8f\\x67\\x7e\\x88\\x86\\xe5\\x10\\xdb\\x72\\xf7\\xcc\\xaf\\x11\\x25\\x5d\\xc4\\x0d\\xaf\\xe9\\x03\\xad\\x37\\xc4\\xe7\\xa7\\x85\\xe7\\x7f\\xb2\\xd9\\x45\\x81\\x09\\x0d\\x2c\\xe1\\xb3\\x38\\x3a\\x4a\\x82\\xe5\\x30\\xae\\x37\\xe4\\x93\\x4d\\x97\\xd8\\x05\\x3b\\x1f\\x52\\xe7\\x43\\xea\\x7c\\x48\\x8f\\xc3\\x87\\x34\\x7f\\xe4\\xc1\\x97\\x04\\xfd\\x78\\x55\\xe0\\x89\\xa0\\x69\\xce\\xc5\\x8a\\xe3\\xbf\\xfe\\xdc\\x5b\\xea\\xd0\\x23\\x85\\x34\\xb2\\x0c\\x07\\xab\\xb9\\x9c\\xb2\\xb2\\xe4\\x10\\x33\\x89\\xef\\x94\\xac\\xee\\x60\\x19\\xe6\\x2f\\xb4\\x64\\x84\\x4d\\x59\\x91\\xc9\\x59\\xbe\\xaa\\xee\\xfd\\xdd\\x84\\xa3\\xdb\\x45\\xb6\\x1c\\x01\\xdf\\x19\\x7e\\x3b\\xc3\\xef\\x17\\x64\\xf8\\xed\\xac\\xb9\\x9d\\x35\\xb7\\xb3\\xe6\\x2e\\xb9\\x3a\\x6b\\x6e\\x67\\xcd\\xed\\xac\\xb9\\x9d\\x35\\x77\\xe1\\xea\\xac\\xb9\\xf6\\x99\\xce\\x9a\\xdb\\x59\\x73\\xef\\xdb\\x9a\\x5b\\x5f\\x2a\\xaa\\x08\\x7d\\x4f\\x6a\\x65\\x93\\x68\\xa7\\x05\\x85\\xde\\xf6\\xe6\\xb5\\x2a\\x7d\\xac\\x99\\x2f\\x51\\xe7\\xb9\\x56\\x2e\\x53\\x15\\x34\\xf7\\x41\\xd8\\xc3\\xaf\\x61\\x31\\xf0\\x76\\xb4\\xf6\\x2e\\x74\\xaa\\xd3\\xa0\\x3b\\x0d\\xba\\x0b\\x9d\\x8a\\xaf\\x4e\\xd9\\xf6\\x57\\xa7\\x6c\\x77\\xca\\x76\\xa7\\x6c\\x77\\xca\\x76\\xa7\\x6c\\xcf\\x5f\\x9d\\xb2\\x8d\\x57\\xa7\\x6c\\x77\\xca\\xf6\\x92\\xeb\\x69\\x28\\xdb\\xeb\\x42\\xa7\\x46\\x06\\x65\\xdd\\xcd\\x4d\\xb1\\x53\\x24\\x0c\\xaa\\xf9\\xba\\x0b\\xaa\\xe9\\x82\\x6a\\xba\\xa0\\x9a\\x2e\\xa8\\xc6\\x5d\\xf7\\x1d\\x54\\x13\\x5b\\xe0\\x30\\xf2\\x25\\xb2\\xb8\\x01\\xce\\x16\\xa5\\x9c\\xf2\\x94\\xa9\\xb9\\x10\\x1c\\x5f\\xac\\x31\\xe0\\x32\\x39\\xb4\\x77\\xac\\xc3\\x6a\\xd8\\xfd\\x04\\xd5\\x74\\xe6\\xb9\\xce\\x3c\\xd7\\x99\\xe7\\x3a\\xf3\\x5c\\x7c\\x75\\xe6\\x39\\x7f\\x75\\xe6\\xb9\\xce\\x3c\\xd7\\x99\\xe7\\x3a\\xf3\\x5c\\x67\\x9e\\x9b\\xbf\\x3a\\xf3\\x1c\\x5e\\x9d\\x79\\xae\\x33\\xcf\\x2d\\xb9\\x9e\\x86\\x79\\x2e\\xc4\\xa0\\x2e\\xbd\\xa2\\xd3\\x3e\\x3b\\xed\\xf3\\xf1\\x69\\x9f\\x9d\\x4a\\xd9\\xa9\\x94\\x9d\\x4a\\xb9\\xe4\\xea\\x54\\xca\\x4e\\xa5\\xec\\x54\\xca\\x4e\\xa5\\x5c\\xb8\\x3a\\x95\\xd2\\x3e\\xd3\\xa9\\x94\\x9d\\x4a\\xd9\\xa5\\x57\\x6c\\x99\\x5e\\xf1\\xee\\xf5\\x9b\\x20\\x9e\\x03\\xe3\\x3c\\x02\\xcc\\x82\\xee\\xec\\x50\\xb5\\xd9\\xf1\\xe4\\xce\\x17\\xdb\\x69\\xc3\\x9d\\x36\\xdc\\xf9\\x62\\xed\\xd5\\x29\\xce\\x9d\\xe2\\xdc\\x29\\xce\\x9d\\xe2\\x1c\\x6d\\x5c\\xa7\\x38\\x77\\x8a\\x73\\xbc\\x95\\x9d\\xe2\\xbc\\x3d\\xd0\\x3a\\xc5\\xb9\\x53\\x9c\\x97\\x6c\\xc5\\x97\\xa1\\x38\\x77\\x55\\x66\\xb5\\x2c\\xa1\\x7a\\xec\\xfd\\x57\\x98\\xfd\\xd6\\xf7\\x87\\x5d\\xac\\x2e\\x0b\\xbf\\xad\\xac\\x2c\\x8b\\x13\\x86\\x9f\\x96\\x55\\x95\\x95\\x88\\x95\\x8b\\xe5\\x64\\x5d\\x47\\xda\\x07\\x28\\x25\\x8b\\x5d\\xa5\\xac\\xe2\\x50\\x09\\x0e\\x62\\x4f\\x5e\\x65\\x9a\\x6b\\x26\\xa8\\x48\\x66\\xc0\\x66\\xdf\\xbd\\x7e\\x43\\x72\\x2a\\xe8\\x38\\x68\\x0c\\xa5\\x06\\xe4\\x42\\x03\\xbd\\xd1\\xa5\\xef\\x04\\x66\\x9b\\x57\\xf9\\x04\\x90\\xb0\\x57\\x16\\x54\\xa2\\xf0\\xed\\xaa\\x40\\xe1\\x08\\xda\\x0f\\x19\\x01\\xd0\\xb0\\x0f\\x68\\x6d\\x15\\x76\\xb5\\xfa\\xcd\\xfc\\x01\\xef\\x52\\x62\\xba\\x94\\x98\\x2e\\x25\\xe6\\x91\\xa4\\xc4\\x00\\xfd\\x58\\xd9\\xaf\\x30\\x22\\x32\\x3b\\x34\\xe2\\xb2\\x3d\\xcb\\x16\\xe5\\xab\\xaa\\x00\\xdb\\x9a\\xb7\\x60\\x91\\x73\\x7c\\x72\\x0b\\x13\\xab\\x62\\x19\\x4b\\xb4\\x2c\\x97\\x09\\x6f\\x71\\x1b\\x61\\xfb\\xa0\\x7d\\x03\\x97\\x19\\x2d\\xed\\x50\\xad\\xa7\\x5b\\x0d\\x56\\xba\\x69\\xb6\\x04\\x44\\x17\\x9d\\x4c\\x5e\\x7e\\x2e\\xc0\\xd2\\xb8\\xc2\\x34\\xbc\\x30\\xfb\\xf9\\x97\\xf0\\x44\\xb9\\x8e\\x8d\\x19\\x1d\\xb2\\xcc\\x83\\xc2\\x51\\xd2\\x1c\\x8f\\x0c\\x4a\\x6a\\xf5\\x1d\\x10\\x30\\x4f\\xdf\\x9e\\x2f\\x5a\\xb9\\xe3\\x05\\xae\\x32\\x4c\\x93\\xf5\\xc6\\xe9\\x85\\xa9\\x9f\\xae\\x99\\x9e\\x25\\x0c\\xee\\x17\\xb0\\x2a\\x78\\xe5\\x15\\x89\\x5e\\x8f\\x50\\x72\\xc3\\x66\\x48\\x1f\\xa3\\x2c\\x2d\\xf3\\x70\\xc9\\x80\\x9a\\xc2\\x66\\xde\\xb0\\x19\\x3c\\x64\\x89\\xe5\\x06\\x01\\xb3\\x95\\x26\\xf4\\x37\\x6c\\x15\\x84\\xf0\\x77\\x37\\xd9\\xd5\\x02\\x6a\\xa3\\x76\\xef\\x37\\x6c\\xb6\\xee\\xe7\\x39\\x80\\x1b\\x38\\x78\\x1b\\xa2\\x81\\xbc\\xb9\\xe1\\x0d\\x36\\x1e\\xd8\\xb4\\x28\\x32\\x68\\x7c\\x28\\x57\\x83\\x8a\\x34\\x6f\\x63\\xee\\x96\\xba\\xc5\\x44\\xfd\\x56\\x06\\x16\\x27\\xd8\\xec\\x43\\x85\\x1b\\x6b\\x30\\x7d\\xc2\\x0b\\x2b\\x64\\xa0\\x68\\xe1\\x58\\xe1\\x0f\\x34\\xe3\\x81\\x18\\x03\\x58\\x7d\\x21\\x7a\\xe4\\xad\\xd4\\xe6\\x9f\\x97\\x9f\\xb9\\x21\\xf5\\x06\\x1f\\xce\\x25\\x53\\x6f\\xa5\\x86\\x3b\\xad\\x2c\\x15\\xa7\\xb0\\xc5\\x42\\xad\\x66\\xc7\\x03\\x4f\\x89\\x1c\\x45\\xfc\\xd0\\x88\\x61\\xa3\\x28\\x1d\\xd0\\x3c\\x7d\\x21\\x8c\\x3a\\x69\\x57\\x14\\x19\\x43\\xcc\\x10\\x79\\xa5\\x80\\x81\\x09\\x29\\xfa\\x68\\xbf\\x58\\x36\\x86\\x05\\x84\\x2c\\x23\\x38\\xac\\x19\\xce\\x0e\\x05\\x76\\x12\\xfc\\x05\\x25\\xa0\\xcc\\x88\\xb2\\x24\\xc5\\xf6\\xd3\\xc0\\xcd\\x0d\\xd1\\xe6\\x09\\x41\\x6f\\x07\\xf8\\x1c\\x9a\\x80\\x77\\x1d\\x5d\\xc1\\x6b\\x03\\x75\\x69\\xb8\\x57\\x40\\x32\\x5f\\x9b\\x03\\xb0\\x05\\x89\\xc5\\xe7\\x91\\x2c\\xe5\\xb4\\x30\\xdb\\xf4\\x4f\\x43\\x7d\\x00\\x52\\xff\\x22\\x05\\xe5\\x46\\x62\\x3e\\x05\\xe9\\x3f\\x63\\xd1\\x6f\\xb6\\xeb\\x66\\x38\\x8c\\x19\\x81\\x2b\\x62\\x48\\xc9\\x94\\x66\\x86\\xde\\x81\\x7d\\x9e\\xb0\\x0c\\xa9\\x9f\\x11\\xd2\\xe7\\x08\\x7b\\x8f\\xdc\\x4e\\xa4\\x42\\x62\\x86\\x56\\x2a\\xae\\xc8\\xc1\\x0d\\x9b\\x1d\\xf4\\x16\\xb6\\xf6\\xe0\\x42\\x58\\x37\\xd5\\xc2\\x66\\x7a\\x22\\x0a\\x3d\\x49\\x0f\\xe0\\xb7\\x83\\xdd\\x79\\xc1\\x5a\\x62\\x49\\x53\\x34\\x1f\\xd0\\xec\\xb2\\x01\\x35\\x5b\\xbb\\x6f\\xb1\\x7f\\xd9\\x68\\x50\\x0d\\xf8\\xfa\\xfc\\x2b\\x8e\\xf8\\x61\\x6a\\x6e\\xa8\\x9b\\xc0\\x93\\x84\\xe2\\xa3\\xd6\\x0f\\x0c\\x9d\\x75\\xd1\\x3c\\x62\\x9b\\xd1\\x16\\x99\\x9c\\x79\\x38\\x1f\\xa9\\x63\\xdc\\x59\\x23\\x8f\\x3a\\xd8\\x83\\xa6\\xb7\\x5a\\x34\\x58\\xb5\\x38\\xa3\\x3e\\x24\\x97\\x98\\x41\\x9c\\x9e\\x5e\\x5e\\x6c\\x6e\\xd4\\x7c\\x0d\\xaf\\x10\\xcd\\xb2\\x0c\\xbd\\xd8\\x46\\x66\\xd5\\xd2\\xca\\xac\\x4b\\x45\\x98\\x22\\x18\\x3f\\x50\\xf2\\x57\\x4e\\x76\\x55\\xef\\x5f\\x14\\x85\\xbc\\x12\\xbb\\x79\\xae\\xef\\xe7\\x5e\\xb0\\xe4\\x8e\\x7d\\x2e\\x32\\x9e\\x70\\xed\\xe8\\x77\\x2d\\x5b\\x81\\x3e\\x04\\x2f\\x01\\xe1\\xe2\\x20\\x0d\\x28\\xa6\\x7b\\xb5\\xac\\xc6\\x15\\xe1\\x63\\x21\\xcb\\xe5\\xf8\\x79\\x37\\x11\\xec\\x84\\x7c\\xee\\xdf\\x54\\x43\\x56\\x0a\\xa6\\x99\\xea\\x1b\\x19\\xab\\x6f\\x5f\\x60\\x8b\\x47\\x60\\x5e\\x84\\xdd\\x04\\xa5\\x83\\xef\\xe3\\x17\\x22\\x05\\xd4\\x0e\\xe6\\x68\\xeb\\x6c\\xa1\\x51\\x35\\x3c\\xe5\\x21\\x08\\xe7\\xb9\\x64\\x68\\x31\\xf4\\x0e\\x14\\x7d\\x2b\\x89\\xaa\\x0a\\x9b\\x64\\x3e\\x37\\xa4\\x39\\x9a\\xe4\\xa3\\x70\\x82\\xf6\\x8b\\xba\\xb9\\x34\\x10\\x0a\\x88\\x97\\x70\\xb9\\xed\\xf6\\x64\\x59\\x4d\\x19\\xb6\\x2b\\x97\\x53\\xe6\\xd4\\x58\\x64\\x09\\x86\\x19\\x14\\x13\\xaa\\x58\\xad\\x83\\xa9\\x2a\\x49\\x18\\x4b\\x59\\x8a\\x3f\\x58\\x56\\xc2\\x46\\x23\\x96\\x68\\x3e\\x65\\xd9\\x0c\\x8c\\xff\\x0a\\x45\\x12\\xff\\x7d\\x83\\xd9\\xf8\\xf9\\x7a\\xc1\\x73\\x5f\\x14\\xec\\xb3\\x76\\x4a\\x3a\\xe1\\xa0\\x84\\xc7\\x96\\x8a\\xd2\\x2f\\x77\\x42\\x15\\x19\\x51\\x9e\\x19\\xbd\\xee\\xa3\\x20\\xef\\x59\\x32\\xb9\\x2c\\xd9\\x94\\xb3\\xdb\\xef\\x85\\xa2\\x23\\xf6\\x8a\\xf2\\xec\\x95\\x2c\\x6f\\x69\\x99\\x06\\x30\\xb8\\x8b\\xe5\\x9b\\x59\\xf9\\xdf\\x70\\x4a\\x0e\\x2e\\xa7\\x9e\\x70\\x66\\xb3\\xa0\\xcd\\xb7\\xf5\\x8c\\x99\\xf5\\xde\\xba\\x05\\x5e\\x66\\x06\\x62\\xe0\\x70\\xa5\\x46\\xa1\\xf5\\x18\\x45\\x4a\\x36\\x62\\x25\\x13\\xe6\\x3c\\x51\\x37\\x7e\\xf0\\x92\\x67\\x0f\\x09\\xb6\\xbf\\xae\\x3b\\x94\\x5b\\xbd\\x17\\x1d\\x63\\x14\\x3e\\xe6\\xa0\\xe7\\xdc\\x40\\xcc\\x88\\x0a\\xd0\\x0e\\x04\\xcf\\x6e\\x60\\x34\\xfa\\x28\\xc8\\x8f\\xa7\\x57\\x6f\\x2f\\xde\\x7e\\xfb\\x02\\xb8\\xca\\x3a\\x08\\x2f\\xe2\\x35\\x57\\xa4\\x82\\xa7\\x02\\xab\\x87\\xaa\\x32\\x6d\\x50\\xbc\\x12\\xde\\x5f\\x34\\x64\\x13\\x3a\\xe5\\xe6\\x0c\\x94\\xd6\\x1e\\x32\\x65\\xd8\\x96\\xde\\xa8\\xc1\\x24\\x93\\xca\\x8c\\x93\\x31\\xa5\\xc8\\x4c\\x56\\x18\\xc7\\x93\\x32\\x56\\xa0\\x8b\\x5b\\x69\\x2a\\xa0\\x99\\x89\\xf5\\x67\\xcc\\x2f\\x82\\x0c\\x99\\xf9\\xd5\\x59\\xc4\\x16\\x4e\\xd7\\x32\\x7f\\xc2\\x06\\xca\\xe1\\x34\\xdd\\x15\\x8a\\x2c\\x59\\xeb\\xf0\\xe8\\xaf\\x79\\xcb\\xfc\\xba\\x0e\\xc4\\xb1\\xda\\xdf\\x3c\\x60\\x0a\\x15\\xff\\x75\\x1d\\xb8\\xc3\\x07\\xaf\\xb6\\xd7\\xfd\\x57\\xeb\\x51\\x18\\xf8\\xf1\\x3d\\x62\\xe1\\x16\\x1a\\xff\\xfa\\xa0\\xaa\\x68\\x95\\x41\\x70\\xcd\\x9c\\xec\\xbd\\x8c\\x73\\x06\\x41\\x42\\x6d\\x32\\x9b\\x2e\\x5a\\xab\\x8b\\xd6\\xea\\xa2\\xb5\\x96\\xfd\\xde\\x45\\x6b\\x75\\xd1\\x5a\\x5d\\xb4\\x56\\x17\\xad\\xd5\\x45\\x6b\\x75\\xd1\\x5a\\x5d\\xb4\\x16\\xe9\\xa2\\xb5\\xea\\x67\\xba\\x68\\xad\\x2e\\x5a\\xeb\\xe1\\xd2\\x9c\\x02\\xc5\\x74\\xa3\\x8e\\xf9\\xba\\x7e\\x16\\xa5\\x13\\xed\\xe2\\xa1\\xdc\\xc9\\x8c\\x45\\xc3\\x79\\xad\\xd3\\x9e\\x62\\xc3\\x8f\\xed\\x30\\x5b\\x1b\\x96\\x9b\\x08\\x5d\\xa2\\xb9\\x21\\x37\\x36\\xe1\\x06\\x96\\x93\\x05\\xef\\xb8\\xe7\\x40\\xd1\\xa2\\x1e\\xab\\xa9\\x36\\x76\\x2e\\x5c\\xb1\\xd1\\x96\\xbe\\x85\\x2b\\x36\\x0a\\xad\\x6d\\x08\\x98\\xd8\\xa5\\x60\\x23\\x56\\xbc\\xcf\\xe1\\x0e\\xc2\\x07\\x56\\xc7\\x38\\x2d\\x5d\\x82\\x11\\xf6\\x9d\\xc9\\xd4\\xe2\\xa3\\x5d\\xc3\\x4a\\x5f\\xe8\\xc6\\x23\\x0d\\xfc\\xf8\\x92\\xea\\x49\\xa3\\x19\\x1c\\x5e\\x58\\xb0\\x81\\xe3\\x10\\x5c\\xb9\\x05\\x67\\x09\\x8b\\xc2\\xa8\\x40\\x8e\\x63\\x34\\xb5\\x37\\x8d\\xe0\\x53\\x32\\xfb\\x5b\\x0f\\x25\\x0e\\xeb\\x2e\\xad\\xc3\\xac\\x8c\\xd0\\x44\\xa8\\x21\\xc4\\x3c\\x25\\xff\\x75\\xfd\\xee\\xed\\xc9\\xb7\\xd2\\xca\\x0a\\x46\\x9b\\x51\\xb6\\x61\\x52\\xce\\x84\\xee\\x11\\x55\\x25\\x13\\x42\\x95\\x99\\x9a\\xd1\\x6f\\xaf\\xc1\\xf4\\x90\\x53\\xc1\\x47\\x4c\\xe9\\x81\\x1d\\x8d\\x95\\xea\\xc3\\xd7\\x9f\\x06\\xb1\\xc5\\x83\\x5b\\x9f\\xaa\\x0b\\x46\\xb2\\x08\\x00\\x67\\xc3\\x2c\\xc6\\xbf\\x0b\\x42\\x2b\\x4c\\xa9\\x90\\xa9\\x9d\\xf4\\x2d\\x4c\\x56\\xd3\\x1b\\x46\\xa4\\x9d\\x6c\\xc5\\x80\\x29\\xbc\\x20\\x07\\x06\\x4d\\x82\\x4f\\xff\\xd3\\x1c\\xac\\x7f\\x1d\\x90\\xa3\\x5b\\xb0\\xea\\x1f\\x98\\x3f\\x0f\\xf0\\x83\\x3e\\x76\\xcc\\xdc\\x0b\\x38\\xbe\\xfd\\x30\\xca\\xf7\\x25\\x1f\\x8f\\x41\\xdc\\x02\\xd3\\xed\\x94\\x09\\x7d\\x0c\\xfc\\x6d\\x44\\x84\\x0c\\x1e\\x16\\xd6\\x45\\x56\\x3b\\xc6\\xe6\\x27\\xf2\\xe1\\xeb\\x4f\\x07\\xe4\\x28\\x5e\\x97\\x11\\x41\\xd9\\x67\\xf2\\xb5\\x77\\x86\\x15\\x32\\x3d\\x76\\x5a\\xeb\\x4c\\x68\\xfa\\x19\\x14\\x83\\x89\\x54\\x4c\\xa0\\x2f\\x41\\x4b\\x34\\xc8\\x2a\\x69\\x94\\x4f\\x96\\x65\\x7d\\x14\\x30\\x53\\x72\\x8b\\x36\\x38\\x07\\x4a\\xf4\\x27\\x17\\xb4\\xd4\\x73\\x91\\x75\\xef\\xdf\\x9d\\xbf\\x7b\\x81\\x5f\\x33\\xdb\\x36\\x16\\x4e\\xcb\\x1d\\x71\\x41\\x33\\x6b\\xd9\\xf6\\xf2\\xa1\\x99\\x48\\x85\\x9b\\xa4\\xa5\\x55\\x6d\\x9d\\x51\\x77\\x54\\xe9\\xaa\\x64\\x83\\xf9\\x48\\xab\\xc6\\x18\\xbf\\x2c\\xcc\\x6d\\x39\\xb2\\x43\\xb8\\xdb\\xfc\\x41\\x7b\\xc0\\x60\\xb2\\xc6\\x4b\\x14\\x2b\\x9c\\xad\\x8b\\x4b\\x7c\\x1b\\xe0\\xe0\\xda\\x25\\xd6\\xa4\\xd9\\xac\\x32\\x95\\x89\\x32\\x0b\\x4c\\x58\\xa1\\xd5\\x89\\x9c\\x1a\\xd2\\xc9\\x6e\\x4f\\x6e\\x65\\x79\\xc3\\xc5\\xb8\\x6f\\x90\\xac\\x8f\\x3b\\xaf\\x4e\\x80\\xc5\\x9c\\xfc\\x1b\\xfc\\xb3\\xd7\\x8a\\x80\\x4f\\x35\\x5f\\x16\\xc6\\xb4\\xde\\xc3\\xda\\x80\\x7d\\x9e\\xec\\xbc\\x34\\x27\\x5f\\x6e\\xc3\\x09\\x0e\\xaf\\x9d\\xf2\\x37\\xf7\\xb6\\x39\\x2e\\xe8\\x0b\\xb7\\xc1\\xae\\x01\\x85\\xcb\\x69\\x8a\\x24\\x90\\x8a\\xd9\\x9d\\xa3\\xb1\\x01\\x20\\xe8\\xf8\\xc9\\xac\\x6f\\xa3\\xd1\\xfb\\x54\\xa4\\x7d\\x2f\\x5f\\x27\\xb3\\x9d\\x21\\x56\\xf1\\x86\\x07\\xf8\\xfb\\x8b\\xf3\\xfb\\x41\\xee\\x8a\\x6f\\x75\\x5a\\xdb\\xca\\x25\\x20\\x51\\xfc\\x39\\xcd\\x8a\\x09\\x6d\\xab\\xf7\\x42\\x17\\x85\\x0e\\x57\\x17\\x85\\xde\\x45\\xa1\\x77\\x51\\xe8\\xf5\\xf5\\x48\\xa2\\xd0\\xbb\\x28\\xf2\\x2e\\x8a\\xbc\\x8b\\x22\\x5f\\xfd\\x73\\x17\\x45\\xde\\x45\\x91\\x77\\x51\\xe4\\xf3\\x57\\x17\\x45\\xde\\x45\\x91\\x77\\x51\\xe4\\x5d\\x14\\xf9\\x92\\xab\\x8d\\x82\\x75\\x4f\\x30\\xfe\\xb2\\x73\\x8e\\x3d\\x0d\\xe7\\x58\\xe7\\xee\\xea\\xdc\\x5d\\x9d\\xbb\\xab\\x73\\x77\\xed\\x80\\xf1\\x9d\\xbb\\xab\\x73\\x77\\x75\\xee\\xae\\xce\\xdd\\xf5\\x48\\xdd\\x5d\\x5b\\x75\\x19\\x7f\\xd2\\xb5\\xb3\\xee\\xbf\\x6c\\x16\\xdc\\x5a\\xac\\x98\\xb5\\xb2\\x58\\x96\\xad\\x93\\xb5\\x50\\x0c\\xab\\xae\\x83\\x75\\x86\\xe9\\x94\\x77\\x5f\\x04\\x2b\\x36\\x00\\xba\\x06\\xcd\\x5b\\x34\\x65\\xef\\x1c\\x7a\\x9d\\x43\\xaf\\x73\\xe8\\x6d\\x3a\\x25\\x5b\\x38\\xf4\\xc0\\x97\\x17\\x1e\\x05\\xab\\x8e\\xd4\\x29\\x1c\\xef\\x96\\xbb\\x36\\x56\\x7f\\xba\\xb9\\x69\\xc5\\x5a\\x55\\xc2\\xcf\\xbb\\x5c\\x94\\xfa\\xfb\\x81\\x85\\x05\\x4e\\x8a\\xd9\\xd0\\x44\\xe6\\x85\\x14\\x06\\x31\\xda\\x71\\x2e\\xd6\\xe3\\x35\\x48\\x58\\x75\\x8f\\xda\\xfb\\x43\\x16\\x06\\x93\\x5b\\xcf\\x56\\x5e\\x48\\xc5\\x22\\x3b\\xee\\x0e\\x8a\\xf7\\x7a\\xd7\\x54\\x1f\\x9d\\x3e\\xce\\x84\\xb6\\x83\\xe2\\x1e\\xbd\\xdf\\x48\\x16\\x79\\x1d\\xbe\\x61\\x5d\\x93\\xe0\\x79\\xfa\\xb9\\x62\\x25\\xb6\\xd1\\xaf\\x1d\\x38\\x35\\x50\\x9c\\xc9\\x15\\x5d\\x52\\x11\\x58\\x0e\\xd7\\x6c\\x66\\x43\\x30\\x35\\x59\\x2a\\xd9\\xc2\\x1f\\xbb\\xb0\\xea\\x7b\\xf5\\xc9\\x92\\xc6\\xfe\\x93\\x06\\xde\\x93\\xc7\\xed\\x9f\\x25\\x4d\\x7d\\xb4\\xa4\\xa1\\x9f\\x96\\x34\\xf0\\xd5\\x92\\x66\\xfe\\x5a\\xd2\\xd8\\x67\\x4b\\x9a\\xf8\\x6d\\xc9\\x1d\\xfb\\x6e\\x49\\x73\\xa7\\x26\\x69\\xec\\xc3\\x5d\\x98\\xf4\\xa3\\xf3\\xe3\\x6e\\xb9\\xec\\x26\\xfe\\xdc\\x85\\x45\\x77\\x3e\\xdd\\x39\\x50\\x6f\\xf6\\xeb\\x92\\xa6\\xbe\\x5d\\xd2\\x3c\\x3d\\x69\\xa3\\x8f\\x97\\x74\\x7e\\xde\\xed\\xf8\\xcb\\x46\\xa2\\xbb\\x9d\\xbf\\xb7\\xd1\\x5e\\x96\\x6c\\xd4\\xcc\\x49\\x7f\\xc5\\x46\\xb8\\x98\\x40\\x9c\\xa8\\x1d\\x1d\\x72\\xa5\\x0c\\x51\\x4b\\x1d\\x3d\\x4b\\x45\\x5d\\xfd\\x9c\\x48\\x76\\xb9\\x9f\\x88\\xa8\\x2b\\x9e\\x4c\\xae\\x42\\xe3\\x15\\x0d\\x6c\\x59\\x40\\x23\\xdd\\x6c\\x7b\\x84\\x89\\x92\\x27\\x13\\x37\\x59\\x23\\xe4\\x5a\\xcf\\xda\\xfa\\x9a\\x27\\xe1\\xb4\\x37\\x6c\\x68\\x33\\x76\\xb6\\xd9\\x9b\\xb3\\x64\\xa1\\x3b\\xf8\\x74\\xc2\\x89\\x6f\\x24\\xde\\xeb\\x0b\\xca\\xac\\x98\\x54\\x50\\x09\\x64\\x2e\\x03\\xdf\\xea\\xe1\\x51\\x96\\xba\\xc7\\xa0\\x7b\\x0c\\x6d\\x59\\x3e\\xdd\\x7a\\xb6\\xe1\\x64\\xa9\\x4b\\x50\\x5d\\xac\\xd9\\x22\\xea\\xc9\\x5b\\x87\\xec\\x9a\\x5c\\xfb\\x70\\x19\\x0d\\xc4\\xae\\xe6\\x82\\xd7\\xc6\\x7a\\x20\\xe1\\x83\\x2b\\x2b\\x83\\xd4\\x57\\x73\\xe9\\x6b\\xbb\\x6a\\x21\\xf5\\xb5\\xe0\\x07\\xdf\\xa7\\x3a\\x48\\x5b\\x9c\\xae\\xbe\\x9a\\x96\\xe9\\x88\\xc1\\x80\\x4e\\xf8\\x56\\x41\\x70\\x4b\\x21\\xda\\x64\\xb8\\x10\\x83\\xf0\\x20\\x8b\\xdc\\x58\\x95\\x64\\xc5\\xea\\x4e\\xf7\\x2d\\x4a\\xd2\\xf6\\xe2\\x37\\x15\\xa2\\x58\\xb1\\x8e\\xf7\\xdb\\x55\\x97\\x68\\x7b\\xd6\\x9b\\xea\\x1f\\xac\\x98\\xf5\\x75\\xab\\x95\\x10\\x76\\x9c\\xfb\\xfa\\xa2\\x04\\x2b\\x66\\xfe\\x7e\\xbe\\x3c\\x41\\x8b\\xd3\\xda\\x18\\xb7\\xb0\\x64\\x3e\\x5d\\xf4\\x42\\x17\\xbd\\xf0\\xc8\\xa3\\x17\\xb6\\x3a\\x03\\xeb\\x22\\x19\\x96\\xa1\\xff\\x63\\x8d\\x67\\xd8\\x6a\\xd1\\xeb\\x62\\x1b\\x96\\x2d\\xfa\\x91\\x44\\x38\\x6c\\xbd\\xc6\\xb5\\xd1\\x0e\\xab\\x16\\xfa\\x48\\x62\\x1e\\xb6\\x5a\\x6c\\xc3\\xf8\\x87\\x65\\x4b\\xfe\\x92\\xa3\\x20\\xb6\\x82\\xe1\\x9a\\x88\\x88\\x65\\x70\\x7b\\x14\\x71\\x11\\x2b\\x17\\xf8\\xab\\x6e\\x2c\\x16\\x96\\x3f\\xbe\\xbf\\x00\\x89\\xeb\\xe0\\xab\\x73\\x41\\x12\\xe1\\x4f\\x0b\\x81\\x12\\xd1\\x6c\\x31\\x58\\x62\\x49\\x53\\x31\\x55\\x0d\\xc3\\xff\\xcf\\x47\\x55\\xa8\\xf8\\xe3\\x4d\\x3a\\x8c\\x85\\xf6\\x35\\x88\\x09\\x38\\x93\\x59\\x95\\x87\\x36\\x8e\\xfe\\xa2\\xe8\\x5f\\xd0\\xe4\\xc6\\x68\\x2d\\xf6\\x7b\\x43\\xf0\\xac\\x05\\xc8\\xf9\\x77\\x25\\x05\\x48\\x94\\x64\\x00\\x62\\x88\\x81\\x60\\xf0\\x33\\xee\\xcf\\x25\\x0e\\xf2\\x9b\\xb5\\x18\\xbc\\xf4\\xf3\\xae\\x46\\xb5\\xf5\\xd6\\x3b\\x0d\\xa4\\x16\\x7e\\x8a\\x85\\xa1\\xe7\\x67\\x84\\xaf\\x2e\\xcc\\xe9\\x7a\\xfe\\x76\\xe3\\x29\\x4d\\xa8\\x10\\x2c\\x33\\xb4\\x00\\x3d\\xfa\\x20\\xdd\\x79\\xf8\\xac\\x07\\x8f\\x7d\\x79\\x61\\x36\\x67\\x0b\\xf7\\x97\\x4c\\x27\\x4a\\xd1\\xdf\\x37\\x46\\x26\\x44\\x51\\x72\\xc3\\x58\\xa1\\x02\\x67\\x49\\x05\\x3e\\x15\\xc8\\x05\\x19\\xce\\x8c\\x7a\\x97\\xdc\\x40\\xb9\\x51\\x90\\xca\\x60\\xbd\\x67\\xb8\\x31\\x2d\\x27\\xd0\\x03\\xb2\\x17\\x2c\\x09\\x6e\\x75\\x21\\x38\\x5d\\x08\\x4e\\x17\\x82\\xb3\\xe9\\x8c\\x35\\x08\\xc1\\x09\\x0f\\x7c\\x14\\x86\\x43\\x05\\x39\\x2d\\x8a\\x0c\\x8c\\x52\\xae\\x34\\xac\\xad\\x39\\x68\\x0b\\x6e\\x2c\\x58\\xe2\\x76\\x4c\\x2f\\x9a\\x63\\x0e\\xee\\xf6\\x02\\x85\\x8e\\x7f\\xf0\\x4c\\x6d\\xee\\x89\\xb5\\x11\\x36\\x48\\x4f\\x97\\xc9\\x77\\x6b\\xa5\\xc3\\x44\\x8a\\x11\\x1f\\x6f\\xce\\x8b\\x09\\x60\\x79\\x06\\xaf\\xd4\\x1e\\x33\\x1c\\xa2\\xb2\\x95\\x6d\\x6b\\x4e\\x05\\xe9\\x5b\\x11\\xdf\\xbe\\x8b\\xe4\\x98\\x11\\x48\\x60\\x2b\\xc3\\x03\\xa2\\x55\\x5c\\x8c\\xea\\xe9\\xf5\\x20\\x9a\\xa6\\xe4\\xa9\\xa5\\x8f\\x85\\x4c\\x0f\\x15\\x50\\xb3\\xb4\\xca\\x6c\\xa9\\x69\\x2c\\xc5\\x62\\x8e\\xa6\\xe0\\x99\\x59\\x49\\x9f\\x6a\\x3c\\x0f\\x4c\\x61\\xbe\\xe3\\x57\\x42\\xea\\xaf\\xfc\\x48\\x68\\x78\\x29\\xf9\\x98\\x7b\\xd2\\xe7\\x5b\\x96\\x14\\x32\\x1d\\xf8\\x62\\x0e\\x1a\\x5c\\x96\\xf1\\x80\\x03\\xf2\\xbd\\xb2\\x0e\\x66\\x47\\x1c\\x8e\\xfe\\xf9\\xaf\\x63\\x43\\x58\\x59\\x89\\x85\\x3a\\xed\\xc0\\xd1\\x7b\\x1b\\xa2\\x40\\x5a\\x8a\\xed\\x11\\x32\\x65\\xa7\\x1b\\x40\\xbd\\x00\\xee\\x73\\x1f\\xbf\\x65\\x5e\\xf7\\x5b\\x15\\x02\\xb9\\xac\\xb2\\x20\\x4d\\xcc\\xc0\\x68\\x7f\\xb7\\x6a\\x53\\xc7\\x46\\x81\\x56\\x3e\\x96\\x9e\\x83\\xdb\\xfe\\xda\\xcf\\xea\\x02\\x33\\x25\\xf1\\xf6\\xcb\\xcf\\x2c\\xa9\\xf4\\x46\\x95\\x73\\x89\\x11\\xd9\\x2e\\x13\\x0c\\x52\\x59\\x66\\x3f\\x07\\xa2\\x93\\xfd\\xc1\\xac\\x17\\x18\\xa7\\x01\\x8f\\x0d\\x6d\\x53\\x54\\x73\\x35\\x9a\\x61\\xde\\xad\\x03\\x18\\x0b\\x62\\xa3\\xea\\xf3\\x65\\x04\\x95\\xa0\\x0e\\xf1\\xb0\\xd2\\x58\\xda\\x74\\x46\\x92\\x89\\x34\\xf8\\x45\\x11\\xee\\x30\\xee\\x94\\x4b\\x0c\\x20\\x02\\x7b\\x70\\x49\\x72\\xc3\\x01\\xac\\x76\\x17\\x0c\\x8f\\x1e\\xef\\xfa\\x35\\xa3\\x0a\\x4b\\xa5\\x6b\\x58\\xb9\\xa0\\x1a\\x33\\x0c\\xd8\\xd9\\xcc\\x1f\\x63\\xa3\\xae\\x80\\xc7\\xaf\\xca\\xcd\\xa0\\xb7\\x8c\\x8f\\x27\\x5a\\xf5\\x08\\x1f\\xb0\\x01\\xec\\x2e\\xa3\\xc9\\x24\\x18\\x36\\x67\\x4c\\x2b\\x42\\xb3\\xcc\\x37\\x26\\x09\\x50\\x22\\x74\\xb7\\x1f\\x79\\xa6\\x69\\x19\\x5c\\xcf\\xd3\\xdb\\xf9\\x5d\\x5b\\x0a\\xae\\x1e\\x61\\x3a\\x19\\x1c\\xf7\\xc0\\x83\\x67\\x4e\\x0b\\x85\\x39\\x0e\\x67\\x84\\x6b\\xa8\\xc5\\x0d\\x0c\\xba\\x94\\xd5\\x18\\x57\\x62\\x03\\x0d\\x94\\x97\\x8e\\xac\\x7d\\x56\\xa4\\xa0\\x4d\\x88\\x31\\x39\\xc0\\xc5\\x1d\\x38\\x81\\xc7\\x0c\\x67\\x4d\\xae\\xb0\\x3e\\x57\\x5a\\x16\\x2d\\x9e\\x65\\xc9\\x54\\x21\\xb1\\x07\\xcb\\x7c\\xe4\\xc2\\xff\\xf1\\x2f\\x1d\\xa9\\xe3\\x1a\\x98\\x13\\x3e\\x9e\\x38\\x58\\xd2\\x12\\x69\\x4a\\xbc\\x07\\xcd\\x9c\\x8f\\x4d\\xc2\\x48\\x1a\\x06\\x91\\xc4\\x7e\\x1e\\x57\\x2e\\xbe\\xc6\\x89\\x60\\xf7\\x34\\x2b\\x73\\x0f\\x03\\xd8\\x60\\xd4\\xf5\\xad\\x51\\x36\\xb7\\x39\\xcc\\x08\\x44\\xf2\\x8c\\x1c\\x01\\x8a\\x70\\x7d\\xa8\\x00\\x5d\\xfb\\xb2\\x38\\x1e\\x90\\x53\\xd0\\x76\\x1b\\x7c\\x40\\x48\\x3f\\xbe\\x1d\\xc8\\x7c\\x54\\xc9\\x7a\\xac\\x66\\x3e\\x8b\\x66\\x9e\\xda\\x6d\\x7c\\xb5\\x86\\x9b\\x17\\xde\\xa4\\xd4\\xe8\\x71\\x84\\xc9\\xc6\\x47\\xb7\\xf1\\xdb\\x92\\x60\\x0e\\x4d\\x9e\\x5e\\x70\\xe9\\x01\\x4a\\xd7\\x61\\x8b\\xac\\xcc\\x7b\\x84\\x2a\\x25\\x13\\x5e\\x37\\x4e\\x5a\\xc4\\x74\\x5c\\x49\\x13\\x3f\\xce\\x96\\xf0\\x27\\x5b\\xaf\\x9f\\x6c\\x19\\x98\\x1a\\x5f\\xf3\\xf1\\x9d\\x36\\x24\\x35\\x86\\x4a\\x44\\xb0\\x86\\x33\\xf8\\x15\\x1c\\x85\\x43\\x96\\x6d\\x88\\xce\\x0c\\xaf\\x6d\\x82\\xbf\\xdc\\xd5\\x38\\x08\\x6c\\xc5\\x82\\x56\\x2e\\xe4\\xc1\\xe2\\x55\\x97\\xc1\\x64\\x0b\\xe4\\xc0\\x6b\\x9b\\x63\\x5a\\x5f\\x4d\\x22\\x5b\\xe7\\xdf\\x68\\x14\\xe7\\x1a\\x5f\\xdb\\xe3\\x2f\\x5e\\x8d\\x62\\x60\\xe3\\x6b\\x41\\x24\\x69\\x2b\\x14\\x36\\xbe\\xb6\\x0c\\x49\\xa8\\xaf\\xe6\\x61\\xb2\\x6b\\xd6\\x75\\x75\\x57\\xb1\\xb2\\xbd\\x38\\x50\\x96\\x7c\\xab\\x11\\xd7\\x5f\\x37\\xa4\\x6c\\x2d\\x00\\xa8\\x69\\x40\\xed\\x1a\\xf0\\x9c\\x3e\\x99\\xa0\\xda\\x25\\x43\\x7d\\xab\\xcd\\x30\\xaf\\x57\\xbe\\x0c\\x0e\\x5b\\xea\\x82\\x4b\\xad\\xf0\\xd6\\x9b\\x2b\\x48\\x03\\xb6\\xa8\\xa2\\x64\\x86\\x61\\x61\\xef\\x2f\\xdb\\x09\\xe5\\xce\\xe2\\x78\\x97\\xed\\xfe\\x76\\x84\\x1d\\xaf\\xad\\xc9\\x7b\\xf8\\xc1\\xad\\xd0\\x0d\\x58\\xe4\\x2b\\x68\\x9c\\x75\\x3f\\xdc\\x11\\x9b\\x74\\x75\\xdc\\xb1\\xe3\\x8e\\xf1\\xd5\\x71\\x47\\x7f\\x75\\xdc\\x71\\xc3\\xd5\\x71\\xc7\\x8e\\x3b\\xde\\x39\\x77\\x44\\x5d\\x76\\x07\\xe5\\xf9\\x47\\x34\\x71\\xcc\\x6b\\xcb\\xc0\\x69\\x9d\\x5f\\x28\\x56\\x9b\\x0d\\xbf\\x71\\x09\\x14\\xef\\x41\\xd5\\xb6\\xb6\\xe3\\x12\\x62\\xc3\\x9e\\xf7\\x9f\\x3f\\x7b\\xb6\\x8d\\x52\\xbd\\xa9\\xe1\\x5b\\x78\\x05\\xcd\\xdf\\x7e\\xff\\xf5\\xda\\x37\\x56\\xd9\\xdf\\x5a\\xb0\\x9a\\x5a\\x1c\\xf7\\x86\\xbc\\x48\\x76\\x58\\x61\\xf8\\x04\\xea\\x24\\xa4\\x26\\x39\\xd3\\x84\\xea\\xc8\\x54\\xc4\\x73\\xd6\\x73\\x86\\xe5\\xba\\xc5\\xf6\\xb0\\x36\\xcd\\xa6\\x44\\x0a\\x17\\xa9\\x28\\x53\\x36\\xd8\\x6d\\x06\\x09\\xa3\\x0a\\xf2\\x4d\\x86\\xcc\\xcf\\x42\\xe6\\xe6\\xab\\x5c\\x68\\x77\\x5c\\xcc\\x14\\x98\\x83\\x0a\\x39\\x62\\x83\\xf1\\x80\\xa4\\x15\\xb3\\x09\\x4e\\xe8\\xa7\\xb3\\xed\\xac\\xd4\\x4c\\x69\\x96\\x83\\x25\\x57\\x96\\xbe\\xe9\\x9b\\x2e\\x21\\x46\\x11\\x02\\x25\\x2b\\x9a\\x65\\x33\\xc2\\xa6\\xdc\\x66\\xfb\\x9a\\xc1\\xc1\\x4d\\x08\\x35\\xe1\\xcd\\x4a\\x1a\\x99\\x08\\x5b\\xcf\\x4f\\x98\\xc7\\xe0\\x4d\\xa9\\x0a\\xdb\\x70\\xfb\\x85\\xb1\\xb7\\x8e\\x34\\xbe\\xb2\\x2b\\x19\\xac\\x14\\x56\\xb5\\x19\\x17\\x6d\\xe0\\xf0\\x5f\\x40\\xae\\x77\\x57\\x9b\\x4d\\xae\\x64\\x6b\\x4a\\xb6\\x05\\xf5\\x9a\\x17\\x4b\\xab\\x2c\\x33\\x88\\x81\\x56\\xd8\\xc5\\x05\\x2c\\xb1\\x8e\\x2e\\x49\\x64\\x43\\xc3\\x7b\\x1e\\x24\\xb4\\x61\\x13\\x73\\x59\\xc8\\x4c\\x8e\\x67\\x21\\xa4\\xb1\\x83\\x1c\\xcf\\x0b\\x67\\x1c\\x47\\xaf\\x1e\\xf3\\x0d\\x9a\\xdf\\xce\\x6d\\x4d\\x67\\xf9\\xeb\\x2c\\x7f\\x9d\\x6e\\xb3\\x70\\x75\\xba\\x8d\\xbf\\x3a\\xdd\\x66\\xc3\\xd5\\xe9\\x36\\x9d\\x6e\\xd3\\x59\\xfe\\x48\\xc7\\x1d\\xd7\\xc0\\xa4\\xe3\\x8e\\xa4\\xe3\\x8e\\x2b\\xd7\\xd5\\x71\\xc7\\xb5\\xe0\\xe9\\xb8\\x63\\xc7\\x1d\\x97\\x5d\\x85\\x4c\\xf7\\x08\\x74\\x2c\\x64\\xba\\x26\\xce\\x11\\xad\\x3e\\x89\\xec\\x67\\x32\\xc1\\xb6\\x13\\x98\\x98\\xea\\xec\\x7c\\x8a\\xe6\\x68\\x88\\xea\\x91\\x7f\\x48\\xc1\\x30\\x78\\xcd\\xec\\x0d\\x98\\x93\\xa0\\x0e\\x82\\x79\\xfc\\x48\\x1d\\xaf\\x0d\\x6c\\xea\\xe2\\x24\\xbb\\x38\\xc9\\x47\\x1f\\x27\\x39\\xa1\\x0a\\xf7\\x15\\x89\\xd2\\xea\\xb0\\xc9\\xe0\\x40\\xbe\\x67\\x65\\xfe\\x44\\xa3\\x26\\x0d\\xba\\xd8\\xed\\x86\\x14\\x9b\\x7a\\x4b\\x71\\xe5\\xa9\\xf5\\x17\\xb0\\xf4\\x32\\x5e\\xaf\\x95\\x97\\xb1\\x56\\x53\\x9a\\xb2\\x94\\x14\\xac\\xec\\x23\\x8a\\x48\\x32\\xe2\\xb6\\x98\\xd5\\x1c\\xf6\\x59\\xf8\\x3c\\x68\\xf4\\x63\\xbc\\x8e\\x07\\x0c\\x81\\x8c\\x27\\xb2\\x83\\xcd\\x35\\x34\\x1c\\x47\\x14\\xfe\\x51\\x04\\x44\\x6e\\x2b\\xd5\\xf7\\x89\\xb6\\x46\\xde\\xef\\x1a\\xca\\xf5\\xdb\\x8b\\xe6\\x8d\\x4a\\x9f\\x2e\\x5e\\x4b\\xeb\\x69\\xae\\xad\\x7d\\xda\\xf3\\x05\\x1e\\x12\\xaa\\x90\\x53\\x6c\\xab\\x5a\\x6e\\xa9\\x46\\xed\\xa6\\xa7\\xec\\x6e\\x89\\x26\\x0f\\x5e\\x2e\\x75\\xf1\\xda\\x55\\x74\\xdb\\x49\\x70\\x7b\\xfc\\x45\\x56\\x57\\x01\\x68\\x6b\\x05\\x9d\\xec\\xac\\xa4\\x93\\x9d\\x14\\x75\\xb2\\xab\\xb2\\x4e\\xf6\\x50\\xd8\\xc9\\x6e\\x4a\\x3b\\xb9\\x87\\x12\\xaf\\x8b\\xd7\\xce\\x2a\\x2a\\xd9\\x43\\x8f\\x27\\x4f\\xa2\\x30\\xec\\xe2\\xb5\\x17\\xb0\\x76\\xd3\\xe9\\x49\\x57\\x4e\\x76\\x8b\\x6b\\x77\\x95\\x9b\\xec\\xae\\x76\\x93\\xdd\\x31\\xa3\\x61\\x59\\xda\\xc5\\xab\\x2b\\x54\\xbb\\x17\\x67\\xdf\\x81\\x71\\x6d\\x5f\\xcc\\x76\\xd5\\xc7\\xb7\\xc2\\x12\\x5f\\x67\\xa8\\x7d\\x61\\x53\\xd7\\x9d\\x0d\\xc3\\x5e\\x9b\\x8e\\xc1\\x40\\xa8\\x45\\xc0\\x5c\\x7c\\xd4\\x08\\xe0\\x18\\xdc\\x4f\\x9d\\xf2\\x5b\\x89\\xa0\\x72\\x6b\\x30\\x98\\xaf\\xa0\\x3b\\x17\\xd2\\x64\\x37\\x5e\\x0a\\xa6\\x40\\xb0\\x63\\xde\\x44\\x14\\x36\\x57\\x34\\xcf\\x0e\\x30\\x1c\\xa4\\xe6\\x76\\x22\\x9d\\x0f\\x10\\xa9\\xdf\\x00\\x19\\x31\\x67\\x54\\x28\\x72\\xe0\\x6c\\x4f\\x87\\xaa\\x7e\\xe2\\x60\\x50\\x67\\xf7\\xf9\\x11\\x21\\x09\\x39\\xcc\\xe8\\x5b\\xdf\\xd4\\x7d\\xdd\\xce\\x76\\x92\\x76\\x27\\x69\\x77\\x92\\x76\\x27\\x69\\x2f\\xbd\\x3a\\x49\\x7b\\x8b\\xab\\x93\\xb4\\x3b\\x49\\x7b\\xdd\\x87\\x3b\\x49\\xbb\\x93\\xb4\\x37\\x7f\\x7c\\x37\\x49\\x7b\\xd7\\x38\\xa1\\x50\\xee\\xb5\\xce\\x39\\xac\\x9c\\x05\\xad\\xf9\\x7d\\x0c\\x91\\x2f\\x50\\x0a\\xff\\x6b\\x57\\xde\\x0e\\x65\\xe9\\xe5\\xd2\\x76\\x28\\x91\\x2f\\xe8\\x16\\x83\\x0d\\xa2\\xb5\\x17\\xbe\\x17\\xde\\x5c\\x2f\\x75\\x3f\\xae\\x58\\xa8\\x1d\\x70\\x23\\x70\\x28\\xec\\x88\\x1c\\xef\\x9d\\x2b\\xdc\\x56\\x9a\\x1b\\xb2\\xda\\x4f\\x9e\\x92\\x23\\xe7\\x71\\x81\\x0a\\xd1\\x42\\xea\\xf8\\x47\\xa1\\x79\\xbf\\x7e\\xc2\\xfb\\x60\\xc0\\xbd\\x18\\xe5\\xdb\\x64\\x71\\x7f\\x35\\x31\\x57\\x5b\\xb1\\xde\\x4f\\x43\\x42\\x58\\x19\\xcd\\x81\\xbb\\x46\\x7a\\x10\\x2d\\x51\\x56\\x42\\x98\\x51\\xa1\\x4a\\x36\\x78\\xe3\\x90\\xe6\\x60\\x01\\x38\\xdf\\xd9\\xdf\\x08\\x4b\\x30\\x1f\\x90\\x98\\x6a\\x28\\x05\\xfe\\x4e\\x6a\\xcb\\x48\\xdb\\x50\\x7e\\x29\\xac\\x47\\xd4\\xdc\\x71\\x5e\\x5f\\x87\\x94\\xb0\\x22\\xee\\xbf\\x3e\\x20\\x2f\\x01\\x0f\\xc3\\x81\\x6d\\xc9\\x69\\x9a\\x65\\xf2\\x76\\x1b\\x92\\x74\\x5f\\x69\\x51\\xb7\\x5b\\xa7\\x45\\xcd\\xf9\\xef\\xba\\xac\\xa8\\x5f\\x49\\x56\\x14\\xfc\\x88\\x47\\xa8\\xf5\\xf4\\x28\\xf2\\xe3\\x84\\x01\\x16\\x95\\x0c\\x40\\x95\\x57\\x99\\xe6\\x45\\x1d\\x2b\\xa5\\xf0\\x53\\x19\\x4a\\x99\\x23\\x1b\\x79\\x12\\xe3\\xa5\\xf9\\x1a\\x4d\\x26\\xf3\\xf8\\x09\\xe3\\x41\\x6c\\x95\\x82\\x43\\x6b\\xa3\\x3b\\x68\\x96\\xd9\\x9c\\x22\\x27\\x92\\x62\\x08\\x0b\\x7f\\xe8\\xc8\\x84\\x73\\x57\\x15\\xd1\\x69\\x33\\x40\\x64\\x8e\\x0c\\x2d\\xcc\\x66\\xb6\\x52\\xdd\\x1a\\x22\\x8a\\x4a\\xd1\\x94\\x39\\xd6\\x3b\\xe6\\x53\\x26\\x6a\\x4a\\x7a\\xa4\\x8e\\x8f\\x1d\\x0f\\x6f\\x95\\xc2\\xdf\\x09\\x85\\xfe\\x4b\\x40\\x49\\xff\\xda\\x84\\x46\\xc3\\x82\\x3c\\x95\\xae\\xc1\\x57\\xd3\\xe8\\x87\\x0c\\xc1\\xd8\\xc6\\xcf\\xbf\\x9d\\x8d\\x61\\x07\\xff\\xfe\\x3d\\xfa\\xf6\\x9f\\x4e\\x66\\xd9\\x03\\x5b\\x18\\x1f\\x22\\xb6\\xfe\\xd1\\x5b\\x15\\xbb\\xe0\\xfa\\xfa\\xda\\x37\\xb8\\xfe\\xce\\x2d\\x87\\x0f\\x1b\\x63\\xff\\x04\\xac\\x85\\x0f\\x19\\x63\\xdf\\x59\\x08\\xd7\\x6e\\xca\\x63\\x0b\\x7d\\x8f\\xaf\\x9d\\x2c\\x82\\x9d\\x35\\x70\\x67\\x2e\\xbc\\x25\\xc3\\xd9\\xd7\\x0a\\xb8\\x25\\x46\\xec\\xe8\\x67\\xef\\x7c\\xec\\xf7\\xe3\\x63\\xef\\x24\\xde\\x86\\x57\\x27\\xf1\\xae\\x04\\x4a\\x27\\xf1\\x92\\x4e\\xe2\\xdd\\xb4\\xbc\\x4e\\xe2\\x5d\\x0b\\x9e\\x4e\\xe2\\x5d\\xbb\\x29\\x9d\\xc4\\xdb\\x49\\xbc\\xe4\\xa9\\x49\\xbc\\xbb\\x54\\xe9\\xea\\x7c\\xdd\\x7b\\xf9\\xba\\xb7\\xa5\\x16\\x5b\\xd1\\x88\\x2d\\xf1\\x60\\x6b\\xdf\\x76\\xe7\\xd7\\x7e\\x2c\\x7e\\xed\\xc6\\x09\\xff\\x42\\xf3\\x7d\\x93\\xfe\\xc3\\xbd\\x5a\\x95\\xf9\\x4f\\xa7\\x92\\xa7\\xa4\\xa8\\xb4\\xcd\\xa7\\xee\\xb2\\xff\\xdb\\xc8\\xfe\\x8f\\x20\\xdf\\x95\\x00\\x68\\x54\\x02\\x60\\x15\\xcc\\xba\\x3a\\x00\\x5d\\x1d\\x80\\x96\\x9d\\xd0\\x5d\\x1d\\x80\\xae\\x0e\\x40\\x57\\x07\\xc0\\x5d\\x5d\\x76\\x12\\xe9\\xb2\\x93\\x1a\\x5d\\x5d\\x76\\xd2\\xea\\xab\\xcb\\x4e\\x7a\\xb4\\xd6\\x57\\xd2\\x65\\x27\\x3d\\x6e\\x4b\\x2c\\xe9\\xb2\\x93\\x3a\\xeb\\x6c\\xc3\\x8d\\x7a\\x82\\xd9\\x49\\x5d\\x1d\\x80\\xc7\\x1a\\xa3\\x40\\x3a\\x49\\xbb\\x93\\xb4\\x3b\\x49\\xbb\\x93\\xb4\\xd7\\x5f\\x9d\\xa4\\xbd\\xc5\\xd5\\x49\\xda\\x9d\\xa4\\xbd\\xee\\xc3\\x9d\\xa4\\xdd\\x49\\xda\\x9b\\x3f\\xde\\xd5\\x01\\x78\\x42\\xb1\\x11\\xa4\\xab\\x03\\xd0\\xc5\\x4b\\x74\\x75\\x00\\x7e\\xbd\\x75\\x00\\x22\\xdf\\xfd\\xc3\\x15\\x03\\xd8\\x7e\\x1a\\x5d\\x45\\x80\\xae\\x22\\x40\\x57\\x11\\xa0\\xab\\x08\\xe0\\xae\\xae\\x22\\x00\\x5e\\x8f\\xc9\\xd6\\xd8\\xe5\\x47\\xad\\x04\\x4a\\x97\\x1f\\x45\\xba\\xfc\\xa8\\x4d\\xcb\\x7b\\x02\\x76\\xc3\\x2e\\x3f\\xea\\x11\\xda\\x0a\\xbb\\xfc\\xa8\\xce\\x2e\\x38\\xbf\\x39\\x4f\\x24\\x3f\\xaa\\xab\\x08\\xf0\\x18\\xbd\\xed\\x9d\\xc4\\xdb\\xf0\\xea\\x24\\xde\\x95\\x40\\xe9\\x24\\x5e\\xd2\\x49\\xbc\\x9b\\x96\\xd7\\x49\\xbc\\x6b\\xc1\\xd3\\x49\\xbc\\x6b\\x37\\xa5\\x93\\x78\\x3b\\x89\\x97\\x3c\\x35\\x89\\xb7\\xab\\x08\\xd0\\x55\\x04\\xe8\\x2a\\x02\\x3c\\x45\\x0f\\xf7\\xc6\\x9d\\xa6\\x42\\x48\\x8d\\x32\\xcb\\xaa\\xbd\\x8d\\x65\\xf9\\xfa\\x79\\xcb\\xe3\\x2b\\xa1\\x74\\x59\\x25\\xba\\x2a\\x59\\x0a\\xc0\\x40\\x40\\x19\\xaa\\xad\\xb4\\x2c\\x9d\\xa3\\x1b\\x1c\\x85\\xe7\\xac\\xc8\\xe4\\xcc\\x10\\xcd\\x1e\\xb9\\x94\\x69\\x8f\\x9c\\x5e\\x5e\\x5c\\xb3\\x72\\xca\\x13\\xe6\\xf6\\xec\\x9d\\x25\\xcd\\x03\\xf2\\x7e\\x56\\xf0\\x84\\x66\\x19\\x48\\xfe\\xf5\\x57\\x73\\x3a\\x03\\xdf\\x21\\xd3\\xe6\\xd4\\xb2\\xcf\\x9a\\x95\\x82\\x66\\x44\\x4b\\x99\\x41\\xda\\x3c\\x7c\\x14\\x0e\\x67\\xc9\\x74\\xc9\\xd9\\x94\\x11\\x5a\\x0e\\xb9\\x2e\\x69\\x39\\x23\\x39\\xd3\\x34\\xa5\\x9a\\x0e\\xc8\\xf7\\x8a\\x85\\x64\\x41\\x4b\\x52\\x94\\xac\\x8f\\x78\\x10\\x7d\\x0f\\xf6\\xf1\\xdd\\xeb\\x37\\x0e\\x7f\\x69\\x9a\\x7a\\xc7\\xa7\\xdd\\xc5\\xeb\\x6a\\xe8\\x41\\x74\\x68\\x90\\xc9\\xad\\x52\\xf5\\x60\\x63\\xad\\xea\\x52\\x70\\x85\\x6b\\x5d\\xa9\\x9a\\x34\\xe0\\x0a\\xdb\\xf1\\x80\\x8d\\xfb\\xcf\\xc4\\xb4\\xd1\\xbe\\xbf\\x14\\xd3\\x58\\x4f\\x65\\x62\\xca\\x4b\\x29\\x80\\x03\\x4f\\x69\\xc9\\xe9\\x30\\x63\\x08\\x7f\\xa6\\xdd\\x5e\\x5a\\xfe\\xc9\\xca\\x01\\x39\\x03\\x90\\x9a\\x8d\\x43\\x4f\\xf6\\x4a\\xfc\\xdd\\x4c\\xf8\\x36\\x90\\xba\\xf9\\x69\\xff\\x40\\x63\\x51\\x5d\\x2c\\x9d\\x3a\\xb1\\x0f\\x98\\xa9\\x53\\x72\\xe6\\x27\\xbe\\x01\\xb2\\x1b\\x18\\x78\\x13\\xfd\\xb0\\x0f\\xc4\\x69\\xe5\\x03\\xcd\\xb4\\x38\\x33\\xc4\\x7a\\xda\\x1c\\x81\\xe5\\x2d\\xcd\\xeb\\x12\\x0f\\x4b\\xa0\\x31\\x20\\x6f\\xac\\x84\\x4c\\xc9\\xd9\\xff\\x5e\\x9c\\xbf\\x7c\\xfb\\xfe\\xe2\\xd5\\xc5\\xcb\\xab\\xf5\\x44\\xa7\\x21\\x5b\\x01\\xfa\\xb0\\xc5\\x64\\x0f\\x7f\\x70\\x7b\\x04\\x69\\xfe\\x4c\\x18\\x0e\\xfc\\xdb\\xa3\\x1f\\x4e\\xaf\\xfe\\xf7\\xed\\xe9\\x9b\\x97\\xc7\\x20\\x7e\\xb1\\xcf\\x05\\x15\\x29\\x4b\\x49\\xa5\\x1c\\x4b\\x28\\x4a\\x36\\xe5\\xb2\\x52\\xd9\\xcc\\x93\\xf7\\xe5\\x48\\x3b\\x8f\\xad\\xd6\\xd0\\x30\\x23\\xf6\\xb8\\x2e\\x7f\\x0d\\x34\\x10\\x5a\\x23\\x50\\xe2\\x31\\xbc\\x64\\x4a\\x66\\x53\\x96\\xa2\\xac\\xe9\\x27\\xed\\xbe\\xc3\\x45\\x51\\x69\\xa7\\x11\\x41\\x08\\x8a\\x39\\x15\\x22\\x99\\x50\\x31\\x66\\xe9\\x80\\x9c\\xcb\\xca\\x8c\\xf7\\xdb\\xdf\\xc2\\xc2\\x4a\\x96\\x56\\x09\\xca\\x3a\\xd4\\x09\\xcc\\xbf\\xed\\x39\\x4e\\x62\\x78\\x81\\xc2\\x32\\x1a\\x2a\\xa1\\x85\\x5b\\x7a\\x08\\x1d\\x35\\x13\\x9a\\x7e\\x7e\\x81\\x31\\x18\\x07\\xbf\\x0d\\x7e\\x3a\\x70\\x25\\x48\\xa4\\xf9\\x04\\xf2\\x23\\x9c\\x55\\x06\\xd5\\x2f\\x32\\x72\\x10\\x3e\\x3d\\x20\\x2f\\xcd\\x37\\x58\\x1a\\xee\\x03\\x86\\xd0\\xb0\\x29\\x2b\\x41\\x9f\\xb2\\xbb\\xd0\\x23\\x25\\x1b\\xd3\\x32\\xcd\\x98\\x82\\xe0\\x91\\xdb\\x09\\x83\\x72\\x2e\\x28\\x61\\x5b\\x80\\x31\\xaf\\xad\\x09\\xa9\\x07\\xe4\\x9c\\x8d\\x68\\x95\\x69\\xa0\\x21\\x07\\x07\\x83\\xc3\\xd6\\x50\\xed\\x55\\x29\\x37\\x14\\x3f\\x88\\xd0\\xed\\x1a\\x8b\\x8a\\x8c\\x64\\xb9\\xf2\\x78\\x1c\\x5a\\xd3\\x54\\x44\\xd6\\x94\\x91\\x24\\xac\\xa6\\xef\\x78\\x35\\xea\\x97\\x0d\\x56\\xd2\\x40\\x11\\x68\\x6e\\xce\\x49\\xa4\\x18\\xf1\\xf1\\x1b\\x5a\\x7c\\xc7\\x66\\x57\\x6c\\xb4\\x65\\x34\\x0c\\x0a\\x51\\xd6\\xa6\\x01\\x02\\x8c\\x21\\x87\\x38\\xe0\\x66\\xa1\\xe3\\x0e\\x63\\x39\\x9a\\x18\\xcd\\xb6\\xb3\\x79\\x35\\xb6\\x74\\x2d\\x94\\x34\\x41\\xa1\\xcf\\x8a\\x6f\\x2d\\x16\\x67\\xaa\\xaf\\xcd\\x14\\x7d\\xe9\\xe4\\x0e\\x43\\xd2\\x6e\\xcf\\xa9\\x1e\\x90\\x37\\x12\\x42\\xb2\\x46\\xf2\\x05\\x99\\x68\\x5d\\xa8\\x17\\x27\\x27\\x37\\xd5\\x90\\x95\\x82\\x69\\xa6\\x06\\x5c\\x9e\\xa4\\x32\\x51\\x27\\x89\\x14\\x09\\x2b\\xb4\\x3a\\x91\\x53\\x43\\xf9\\xd8\\xed\\xc9\\xad\\x2c\\x6f\\xb8\\x18\\xf7\\x8d\\x08\\xd7\\xc7\\x5d\\x55\\x27\\x20\\x4c\\x9f\\xfc\\x1b\\x6a\\x6c\\xef\\xdf\\x9d\\xbf\\x7b\\x41\\x4e\\xd3\\xd4\\x56\\x6c\\xaa\\x14\\x1b\\x55\\x99\\xad\\xde\\x32\\x30\\x42\\xcf\\x0f\\xac\\x34\\x4a\\x79\\x8f\\xdc\\x70\\x91\\xf6\\x48\\xc5\\xd3\\x6f\\xd6\\x1f\\xee\\x1d\\x21\\x26\\x0b\\x94\\x8b\\x76\\x80\\xda\\x35\\x28\\x0a\\xb3\\x88\\x4e\\x79\\xa4\\x37\\x14\\x8a\\x6b\\x05\\x7b\\xee\\x0c\\x47\\x96\\xa1\\x6c\\xb1\\x8c\\xa1\\x94\\x19\\xa3\\x62\\xc3\\x1b\\x00\\xb6\\xed\\xcf\\xec\\x61\\x7d\\x68\\x51\\x9c\\xb5\\x08\\x50\\xc8\\xf4\\x05\\x51\\x55\\x51\\xc8\\x52\\xab\\x5a\\xf8\\x35\\x3b\\xd7\\x8b\\xff\\x04\\xe5\\xa8\\x47\\x7e\\xf2\\x37\\x41\\xc3\\x51\\x1f\\x0e\\x0f\\xff\\xf2\\xdd\\xcb\\xff\\xfe\\xeb\\xe1\\xe1\\xa7\\x9f\\xc2\\x5f\\x03\\x01\\x39\\x7e\\xc4\\xa8\\x5c\\x03\\xa3\\xee\\xbc\\x85\\x6f\\xc0\\x9f\\x96\\x8d\\x9e\\x26\\x89\\xac\\x84\\xb6\\x3f\\x68\\xaa\\x2b\\x35\\x98\\x48\\xa5\\x2f\\x2e\\xfd\\x9f\\x85\\x4c\\xe7\\xff\\x52\\x1b\\x38\\x01\\xb9\\x5b\\xa2\\x03\\xe0\\xbc\\xa4\\x7a\\xd2\\x32\\xe9\\xa9\\xcf\\xc5\\x0e\\xe8\\x6a\\xdf\\x0c\\x2b\\x64\\xe5\\x14\\xfe\\xfb\\xca\\x4d\\xd7\\x70\\xa0\\xdb\\x92\\x6b\\xcd\\x04\\xc8\\x1d\\x10\\x77\\x29\\x47\\x3d\\x83\\xb9\\x35\\x9b\\x9d\\x3e\\xdf\\xca\\x1c\\xd1\\xf8\\x28\\x7a\\xa8\\xed\\xb0\\x38\\x98\\xbd\\x5d\\x99\\xd7\\xcd\\x90\\xd0\\x2e\\xea\\xf5\\xa7\\x97\\x17\\x64\\x8a\\xd0\\x68\\x7d\\x21\\x2e\\x0a\\xef\\xd5\\xde\\x67\\xd2\\x57\\x2a\\xb3\\xcb\\xf2\\x92\\xe6\\x0b\\xb4\\x2c\\xfa\\x78\\x3f\\x92\\xf1\\x9c\\x5b\\x07\\x80\\xad\\x6a\\xa6\\xc8\\x11\\xde\\x1c\\x24\\x45\\xd5\\xb3\\x0f\\x0c\\x72\\x96\\xcb\\x72\\xe6\\xff\\x64\\xc5\\x84\\xe5\\x46\\x62\\xeb\\x1b\\xed\\x97\\x8e\\x59\\xcf\\xbf\\x8e\\xaf\\xf9\\xbf\\xf0\\xc5\\xe8\\x03\\x8b\\x6f\\xa3\\x48\\x9d\\x54\\xa5\\x61\\x1e\\xd9\\xcc\\x51\\x10\\x96\\x3e\\xec\\x59\\x74\\x60\\x6a\\xf9\\x28\\xfa\\xdd\\x78\\xbb\\x23\\xcb\\xf5\\xda\\x22\\x32\\x6d\\xbf\\x2a\\x90\\x21\\xa7\\x32\\xab\\x72\\xa6\\x7a\\x9e\\x3d\\xa1\\xb4\\x2e\\xa6\\x46\\x9a\\x54\\x77\\xc2\\x08\\x53\\x3e\\xe5\\x6a\\xa7\\xf8\\x84\\x6b\\x6f\\xa9\\x05\\x13\\x69\\xa5\\x8d\\xa6\\x82\\xc9\\x00\\x41\\x45\\x40\\xa9\\x40\\x07\\xf0\\x31\\xaa\\x11\\x49\\x79\\x7e\\xd0\\xcc\\xfb\\x4e\\xb5\\x66\\xa5\\x78\\x41\\xfe\\xe7\\xe8\\xe3\\xef\\x7e\\xe9\\x1f\\x7f\\x73\\x74\\xf4\\xe1\\x59\\xff\\xcf\\x9f\\x7e\\x77\\xf4\\x71\\x00\\xff\\xf9\\xea\\xf8\\x9b\\xe3\\x5f\\xdc\\x1f\\xbf\\x3b\\x3e\\x3e\\x3a\\xfa\\xf0\\xdd\\x9b\\x6f\\xdf\\x5f\\xbe\\xfc\\xc4\\x8f\\x7f\\xf9\\x20\\xaa\\xfc\\x06\\xff\\xfa\\xe5\\xe8\\x03\\x7b\\xf9\\xa9\\xe1\\x20\\xc7\\xc7\\xdf\\xfc\\xb6\\xd1\\xf4\\xa8\\x98\\xbd\\x6b\\x70\\xe0\\xf1\\xea\\xef\\x90\\x61\\x51\\xbf\\xb5\\x85\\x83\\xe6\\x73\\xbf\\x16\\xda\\xfa\\x5c\\xe8\\xbe\\x2c\\xfb\\xf8\\xfa\\x0b\\xa2\\xcb\\x6a\\xf3\\xc1\\xa8\\x89\\xda\\x2e\\x78\\xee\\xca\\xc1\\xbd\\xa8\\x09\\x9a\\x27\\xcd\\xad\\x23\\xb2\\x62\\x49\\xc9\\x74\\x5b\\x1a\\x0c\\x8e\\xe6\\xf8\\xc7\\x9c\\x49\\xbe\\x53\\x6a\\x6a\\xa5\\xc6\\xdb\\xa5\\x01\\x5e\\x35\\xe7\\x1d\\x95\\x32\\x1f\\x90\\xc0\\x2c\\x34\\x05\\x4f\\xb6\\x7d\\xee\\x86\\x6d\\xd0\\x72\\xdd\\xd5\\x29\\x41\\x4f\\x4b\\x09\\xba\\xc6\\xfd\\xbd\\x73\\x0d\\x88\\x89\\xe9\\x3a\\x33\\xcd\\xbc\\x4d\\xf7\\x15\\xa4\\x32\\x85\\xe6\\x68\\x27\\x40\\x69\\x49\\x0a\\x59\\x54\\x19\\xd5\\x2b\\xcc\\x76\\x4b\\x6c\\xd3\\x16\\xf7\\x6b\\x2f\\x90\\xd9\\x68\\xb0\\x03\\x5b\\x2a\\x97\\x2f\\x37\\x86\\x92\\xd3\\x2c\\x23\\x5c\\xe0\\x49\\x80\\x01\\x9c\\x35\\xaf\\x64\\x28\\x2f\\x11\\x8a\\x06\\xe7\\xa9\\x99\\xc2\\xad\\x4d\\xb8\\x0a\\x0c\\x8d\\x5c\\x19\\x5d\\xa7\\xd4\\xe0\\xf1\\x81\\x84\\x2c\\xa4\\x59\\xd6\\x34\\xc6\\x45\\x9d\\x96\\xe5\\xb9\\xad\\xf7\\x52\\x2f\\xad\\xbf\\x99\\x51\\xa5\\xdd\\xb4\\x61\\x36\\x9a\\xde\\x80\\x29\\x34\\x61\\x29\\x13\\x09\\x83\\x10\\x94\\x8a\\xd5\\x6b\\x1d\\x1a\\x61\\x10\\xcc\\xfb\\x30\\x06\\x25\\x69\\x55\\x64\\x3c\\x31\\xf0\\x33\\x33\\x59\\x3e\\xc6\\x45\\x9e\\x57\\x1a\\x0c\\xc5\\xf7\\x65\\xc5\\x37\\x3b\\x7e\\xed\\xca\\xfd\\x7a\\x63\\x3e\\x90\\x2a\\x2f\\x5a\\xfb\\x68\\x1b\\xaf\\xba\\xab\\xfd\\xcc\\xf7\\xcd\\x08\\xaf\\x37\\xb7\\x6d\\xe4\\x54\\x0b\\x14\\xb7\\xb6\\x31\\xc4\\x94\\xf6\\xbe\\x2d\\x86\\xcd\\xe8\\xec\\x17\\x49\\x63\\xb7\\xa0\\xaf\\xcd\\x69\\xeb\\x16\\xc6\\xa5\\x6d\\xe9\\x69\\x53\\x6b\\x52\\x51\\xb2\\x11\\xff\\xbc\\x05\\x3e\\x9e\\x8a\\x5a\\x45\\xe1\\x29\\x13\\xda\\x28\\x02\\xa5\\x75\\x8c\\x16\\x4c\\xd4\\x5e\\x4f\\x08\\xf0\\x13\\xf1\\x3a\\xee\\xd4\\x63\\x84\\x52\\xc6\\xf6\\xc7\\xeb\\x7a\\x99\\x14\\xd3\\x9d\\xad\\x2f\\xfc\\x6c\\xd9\\x5d\\x6f\\xff\\x60\\x09\\x99\\x6e\\x0c\\xfe\\x9f\\xdb\\xc7\\xe0\\x8d\\xb9\\x48\\x67\\x5b\\xfe\\xdd\\x4e\\xd2\\x68\\x6f\\xde\\xe5\\x54\\xc8\\x14\\x6b\\x9c\\xeb\\x3a\\x08\\x65\\x40\\xae\\x97\\xbc\\x09\\xb1\\x26\\xf6\\x89\\xc3\\x43\\x85\\x61\\x29\\x6a\\x7e\\xa0\\xb9\\xec\\x76\\x8c\\x68\\xc0\\x41\\xb7\\x44\\x29\\x64\\x75\\x55\\x09\\x96\\xdf\\x13\\xaa\\x14\\x1f\\x8b\\x7e\\x21\\x53\\xa8\\xcb\\x7e\\xb2\\x0a\\x21\\xee\\x3f\\xaa\\xc1\\x1b\\x27\\x9a\\x6d\\xd3\\x95\\xb7\\xbf\\x05\\xb2\\x85\\xeb\\x08\\x50\\x06\\x3f\\x5a\\xbb\\x8e\\xcb\\xa3\\x08\\x64\\xc8\\x5a\\x22\\xda\\x0f\\xa6\\x39\\x15\\x74\\xcc\\xfa\\xf6\\xe3\\x7d\\xff\\xf1\\xbe\\xff\\xd6\\x3e\\x60\\x6e\\x42\\xb5\\x92\\x8c\\xf2\\xf5\\xa1\\x64\\x11\\xf0\\x0e\\xce\\xe0\\x79\\x5b\\x28\\xc0\\x47\\xe0\\xcd\\xa5\\x31\\x3b\\x69\\x93\\x0b\\x74\\x09\\xb8\\x9f\\xf0\\xe5\\x1e\\xa2\\x24\\x2d\\xad\\x1b\\x75\\x09\\x7c\\x3f\\x0a\\x0c\\x24\\xb3\\x71\\xc5\\x59\\x31\\xa1\\x41\\x40\\x9f\\xdd\\x19\\x45\\x98\\xa0\\xc3\\xcc\\x79\\xc1\\xcf\\x67\\x82\\xe6\\x3c\\x71\\xbb\\x7b\\x9a\\x41\\xc0\\x17\\x97\\x82\\x8c\\x18\\xd5\\x55\\xc9\\xc8\\x98\\x6a\\x56\\x8f\\xed\\x23\\x45\\x79\\xbd\\x99\\x17\\x9a\\x24\\x54\\xa0\\x99\\xd6\\x46\\x1d\\x99\\xd3\\xe5\\x67\\xa6\\x06\\xeb\\xec\\x5d\\xcd\\xa2\\xf8\\x1a\\xc4\\xee\\xcd\\x95\\xe5\\x0f\\x80\\x17\\x3a\\xe3\\xa5\\x30\\x4a\\x8f\\x2e\\x81\\x3d\\x5f\\xca\\xd4\\x50\\xc7\\x41\\xf4\\xf4\\x86\\xa4\\x88\\xc6\\xec\\xaf\\xa9\\x91\\x63\\x43\\x70\\x0b\\xb9\\x6b\\x4e\\x0a\\x8c\\x34\\x20\\x95\\x0e\\x3f\\x0d\\x7a\\x46\\xd0\\x2a\\x64\\x3a\\x58\\x82\\x99\\x8e\\x09\\x5f\\xca\\xd4\\xc6\\x0d\\xea\\x08\\x53\\x0c\\xba\\x02\\x92\\xe4\\xf4\\xc6\\xc5\\xfc\\x79\\xe3\\x18\\x9d\\x52\\x9e\\x41\\xa8\\x03\\x17\\x8a\\xa7\\x46\\x34\\x4a\\x36\\x07\\x16\\xb9\\xab\\x21\\xf3\\x8c\\x6c\\x82\\xe6\\x10\\xf6\\x73\\x5a\\xf4\\x8d\\x36\\xba\\x1e\\x54\\x1b\\x77\\x66\\x71\\x60\\x9c\\x51\\x4e\\x8b\\x95\\x6f\\xa1\\x3b\\xa2\\x31\\xed\\x38\\x7c\\x8d\\xee\\x8e\\xd4\\xb7\\x16\\xc2\\xd8\\xef\\xcf\\x3c\\xaf\\x72\\x42\\x73\\x59\\x61\\x78\\xf7\\x22\\x29\\x76\\x41\\x90\\xad\\x10\\xdb\\x25\\x44\\x56\\xad\\xa4\\xb2\\xa4\\xf9\\x31\\xd9\\x3e\\x5c\\xfb\\x91\\x5a\\xc5\\x1b\\x59\\xc3\\xb7\\xb3\\x82\\x6f\\x61\\xfd\\xde\\xd9\\xea\\xed\\x1c\\x5c\\xcd\\xf1\\xf1\\xca\\xf9\\xdc\\xe6\\x30\\x92\\x8b\\x8d\\x18\\x59\\xfa\\x5e\\x29\\x17\\x23\\xe2\\xc7\\xe1\\x8a\\xc8\\x9c\\x6b\\x6d\\x9d\\x41\\x01\\x01\\xe8\\x11\\xae\\x23\\xcf\\x89\\x3d\\x0b\\xd0\\x2b\\x08\\xdb\\x2b\\xb1\\xcf\\x45\\xc6\\x13\\x0e\\x1e\\x38\\xe7\\xf1\\xec\\xa1\\x84\\x7e\\xcb\\xb1\\xb2\\x10\\x15\\x84\\xe7\\x05\\x26\\x42\\x00\\x4e\\xf7\\x1d\\xa7\\xb5\\x01\\x4a\\x7e\\x26\\x36\\x3c\\x8d\\x7d\\x4e\\x18\\x4b\\xed\\xc7\\xba\\xe3\\xd3\\x1d\\x9f\\xe5\\xc7\\x47\\x6d\\xa3\\xe6\\x84\\x1a\\x4e\\x1d\\x1c\\xef\\x35\\x1d\\x83\\xf8\\xae\\xa7\\x19\\x04\\xff\\x23\\x0e\\x99\\xa3\\x02\\xf9\\x59\\x46\\x5c\\xbb\\x62\\x60\\x74\\xbc\\x66\\x5a\\xd9\\x70\\x7b\\x78\\xc3\\x48\\x84\\x0b\\xd9\\xcb\\xce\\xc8\\xea\\xb3\\x38\\xe8\\x68\\x14\\x3f\\x51\\x07\\x60\\x23\\x6f\\x8e\\xf9\\x3f\\x68\\x45\\x2c\\x2f\\x32\\xaa\\x99\\xd7\\x99\\xf6\\x88\\xc8\\x6e\\x22\\xc0\\x6c\\x93\\x3a\\xfc\\xb0\\xc9\\xc2\\x77\\x23\\xb2\\x3e\\xca\\x14\\xe0\\x3b\\x90\\x76\\x37\\xbb\\xf3\\x1a\\xa6\\xf2\\x36\\x97\\x8a\\x1b\\xf9\\xfb\\xee\\x3a\\x41\\x77\\x2b\\x4b\\x4f\\xd3\\x24\\xdc\\xc7\\x9f\\x76\\xbb\\xc5\\xb2\\x9b\\xa6\\xd6\\x76\\xc9\\xb4\\xeb\\x40\\xdd\\x2c\\x21\\xae\\x71\\x32\\x5c\\xa3\\xfd\\x6b\\x98\\x14\\xdb\\xa5\\xc1\\x6e\\xc1\\x5f\\xee\\x40\\xf8\\xdb\\xb8\\x97\\x5a\\x66\\xac\\xdc\\x22\\xd5\\xed\\x7d\\xfd\\xbc\\x6f\\xad\\x89\\x91\\x23\\xc1\\x48\\xf7\\xe3\\x00\\x7d\\xef\\xc4\\x16\\x73\\xb6\\xea\\x79\\x01\\x6a\\x69\\x4d\\xa1\\x8f\\xa6\\x96\\x6e\\x5e\\x66\\xe3\\xc4\\x8c\\x98\\x3d\\xd3\\xb6\\xa9\\x6a\\xd0\\x65\\x54\\x97\\xe0\\x4f\\xfe\\x8b\\xc7\\xb6\\x1e\\x03\\xf9\\xe9\\xaf\\x41\\xea\\x8c\\x4f\\xad\\xf4\\x18\\xf2\\x17\\xf7\\xbf\\xbf\\xee\\x99\\x12\\xd5\\x8c\\xb1\\xe1\\x94\\xb6\\x10\\x30\\x5e\\xc2\\x0b\\x84\\x8b\\x14\\x7c\\xd7\\x76\\xa9\\x00\\x01\\x1c\\xcb\\xc0\\x07\\x96\\xe5\\x52\\x2b\\x31\\x47\\xd7\\x5a\\xd0\\xc1\\xc9\\x5d\\x3f\\xac\\xac\\x37\\x3e\\x50\\xbb\\xac\\xc5\\xa1\\x3e\\x19\\x8c\\xbc\\x95\\xb6\\xde\\x2d\\xeb\\x91\\x4b\\x30\\xc3\\xd5\\x77\\xe0\\x24\\xbd\\x95\\x58\\xf9\\x76\\xa5\\x9b\\x3c\\x84\\xdb\\x46\\x2e\\xb2\\x91\\xd1\\x47\\x00\\xf9\\xae\\x66\\xf2\\xb8\\xb2\\x88\\xc9\\xd7\\x18\\x1c\\x25\\x59\\xaf\\x83\\xcc\\x0d\\x9b\\xd5\\xcc\\xc6\\x8a\\x10\\x40\\xf2\\x7b\\x35\\x96\\x38\\x56\\x80\\xbc\\xe3\\xff\\x38\\x2b\\x6e\\x3e\\xe4\\x02\\x3f\\x86\\x43\\xbb\\xad\\x80\\xd1\\x1d\\x40\\x8d\\x64\\x97\\x65\\xf8\\x99\\x36\\xc0\\xd5\\x4c\\xce\\x88\\x60\\xf6\\x6e\\x0b\\x19\\xc3\\x53\\xc9\\xe5\\xd2\\x45\\x20\\x52\\xbc\\xfc\\xb9\\xa2\\x59\\x9c\\xdf\\x64\\x6f\\xd9\\x87\\x16\\xa8\\xfa\\x2d\\xcf\\xd2\\x84\\xfe\\xff\\xec\\x7d\\xeb\\x73\\x1b\\x39\\x76\\xef\\xf7\\xfc\\x15\\x28\\xed\\x07\\x49\\x29\\x92\\xb6\\xf7\\x4e\\x66\\xb6\\x7c\\x53\\x5b\\x25\\x4b\\xf6\\xac\\xb2\\xb6\\x47\\xb1\\xec\\x99\\xca\\x4d\\x52\\x59\\xb0\\x1b\\x24\\xb1\\x6a\\x02\\x9c\\x06\\x5a\\x32\\x93\\xca\\xff\\x7e\\x0b\\xe7\\x1c\\xbc\\x9a\\xa4\\xd8\\x4d\\x51\\x0f\\xcf\\x88\\x1f\\x66\\x2c\\xb2\\x81\\xc6\\xf3\\xbc\\xcf\\xef\\xd4\\x14\\x40\\x0a\\x77\\x94\\x19\\x4d\\x46\\x72\\x20\\x04\\x05\\x57\\xe1\\xb6\\xc7\\x3d\\xc2\\x12\\xbb\\x6c\\xc1\\x6b\\x2b\\x8b\\xa6\\xe2\\x35\\x73\\x77\\x61\\xaa\\xeb\\x4e\\x39\\x48\\x5b\\x57\\x34\\x1e\\x9a\\x4b\\x51\\x68\\x55\\xf6\\x51\\x00\\x3e\\xb7\\xdb\\xb6\\xc3\\x38\\x16\\xa2\\x96\\x84\\x24\\x2b\\xe7\\xa2\\x7d\\x48\\x8f\\x72\\x77\\x99\\x9e\\xf8\\x5b\\x1d\\xae\\x58\\x66\\x18\\xc9\\xad\\xf9\\x08\\x45\\x7d\\x9c\\x90\\xc7\\x70\\x2b\\x46\\xec\\xcd\\xd2\\x5b\\x61\\xc0\\x22\\x43\\x89\\x5b\\x46\\x58\\x9f\\x63\\xe7\\x8f\\x2c\\x2d\\x76\\xbc\\x50\\x13\\x5d\\x43\\xde\\xdb\\x51\\xa9\\x31\\xd9\\xeb\\x5a\\x16\\xf6\\x78\\xc4\\xfe\\x9f\\xa8\\x35\\x82\\x03\\x88\\x29\\x02\\x03\\xd3\\x11\\x0f\\x8a\\x2b\\xd4\\xc4\\x86\\xe0\\xa0\\x97\\xec\\x08\\x41\\x9a\\xe5\\x7c\\x2e\\x4a\\xc9\\xad\\xa8\\x96\\xc7\\xa8\\xc7\\x7a\\x98\\xe7\\x2e\\x5b\\xd7\\xc5\\x68\\x90\\x60\\x7a\\x7f\\xff\\xdd\\x2d\\x4f\\xf6\\x4d\\xcf\\xfc\\xd9\\x27\\xbc\\xc5\\x95\\xc1\\xf0\\xa4\\xd6\\x16\\x06\\x1e\\xa4\\x6f\\x11\\x37\\xd3\\xf0\\xa6\\x88\\x17\\xe0\\xc9\\x4c\\xd8\\xe0\\xbf\\xbb\\x73\\xc0\\x59\\x2d\\xa6\\x70\\xca\\xf1\\xe4\\xde\\xf1\\x8c\\x63\\xa0\\xf6\\x07\\xdd\\xa8\\xcd\\x16\\xc3\\x6c\\xe2\\xef\\x49\\x09\\xff\\x39\\x69\\xb8\\x31\\x01\\xfa\\x41\\xc4\\x84\\x64\\x24\\x89\\x05\\x93\\x33\\x30\\x5b\\x02\\x3b\\x77\\xe4\\x01\\x9f\\x8a\\x41\\x6e\\x1d\\x7c\\x12\\x7b\\x4c\\x76\\x86\\xb1\\x6c\\x49\\xa8\\xd9\\x4b\\x4a\\x74\\x78\\x51\\x8f\\xb3\\x0c\\xb9\\x27\\xb4\\x30\\xad\\x94\\x60\\x4b\\xe4\\x00\\xce\\x27\\xae\\x60\\x3c\\xa0\\xf0\\x2e\\x51\\xfa\\x00\\x59\\x84\\xb1\\x80\\xa6\\xec\\xf0\\xf5\\xe1\\x5e\\x88\\x2f\\x4e\\xa7\\xd6\\x0b\\x3e\\xe5\\xdb\\xa1\\xf4\\x73\\x65\\xa4\\xd5\\x94\\x95\\xc2\\x8a\\x7a\\x0e\\x98\\xe7\\x33\\x7d\\x83\\xbf\\x23\\xdb\\x5a\\xd0\\x53\\x82\\xe0\\xe2\\xdd\\x6c\\x67\\xda\\x00\\x57\\xca\\xf3\\xa3\\xe1\\xfe\\x42\\xcc\\xc5\\x0d\\x5f\\x32\\x5e\\xeb\\x46\\x95\\x24\\x35\\x05\\x02\\xfa\\xa1\\xf5\\xe2\\x8f\\x5a\\x89\\xe8\\x35\\xcb\\x7d\\xae\\x63\\x61\\xb9\\xbb\\x36\\xaf\\x46\\xaf\\xb6\\x94\\x35\\xe8\\xb8\\x60\\x3d\\x53\\xe2\\x61\\x34\\x2d\\x4b\\xa1\\x0f\\xc3\\xf1\\x77\\x66\\x2f\\xe3\\xaa\\x05\\x2f\\x7f\\x52\\x55\\x1f\\x59\\xee\\x03\\x1e\\x2f\\x68\\x3a\\x04\\x25\\x4c\\x4e\\xc0\\x76\\x3b\\xc0\\xaf\\x6e\\x6a\\x69\\x45\\x42\\x1e\\x8f\\x26\\xbc\\x32\\xc2\\xa9\\xee\\x8d\\x0a\\x22\\xec\\x71\\x2e\\x82\\xc0\\x23\\x5d\\x26\\xb4\\x3d\\xd4\\xcc\\x34\\xe3\\x3b\\xde\\x33\\xba\\x50\\x70\\xe4\\xe2\\x35\\x0b\\x07\\xee\\xd0\\xdc\\x72\\xe5\\xf2\\xbc\\x71\\x76\\x84\\x4f\\x3a\\x89\\x4d\\x6b\\x7b\\xbc\\x9f\\xf8\\x33\\x9c\\xa0\\xd3\\xac\\xfb\\xa8\\x24\\x1e\\x92\\x60\\xb1\\xc7\\xd9\\xbe\\x11\\x33\\x7e\\x2d\\x0c\\x33\\x72\\x2e\\x2b\\x5e\\x57\\x90\\x86\\x7c\\x89\\xe3\\x63\\xe3\\xc6\\xae\\x07\\xb7\\xe8\\x07\\x9c\\x90\\x8e\\x24\\xe9\\x6e\\xeb\\x52\\xfb\\x71\\xb8\\x75\\x02\\x1a\\xe1\\xc7\\x85\\xf5\\x25\\x7c\\x51\\x8a\\xaf\\x45\\xd5\\x18\\x79\\x7d\\xd7\\xdb\\x44\\x89\\x55\\x3b\\xb0\\xea\\x36\\x97\\x5e\\x50\\xa4\\xc4\\x03\\xf2\\xe8\\x5c\\xc3\\x70\\xa4\\xaa\\xf4\\x9b\\x0e\\x3c\\x19\\x95\\x7d\\xd0\\xdc\\x21\\xee\\x84\\x17\\x85\\x30\\xc6\\x87\\x6b\\x2f\\xd3\\x10\\xf2\\x30\\x87\\x6f\\x05\\xab\\x84\\xdf\\x98\\xb7\\x15\\x37\\x56\\x16\\x6f\\x2a\\x5d\\x5c\\x5d\\x5a\\x5d\\xf7\\x82\\x03\\x59\\xd7\\xbe\\x85\\xf0\\x72\\xf2\\xcb\\x25\\x3b\\x93\\xe6\\x2a\\x49\\x54\\x22\\x9f\\x6a\\x6a\\x2e\\xe1\\xec\\xaa\\x19\\x8b\\x4a\\xd8\\xc3\\x43\\x83\\x5c\\x6e\\xce\\x8b\\x19\\xe2\\xff\\x00\\x83\\x53\\x21\\xdb\\x8d\\x14\\x3e\\xb7\\xca\\x7d\\x7d\\xa6\\x94\\x53\\xf9\\x82\\xce\\xeb\\x1f\\xf8\\x8d\\x11\\x38\\xfc\\xb1\\x1b\\x3e\\xc0\\x15\\x75\\x01\\xbb\\xd8\\xab\\x9f\\x02\\x07\\x73\\x7e\\xb6\\x27\\x1f\\xc4\\xc4\\x7c\\x76\\x63\\xec\\x67\\xdc\\x3e\\xc4\\x56\\x5e\\x75\\x98\\xc8\\x4a\\x50\\x61\\x1b\\x37\\x61\\x1f\\x79\\x43\\xb7\\x02\\xf6\\x6f\\xa9\\x1b\\x76\\xc3\\x51\\x47\\x06\\x8a\\x38\\x62\\x9f\\xe5\\xe2\\x35\\x7b\\xab\\x4c\\x53\\x8b\\x68\\xdd\\x68\\x77\\x25\\x4d\\x4c\\x61\\xf5\\xca\\x15\\xec\\x37\\x2a\\x20\\x8e\\xee\\x91\\xae\\xc5\\xde\\x7e\\xe5\\xf3\\x45\\x25\\xcc\\x6b\\x76\\x20\\xbe\\xda\\xef\\x0e\\x06\\xec\\xe0\\xeb\\xc4\\xb8\\xff\\x29\\x3b\\x31\\x07\\x23\\x76\\x3e\\x0f\\x4e\\x79\\xa9\\x26\\xa2\\xae\\x85\\x8f\\xb1\\xc4\\x06\\x8e\\x35\\x27\\x5c\\xf7\\x5e\\x8e\\x0b\\xc5\\xeb\\x3a\\xd9\\xad\\xd4\\xec\\x06\\xa1\\x6e\\x1c\\xc1\\x17\\x75\\xad\\xeb\\x90\\xe2\\x92\\x2c\\x03\\xf0\\x9a\\x42\\xcf\\x17\\xb5\\x9e\\xcb\\xc4\\xcc\\x07\\xc7\\x7d\\xaf\\x81\\xbc\\x60\\x7c\\xe8\\x52\\xeb\\xa9\\x7d\\x1a\\x42\\x43\\x7f\\x20\\x92\\x2f\\x54\\x97\\xa3\\x70\\x3e\\xf1\\xb1\\x16\\xa8\\x45\\x92\\x5a\\x0f\\xdd\\xd1\\x43\\x6e\\xf3\\xa9\\x17\\x47\\xc8\\xd2\\xed\\x7e\\x17\\x72\\x75\\xd9\\x8b\\x52\\x5c\\xbf\\x30\\x25\\x7f\\x35\\x80\\xd7\\x18\\x8a\\x31\\xce\\xc7\\xc4\\x0d\\x3b\\x78\\x75\\x30\\x62\\x97\\x9e\\x11\\x0f\\xd2\\x31\\xc6\\xe7\\x26\\xba\\x0e\\x1d\\x82\\x9d\\xfd\\xe5\\x01\\x3b\\xd2\\x35\\xf4\\x5c\\x70\\xc5\\x2a\\xc1\\xaf\\xc9\\xb6\\x8c\\xd7\\x6d\\x89\\xea\\xee\\x71\\xe7\\x5c\\xeb\\xae\\x69\\xa7\\xdd\\x8b\\x7a\\x75\\x15\\x52\\x57\\x37\\xd1\\xb7\\xf3\\x26\\x80\\xba\\xa1\\x34\\xa4\\x89\\xae\\x09\\x62\\x28\\x3c\\x62\\x84\\x85\\xab\\x27\\x55\\xa6\\x42\\x3f\\x02\\x81\\x65\\x3d\\x51\\x3a\\x3c\\xf5\\xec\\xbb\\x3a\\xbe\\x1d\\xe8\\x40\\x4a\\xfe\\xda\\x08\\x76\\x7e\\x16\\xb0\\x3a\\x44\\x6d\\xa4\\xb1\\xee\\x1a\\x97\\x19\\xeb\\x92\\xc8\\xcf\\x8e\\x4e\\xe6\\xfc\\xbf\\xb5\\x62\\x6f\\xdf\\x5c\\xd2\\x00\\x8e\\x1f\\x75\\xa9\\xb6\\x52\\x03\\xfe\\xdf\\x4d\\x2d\\x1c\\x17\\xee\\xc1\\xdc\\x43\\x9b\\x36\\x43\\x77\\xdf\\xb3\\x33\\x6e\\x39\\xf2\\x75\\x0a\\xc4\\x52\\x91\\x94\\x3b\\x96\\x3d\\x96\\xaa\\xa4\\x9f\\x12\\x86\\xfd\\xd0\\xbc\\xd5\\xed\\xde\\xc7\\x6d\\x51\\xaf\\xfe\\xc1\\x2f\\x9f\\xce\\xf7\\xc4\\x83\\x0b\\x20\\xe6\\xd3\\x0f\\xba\\xec\\xcd\\x88\\x93\\xa6\\x9e\\xf8\\xfe\\xc5\\xad\\xe9\\x29\\x7e\\xcf\\xe6\\xae\\x4f\\xe6\\xb4\\xf7\\x01\\xfb\\x24\\x78\\xc9\\xdc\\xfd\\xa5\\x7f\\xfe\\xe2\\x74\\xcf\\xce\\xb4\\xaa\\x13\\x0b\\xf1\\x0b\\xd8\\x73\\x1a\\xbe\\x99\\x9f\\x42\\x9a\\x44\\x53\\xba\\x93\\x03\\xd7\\x8a\\x78\\xc9\\xb8\\xd2\\x63\\x46\\xd7\\x61\\xdf\\x63\\xff\\xf2\\xe9\\x7c\\x87\\xa1\\x7f\\xf9\\x74\\xee\\x47\\xee\\xfe\\xa9\\x27\\x0f\\x37\\xe8\\x9d\\xc4\\xb7\\x28\\xbd\\xbd\\x6b\\x89\\x5b\\x91\\x25\\xc7\\x9c\\xb0\\xb6\\x48\\xd6\\x5d\\x1e\\x1b\\xed\\x4b\\x12\\xdb\\xe7\\x8a\\x5d\\x49\\xd5\\x21\\xc1\\x3f\\xbf\\x65\\xae\\x8d\\x53\\x28\\x30\\x56\\x2d\\xf1\\x23\\x5e\\xce\\x38\\xa0\\x2a\\x84\\x5c\\x5f\\xd8\\x67\\xb7\\xf1\\xc6\\x71\\x05\\xbf\\xe3\\x4e\\x09\\x04\\xda\\xc6\\xce\\x04\\x7a\\x39\\xcb\\xd7\\x3e\\x76\\x20\\xb4\\x58\\xdf\\xe0\\x03\\x44\\x6a\\x96\\x44\\x5f\\x19\\x06\\x6e\\x96\\xc9\\x01\\x3b\\x42\\xab\\x92\\x0a\\x3f\\x51\\xec\\xba\\xac\\x24\\x54\\xe9\\x70\\xda\\x7d\\x1a\\xac\\x6a\\x60\\xc8\\x7b\\xbd\\xf5\\x3b\\x8a\\x1c\\x41\\x9c\\x58\\x31\\x6e\\xb1\\x23\\xf7\\xdb\\x0b\\x30\\x8e\\x1d\\x8f\\x80\\x5a\\xc1\\x83\\x10\\xc6\\xdf\\x12\\x4a\\x3e\\x6d\\x13\\x4a\\xf6\\x26\\x3f\\xc0\\x0e\\xb8\\x1b\\xd3\\x97\\x2b\\xba\\x36\\x6b\\xb9\\x22\\xfc\\xe0\\x51\\x74\\x9f\\x32\\x63\\xc4\\x34\\xce\\x4e\\xac\\x11\\xce\\xd7\\xd6\\x27\\xbb\\x33\\xc7\\xbb\\x1e\\xae\\xf2\\xdb\\x38\\x5c\\x2c\\x24\\xcb\\xee\\xc0\\x3f\\x63\\x43\\xcf\\x87\\x42\\xaa\\x8c\\x87\\x03\\xc9\\x42\\x33\\xf1\\xf4\\x5d\\x12\\xad\\x21\\x74\\x37\\xe4\\xba\\xee\\xcc\\x75\\x29\\xb9\\xd9\\x07\\x0f\\xc6\\x9f\\x88\\xbe\\xb3\\xf2\\xed\\xfc\\xa4\\x90\\x04\\xc2\\xd7\\xac\\xc3\\x59\\xec\\x3c\\xc8\\x42\\x2c\\x66\\x93\\x3e\\x2e\\x71\\xd7\\xe0\\xdd\\x65\\x6e\\x09\\x3c\\x15\\x8b\\x19\\x7b\\x77\\xb9\\xe6\\x1a\\xc3\\xda\\xc3\\xa8\\x0d\\xda\\x07\\x0f\\x0d\\xab\\xe4\\x44\\x58\\xb9\\x65\\x0a\\xf7\\x70\\x91\\xe7\\x5a\\x49\\xab\\xeb\\xcd\\xe8\\x0a\\xac\\xd7\\xe5\\xf4\\xdd\\xf5\\x65\\xa8\\xbe\\x9d\\xdb\\xd9\\x88\\x4d\\xf4\\x21\\xf9\\x96\\xb3\\x42\\x57\\x95\\x28\\x2c\\xa1\\xe5\\xc1\\xf2\\x86\\x66\\x6b\\x94\\x27\\x41\\xf6\\x80\\xd1\\xd5\\x9f\\x40\\x7d\\x22\\x45\\xe9\\x05\\x6e\\xee\\x8b\\x4f\\x6f\\x4f\\xce\\x3e\\xbc\\x1d\\xcd\\xcb\\x3f\\xcc\\xf4\\xcd\\xd0\\xea\\x61\\x63\\xc4\\x50\\x76\\x00\\x3f\\x7a\\xbc\\xe8\\x45\\xfc\\x2c\\x3a\\x61\\xf1\\xb5\\x0d\\x32\\x08\\x23\\xf8\\x93\\x4f\\xcd\\x66\\x5f\\x0c\\x46\\x2d\\x80\\xed\\xc8\\xfb\\xa4\\xb4\\xb6\\x03\\x56\\x73\\x4a\\xbf\\xe6\\x64\\x7a\\x6a\\xaa\\x0a\\x57\\xdb\\xd6\\x42\\x0c\\x52\\x5b\\xcc\\xad\\xa9\\x21\\xbd\\x27\\x76\\x67\\x43\\x45\\x36\\xc1\\xfb\\x95\\x21\\x1e\\xfe\\xc0\\xf5\\xe1\\x18\\xdb\\x65\\x92\\xd5\\x55\\x8c\\x2d\\xf3\\x75\\xbc\\xcc\\xbe\\x47\\xc3\\x99\\x9d\\xb9\\x55\\xbd\\x12\\x4b\\x06\\x81\\xc0\\x13\\x5d\\xbb\\xf3\\x54\\xe7\\x67\\x43\\xd8\\x02\\xa6\\xfe\\xa2\\x31\\xa2\\x1e\\x11\\xdb\\x79\\xf0\\x65\\xeb\\x01\\x50\\xb6\\x03\\x2e\\x64\\x68\\xb8\\x6e\\xcd\\xe8\\xeb\\x08\\x1a\\x4e\\xf2\\x1a\\x6f\\xec\\x4c\\x28\\x2b\\x29\\x81\\x99\\x56\\x66\\xed\\x22\\x52\\x1c\\xf6\\x83\\xaf\\x5a\\x47\\x7c\\xb4\\x7e\\x68\\x66\\xcf\\x08\\x60\\x7d\\xce\\xa4\\xbb\\x35\\x7d\\x8f\\xa3\\x6b\\x03\\x79\\x8a\\x29\\x99\\x0f\\xb9\\x5c\\x35\\x2f\\x35\\x04\\x6c\\x20\\xb8\\x65\\x76\\xd0\\x78\\x39\\x97\\xea\\x09\\xde\\xce\\x42\\xaa\\x72\\xdb\\x3a\\xb4\\x0c\\x60\\xd0\\x22\\x17\\xc5\\xe8\\x3b\\x32\\xe8\\x07\\xbf\\x21\\xf7\\x9a\\x14\\x62\\x69\\x90\\x07\\x31\\xf7\\x1f\\x76\\xba\\x7c\\xf3\\xa5\\xf9\\xb5\\x1a\\xe2\\x5b\\x86\\x8b\\x32\\xae\\xca\\xb3\\x33\\x70\\xd5\\x83\\xb7\\x5f\\x93\\xd2\\x03\\xb8\\xf8\\xf6\\xb4\\xdb\\xec\\x81\\xa5\\xa1\\xfb\\xd5\\x73\\x1f\\x64\\xa1\\xfa\\xc8\\x3c\\x77\\xe5\\xde\\x91\\x66\\x2e\\xb4\\xa4\\xf0\\xcf\\x00\\x36\\x8a\\x77\\xd4\\xeb\\xcb\\x6e\\x3d\\x16\\xbc\\xe6\\x73\\x61\\x45\\x8d\\x21\\x70\\x14\\x54\\xa7\\x28\\x3b\\xe1\\xa7\\x85\\x50\\x97\\x96\\x17\\x57\\xfb\\x46\\x59\\x7e\\xe6\\xb8\\xf7\\xc7\\x71\\xef\\xec\\x0a\\xf4\\x07\\x81\\x20\\xd7\\x96\\xa9\\x17\\x59\\x2a\\xe2\\x42\\x4f\\x84\\xc4\\x04\\xa4\\xc3\\x3e\\x56\\x8e\\x80\\x74\\x97\\x73\\xd7\\x88\\x7c\\x88\\x86\\x0d\\x88\\x74\\x0b\\xd0\\x9d\\x10\\xc1\\x8f\\xab\\xb0\\x1f\\x6e\\xd8\\xfd\\x0e\\x10\\x09\\xdc\\xc5\\x8f\\x96\\x34\\xcd\\xa9\\xc3\\xdc\\x7d\\x33\\x96\\x36\\xde\\x7b\\x23\\x2c\\x5b\\x88\\x7a\\x2e\\x29\\xad\\x5b\\x2b\\x56\\x50\\x5a\\x00\\xf0\\x35\\xc7\\xc3\\xa8\\xbb\\x84\\xe7\\x29\\xa6\\x0b\\xcb\\x29\\x67\\x86\\x8d\\x85\\xbd\\x11\\x42\\xb1\\x97\\x2f\\x5f\\xbe\\x04\\xb9\\xe4\\xe5\\x0f\\x3f\\xfc\\xc0\\x00\\x66\\xa2\\x14\\x85\\x9c\\xaf\\x3e\\x08\\x4f\\xfd\\xd3\\xab\\x57\\x23\\xf6\\x6f\\x27\\x1f\\xde\\x43\\x54\\xd9\\xc2\\x1a\\x36\\xd6\\x76\\x46\\x3d\\xbb\\x07\\xb2\\xc6\\x66\\xc0\\xfe\\xe5\\xf2\\xa7\\x8f\\x11\\x62\\x29\\xff\\x15\\x54\\x90\\x30\\xbd\\x3c\\x44\\xf0\\xe5\\xf7\\xdf\\x7d\\x37\\x62\\x67\\xb2\\x86\\x7c\\x62\\x09\\x19\\x10\\x21\\x08\\x72\\xe1\\x03\\x03\\xa1\\xa6\\x5d\\x3b\\x83\\x9f\\x38\\x08\\x05\\x09\\xcf\\xe5\\x74\\x06\\x0b\\xe0\\x2e\\x84\\x56\\x93\\x4a\\x16\\x16\\xe1\\x4a\\xf1\\xea\\xe3\\x42\\x13\\xfc\\x0e\\xa7\\x74\\x2f\\x92\\x22\\x60\\x70\\x03\\x56\\xc9\\x2b\\xc1\\x26\\xe6\\xc7\\x5a\\x37\\x8b\\x98\\xe6\\x58\\x0b\\xe3\\x64\\xd9\\x82\\x2b\\xc8\\x2a\\x81\\xce\\xe2\\x5e\\x19\\x61\\x1f\\x35\\x08\\xa3\\xa3\\x21\\x28\\x3b\\x83\\xd0\\xa6\\x25\\xa0\\x0c\\x02\\x6c\\xe3\\x10\\xcf\\xc3\\x82\\xcb\\x10\\x38\\x08\\x3e\\xf5\\xac\\x68\\x48\\xd0\\x3d\\xcb\\x04\\xa6\\xd2\\xe7\\xae\\x2c\\x6a\\xfd\\x77\\xdc\\x2a\\xa9\\x7c\\x16\\x14\\x49\\xc8\\x86\\x64\\x32\\x4a\\x3a\\x55\\x89\\xcd\\xd5\\x67\\xe5\\x3b\\x5e\\x48\\x19\\xff\\x49\\xfe\\xd4\\xf9\\x24\\x4d\\xb4\\x83\\xb4\\x74\\xac\\xdc\\x99\\x61\\xea\\xae\\x79\\x73\\xac\\x03\\xe1\\x4e\\x13\\x95\\xd9\\x6b\\xd4\\x4a\\x6b\\x2a\\xd1\\x44\\xe4\\x87\\x0a\\x77\\x51\\x0a\\x5b\\xec\\x03\\x43\\x71\\x29\\x01\\x28\\x29\\x07\\x97\\xe1\\x5c\\x66\\x51\\x3e\\x46\\xd8\\x86\\x96\\x06\\x22\\xaf\\xdc\\xbb\\x85\\x31\\x94\\x47\\x34\\xe7\\xf5\\x95\\x53\\x12\\x88\\x0a\\x8c\\x20\\xea\\xd9\\x84\\x1c\\x26\\x4c\\x28\\xbb\\x46\\x63\\xf9\\x9c\\x2f\\xb3\\xac\\x01\\xf7\\x92\\xc3\\xd1\\xe8\\x10\\xaf\\x89\\xae\\x11\\x26\\x18\\xcf\\xbc\\xfb\\xfe\\x91\\xf2\\xa5\\xf3\\xa8\\x74\\xbe\\xc0\\x8a\\xae\\x60\\xcf\\xa1\\x8a\\x48\\x3c\\x8b\\x76\\xe6\\xb4\\x52\\x5d\\xc0\\xc1\\x7b\\x56\\xc4\\xed\\x57\\x7a\\xbd\\x7b\\xc9\\xf5\\x21\\x4c\\xa0\\xc3\\xa3\\x7d\\xcb\\xab\\xf7\\x28\\xab\\xbe\\x09\\xad\\x81\\xd6\\x98\\x6e\\x42\\xd7\\x62\\xc3\\xbd\\xcb\\x0c\\xcc\\x3b\\xb1\\xbe\\x35\\x43\\x3d\\x9c\\x13\\xe7\\xfb\\xa9\\x1f\\xe7\\xa3\\x7c\\xbd\\xac\\xee\\xe0\\xd3\\x67\\x75\\xe7\\x13\\xcc\\x74\\xc9\\x49\\x17\\x91\\x86\\x54\\x14\\x08\\x35\\xfe\\x62\\xda\\xcb\\x93\\xe6\\x68\\xe9\\xb1\\xe9\\x57\\xd3\\xa2\\x0f\\x77\\xc3\\x4f\\x37\\xc7\\x04\\x7e\\xb2\\xb3\\xe6\\xbd\\x13\\x38\\x69\\x22\\xa5\\x8b\\xac\\x76\\x50\\x85\\x76\\x03\\x90\\x31\\xfd\\xe5\\x19\\xb1\\x0f\\x44\\x6a\\xf1\\x90\\xf1\\xb1\\xd1\\x55\\x63\\xb1\\x69\\xfc\\x31\\xa5\\xc3\\xd0\\xa9\\x47\\x59\\x00\\xe2\\x1b\\x1e\\x4b\\xa8\\xb2\\x8d\\xd5\\x13\\xbb\\x11\\x68\\xfc\\xf4\\xb8\\x9c\\xcf\\x40\\xc2\\xf7\\x08\\x24\\x1c\\xa0\\xaf\\x4d\\xc7\\x52\\x70\\xe6\\xde\\x90\\xbb\\x0b\\x23\\xfb\\xe8\\x57\\x46\\xb2\\xa3\\x58\\x81\\xc8\\xbb\\xe3\\xcf\\x95\\x15\\xf5\\x84\\x17\\xe2\\x38\\xd5\\xbb\\x42\\xa5\\xa7\\x10\\x22\\xe4\\xf3\\x22\\x66\\x5c\\x95\\x15\\x0a\\xe0\\x85\\xa8\\xe1\\xec\\x87\\xd2\\xca\\xa7\\x97\\xe7\\xac\\xac\\xe5\\xb5\\xa8\\x0d\\x3b\\x7a\\x23\\x9c\\xbc\\x88\\xf8\\xa9\\x9d\\xb2\\xab\\xf6\\x1b\\x5b\\x09\\xc3\\xd8\\x97\\xa6\\x07\\x9d\\xf5\\x0d\\xd5\\x83\\x46\\x9e\\xf2\\xa8\\xe4\\x7e\\xc5\\x65\\xc2\\x55\\xc5\\x25\\x35\\xa9\\x2e\\x3b\\x72\\x47\\x09\\x08\\x34\\xd0\\x8c\\xa5\\x6e\\x6a\\xb2\\xa2\\x7b\\xc8\\xe6\\x42\\xd7\\x4e\\x5d\\xc2\\x8e\\xb9\\x61\\xb5\\x98\\x3a\\x69\\xb6\\xf6\\x75\\xec\\x05\\x2b\\xaa\\xc6\\x7d\\xb1\\xd7\\x70\\xb6\\xbb\\x04\\x00\\x46\\xd3\\xec\\x6d\\xb1\\x7a\\x13\\x92\\xaa\\xf5\\xb5\\x2c\\x3d\\xab\\xc4\\xb2\\xfa\\xa1\\x60\\xea\\x82\\x9b\\x24\\xd5\\x26\\x29\\x6e\\x91\\x2c\\x2c\\xca\\xe8\\xc0\\x50\\x43\\x12\\x6b\\x16\\xec\\x9f\\x1a\\x85\\x35\\x60\\x5b\\x74\\xa8\\x4c\\xd3\\x87\\x08\\xeb\\x52\\x5c\\x34\\xe3\\x4a\\x9a\\xd9\\xe5\\x8e\\x26\\xc4\\x75\\x5d\\x60\\xb0\\xc2\\x8a\\xd7\\x6f\\xa3\\x25\\xd1\\x08\\x65\\x24\\xb0\\x3c\\x47\\xc6\\x1d\\xd3\\x95\\x4e\\x8e\\xd2\\xb0\\x88\\xbe\\x75\\x7a\\x20\\x35\\x64\\x7f\\x54\\x82\\x10\\x0c\\xdc\\x4f\\x1f\\xe3\\x38\\x28\\x29\\x0d\\x31\\x4b\\x4a\\xf1\\x45\\x2d\\xb2\\xef\\x0b\\x5e\\x55\\xa6\\x9d\\xb0\\xeb\\x29\\x26\\xca\\x1e\\x3e\\x51\\x0d\\xf7\\x54\\xba\\xed\\x0e\\x45\\x97\\x5a\\xe0\\x98\\x1b\\x27\\x66\\xd8\\x5c\\x63\\x1a\\x8f\\x02\\x70\\x5e\\x7c\\x08\\xa0\\x57\\x7c\\x83\\x24\\x91\\x11\\xd2\\x95\\xe1\\xc8\\xec\\xb9\\x2a\\xed\\xb3\\xb9\\xf4\\xfe\\xcc\\xa5\\x77\\x8d\\xc3\\x33\\xa1\\x40\\x1d\\x4f\\xb2\\xa1\\x33\\x58\\xd2\\x40\\x4a\\x3d\\xc9\\xdd\\x12\\xd4\\xb1\\x57\\xb7\\x02\\xbe\\xf3\\xc4\\xda\\x5a\\x8e\\x1b\\xdb\\x1f\\xef\\xad\\xd5\\x1c\\xd8\\xb4\\x53\\x44\\xe0\\x16\\x0f\\x69\\xf6\\x45\\x72\\x44\\x23\\x72\\x7a\\x4e\\x3e\\xe3\\xdd\\x8f\\x3c\\x07\\xd8\\x0d\\x7e\\x79\\x68\\x58\\xa9\\x8b\\x26\\xc0\\xc6\\xc2\\xa2\\x45\\x07\\x5a\\x17\\xf4\\x44\\xd6\\xf7\\x5e\\xf5\\x87\\xf4\\x4a\\x5f\\xb2\\xf5\\x78\\x95\\xfa\\x46\\xdd\\xf0\\xba\\x3c\\xb9\\xd8\\x12\\x7d\\x9f\\xb3\\xf3\\xd8\\x2a\\x15\\x94\\xfc\\xd7\\x50\\x60\\x94\\x8f\\x75\\x63\\x23\\x74\\xe8\\x6f\\xc7\\x5e\\xbd\\x4e\\x4d\\xb7\\xda\\x91\\x86\\x8e\\xf6\\xe8\\xbe\\x8a\\xfe\\xb3\\x89\\xfb\\xd9\\xc4\\x9d\\x7d\\x76\\x31\\x71\\x9f\\xa3\\x89\\x3b\\xc5\\xc1\\xcd\\xae\\xab\\x87\\x57\\x90\\x55\\xd7\\xd8\\xde\\xfb\\xb4\\x92\\x9e\\x45\\x02\\x83\\xd2\\x54\\x3b\\x8e\\xbf\\x25\\xc0\\xe1\\x15\\x89\\x7b\\x9b\\x08\\x7d\\x9e\\x02\\x01\\xcf\\x7e\\x7c\\x8b\\xea\\x3d\\xd9\\x49\\xbb\\x97\\x40\\xc7\\xcf\\xa6\\x1a\\xa5\\xb7\\x95\\x44\\x07\\xa9\\x21\\xa9\\x61\\x3e\\x20\\x14\\xe8\\x01\\xe9\\x5d\\xaa\\x8c\\xd5\\x41\\x11\\x84\\xba\\x47\\x05\\x64\\xfc\\xf4\\x5c\\x7c\\xd6\\x7b\\x03\\x58\\xcf\\xfa\\xe4\\xf8\\xe9\\xbb\\x1b\\x6c\\x87\\x5a\\xe5\\xf8\\x79\\xe4\\x8a\\xe5\\xf8\\xe9\\x6d\\xfb\\x66\\xfd\\xab\\x97\\xaf\\x99\\xee\\xfd\\xd6\\x30\\xdf\\x71\\x6a\\xbb\\x9b\\xf5\\x77\\x35\\xe7\\x0f\\x62\\xe5\\xcc\\xa7\\xcf\\xd6\\x9f\\xcd\\xf9\\x2b\\x9f\\x07\\x34\\xe7\\x27\\x84\\xdb\\x13\\x83\\x35\\xa6\\xfd\\xd4\\xdc\\xe6\\xed\\xfb\\x63\\xe1\\xc5\\xca\\x51\\x44\\x5f\\x73\\x47\\xce\\x5b\\xf6\\x63\\xb9\\x26\\x74\\xab\\x1e\\x8e\\x46\\x87\\x87\\xde\\xde\\x4f\\xe7\\xb3\\xb1\\x93\\xe1\\x9f\\x98\\x50\\x85\\x2e\\x71\\x53\\x5d\\xff\\xb5\\xb1\\xc0\\xf4\\xa3\\x9a\\x9e\\x8e\\x65\\xee\\xdf\\x95\\xba\\x66\\xa1\\xef\\x7e\\x5b\\xd2\\xe3\\x06\\x7b\\x48\\x80\\x77\\x77\\x62\\x91\\x91\\x31\\x06\\x88\\x01\\x9a\\x60\\x40\\x15\\x22\\x0e\\x19\\xab\\x9b\\x60\\x61\\x9f\\x50\\x6b\\x0b\\x2a\\x8a\\x1c\\xe1\\x97\\xa3\\x62\\xd1\\x0c\\xe8\\x81\\xd1\\x5c\\xcc\\x75\\xbd\\x1c\\x84\\x87\\xdc\\x8f\\x59\\x2b\\x7a\\x02\\xb1\\xa7\\x8a\\xa6\\xae\\x85\\x82\\xfa\\x26\\x4f\\x95\\xbf\\xfa\\x25\\xb8\\x47\\xf6\\x1a\\x56\\xbd\\x5b\\x76\\x5b\\xfc\\xe4\\xdb\\x1a\\x7d\\x00\\x60\\x92\\x8a\\xd5\\xea\\x26\\x01\\xd9\\xc4\\x0c\\xa2\\x9f\\xc3\\x7d\\x2b\\xd4\\x35\\xbb\\xe6\\xb5\\xe9\\xba\\xe6\\x6c\\x57\\x8e\\x5a\\xca\\x6b\\x69\\xba\\x40\\xfe\\x6f\\x98\\xdc\\x65\\x30\\xfb\\x00\\xec\\x60\\x63\\x17\\x8d\\x25\\xea\\xe4\\xcf\\xae\\x47\\x6a\\xca\\x8b\\xce\\x45\\xc1\\xe1\\xd5\\x6d\\x75\\xda\\xda\\x9f\\x27\\x5a\\x48\\x26\\xff\\x74\\x2a\\x2b\\x93\\x7f\\xfa\\x15\\x99\\x59\\xdf\\xb6\\xe7\\xd6\\xdf\\xa1\\x7e\\x53\\xfb\\xe3\\xb7\\x76\\xf7\\x3b\\x12\\x99\\x4c\\x04\\x06\\xf3\\x82\\xd9\\x3d\\x5c\\x02\\x30\\x86\\x9f\\xc9\\x5e\\xa9\\x08\\xbe\\x4d\\x1e\\x2e\\x69\\xc5\\x7c\\xa1\\x6b\\x5e\\x2f\\x59\\x49\\xb6\\x86\\xe5\\x9a\\x8c\\xd0\\x24\\x25\\xf4\\xce\\xd0\\x30\\x30\\x8e\\x52\\xd6\\x7b\\xca\\x46\\xe8\\x91\\x0d\\x2a\\x4a\\xd9\\x6c\\xac\\x04\\xbf\\x69\\xd9\\xb0\\x55\\xba\\x68\\x37\\x80\\x06\\x46\\x48\\x62\\xde\\xdd\\x49\\x8f\\x79\\x60\\x45\\x5e\\x5c\\x51\\xc5\\x20\\xbf\\xaa\\xc8\\xfb\\x93\\x24\\x97\\x83\\x83\\x16\\x0e\\x34\\x98\\xc7\\xc0\\xf7\\x47\\x45\\x57\\xfd\\xc3\\xd8\\x77\\x66\\xca\\x42\\x6f\\x08\\x85\\x05\\x1c\\xd1\\x83\\xc7\\x4e\\x22\\xf9\\x00\\x6c\\xf0\\x81\\x76\\x89\\xf5\\xcc\\x6c\\x93\\xff\\x2d\\xa0\\x40\\x58\\xef\\xd8\\x78\\xdf\\x30\\xc0\\x41\\x6b\\x90\\xcc\\x43\\xd9\\xb4\\x4a\\x17\\x89\\xef\\x39\\xe3\\x50\\xb0\\x0d\\x6f\\xfd\\xe1\\xf7\\xb6\\x7b\\xb7\\x19\\xae\\x57\\x94\\x2f\\xc0\\xe8\\x53\\x19\\xf4\\xeb\\xc9\\x02\\xa0\\x2d\\x41\\x8a\\x87\\xc5\\x0c\\x1b\\xf0\\x39\\x29\\x22\\xd8\\x18\\xf7\\x26\\x40\\x9e\\x4f\\x9e\\x89\\x2f\\xba\\xf1\\x08\\x9b\\x36\\xa9\\xf3\\x96\\xeb\\x1e\\xee\\x97\\xcb\\x30\\xb3\\xa8\\xb7\\x41\\x0a\\x84\\x17\\xd4\\x4d\\x03\\x62\\x22\\xbd\\x85\\xc4\\x25\\x3d\\x01\\xdf\\x55\\x2c\\x8b\\x16\\xc0\\x1d\\x57\\x8e\\x99\\x92\\x55\\x7e\\xce\\x3c\\x96\\x5d\\x98\\x78\\xa3\\x28\\xd0\\xe0\\x01\\x0f\\xcd\\x13\\xe6\\x83\\x9d\\xb9\\x5f\\x7f\\x9e\\xd7\\x93\\xd3\\xdd\\x81\\xbf\\x85\\x78\\x8c\\x1e\\x1c\\xe2\\x20\\x06\\x71\\x64\\x2c\\x22\\x45\\xc7\\xcb\\x03\\x3a\\xb8\\x8f\\x19\\x08\\x37\\xcf\\x7b\\x86\\x3e\\x07\\x0d\\x97\\x58\\x47\\xb1\\x2c\\x28\\x67\\x57\\x66\\xa8\\x97\\xd8\\x2d\\x1e\\x40\\x88\\x6f\\x1d\\xba\\xff\\x78\\x4d\\xd8\\x9b\\xf5\\xc7\\x62\\xa2\\x63\\xa1\\x14\\x54\\x8c\\x28\\x2a\\xb7\\x14\\x95\\xb0\\x10\\x64\\x2b\\x02\\x60\\x29\\x7a\\x86\\xe7\\xfa\\xda\\x9d\\xe9\\xff\\x50\\xec\\x8b\\x87\\xee\\x97\\x93\\xd7\\x8c\\x1f\\x67\\x99\\x10\\x54\\x7c\\x46\\x09\\x51\\x62\\xa8\\x6e\\x15\\xdf\\x53\\x37\\xca\\x0c\\xd8\\xf8\\xd8\\x87\\xa5\\xc0\\xc5\\x53\\x4e\\x3a\\xac\\xbc\\xe0\\x8b\\xea\\x75\\x2d\\xdc\\x02\\x40\\xf6\\x71\\xad\\xe7\\xcc\\x28\\xbe\\x30\\x33\\x6d\\x41\\x43\\xe4\\x0b\\x5e\\x48\\xbb\\x64\\xb6\\xe6\\xc5\\x15\\x54\\x2a\\xaa\\x05\\xbd\\x6e\\xc0\\x8a\\x63\\x8a\\xef\\x4a\\x97\\x2f\\x8f\\x1e\\xb6\\xb3\\x5a\\x37\\xd3\\x19\\x04\\xc4\\xe2\\x53\\x45\\xc5\\x8d\\x9f\\xfd\\xda\\xf6\\xa4\\xf4\\x18\\x56\\x62\\xa1\\xe2\\x00\\x1e\\x58\\xeb\\x6b\\x69\\xa4\\x26\\xa3\\xaf\\xef\\xf7\\x22\\x00\\xc4\\xa1\\x21\\x19\\xcb\\xff\\x1e\\x19\\x21\\xd8\\x5b\\x7f\\x24\\xf0\\x97\\x4b\\x14\\x6d\\xd0\\xc0\\x51\\xe7\\x31\\x02\\x3a\\x20\\x9b\\x2b\\xc2\\x45\\x88\\x74\\x2e\\xf8\\xb0\\x90\\x6f\\xba\\x91\\xaf\\x7d\\xe9\\x71\\xd8\\xae\\xf5\\x63\\xd2\\x35\\xf8\\xef\\x3d\\x82\\xa7\\x50\\xa5\\x4e\\x9c\\x97\\x27\\x17\\xe7\\x26\\x55\\x4a\\xf0\\x6c\\x11\\xfc\\x1d\\xfc\\x50\\x69\\x35\\x4d\\xd1\\x04\\xe2\\xc9\\x74\\x14\\x55\\x41\\x95\\x97\\x6b\\x59\\x36\\xbc\\x42\\x5a\\x4a\\x83\\x39\\xbd\\x3c\\xc7\\xe6\\x72\\x3a\\xb3\\xc3\\x1b\\x01\\x46\\x19\\x64\\x39\\xf1\\xce\\xf8\\x97\\xca\\x95\\xa0\\x1d\\x69\\x80\\xf6\\x5a\\x32\\x2a\\xa0\\x81\\xcb\\x0d\\xed\\x86\\x2f\\x01\\xbd\\x86\\x22\\x4d\\x32\\xbf\\xa9\\xc7\\x17\\xc3\\x2e\\xd6\\xad\\x38\\x0c\\xef\\x24\\x54\\xed\\x70\\xd2\\x03\\x58\\xad\\xdc\\x12\\xc3\\x49\\x5d\\x1d\\x9b\\x5b\\xf8\\x04\\x0e\\x30\\x7c\\x4d\\x05\\xda\\xb8\\xdb\\x20\\x27\\xe3\\xdd\\xae\\xd2\\xdc\\x83\\x6c\\x76\\x1d\\x37\\xf9\\x33\\x55\\x50\\xec\\x29\\x23\\x1c\\xfc\\x92\\x58\\xcf\\x12\\x7f\\x87\\xbb\\x36\\x5c\\x95\\x43\\x5e\\xb9\\x93\\x73\\xf1\\xf3\\x29\\x05\\x3a\\xe3\\x45\\xc8\\xfc\\xf9\\xbe\\x18\\x92\\x54\\x01\\x3d\\xdb\\x89\\x0e\\x6b\\xaf\\x00\\xa4\\xc3\\x8f\\x45\\x09\\x44\\x23\\xad\\x1b\\x79\\xe3\\x14\\x65\\x5f\\xdc\\xf9\\xe7\\xd3\\x01\\x93\\x23\\x31\\xf2\\x7f\\x85\\x47\\x3d\\xd5\\xb2\\x7a\\x8a\\xd1\\x80\\x21\\xd4\\x13\\xce\\x1d\\x0c\\x25\\xb5\\x49\\xa5\\x6d\\xff\\xf6\\xcf\\x6e\\x90\\xee\\xd7\\x3f\\x0f\\xff\\x39\\x01\\x1d\\xfd\\xf3\\xdf\\xa8\\x92\\xf4\\xdf\\x5a\\xdf\\xa6\\x21\\x65\\x01\\x7c\\xff\\x6f\\xbe\\x8c\\x37\\x41\\x57\\xff\\x8d\\x6a\\x72\\x41\\xe1\\xea\\x11\\xd4\\xa5\\xbe\\xe6\\x95\\x2c\\xf1\\x34\\xc2\\xbb\\x6b\\xf1\\x77\\x6f\\x5f\\x84\\x65\\x0a\\xb6\\x9d\\x82\\x5b\\xa1\\x80\\x50\\xfb\\xdc\\x0c\\xa5\\x2d\\x36\\xa7\\xea\\xb4\\x6e\\xfc\\x47\\x60\\x19\\xc0\\xdc\\xb2\\x01\\xb3\\x5a\\xc3\\x75\\xc4\\x2b\\x7f\\xa2\\x98\\xf0\\x25\\x3b\\x71\\xae\\xb0\\x1c\\x9c\\xe2\\xd5\\x3c\\xef\\x71\\xdd\\xba\\x15\\x0e\\x99\\xb8\\x6e\\x1c\\x30\\xb6\\x7f\\x54\\xda\\xfe\\x63\\xd8\\x7e\\x1f\\xa9\\x01\\x0c\\x46\\x33\\x7e\\xad\\xa5\\xc7\\x21\\x77\\x37\\x45\\x61\\x61\\xc7\\x80\\x8c\\x3d\\x5e\\xb2\\xb9\\x34\\x96\\x5f\\x89\\x11\\xbb\\x74\\xbc\\x25\\x75\\x8a\\xe1\\xea\\x29\\x06\\x40\\x96\\xa2\\x64\\x8d\\xb2\\xb2\\x82\\x5f\\x63\\x3f\\x6e\\xc8\\x29\\xcf\\x39\\x9f\\x30\\xd3\\x14\\x8e\\xb6\\x2e\\x6a\\x31\\xf4\\x5c\\x8c\\x9e\\x5a\\xa1\\x05\\x71\\x2e\\x83\\xb0\\xd9\\x33\\x8e\\x2a\\xc1\\xa2\\x84\\xa6\\xb0\\x1e\\x5c\\xd1\\xf1\\x5a\\x09\\xe7\\x72\\xe3\\xd4\\xaa\\x88\\x9c\\x0b\\x16\\xd3\\x8c\\xd8\\x47\\x60\\x56\\x95\\xf7\\x0c\\xa3\\x76\\x42\\x76\\x4c\\x25\\x0a\\x61\\x0c\\xaf\\x97\\x03\\xc0\\x77\\x97\\x01\\x13\\x9c\\x22\\x78\\x80\\xa3\\xce\\xb9\\x42\\x74\\xf5\\x5a\\x14\\x5a\\x19\\x5b\\x37\\x85\\xc5\\x72\\x7b\\xe3\\x5a\\x5f\\x09\\x15\\xa2\\x06\\x57\\x8b\\xdd\\xc7\\x30\\x1a\\x70\\x7b\\x69\\x56\\xcc\\xb8\\x9a\\x26\\xe5\\x6a\\xe6\\xbc\\x84\\xb5\\xff\\x6b\\x90\\x72\\xfc\\x7c\\xdc\\x0a\\xf0\\x89\\x13\\x2c\\xa4\\x85\\xa5\\x18\\x3b\\x3e\\x12\\xac\\xb1\\xff\\xa1\\x02\\x2c\\xcf\\x20\\x9a\\x4b\\xdd\\x94\\x64\\xb5\\x85\\x76\\xf5\\xa2\\x5f\\xac\\xa7\\x6d\\x6f\\x08\\x6c\\x7b\\xcf\\x71\\x60\\x73\\x61\\x79\\xc9\\x2d\\xdf\\x21\\x16\\xec\\x43\\xac\\xb1\\x47\\x7e\\x48\\xaa\\x73\\x1a\\xfc\\x93\\xc4\\x87\\xbc\\xb8\\xa5\\x17\\x32\\x4d\\x83\\x82\\x9b\\x38\\xf3\\x2b\\x0f\\x89\\xd7\\xd6\\x9d\\x29\\xf2\\x17\\x60\\x88\\x17\\xc8\\x33\\xbe\\x88\\x99\\xeb\\xde\\xf7\\x86\\xe4\\x22\\x56\\x68\\x8c\\xe4\\xa4\\x9b\\x37\\xaa\\xa7\\x21\\xd6\\x2d\\xfd\\x0e\\x6b\\xf4\\x39\\xba\\xcc\\x8a\\x3c\\xcc\\x6b\\xad\\x08\\x82\\x5c\\x42\\x28\\x2b\\x6b\\x91\\x66\\x9d\\xd1\\xd2\\x35\\x0a\\x0f\\x79\\x6b\\x11\\x61\\x95\\xa7\\xc2\\x9a\\x18\\xa8\\x82\\x74\\xd8\\x11\\x17\\xe2\\x77\\xa4\\x93\\x02\\x91\\xa6\\x85\\x25\\xb5\\x6e\\xbd\\x2c\\x84\\xcb\\x6e\\x34\\xd1\\x59\\x47\\xf9\\xef\\x65\\x5d\\x77\\xb1\\x3d\\x63\\x55\\x81\\x0f\\xba\\xec\\x63\\xae\\x6e\\x81\\xf1\\xc7\\x2e\\x62\\x18\\x27\\x06\\xe4\\x1a\\xd0\\xed\\xf1\\x01\\x70\\x5a\\x99\\x2c\\x77\\x0e\\x89\\xdc\\x8c\\x5f\\xef\\x6e\\xab\\x8a\\x32\\xd2\\x30\\x20\\x1a\\xc3\\xeb\\x86\\xf0\\xba\\xe1\\xab\\xee\\x36\\xbd\\x3e\\x81\\x20\\xfe\\xd3\\x39\\x20\\x24\\x7f\\x49\\x2f\\x03\\xaa\\x23\\x29\\x97\\x3d\\xad\\x9e\\xad\\xa4\\xe4\\xd0\\x03\\xd1\\x7c\\x72\\x26\\x06\\x07\\x2e\\x25\\x3c\\x08\\xe9\\xa8\\xc5\\x6b\\xf6\\x8f\\x19\\x97\\x27\\x69\\x2a\\x68\\x4a\\x18\\xb0\\x7b\\xe4\\x55\\xa7\\x11\\x6d\\x85\\xcf\\x41\\xcf\\x1f\\x3f\\x6e\\x75\\x06\\xe2\\xc5\\x7a\\x8d\\xc2\\x07\\x06\\x07\\x91\\xcf\\x89\\x67\\x35\\xd8\\xd0\\x7c\\x1a\\x82\\x3b\\x5e\\xb5\\xae\\x2a\\x51\\xc3\\x14\\x48\\x7b\\x6a\\x39\\xd3\\x01\\xd2\\x14\\x4d\\xbb\\x83\\xa0\\xa2\\x06\\x19\\x53\\x89\\x9b\\x20\\x4c\\x70\\x83\\x08\\x2e\\xde\\xf1\\x25\\xa8\\x7e\\xde\\xc6\\xfe\\xa8\\xba\\x91\\xfb\\xfd\\x44\\x2d\\x71\\xf0\\x67\\xc9\\xe2\\xa2\\xf2\\xc9\\xa6\\xee\\x55\\x4e\\xee\\x54\\x7c\\x5c\\x39\\xce\\x97\\x6c\\x40\\x78\\x4f\\x8b\\x94\\x5b\\x9d\\x3c\\xf5\\x49\\x4c\\x48\\x6b\\x4c\\xbf\\xea\\xd6\\x16\\xf9\\x40\\xd6\\x70\\x14\\x23\\x59\\x7c\\x71\\xbb\\x88\\x5c\\x42\\xab\\x9e\\x3d\\x92\\x7b\\xc0\\x5b\\xbd\\x65\\x09\\xb5\\xeb\\x46\\xd0\\xd9\\x81\\xb7\\x93\\x0b\\x6f\\x17\\x27\\x1e\\x64\\x7f\\x4a\\xd5\\x25\\x62\\x2a\\x36\\xb8\\xb5\\xce\\x49\\xfb\\xb3\\x8b\\xd7\\x0f\\xc2\\x6a\\xc0\\xdb\\xdf\\xcf\\x85\\x93\\x97\\x55\\xbf\\x38\\x87\\x2e\\xbc\\xee\\x30\\x85\\x3f\\x3c\\x67\\x0c\\x3e\\x8e\\xb1\\x70\\xb7\\x2f\\xe6\\x75\\xc3\\xbe\\xa7\\x6d\\xd7\\x04\\x3e\\xc4\\x2b\\xf0\\x57\\x00\\x8f\\x25\\xa3\\x76\\x28\\x8c\\x56\\x0b\\x08\\x5c\\x81\\x37\\x8e\\xa0\\x7a\\x02\\x57\\x4b\\x92\\x38\\xec\\x4c\\xd6\\xe5\\x70\\xc1\\x6b\\xbb\\x44\\x35\\x77\\x90\\xbd\\x2d\\x64\\x03\\xf4\\x9a\\xf8\\x8e\\xde\\xa7\\x6e\\x48\\xcd\\x1b\\x57\\x18\\x26\\xef\\xad\\xd9\\xe4\\x4c\\xd8\\xb8\\xae\\x0f\\x31\\x9f\\xee\\xf9\\x06\\x6b\\xe7\\x93\\x22\\xa1\\x7a\\xcd\\xf5\\xd1\\xe6\\x93\\x51\\x96\\xbb\\xf3\\x37\\x47\\x9e\\x4c\\xee\\x29\\x46\\x76\\x95\\x56\\xda\\xd2\\x69\\xd0\\x76\\x90\\x46\\x40\\x71\\x73\\x3d\\x0d\\x9c\\xbe\\xcc\\x63\\x69\\xf4\\xc4\\x00\\x49\\x12\\x8d\\x0f\\xf9\\xa1\\xc2\\x4c\\xee\\xd0\\x27\\x6f\\x49\\x9b\\x86\\xfb\\xc1\\x8e\\x94\\x56\\x78\\x67\\xf0\\xd9\\x63\\x8c\\x75\\xda\\x60\\x3d\\x83\\x47\\x02\\xb7\\x49\\x75\\xb5\\xe4\\x8e\\x7a\\x36\\x26\\x55\\xe9\\x36\\x0d\\xc8\\x32\\x68\\x71\\xa6\\x29\\x0a\\x21\\x82\\xde\\x9f\\xd6\\xd2\\x89\\x77\\x9a\\x86\\xec\\x6b\\x72\\x1a\\x0d\\x68\\x33\\xc6\\xf2\\xaa\\x8a\\xfa\\x36\\x2d\\x94\\x06\\x4e\\xec\\x6d\\x94\\x09\\x83\\xce\\x32\\x82\\xc8\\xf4\\x00\\xd5\\xde\\x31\\x3e\\xa7\\x51\\x05\\xc6\\x1a\\x48\\xbb\\x4c\\x71\\xf8\\x33\\x61\\x04\\x14\\x1d\\x83\\x6a\\xb8\\x9c\\xa0\\x65\\x2c\\x51\\x58\\xc2\\x62\\x02\\x51\\xa2\\x5a\\xf3\\x33\\x5f\\x31\\x05\\xa4\\x70\\x02\\x91\\x70\\x14\\x68\\xcc\\x8b\\xab\\x1b\\x5e\\x97\\x50\\x73\\x78\\xc1\\xad\\x44\\xfc\\xf2\\x01\\x72\\xc5\\x94\\xc9\\xa9\\xc3\\xc3\\xd4\\x95\\x23\\x55\\x9b\\xff\\xa6\\x03\\x39\\x4a\\x46\\xbd\\xc2\\x97\\x8f\\x03\\x3f\\x36\\x22\\xa0\\x6b\\xc7\\x81\\x31\\xde\\x58\\x3d\\xe7\\x56\\x16\\xa0\\x9e\\xcb\\x49\\x62\\x19\\x9d\\x07\\xb4\\xc6\\x56\\x45\\x45\\xa0\\xc8\\xa1\\x36\\xff\\x2f\\xed\\xc1\\xdf\\x3a\\xf0\\x64\\xac\\x7e\\x9a\\xeb\\xc7\\x95\\x10\\xf5\\x50\\xb9\\x1f\\x3c\\x5a\\x60\\xc1\\xaf\\x85\\x60\\x72\\xee\\x04\\x2c\\x0e\\x05\\x49\\x26\\x21\\xef\\xca\\x9b\\x8b\\x6f\\x5b\\x14\\x27\\x45\\xfe\\x02\\x36\\xfa\\xe4\\x29\\xb4\\x31\\x38\\x0d\\xd4\\x30\\x7b\\xa3\\x83\\x3a\\x17\\x2d\\xa1\\x94\\xb8\\x34\\x68\\x89\\x1c\\xd4\\xc6\\x5d\\x35\\xb7\\x2c\\xc9\\x3d\\x1a\\xb8\\xb3\\x73\\x23\\xaa\\xca\\xfd\\xff\\xb6\\xdb\\x64\\x46\\xeb\\x46\\x84\\x95\\x81\\x0d\\x2b\\xa5\\x69\\x95\\xf7\\x3e\\x2a\\x6b\\xbd\\x58\\x90\\x7d\\x69\\x7e\\xdc\\x1e\\x11\\xb8\\x5d\\xea\\x6b\\x61\\x92\\x0a\\xd6\\x28\\xb3\\x4d\\x85\\x0a\\x25\\xd8\\x09\\x14\\x04\\x08\\x4a\\xfb\\x15\\xd9\\x36\\xae\\x1d\\x5c\\xba\\x5c\\x68\\xc4\\xbe\\x7d\\x79\\xe8\\x57\\xd0\\x45\\xdd\\x4a\\xf9\\x03\\x63\\x46\\x98\\xb4\\x7b\\xcc\\xbe\\x50\\xe1\\xa7\\x70\\x67\\x43\\x64\\x64\\x27\\x99\\x16\\x4d\\x61\\x24\\xd6\\x8e\\xd8\\xd1\\x49\\xb5\\x98\\x25\\xbd\\xa6\\x52\\x64\\x88\\xb8\\xce\\x47\\x9a\\xbd\\xef\\xb4\\xd6\\xc6\\x7c\\xf4\\x4d\\xfa\\xbc\\xfa\\x59\\xc2\\xec\\xf8\\x79\\x96\\x30\\x9f\\x25\\xcc\\xdf\\xb7\\x84\\xe9\\xe7\\x03\\x34\\xe6\\x8e\\x93\\x0a\\xec\\x37\\xa7\\x75\\xb7\\x4d\\x8f\\x7d\\xd4\\x96\\xdc\\x22\\x20\\x82\\xf0\\x8d\\x9a\\x36\\x07\\x42\\x77\\xc3\\x97\\x23\\x25\\x2c\\x65\\xf3\\x7a\\xa3\\xca\\x27\\xdf\\xdf\\x8f\\xb5\\x63\\xc6\\x24\\xbb\\x25\\xc7\\xdc\\xdf\\x19\\x9f\\x47\\x9c\\xbc\\xc5\\x6a\\xe4\\x0f\\xd1\\x4b\\x03\\xdf\\x1f\\x1a\\xf2\\x51\\xb8\\xdf\\x21\\x96\\x3e\\xed\\xa0\\x10\\x23\\x76\\x29\\x3c\\xa8\\x67\\xf6\\xf2\\xd5\\xac\\xd1\\x52\\x58\\x2e\\x2b\\x13\\x19\\xc2\\xe7\\x0d\\x0c\\x66\\x77\\x82\\x7f\\xdf\\xa7\\x24\\xc4\\x8c\\xee\\xaa\\x83\\xc4\\x40\\xe9\\x24\\x24\\x23\\x8d\\x28\\x8a\\x0f\\x6c\\x32\\x81\\x9e\\x4f\\xd8\\x27\\x51\\xe8\\x6b\\x51\\xe3\\xca\\x40\\xf5\\x60\\x27\\x67\\xbf\\xe3\\xb2\\x72\\xeb\\xe2\\xd7\\x27\\x9a\\x96\\x00\\x96\\x39\\x37\\xec\\x27\\xf6\\xbc\\x70\\x28\\x69\\x13\\xe6\\x34\\x28\\x4a\\x17\\x76\\xcf\\x93\\x8b\\x7d\\x51\\x8b\\x6b\\xa9\\x1b\\xe3\\xe3\\x9e\\x1a\\x8b\\xc4\\xd8\\x58\\x92\\x6c\\x67\\x72\\x1a\\xd0\\xfd\\x43\\xa0\\x44\\x2d\\x0a\\x5d\\x97\\xf1\\xf0\\x19\\xcb\\x6d\\x63\\xf2\\x64\\xab\\x02\\x6d\\xf1\\xfb\\x33\\xef\\x86\\x75\\xbc\\x67\\x19\\x60\\x37\\x7e\\x0b\\xd3\\xed\\xd5\\xa2\\xed\\x1d\\x07\\x99\\xd5\\x40\\x5e\\x63\\x42\\x67\\x52\\x1a\\x83\\x71\\xcd\\x52\\xe1\\xc2\\xbb\\xcd\\x1e\\xf9\\x9f\\xb0\\xf1\\x20\\xee\\x71\\x74\\x5b\\x4a\\x93\\x94\\xf9\\x0f\\x3e\\x40\\x09\\x52\\x2a\\x77\\xd7\\x36\\x51\\xc7\\xc2\\xa5\\x85\\x63\\xe6\\x85\\xbb\\x33\\xd4\\xff\\x3e\\xd1\\xbb\\x4e\\x2a\\x27\\x93\\x22\\x11\\x48\\x2e\\xee\\x1a\\xff\\xa2\\x9c\\xcf\\x1b\\xeb\\xce\\xeb\\x88\\x9d\\x63\\x26\\x0b\\x48\\xb6\\xa4\\x30\\x4d\\x62\\x76\\x86\\xa8\\x4d\\x07\\xaf\\x60\\xfa\\xd9\\xc5\\x68\\xcf\\x76\\x31\\xdc\\xaf\\x6c\\xd4\\xa7\\x74\\xc9\\x53\\x54\\x0a\\xa7\\xdd\\x81\\x6f\\xde\\xed\\x8e\\xf7\\xdd\\x67\\x4f\\x77\\x48\\xab\\x5f\\x37\\xcb\\x9e\\x07\\x18\\x3f\\xbb\\x88\\xb2\\xf8\\xe9\\x29\\x9f\\xe2\\x67\\xb7\\x5b\\x83\\x9f\\xfe\\x52\\x07\\x7e\\x56\\x65\\x8f\\x56\\x11\\x7f\\x2f\\x83\\x64\\x3b\\xb3\\xd0\\xe5\\x68\\xcd\\xdd\\x09\\x71\\x1c\\xba\\xa4\\x20\\x8d\\xdc\\xfe\\x82\\x29\\x5f\\xe7\\xae\\xfb\\x2b\\x1f\\xb8\\x14\\xe8\\x2c\\x95\\x4c\\xab\\xc0\\x92\\x22\\x4b\\x81\\x28\\xb7\\x74\\xe7\\x76\\x98\\xd9\\x8e\\xe2\\x4e\\x2b\\x20\\xd1\\x91\\x92\\xe1\\x9c\\x2f\\x86\\x57\\x62\\xd9\\x7b\\x5b\\x76\\x38\\x05\\xab\\x2f\\xc7\\x79\\xcc\\xf9\\xa2\\x47\\x3f\\x18\\x40\\x7b\\x07\\x4a\\x7a\\xf8\\x1e\\x43\\x70\\xf1\\xcb\\x31\\x31\\x5e\\x1f\\x15\\x1c\\x23\\x92\\x0b\\x3d\\x5f\\x34\\x56\\x24\\x0c\\x9a\\x58\\x69\\x6f\\xae\\x95\\x81\\x90\\xbc\\xc0\\x3a\\x7a\\xc3\\xd0\\xed\\x30\\x12\\xb9\\x0e\\x05\\x70\\xd2\\xcf\\xce\\xd7\\x7f\\x57\\xbc\\x8d\\xf4\\xf3\\x84\\x03\\x80\\x5b\\x93\\xed\\x9f\\x0c\\xc3\\xee\\x98\\x10\\xc3\\xee\\x92\\x14\\xc3\\xf6\\x99\\x18\\xc3\\x42\\x7a\\xdd\\x5d\\x6e\\xcc\\x27\\x9f\\xd8\\xd7\\xba\\x33\\x24\\xc2\\xde\\x76\\x67\\x32\\x7c\\xa7\\xd0\\x8f\\x34\\xbe\\x20\\x37\\x85\\x97\\x85\\x3b\\x00\\xae\\xd9\\x34\\x3d\\x8b\\x6e\\x2b\\xd8\\xac\\x31\\x86\\x4c\\x7c\\x0d\\x45\\x18\\x12\\x35\\x09\\xb4\\xff\\x1b\\x69\\x50\\xb1\\x51\\x4c\\xce\\x17\\x08\\xcc\\x08\\xb7\\x6e\\xe8\\x25\\x23\\xb2\\x09\\x87\\x91\\x14\\x10\\x4b\\xc3\\xc4\\x57\\xb0\\x8c\\xe3\\xcb\\x9e\\x2f\\x38\\x7b\\xbe\\xe0\\x9d\\xdb\\x3f\\xe6\\x05\\xc7\\xfc\\xb4\\x3e\\xe9\\x93\\xad\\xba\\x8e\\xd8\\x9c\\x20\\x53\\xf8\\x58\\x54\\xec\\xd7\\x46\\xd4\\x4b\\xe6\\xb4\\xcd\\x18\\x85\\x0d\\xc5\\x28\\x9c\\xe0\\x82\\x71\\xcc\\xe4\\x59\\xea\\x2e\\xb9\\x3c\\xa0\\xa2\\x05\\xd2\\xdd\\xdb\\xaf\\x4e\\xd5\\x06\\xd4\\x81\\x3b\\x90\\xbd\\x76\\x57\\x39\\xb0\\x0c\\xae\\x56\\x58\\xc1\\x54\\x95\\xc6\\x40\\xb0\\x4c\\xb9\\x76\\x3a\\xd7\\xc9\\xc7\\xb3\\xdd\\x2c\\x16\\x8f\\xa1\\xc6\\x9c\\xdc\\x32\\x41\\x5c\\x88\\xf0\\x4b\\x5e\\xfb\\x33\\xb8\\x3c\\xd8\\x95\\x58\\x0e\\x28\\x5c\\x91\\x6a\\xed\\xf8\\x87\\x31\\xea\\x36\\x07\\x80\\xef\\x0a\\x2c\\xb6\\x6e\\x81\\x1e\\x5c\\x03\\xea\\x0a\\x19\\x9e\\xb7\\xf2\\x8b\\xf0\\x80\\xba\\x53\\x0f\\x68\\xf1\\xf4\\xb3\\x09\\x66\\x1c\\xcf\\x04\\xe0\\x25\\xfb\\x2c\\xb4\\x70\\x0c\\x20\\xf3\\x0e\\xa8\\xc5\\x83\\xaa\\x34\\x0c\\x90\\x7d\\x71\\x61\\xef\\x3c\\xd5\\x70\\x4c\\xb3\\xfc\\xa9\\x2b\\xb1\\x3c\\x34\\x84\\xf1\\xa0\\x95\\x99\\xc9\\x85\\xaf\\xe6\\x03\\x94\\x80\\x4e\\x2e\\xfb\\x19\\xc2\\x38\\x7d\\x17\\x78\\xe7\\xcf\\xd5\\x80\\x7d\\xd4\\xd6\\xfd\\xef\\x2d\\x44\\x74\\xc3\\x59\\x3f\\xd3\\xc2\\x7c\\xd4\\x16\\xbe\\x79\\xf0\\xc5\\xc2\\xe1\\xde\\x79\\xa9\\xc8\\x1d\\x4a\\x86\\x22\\xc8\\x3c\\x80\\x6c\\x5a\\x1f\\x29\\x0c\\x4b\\x42\\x41\\x64\\x61\\x59\\xa5\\x61\\xe7\\x8a\\xe9\\xda\\xaf\\x89\\xf5\\xa5\\x1e\\x0c\\x75\\xe1\\x5d\\x3d\\x89\\x93\\x7b\\x4d\\x1f\\xb4\\x94\\xba\\xce\\x56\\xf2\\x96\\xee\\x82\\x1b\\x5b\\xfa\\x5f\\xc0\\x46\\x0e\\x21\\x09\\x21\\xbc\\x19\\x0a\\x16\\x70\\x2b\\xa6\\xb2\\x60\\x73\\x51\\x4f\\x01\\xcd\\xa3\\x98\\xed\\xbe\\x41\\xfd\\xe9\\x36\\x7e\\x76\\xa2\\xde\\xe9\\x8b\\x7b\\x9f\\x0c\\x60\\x75\\xef\\x21\\xc0\\xfc\\xae\\x0c\\x13\\x7b\\x41\\x16\\x31\\xe7\\x0b\\x77\\x28\\xfe\\xc7\\x71\\x02\\xd8\\x97\\xff\\x85\\x02\\x23\\x66\\xc4\\x4e\\x7c\\x79\\xfa\\xf4\\x37\\x32\\x17\\xa7\\xdd\\xb8\\x1e\\x9c\\xc8\\xff\\x6b\\x23\\xaf\\x79\\x25\\x30\\xed\\x82\\xab\\x00\\xba\\xae\\x27\\x2b\\x6c\\x7a\\x40\\x55\\x46\\x1c\\x95\\x0a\\xe6\\x99\\x83\\x2b\\xb1\\x3c\\x18\\xac\\x1c\\xa4\\x83\\x73\\x75\\x10\\x21\\x75\\xb2\\xa3\\x13\\x18\\x1a\\xd8\\x24\\x0f\\xe0\\xb7\\x83\\x7d\\x73\\xf6\\x47\\x12\\xed\\x77\\x38\\x25\\x64\\x79\\x3f\\xad\\x38\\x7a\\x6a\\x76\\xf5\\x87\\xb4\\xfb\\x59\\x07\\x97\\x7d\\x99\\x3c\\x13\\x3d\\x59\\x94\\x64\\xb3\\x77\\xc7\\x01\\x24\\x63\\xf6\\x0f\\x08\\xef\\xb5\\x7a\\xd7\\x54\\xeb\\xae\\x3b\\xcc\\xd6\\x5a\\xf8\\x57\\x00\\x99\\xf2\\xa9\\xb6\\x19\\x8a\\x41\\x8c\\x45\\xdb\\xb0\\x5e\\x3f\\x83\\x03\\x47\\x4f\\xd8\\xbb\\x08\\x83\\x0d\\x26\\x78\\xc7\\xb4\\x29\\xf9\\xd6\\x29\\xc2\\x52\\x15\\x55\\x43\\xbe\\x1b\\x68\\x8a\\x8e\\x84\\xfb\\x5f\\x9c\\x3b\\x1c\\xaa\\xd8\\x81\\x3f\\x4d\\x3e\\xf6\\x6d\\x25\\xcf\\xaa\\x1d\\x09\\x04\\x81\\x61\\x21\\xf6\\x05\\xd7\\x6a\\xdf\\x73\\x9d\\x6c\\xc9\\x6a\\xc9\\xa1\\xd3\\x8b\\x5c\\xf6\\x78\\x27\\xc7\\xb5\\x60\\xa7\\x33\\xae\\x94\\xa8\\x12\\x6c\\x12\\xb2\\x85\\x84\\xe2\\xa3\\x20\\x90\\x50\\xc9\\xd1\\xc3\\xbc\\xe6\\xa8\\xa7\\x6f\\x2a\\x20\\xe1\\xc4\\xa4\\xb3\\x3d\\xc1\\xf4\\xff\\x96\\x4a\\x80\\x6e\\x46\\xaa\\xef\\x5b\\xfc\\x13\\x81\\xb5\\x67\\xfa\\x86\\x95\\x9a\\xdd\\x40\\x95\\xa9\\x6b\\xc7\\xb4\\x20\\xf8\\xcb\\x78\\x76\\x97\\x8c\\x14\\xe2\\x44\\x0b\\x3d\\x5f\\xd4\\x7a\\x2e\\x43\\xf0\\x14\\x6d\\xe3\\x5e\\x81\\x3c\\xaa\\xa6\\x03\\x62\\x63\\xbe\\x07\\x55\\xa3\\xf2\\x02\\x3e\\xef\\x4e\\x99\\xe5\\xf5\\x54\\x58\\xd7\\x1b\\x53\\xcd\\x7c\\x2c\\x3a\\xa3\\x8d\\xdc\\x07\\x62\\xec\\xb7\\x54\\xf0\\x7d\\xbf\\x25\\x4b\\x71\\x1b\\x7e\\xf9\\xe5\\x63\\x5f\\xc0\\xdc\\xc3\\xd8\\x72\\xd3\\xde\\xde\\xe8\\xba\\x2a\\x6f\\x64\\xe9\\x1d\\xce\\x47\\xee\\xe1\\xe3\\xae\\xe3\\xdf\\x33\\x7e\\x6e\\x8f\\x13\\x7e\\x73\\x23\\xcb\\xde\\xcb\\x01\\x8d\\xf2\\x65\\xf0\\x61\\xe0\\x6e\\x19\\x18\\xac\\x03\\xd5\\xe3\\x94\\x50\\xf4\\x04\\x5a\\x1c\\xb3\\xb7\\x12\\x93\\xc0\\xa1\\x3d\\x38\\xae\\xe7\\x63\\xa9\\x22\\x10\\x40\\x5c\\x66\\x47\\x8c\\xdd\\x7d\\xf1\\xaa\\x89\\x11\\x16\\xd3\\x77\\x21\\x73\\x46\\xdb\\x19\\x33\\x72\\xde\\x54\\x96\\x2b\\xa1\\x1b\\x53\\x2d\\x3b\\x1f\\x95\\xc7\\x59\\xea\\x49\\x25\\xbe\\xe2\\xc9\\xee\\xc3\\xe4\\x42\\xa3\\x9c\\xd9\\x41\\x88\\x6c\\x44\\xbb\\x58\\xe1\\x76\\x31\\xc2\\xbc\\x7c\\x11\\x38\\x5f\\xc8\\x0a\\x17\\x5f\\x45\\x41\\xc9\\x5b\\x8b\\xaa\\x99\\xca\\x2d\\x59\\xaa\\xbf\\xb3\\x1a\\x34\\xb1\\xdc\\x47\\x63\\x44\\xc4\\x55\\xea\\x5a\\x85\\xef\\x81\\x4a\\xc6\\x3c\\x2e\\x87\\xff\\xbc\\xbe\\x5c\\x4c\\x29\\x16\\x42\\x95\\x00\\x60\\xfb\\x2e\\x9e\\x5c\\x1c\\xfc\\x5e\\x57\\x8e\\xc0\\x60\\xfb\\x52\\x2d\\x8f\\x21\\x9b\\x51\\xf0\\x24\\x3c\\x61\\xa6\\xab\\xd2\\x30\\xf1\\xd5\\xd6\\xdc\\x11\\xa6\\xb9\\x23\\x41\\xa1\\xcd\\x84\\x71\\xd5\\x9d\\xc8\\x3c\\x8d\\x82\\x0e\\x6c\\xef\\xdc\\xfe\\x7e\\xab\\x9b\\x3f\\xc5\\x02\\xe5\\x71\\xee\\xd9\\xd7\\x7b\\x2e\\x34\\x84\\x84\\x98\\xee\\x8a\\xc9\\x13\\xa4\\xd6\\x14\\x04\\x8a\\x01\\xac\\xab\\x99\\xa8\\x3b\\x16\\x06\\x32\\x6b\\x4a\\xa0\\xb4\\x46\\xf5\\x5c\\x54\\xfd\\x9b\\xa8\\x12\\x34\\x01\\xfc\\x96\\x3e\\x90\\x99\\xd4\\xa2\\xa5\\x51\\xd3\\x97\\xbe\\x38\\x71\\x07\\x0d\\x9a\\xce\\x6d\\xc2\\x07\\xdc\\xaa\\xfb\\x8e\\x28\\xfb\\x9c\\x19\\xb7\\x96\\x31\\xd4\\xbb\\x51\\x6a\\x1b\\x15\\xbb\\x8f\\x9a\\x2f\\xdc\\x72\\x23\\x6c\\x37\\x6b\\x4a\\x2e\\x3a\\xc4\\x96\\xee\\x02\\xa6\\xe7\\x8b\\x7e\\xc2\\x9a\\x43\\x90\\x95\\xe7\\x31\\x4d\\xd8\\xf0\\xcf\\x24\\x65\\xa8\\xec\\x49\\x27\\x5f\\xf8\\xf5\\xf1\\x90\\x9a\\x22\\x78\\x91\\xb1\\x8f\\xd2\\xed\\x4a\\xc1\\x6d\\xe7\\x02\\x89\\x9d\\xf8\\x02\\x8d\\xe0\\xcb\\x97\\xde\\x95\\xf7\\x93\\x96\\x5e\\x0e\\x81\\x7f\\xe7\\x8b\\x30\\x0a\\x01\\xb2\\x8d\\x92\\xbf\\x36\\xa9\\x3a\\x00\\x18\\x64\\x61\\xda\\xf4\\xfc\\xbe\\xe6\\x36\\x2d\\x44\\x34\\x5e\\x9d\\x49\\x73\\xd5\\x07\\x3a\\x76\\xa5\\x71\\x7e\\x25\\x7e\\x3c\\x7d\\xcb\\xe8\\xdb\\x4e\\xf6\\xa5\\x3e\\x06\\xa6\\xbb\\x42\\x52\\x4e\\x0b\\x11\\x8d\\xb6\\xa5\\x34\\x57\\x7b\\x82\\x9d\\xed\\x2e\\xd5\\x2f\\xca\\x8f\\xdb\\x42\\x1d\\x1f\\xce\\xfe\\xd5\\x96\\x7a\\x3d\\x92\\x5e\\x02\\xf1\\xb8\\xd4\\x0d\\xbb\\x21\\x84\\x2a\\x92\\x9a\\x3f\\xcb\\xc5\\x6b\\xf6\\x56\\x99\\xa6\\x16\\xd1\\x73\\xdb\\xee\\xca\\x71\\xdd\\xce\\x32\\x34\\x80\\x80\\x99\\xd7\\x7b\\xb3\\x95\\xed\\xfb\\x94\\x3c\\x65\\xe3\\xdb\\x82\\xd7\\x16\\xc4\\xe3\\xbe\\xc7\\x20\\x34\\xf4\\xf4\\x29\\xf9\\x42\\x75\\x39\\x07\\xe7\\x13\\x1f\\x77\\x37\\x20\\x28\\x9e\\x00\\x33\\xeb\\x1f\\x72\\x3b\\x9f\\xa0\\xcf\\xa5\\x7b\\xfd\\x2e\\x20\\x33\\xb2\\x17\\xa5\\xb8\\x7e\\x61\\x4a\\xfe\\x6a\\x00\\xaf\\xf1\\x99\\x25\\xf9\\x98\\xb8\\x61\\x07\\xaf\\x0e\\x46\\xec\\x52\\xce\\x65\\xc5\\xeb\\x6a\\x99\\x15\\xce\\x88\\xcf\\x39\\x66\\xe1\\x3b\\x04\\xaf\\xdc\\xcb\\x03\\x76\\xa4\\x6b\\xe8\\xb9\\xe0\\x8a\\x55\\xc2\\xa7\\x75\\xd3\\x3d\\x5b\\xa2\\xec\\x78\\xfc\\xd0\\xc4\\x85\\xdd\\xab\\xfd\\x12\\xe9\\x4c\\xef\\x33\\x51\\x7a\\x8e\\x4d\\xfc\\x28\\x43\\x1d\\x3c\\x8b\\x24\\x5d\\x2a\\x47\\xe7\\x47\\xec\\x0b\\x11\\x68\\xe2\\x5b\\xb8\\x69\\x70\\x65\\xfc\\x13\\x8f\\xb5\\xa8\\x0f\\xa3\\xf7\\xed\\xa4\\xc1\\xad\\x9a\\x83\\x1f\\x6f\\x99\\xb6\\x6b\\x89\\x53\\x69\\x3f\\x89\\x85\\xee\\x25\\x21\\x60\\x93\\x96\\x3d\\x4e\\x5a\\xf7\\x85\\x36\\x12\\x60\\xe5\\xb9\\x65\\x1c\\xaf\\x6d\\xd1\\x54\\xdc\\x89\\xd5\\x68\\x8d\\x1b\\xb1\\xb3\\xb7\\x17\\x9f\\xde\\x9e\\x9e\\x7c\\x7e\\x7b\\xf6\\x9a\\xfd\\x48\\x3d\\xc9\\x54\\xc2\\x1b\\xb1\\xcf\\x29\\x68\\x67\\x12\\xf0\\x4b\\xc8\\x88\\xe1\\x5d\\x03\\x22\\x43\\x5c\\x45\\x28\\x6e\\x80\\x62\\xe3\\x8a\\x9d\\x2b\\x69\\x63\\x31\\x0b\\x8c\\x3b\\xab\\xb4\\x12\\xbe\\xd6\\xfb\\x42\\x93\\x35\\x70\\x2a\\x2d\\x41\\x14\\x61\\x67\\xee\\xe7\\xbc\\x37\\xca\\xe5\\x70\\xa2\\x4c\\x4c\\xc5\\x78\\x70\\xd1\\x22\\x2e\\xee\\xbe\\xc4\\x7f\\x8f\\x56\\xdf\\x57\\xf6\\x0d\\xb5\\x03\\x7c\\xbe\\x31\\x5a\\xff\\xe3\\xf7\\xc8\\x0c\\x42\\x19\\x1d\\x8f\\x4a\\xa8\\xeb\\xac\\xca\\x0d\\xd4\\xc0\\x77\\x6c\\xe6\\x70\\x74\\xe8\\x05\\x8a\\x6a\\xa5\\x64\\x52\\xe8\\x34\\x05\\x5e\\xcd\\x0f\\xdb\\x88\\xb1\\x9f\\x7c\\x44\\x37\\x20\\xaf\\xac\\xaf\\xbe\\x84\\x20\\x5e\\x49\\x0d\\x9f\\xd6\\x91\\xf5\\x19\\x88\\xcd\\x38\\x7d\\x29\\x21\\xb5\\x4e\\xe5\\x35\\xe1\\x67\\xec\\xd5\\x8a\\x17\\x5f\\xdf\\xbb\\x96\\x6d\\x1c\\x37\\xe9\\x1f\\x9f\\xde\\xef\\x77\\x64\\x78\\xff\\x7a\\x8f\\x8b\\xae\\x2d\\x8d\\xaa\\xd0\\xf3\\x39\\xc2\\x7a\\xce\\x42\\xbe\\x7f\\x4c\\xd9\\x0f\\x54\\x61\\x6f\\x9a\\x0f\\x02\\x94\\x4e\\xb6\\x1c\\xfe\\x16\\x3d\\xf3\\x8d\\x5a\\x9a\\x4e\\xf8\\x9a\\x72\\x16\\x54\\x14\\x73\\xfb\\x57\\xcd\\x20\\x2c\\x5c\\xe3\\xd3\\xb1\\x89\\xb4\\xbf\\x08\\x2f\\x7f\\xf1\\xe9\\xed\\xc9\\xd9\\x87\\xb7\\xa3\\x79\\xf9\\xe0\\xa4\\x45\\xa8\\x72\\xa1\\xa5\\xb2\\x66\\xbb\\x7e\\xb3\\xad\\x46\\x60\\x77\\xf2\\x13\\x5e\\xda\\x97\\x3b\\x87\\x86\\xfe\\x8c\\xf9\\x2f\\x12\\xf8\\x60\\x4a\\x27\\x4f\\xf6\\xd0\\xea\\x85\\xae\\xf4\\x74\\x7d\\xb1\\x8c\\x1e\\x9b\\xf3\\x07\\x84\\x01\\x1c\\xf2\\xa1\\xdb\\xf5\\xfd\\x8a\\xfa\\x5d\\xaa\\x9e\\xb5\\xa5\\x7c\\xac\\x72\\xe6\\x96\\x21\\xce\\x35\\x48\\xcd\\x50\\x9c\\xec\\x89\\x4e\\xf7\\x5e\\x84\\xb3\\x95\\x35\\x40\\x45\\x12\\x2e\\xb0\\x47\\x56\\x8e\\x50\\xc5\\x49\\xc5\\xc1\\xae\\x52\\xdb\\x7d\\x2f\\xdd\\x76\\x81\\xcd\\xd1\\x9f\\xed\\x65\\x25\\xf3\\x35\\xf3\\x6d\\x72\\x02\\xb7\\xa8\\xc5\\x30\\xa0\\x6a\\x42\\x21\\x3c\\x5d\\x27\\x0c\\x37\\xa5\\x77\\xde\\x7a\\xe3\\x6d\\x3d\\xf8\\x54\\xb5\\x6c\\x5b\\x71\\x92\\xf4\\x70\\x6f\\xfa\\x42\\x2c\\xa3\\xaa\\x5a\\x46\\xb4\\x6e\\xd2\\xa2\\xf9\\x14\\xd1\\x32\\x6b\\x32\\x13\\x2f\\x6a\\x79\\x2d\\x2b\\x31\\x05\\xc4\\x7c\\xa9\\xa6\\x09\\xce\\x40\\x8a\\x4c\\x40\\x90\\x12\\xb9\\xd1\\xf5\\x83\\xfb\\x2b\\x29\\x91\\x02\\xe7\\xe2\\xe3\\x4f\\x9f\\xa1\\xf8\\x02\\x38\\xb8\\xee\\x2c\\x84\\xbb\\x17\\xc2\\x7d\\x1b\\x0e\\x87\\x60\\x32\\x38\\xfa\\xbb\\x93\\x27\\xcb\\xea\\x98\\xfd\\x22\\xe8\\x3d\\x1a\\xaa\\x43\\xd4\\x50\\xb8\\x71\\xa6\\x03\\x54\\x3f\\x8c\\x35\\xae\\x2c\\x1c\\x47\\x74\\xef\\xd3\\x53\\x2f\\xdc\\x93\\x4e\\x56\\x42\\x56\\x93\\x3d\\x0f\\x75\\xea\\x11\\x61\\x1b\\x7d\\x4c\\x0f\\x2f\\x7b\\xee\\x91\\xec\\xef\\x4c\\xe5\\xbc\\x69\\x75\\xdd\\xf9\\x0c\\x8e\\x1f\\x4f\\x0f\\x39\\x33\\xcb\\x79\\x25\\xd5\\x55\\x84\\x6f\\x9d\\x68\\x42\\x30\\x11\\xcc\\xfd\\xe0\\x4f\\x6c\\x2d\\x78\\xb5\\x99\\x52\\xee\\x72\\x3e\\xf6\\x4a\\x25\\xed\\x0e\\x16\\x40\\xb0\\xd0\\xb9\\x7b\\xf6\\x17\\x7f\\xed\\xc9\\x0d\\x9d\\x92\\xb8\\x83\\x83\\x27\\x37\\x5f\\x69\\x0a\\x23\\xfb\\x90\\x35\\x68\\x90\\xd1\\x34\\xc5\\xce\\x2f\\x4f\\x2f\\xcf\\x1f\\xd4\\x42\\xbd\\x89\\x25\\xc0\\xe8\\x1e\\x51\\xaa\\x93\\xbf\\x6e\\xf3\\x0e\\x0f\\x59\\xd5\\x6c\\x7f\\x06\\xd5\\xbb\\x0b\\x5d\\x5b\\x5e\\xed\\x89\\x08\\x14\\x33\\xbe\\x38\\x69\\xec\\xec\\x4c\\x1a\\x00\\xab\\xe9\\x2b\\x04\\xac\\xb4\\x4f\\x22\\x9d\\xb1\\xc4\\x86\\xc7\\x75\\x96\\xfe\\x38\\xd0\\x73\\xa7\\x7f\\x39\\xb9\\x60\\xbc\\x71\\xfb\\x6b\\x09\\x03\\x7e\\xaf\\x0e\\x77\\x3f\\xb2\\x4b\\xcc\\x30\\xd8\\x71\\x5e\\xd4\\x7a\\xcb\\xac\\xfc\\x53\\xf7\\x3d\\xa7\\xfb\\x88\\xc3\\x7d\\xf6\\x45\\x00\\x0d\\x45\\x0a\\xf6\\x84\\xfd\\x0f\\x52\\x49\\x2b\\xb9\\xd5\\x1d\\xcb\\xca\\x66\\x47\\x20\\x6b\\x1b\\x0c\\x02\\x8d\\xb1\\x7a\\x4e\\x27\\xf8\\xdc\\x3f\\x01\\x2e\\x64\\xe0\\xe2\\x2b\\x8d\\xa2\\xb5\\x00\\xa4\\x77\\x58\\xb1\\x73\\xe5\\x64\\x6d\\x5e\\x88\\x56\\x00\\xe4\\x00\\xb0\\xd9\\xb1\\x6f\\x19\\x9e\\xf9\\x67\\x32\\x50\\x01\\x0e\\x69\\xf5\\xe7\\xd7\\x59\\xc5\\x9c\\x95\\xf2\\x63\\xde\\x4a\\x11\\x6b\\x5b\\xed\\xd5\\xe2\\x23\\x7f\\xed\\x4b\\x14\\xe4\\xaf\\xaa\\x65\\x69\\xc3\\x09\\xfe\\x6b\\xc3\\x2b\\x5c\\x98\\x8f\\xfb\\x36\\x4b\\xe5\\x8b\\xdc\\x77\\xbc\\xf9\\x0e\\xd1\\xd0\\xe3\\x76\\x7c\\x0c\\x5a\\x7a\\x63\\x10\\xe1\\x14\\xe7\\x63\\x6b\\xae\\x8c\\xdb\\xa3\\x5c\\x17\\x3b\\x24\\xc7\\xd3\\x21\\x3b\\xb2\\xc5\\xe2\\x78\\xaf\\xf3\\xec\\x1f\\xda\\x5e\\x35\\x2a\\x15\\x38\\x70\\xe4\\x9f\\x71\\x5b\\xde\\x87\\xd0\\xf6\\xae\\x83\\xbc\\x17\\xd7\\x10\\x9c\\xf2\\xbe\\x56\\x15\\x6a\\x15\\x76\\x2b\\x9d\\x17\\xb2\\x7e\\xf6\\x5e\\x1a\\xeb\\xeb\\x66\\xc1\\x17\\xd2\\x50\\xb9\\x07\\x90\\xbb\\x2e\\x9c\\x22\\x27\\x17\\xff\\xc5\\xcb\\xb2\\x7e\\x8d\\x5c\\x8a\\x64\\x72\\xf8\\xb7\\x09\\x98\\x9b\\x5c\\x05\\x5f\\xe2\\x91\\x5d\\x2e\\x08\\xd3\\xf8\\xf3\\xe9\\x05\\xc3\\x3a\\x76\\x7f\\xfa\\x1e\\xeb\\xf4\\xff\\x9f\\x3f\\x7e\\xff\\xb2\\xf3\\x76\\x3f\\x5e\\xf0\\xf8\\x8e\\x76\\x8c\\xbd\\xfb\\x98\\x9e\\x44\\xdc\\x60\\x16\\x1f\\x08\\x70\\x8d\\x4e\\x36\\xb9\\xc4\\x70\\x3c\\x47\\x59\\xe9\\xaa\\xe3\\xc1\\x72\\xbb\\x1c\\xe8\\xfd\\x6e\\x12\\xcc\\x73\\x9c\\xdd\\xa3\\xc6\\xd9\\xb1\\x90\\x51\\x82\\x44\\xa2\\xe7\\x71\\x49\\x9b\\x42\\x8a\\xe1\\x2a\\xd9\\x41\\x8a\\x73\\xf1\\xf4\\x28\\xce\\xd6\\xb5\\xd9\\x7e\\x8a\\xf2\\xd3\\x93\\x3a\\xe3\\x7d\\x95\\xc2\\x18\\xc2\\x7e\\xf6\\xf1\\xf2\\xbf\\xde\\x9f\\xbc\\x79\\xfb\\x1e\\x46\\x4a\\xfe\\x7b\\x77\\x34\\xa4\\xda\\x39\\x7e\\xaa\\xfb\\x51\\xeb\\xa2\\xbc\\x6e\\x5f\\x90\\x7e\\x6e\\x19\\xd5\\x72\\xc8\\x28\\xf6\\xf1\\xdd\\x65\\x5f\\x5f\\xcc\\x5d\\x05\\x74\\x35\\xe9\\x34\\xf7\\x87\\xb5\\xb6\\x41\\xf1\\x39\\x51\\xef\\x2f\\x7f\\x64\\x67\\xa3\\x5c\\x82\\xb3\\x95\\xe9\\x5f\\x6e\\xa7\\x70\\x84\\x77\\x56\\x91\\xb6\\xee\\x00\\x7b\\x02\\x7e\\x07\\x37\\x5f\\x5c\\x83\\xbd\\x7b\\x1c\\xee\\x69\\xad\\xba\\xca\\x01\\x75\\xff\\xc4\\xa2\\x43\\x6c\\xe5\\x45\\x00\\x77\\x49\\x91\\xb6\\xd5\\x8e\\x66\\x3b\\x6a\\x2d\\x4c\\x00\\xc9\\x7c\\xa2\\x27\\x65\\xb1\\xae\\x0c\\x44\\x1f\\xea\\xb5\\xb6\\x83\\xac\\xaa\\x6c\\xe6\\x8b\\xc9\\x72\\x29\\x36\\xd5\\x74\\xf1\\x11\\x0a\\x7c\\x9e\\x40\\x87\\xef\\x13\\xdf\\x20\\x7e\\x85\\xdf\\x20\\x14\\xf1\\x83\\x13\\x40\\x78\\xed\\x1e\\x03\\x69\\x43\\x7f\\x7d\\x0f\\x72\\x68\\xd8\\xce\\x92\\xeb\\xb5\\x43\\x8c\\x1b\\xcf\\xa2\\x29\\xe6\\x28\\x4d\\xa7\\x7b\\xe4\\xed\\x63\\x0f\\xab\\xed\\xfc\\xb2\\xa3\\xa2\\xb3\\x6f\\x25\\x67\\x31\\xd3\\x56\\xab\\x9d\\xa3\\xe4\\xd7\\x35\\xcf\\x2f\\xf4\\x05\\x3c\\x71\\x1a\\xab\\x0d\\x26\\xa5\\xb8\\x21\\x82\\x32\\x38\\x23\\xa0\\x86\\x0e\\xb1\\x0b\\xad\\xbc\\x5b\\x22\\x77\\x4a\\x3c\\xb8\\x08\\x52\\x9e\\x9f\\xed\\xe9\\xf2\\x7d\\xbb\\x29\\x9e\\x7d\\x8d\\xc1\\x7b\\x0d\\x06\\x29\\x7b\\xe7\\xa4\\xb8\\x26\\x7e\\xc5\\xce\\xcf\\x48\\x34\\xf3\\x09\\x27\\x86\\x0e\\x24\\xdb\\x7c\\x22\\xf7\\xc6\\x3a\\x75\\x6d\\x6f\\x74\\xdd\\x3f\\xd5\\x3b\\x6f\\xd8\\x8a\\x55\\xa0\\xdf\\x56\\x52\\xb1\\x9e\\xe2\\xed\\xc1\\x31\\x3e\\xf2\\x0d\\xba\\x84\\x1b\\xd4\\xaa\\x24\\xb1\\xe9\\x26\\xdd\\xc7\\x45\\x7a\\xdc\\x0b\\x74\\x57\\x46\\x75\\xbf\\x59\\xbe\\x7b\\x15\\xd2\\xfd\\x71\\xeb\\x39\\x55\\xdf\\x8c\\x8c\\x09\\x6e\\x93\\x22\\xb5\\xe0\\x60\\x72\\x49\\x6e\\xdc\\xde\\xa8\\x43\\xad\\xb1\\x52\\x78\\x1f\\xc2\\xe0\\xdb\\xa0\\x01\\x17\\x71\\xa0\\xab\\xca\\xad\\xaa\\x56\\x29\\x82\\x34\\xa5\\xf1\\x0e\\x18\\xa2\\x2c\\xcf\\xf9\\x82\\x0a\\xaa\\x95\\xfa\\x46\\xdd\\xf0\\xba\\x64\\x27\\x17\\xe7\\xfb\\xa1\\x06\\x3d\\xe2\\xac\\xf1\\x24\\x75\\x43\\xf4\\xca\\x23\\xad\\x63\\x4b\\x2a\\xa8\\x27\\xa0\\x04\\x36\\x1b\\x4b\\x6b\\x62\\xe9\\x65\\x61\\x53\\xbd\\xd2\\x51\\xc1\\xe0\\xcb\\x72\\x77\\xd9\\xdd\\x5b\\xea\\x29\\x61\\x98\\x8a\\xe9\\xc2\\xf2\\xca\\x57\\x6b\\xa1\\x72\\x7c\\x2f\\x5f\\xbe\\x44\\x53\\xd8\\xcb\\x1f\\x7e\\xf8\\x01\\xcb\\x4b\\x96\\xa2\\x90\\xf3\\xd5\\x07\\xe1\\xa9\\x7f\\x7a\\xf5\\x6a\\xc4\\xfe\\xed\\xe4\\xc3\\x7b\\x2a\\xff\\x63\\x10\\x95\\x04\\x7b\\x86\\x75\\x4f\\x1b\\x9b\\x01\\xfb\\x97\\xcb\\x9f\\x3e\\xc6\\xd2\\x20\\xf9\\xaf\\xb0\\xad\\x61\\x7a\\x23\\x76\\x96\\xc4\\x3f\\xa5\\x86\\x2e\\x6e\\x67\\x54\\xd5\\xd1\\x32\\x3e\\x99\\xe0\\xc1\\xf0\\xf5\\x49\\xe8\\xc2\\xf9\\xec\\x71\\x39\\x9d\\xf9\\x72\\x60\\xee\\x48\\x54\\x10\\x98\\xe5\\x54\\x72\\x34\\x0d\\x7a\\x64\\x03\\x8c\\x33\\x83\\xbe\\x02\\x99\\x84\\xa1\\x0c\\x58\\x25\\xaf\\x04\\x9b\\x18\\x28\\x0a\\x16\\xe1\\xff\\x6a\\x61\\x9c\\x50\\x4a\\x45\\xb0\\xb1\\xb3\\xb8\\x33\\x46\\x74\\xc6\\x7a\\xb8\\x0f\\x0f\\x50\\xe7\\x32\\x44\\xb9\\xe9\\x9e\\xee\\x90\\x87\\x6f\\x25\\xec\\x62\\x1f\\x4b\\x8a\\x57\\xd0\\xad\\xd6\\xe3\\x78\\x64\\xb2\\xb1\\x5e\\x84\\xd1\\xe0\\xd6\\x11\\x4a\\x40\\xa4\\x13\\xbc\\xd2\\x50\\xce\\x34\\xec\\x74\\xe4\\x62\\x3e\\xe4\\x60\\xb9\\x10\\xdb\\xa7\\xd2\\x1b\\x7c\\xb1\\x2f\\x00\\x2f\\x12\\xaa\\x0f\\xbc\\x73\\x75\\xbd\\x3c\\x5e\\xc4\\xb7\\xce\\x70\\x15\\xf8\\x58\\x37\\xd6\\xfb\\xb0\\xe9\\x77\\x48\\xc0\\xb6\\xda\\x2f\\x51\\xc7\\x97\\xed\\x80\\x3c\\xb9\\x0b\\x02\\x71\\x6f\\x10\\xd3\\xdc\\xdf\\x0c\\x3c\\x21\\x17\\x25\\x06\\x4c\\xf0\\x62\\xc6\\xae\\xc4\\x72\\x88\\x74\\x6b\\xc1\\x21\\x9b\\x07\\x8b\\x10\\xb9\\xb5\\xc8\\x2a\\x4c\\x25\\xb5\\xd6\\x4e\\xc3\\x92\\xf9\\xc0\\x80\\x84\\xfb\\xf8\\x6c\\x20\\x2f\\x84\\x1a\\x92\\x97\\x08\\x46\\x54\\x25\\x96\\x02\\x8f\\x55\\x4d\\x05\\xd7\\xfd\\xd7\\x54\\x53\\xe0\\x7c\\x25\\x49\\xc5\\xdd\\x37\\x51\\xba\\x66\\xe6\\xb6\\x37\\xc7\\x68\\x08\\x47\\x07\\x89\\xbb\\x35\\x6a\\xa5\\x35\\xd5\\x56\\x27\\xe1\\x0f\\x5e\\xc8\\x3d\\x3a\\x73\\x12\\x51\\x01\\xd5\\x8c\\xa9\\xb0\\x22\\x3d\\xeb\\x57\\x29\\x2c\\x44\\x96\\x44\\x63\\x84\\x6d\\x68\\x69\\xb0\\x2e\\x69\\xa3\\x2a\\x61\\x0c\\x93\\x30\\xc3\\x39\\xaf\\xaf\\x84\\x07\\x8c\\xe1\\xd5\\x88\\x5d\\xb8\\x41\\x06\\xfc\\x2a\\x84\\x45\\xbe\\xa6\\xb2\\xb1\\x7c\\x99\\x65\\x07\\xb9\\x97\\x1c\\x8e\\x46\\x87\\x48\\xe0\\xd7\\xe4\\x0a\\xf5\\x38\\x1f\\xbb\\x61\\xea\\xee\\x80\\xa5\\x9b\\x1d\\xc4\\x0f\\x7c\\x61\\x10\\x19\\xd8\\x89\\x7c\\x80\\x7c\\xad\\x21\\x0b\\xce\\xce\\x3c\\x03\\xe3\\x9d\\x41\\x94\\x56\\xa7\\xb3\\x03\\x00\\xec\\xae\\xb8\\xe5\\xbb\\xa0\\x96\\x77\\xf2\\x5b\\xe4\\x9f\\xdd\\xd1\\xca\\x77\\xc2\\x2a\\xdf\\x84\\x54\\x4e\\x3b\\x45\\xb7\\xad\\x3f\\x86\\xf3\\x1d\\x20\\xb6\\xe7\\xbd\\x60\\x5e\\xfd\\x27\\x37\\x52\\x82\\xdc\\x91\\xa1\\xf4\\x74\\x92\\x11\\x09\\xf4\\xa9\\x12\\xdf\\x94\\x50\\x78\\x3e\\x59\\x57\\x04\\xd6\\x27\\x0b\\x26\\xf2\\xb2\\xa7\\xa1\\x58\\x6c\\xeb\\xb1\\xa5\\xc1\\x7e\\xb5\\x5c\\x58\\x6f\\xf1\\xb0\\xfd\\xe9\\x23\\x2e\\xb6\\x3f\\xdd\\x9c\\x81\\xed\\x4f\\xae\\xb0\\x25\\x69\\x49\\x81\\xe8\\xa7\\x51\\xfc\\xb0\\xa4\\x56\\x03\\x66\\x77\\xbc\\x82\\x23\\xf6\\x81\\x98\\x02\\x1e\\x46\\x3e\\x36\\xba\\x6a\\x6c\\xc8\\x64\\x5a\\xc3\\x31\\xa0\\x53\\x8f\\xf0\\x8d\\x29\\xa5\\xfe\\xb1\\x84\\x7f\\x00\\xe7\\x44\\xb2\\xdc\\x97\\x95\\xe0\\x67\\xa7\\x2b\\xde\\xb7\\x18\\xdd\\x6f\\x36\\x98\\xe4\\x0e\\x6b\\xe8\\x45\\x89\\x9d\\xd7\\xd1\\x77\\x10\\x70\\x27\\x7c\\x2c\\x75\\x26\\xe3\\x40\\x24\\x89\\x35\\x28\\x40\\x79\\x71\\x85\\xea\\x40\\xf5\\x9e\\x62\\x37\\xab\\x0d\\x8d\\x95\\x0c\\x13\\x27\\x17\\xe7\\x3b\\x69\\x00\\x49\\xfb\\x0d\\x3a\\x40\\xfa\\xc4\\x6f\\x58\\x0b\\x38\\x47\\x2d\\x20\\x2d\\xbb\\x73\\x16\\x67\\x4e\\x26\\x65\\x47\\x76\\x9e\\xbc\\x18\\xb9\\x32\\xec\\x77\\x8e\\x58\\xa6\\x41\\xa7\\x39\\x86\\x1e\\x1a\\x7b\\x22\\x59\\x4d\\x70\\xf7\\xbc\\xd7\\x11\\x2e\\xf1\\x53\\x17\\x39\\x1f\\x50\\x7c\\x84\\xf5\\xe8\\x14\\xdd\\xd8\\xfe\\xac\\x16\\xbb\\x83\\xc9\\xb2\\x4b\\x28\\x6d\\x83\\xfa\\x60\\xa2\\x58\\x2e\\x74\\xf9\\x1a\\xab\\x42\\x40\\xed\\x38\\x2c\\x0a\\x33\\xc0\\xda\\x38\\x66\\x80\\x0a\\xa3\\x93\\x22\\x12\\x5f\\x71\\x9d\\x98\\xdc\\x77\\x96\\x1b\\x76\\xaa\\x72\\x74\\x97\\x3a\\x47\\x6e\\x03\\x61\\xe6\\x17\\x7d\\x77\\x91\\xdd\\xb1\\x6c\\x11\\x4b\\x58\\xd3\\x6e\\x85\\x50\\xb2\\x3d\\xa5\\x9e\\xfc\\x06\\x9a\\x62\\x26\\xe6\\x1c\\x31\\xfc\\xfc\\xf4\\x1c\\x95\\xb9\\xa9\\xa5\\xb5\\x02\\xb1\\x94\\x44\\x0d\\x35\\x5f\\x07\\x99\\xcf\\xe0\\xe0\\xfa\\xd5\\xc1\\x2e\\xe5\\x60\\xee\\x58\\xb1\\x87\\xc5\\x5d\\xd8\\xc3\\x62\\x5c\\x64\\x22\\x9b\\x3b\\xd7\\xa0\\x4b\\x54\\x00\\xbc\\xa9\\x5a\\x06\\x09\\xc7\\x60\\xae\\x71\\xf5\\x1e\\x7c\\xe2\\xfb\\xd0\\xa3\\x76\\xd5\\x9f\\x06\\x41\\x60\\x78\\xd6\\x9f\\x9e\\xf5\\xa7\\xbd\\xe8\\x4f\\x09\\x63\\xf1\\x04\\x67\\x8d\\x2e\\x95\\x06\\x0c\\x7b\\x85\\x2a\\x26\\x32\\x25\\x00\\x3c\\xee\\x68\\x7a\\x55\\x2a\\x56\\x4a\\x47\\x8b\\x9b\\xd3\\x87\\x0e\\xbd\\x82\\x45\\xe7\\xb8\\xb1\\x93\\xe1\\x9f\\x98\\x50\\x85\\x2e\\x71\\xf3\\x5d\\xff\\xb5\\xb1\\x20\\xda\\x44\\x9d\\x24\\x1d\\xcb\\xdc\\xbf\\x2b\\xb5\\xda\\x41\\xdf\\xbb\\x6e\\xdd\\x4e\\x74\\xc0\\xbb\\x02\\xdf\\xed\\x89\\xc1\\x47\\xb6\\x1e\\x92\\x89\\x69\\xfa\\x01\\x6b\\x80\\xf8\\x7b\\x74\\x42\\x62\\xd5\\xe9\\x50\\x04\\x1f\\x4a\\xc7\\x1e\\xe1\\x97\\xa3\\x62\\xd1\\x0c\\xe8\\x81\\xd1\\x5c\\xcc\\x75\\xbd\\x1c\\x84\\x87\\xdc\\x8f\\x59\\x2b\\x7a\\xe2\\x18\\x64\\x82\\xa2\\xa9\\x9d\\x06\\x58\\x2d\\xbf\\x55\\xe9\\xc0\\x2f\\xd0\\x03\\x0b\\x07\\x61\\x9f\\xfa\\x15\\x0d\\x4a\\x3f\\xf9\\x91\\x88\\xa0\\x62\\xa0\\xdf\\xc7\\x22\\x4a\\x93\\x00\\x79\\x68\\x06\\x51\\xed\\x74\\xdf\\x0a\\x75\\xcd\\xae\\x79\\xdd\\x21\\x12\\x6f\\xdd\\xe7\\x8e\\xf2\\x40\\x29\\xaf\\xa5\\xd9\\xad\\xde\\x61\\x6b\\xea\\x97\\xc4\\x34\\xd0\\xae\\xa3\\x1b\\xbb\\x68\\x2c\\x51\\x4a\\x7f\\x2b\\x7c\\xca\\x7c\\xb8\\x0d\\x2d\\xa1\\xe8\\xd5\\xc1\\x4e\\xc3\\xf8\\x66\\xea\\x0b\\xe3\\x67\\xc7\\x2a\\xc3\\xf8\\xb9\\x6b\\xad\\xe1\\xbc\\x97\\x9d\\x8f\\xcd\\x5e\\x0b\\x8b\\xfb\\x8f\\x3f\\x16\\xfb\\xb8\\x87\\x91\\x45\\x46\\x9c\\x07\\x2f\\x9c\\x3e\\xd0\\x45\\xc3\\x70\\x93\\x9d\\xec\\x36\\x84\\x50\\xbf\\xde\\x64\\x43\\x3f\\xfe\\x86\\xad\\x35\\xfb\\xf5\\xd9\\x52\\x7e\\xe1\\xef\\xdc\\x61\\x7b\\x49\\xf5\\x0c\\x9e\\xbd\\xb5\\x9d\\x8e\\xe0\\xb3\\xb7\\xf6\\xd9\\x5b\\xfb\\xec\\xad\\x7d\\xb6\\x36\\x3c\\x5b\\x1b\\x9e\\xbd\\xb5\\xec\\xd9\\x5b\\xbb\\x97\\x35\\xdc\\x9f\\xb7\\x16\\x45\\xbd\\x75\\x3e\\x5b\\x12\\xf6\\xa2\\xc3\\xf6\\x41\\xfd\\xb5\\x54\\xb8\\xe7\\xa4\\x28\\x74\\xa3\\xec\\x67\\x7d\\x25\\x3a\\x3b\\x1d\\x5a\\xf2\\xff\\x4a\\x3f\\x00\\x80\\xb0\\x41\\x1f\\x58\\x7d\\xf8\\xc1\\x94\\x83\\xfe\\x52\\x49\\x2f\\xd9\\x62\\x17\\xa9\\x82\\x37\\xa5\\x74\\x92\\xff\\xce\\xc7\\xcc\\x77\\x90\\x82\\x13\\xa9\\x52\\x94\\xf1\\x07\\xba\\xca\\xd6\\xad\\xf5\\x88\\x9d\\xb0\\x5a\\x14\\x72\\x21\\xa9\\x8c\\x3c\\xc7\\xef\\xf1\\xe0\\x85\\xda\\x08\\xd2\\x1a\\x51\\x4d\\x08\\xa3\\x5e\\xa5\\xb5\\x7e\\xa2\\xfc\\x4e\\x74\\x70\\xed\\x6b\\x90\\x43\\x69\\x8f\\x64\\xee\\x6b\\x21\\xd5\\xe2\\xef\\x9e\\xb5\\xd1\\x68\\x3e\\xa7\\x3d\\xa4\\xe6\\x15\\x98\\x4a\\x56\\x62\\x08\\x5e\\xb6\\x90\\x94\\x60\\x7d\\xdf\\xd7\\x5f\\x7c\\x5d\\xc8\\x1a\\x0e\\xef\\xa5\\x28\\xb4\\xea\\x52\\x53\\x75\\xc3\\x06\\xad\\xf4\\x14\\xf9\\x13\\xd8\\x46\\x45\\xc9\\xca\\xa6\\x0e\\x35\\x53\\xaf\\x79\\x25\\x4b\\x69\\x97\\xc1\\x6b\\x47\\xe5\\xb5\\x38\\xde\\x98\\xb0\\x8d\\x26\\x2e\\x23\\xe3\\x8b\\x45\\xad\\x79\\x31\\x13\\x26\\x79\\x1b\\x0a\\x28\\x94\\x44\\x16\\x62\\xdf\\xb1\\x04\\x1c\\xc8\\x28\\xd0\\xc6\\x31\\xc8\\x6a\\xc9\\x6a\\x6d\\xbd\\xe3\\x7d\\xc3\\x0b\\x3f\\x27\\x9d\\x41\\x73\\xe4\\x72\\xb6\\x5e\\x82\\x77\\x5e\\xa7\\x5d\\xe0\\xa8\\xe4\\x24\\xfd\\xc3\\x30\\x5d\\x95\\x1e\\xc2\\xe4\\x4f\\x2f\\x9d\\x50\\x58\\xd0\\x19\\x74\\xc4\\x0f\\x00\\x2e\\xac\\x66\\x95\\x63\\xd8\\x8e\\x20\\x6e\\x6e\\xfc\\xc7\\xef\\xd8\\x4c\\x37\\xb5\\x19\\xa5\\xa0\\x03\\xaf\\xe0\\x3b\\xd4\\xef\\xbc\\x50\\x69\\x59\\x25\\xb8\\xb1\\xec\\xd5\\x4b\\x36\\x97\\xaa\\x71\\x7c\\xaa\\xf7\\xb1\\xe9\\x2f\\x07\\x25\\x12\\xd0\\xf7\\xdf\\x75\\x6e\\xd7\\x57\\xf6\\xd9\\x28\\xf5\\x2c\\x10\\x1b\\x99\\x44\\x1f\\xba\\x49\\x98\\x18\\x87\\xc8\\xe2\\x2d\\x41\\x88\\x88\\x6e\\xba\\xda\\xca\\xea\\x7b\\xb8\\x5f\\xbf\\x36\\x7a\\xbc\\xb4\\x7d\\x92\\x28\\xa9\\x45\\x9e\\x3d\\xf9\\xaf\\xf4\\x65\\x17\\xf0\\x94\\x88\\x9d\\x72\\xeb\\x4b\\xef\\xa5\\xc2\\xc5\\x54\\x1a\\xbb\\xa5\\xbe\\x45\\xcc\\xaf\\xbc\\xf5\\xb1\\xee\\x6c\\x65\\xea\\xb4\\x83\\x9e\\xb9\\x32\\xd0\\xc6\\x4b\\xc4\\xde\\xb6\\x54\\x14\\x02\\x8b\\x59\\x9e\\xc5\\x4a\\x49\\x4a\\xe3\\xb3\\x5b\\xbb\\x7f\\x64\\xc0\\x31\\x7f\\x40\\xf6\\x80\\x9a\\xde\\x71\\xaa\\xdd\\x84\\x2e\\x7f\\x24\\x7a\\xcf\\x15\\x9b\\xe5\\xb7\\xc0\\x48\\x35\\x45\\x90\\xf3\\x79\\x53\\x59\\xb9\\xa8\\xe2\\xbc\\x3f\\xf9\\x06\\x44\\xc8\\x53\\x9b\\x1b\\x4f\\xcc\\x44\\x1c\\x13\\x8b\\x11\\x6d\\x0a\\xec\\x93\\x47\\xa1\\x2f\\xa1\\x2c\\x62\\x75\\xd7\\x8e\\x1f\\x2c\\x78\\xcd\\xc3\\xe2\\x41\\x25\\x5d\\x73\\x4c\\xe6\\x3b\\x0e\\x1e\\x45\\x82\\xc3\\x74\\xad\\x78\\x15\\x47\\x9c\\x78\\x91\\xf6\\x79\\x68\\xac\\x50\\x5c\\x75\\x30\\x55\\xe7\\xf0\\x5c\\xd0\\x88\\xe9\\x9b\\x10\\x4c\\x86\\x65\\x50\\x5a\\xa7\\x85\\x84\\x9a\\x37\\xbc\\xb8\\x12\\xaa\\xc4\\xa2\\x51\\x30\\xed\\x72\\xa9\\xf8\\x9c\\xd0\\xb6\\x92\\x7a\\xdc\\xad\\xf6\\x66\\x40\\x86\\x09\\x4c\\xdf\\xf3\\x69\\xc6\\xc8\\x75\\xf7\\xb9\\x06\\x8d\\xe9\\x0d\\x65\\xe3\\x9a\\x6c\\xbb\\xe7\\x06\\x4d\\x36\\xb5\\xbc\\x2e\\x84\\xe7\\xff\\xae\\xdd\\x3e\\x87\\x7e\\xdd\\x21\\x97\\x7e\\x65\\xf0\\x7e\\x7b\\x92\\xf3\\x0b\\xe4\\x3e\\x58\\xce\\x01\\x54\\x8b\\x57\\xee\\x6a\\x2f\\x43\\xce\\x68\\x6b\\x73\\xc7\\xcb\\xfd\\x56\\xbd\\xa9\\xc7\\x7d\\x32\\x7f\\x0f\\xeb\\x71\\x99\\x5f\\xe2\\x4f\\xbc\\xd4\\x86\\xbd\\xa9\\x74\\x71\\xc5\\xce\\x04\\x08\\x5d\\xf7\\x59\\x9e\\xa5\\x1e\\x97\\x8f\\x09\\xe1\\x3d\\xe7\\xd3\\x6d\\x7e\\xb6\\x21\\x9b\\x6b\\x25\\xad\\xae\\x6f\\xa7\\x17\\x0f\\x57\\x76\\xf2\\x19\\xee\\x79\\x23\\x42\\x95\\x3b\\xcd\\x4f\\x19\\xec\\xd9\\x1d\\xb7\\xbe\\x1b\\x0f\\x8d\\x82\\x7a\\x06\\xb7\\x13\\xbf\\xa2\\x2a\\x60\\x3b\\xde\\xb5\\x3f\\xcc\\xf4\\xcd\\xd0\\xea\\x61\\x63\\xc4\\x50\\x76\\x70\\xe8\\xf6\\x98\\xe6\\x95\\x58\\x82\\x17\\xbb\\xe7\\x44\\xa9\\x59\\xa6\\x33\\x58\\x0d\\x16\\x28\\xf8\\xde\\x71\\xee\\x4f\\x6f\\xce\\xbe\\x18\\x51\\x8f\\x52\\x19\\xf0\\x85\\xb0\\xc5\\x8b\\x42\\x2c\\x66\\x2f\\xa8\\x87\\x27\\xb9\\x28\\x9e\\x88\\xf4\\x5d\\x15\\xdf\\x0e\\xd9\\x4c\\xa1\\xab\\x8a\\x12\\xb3\\xf5\\x84\\x9d\\x8a\\xc5\\x2c\\x74\\xfc\\xd0\\xb3\\x7e\\x3c\\x44\\xe0\\x85\\xd6\\x7d\\x81\\x50\\x0f\\x5d\\x9b\\xfc\\x12\\xc1\\x37\\x78\\x87\\x92\\xc3\\x54\\x8f\\xfb\\x15\\xa1\\x78\\xa8\\xe3\\xf3\\xa4\\x4b\\x6d\\xde\\xe3\\xe2\\xdc\\x2f\\x9c\\xf2\\x61\\x86\\xa7\\x9c\\xc6\\x7b\\xe6\\x60\\xc9\\x3e\\x62\\x24\\x23\\x41\\xe7\\x13\\x14\\xba\\x4b\\x51\\x32\\x7d\\x2d\\xea\\x5a\\x96\\xc2\\xb0\\x40\\x83\\x52\\x2d\\x55\\x56\\x0f\\xbd\\x6e\\xcf\\xb8\\xcd\\x8f\\x8e\\xdb\\xbc\\x83\\x3a\\x74\\x08\\xfa\\x50\\x46\\xa6\\xe0\\x9b\\x15\\x32\\xc5\\xcb\\xb9\\x54\\x4f\\x8e\\x50\\x99\\x82\\x57\\xe2\\xfc\\xa7\\x1e\\xfa\\x07\\xb5\\xc8\\x55\\x90\\x4b\\xfa\\x32\\xc1\\x4f\\xdb\\x82\\x4a\\xf6\\xd7\\x70\\x6e\\x98\\xd2\\xe5\\x36\\x93\\xea\\x3d\\x28\\x12\\x53\\x6e\\xc5\\xcd\\x56\\x76\\x38\\x8c\\x84\\x6a\\xfb\\x93\\x20\\x9c\\x3e\\xa6\\xca\\xf1\\x24\\x30\\x02\\x93\\x33\\x8f\\xa0\\x67\\xfb\\x64\\xaa\\xb4\\x6b\\x7d\\x8d\\x93\\xd8\\x2a\\x85\\xdf\\x6d\\x83\\xee\\xfa\\x13\\x7c\\x72\\x71\\xce\\x7e\\xc4\\xc7\\xf7\\x8b\\x5e\\x58\\x6b\\x8b\\x62\\xe0\\x99\\x9e\\x73\\xd9\\xb7\\xc8\\x46\\xbb\\x79\\x1b\\x7d\\x35\\x9d\\xc2\\x45\\x78\\x96\\xd1\\xc3\\x49\\x01\\x97\\x89\\x9c\\x36\\x4e\\xa7\\x23\\x3d\\xec\\x49\\x01\\xcc\\xad\\x88\\x2e\\x4f\\x17\\x60\\xee\\xee\\xd5\\x20\\x12\\x93\\x93\\x8f\\x8b\\x8c\\x12\\x8b\\xdf\\x4a\\x60\\x25\\xc1\\x07\\xca\\x8c\\x50\\x46\\x82\\x43\\x26\\xf1\\x8a\\x53\\xa5\\x3f\\x2c\\x2d\\x89\\x41\\x90\\x28\\xe2\\x0c\\xd8\\x7b\\x3d\\x95\\xca\\xdf\\x5e\\x4d\\xfe\\xba\\x09\\x97\\x55\\xd7\\xc5\\x78\\x96\\x49\\x1e\\x5d\\x26\\x31\\xa6\\x7a\\xab\\xf8\\xb8\\xea\\x12\\x6e\\x90\\x1f\\xb5\\xd0\\x90\\xbd\\xab\\xf8\\x94\\x09\\xf8\\xe3\\x45\\x29\\x8d\\xfb\\x3f\\xbb\\xbc\\x7c\\x0f\\x46\\xf8\\x46\\x79\\x89\\x19\\x0c\\xd4\\x44\\xfb\\x42\\x92\\x02\\x5e\\xc4\\xfd\\xde\\x1d\\x24\\x3d\\x3b\\xa0\\xff\\x25\\x2d\\x99\\x54\\xa5\\x1b\\x78\\x52\\x0a\\x0e\\x83\\xa4\\xe0\\x09\\xc4\\x43\\x0c\\x31\\xbf\\x18\\x36\\x30\\x16\\xec\\xf3\\x4c\\x16\\x57\\x17\\x89\\xdd\\x5d\\xd7\\xee\\x3b\\x95\\x7c\\x95\\x31\\xb0\\xf6\\x6f\\xfb\\xa4\\x96\\x34\\xd4\\x8b\\xfe\\xaa\\x71\\xd2\\xd2\\xf3\\x01\\x4f\\x30\\x2e\\x69\\xfe\\xf0\\x1b\\x37\\x46\\x17\\x32\\xfa\\x5c\\xc0\\x46\\x13\\x99\\x43\\x09\\xcc\\x61\\xbf\\x73\\x02\\xf1\\xa0\\xef\\x74\\x50\\xfe\\x58\\xc3\\xd1\\xfc\\x6e\\xfa\\xea\\xb8\\x26\\xe5\\x60\\x52\\xf9\\x59\\xef\\x75\\x0a\\x78\\x66\\x76\\x80\\x46\\x8f\\x0d\\x57\\xa1\\xd1\\xbd\\x30\\xdc\\x72\\x2c\\xf8\\x30\\x75\\xda\\x3c\\x2f\\x88\\xf9\\xda\\x9c\\x2b\\xdb\\x17\\x20\\xd2\\x09\\x9a\\x70\\x6f\\x13\\xef\\x92\\xb6\\xb1\\x4e\\x0d\\x6f\\x79\\x13\\xf1\\x3b\\x72\\x35\\xc0\\x9d\\x5b\\xe8\\x45\\x53\\x61\\x3c\\xc7\\xdd\\xf1\\xdd\\xbd\\xcd\\x18\\xdf\\xb3\\x27\\xd7\\xc3\\x43\\xa0\\x96\\x1e\\xa6\\x81\\xbd\\xfd\\x23\\x9d\\x7f\\x1b\\xd8\\xa5\\x89\\x70\\xf7\\xf2\\xfb\\xef\\xbe\\xfb\\xd6\\xd1\\x4c\\xbb\\xaa\\xe0\\xf7\\x01\\x67\\xda\\xd1\\x44\\xbb\\x26\\xbf\\xe8\\xfc\\x39\\xbf\\xe8\\xf7\\x9b\\x5f\\x74\\xff\\x28\\xb4\\x7b\\xce\\x20\\xea\\x19\\x9b\\xdb\\x2f\\x2e\\xb7\\x7b\\x8e\\x50\\xe7\\xe8\\xdd\\xbe\\x91\\xbb\\x3d\\xb2\\x80\\xf6\\x9b\\xfb\\xd3\\x3b\\x96\\xb5\\x4f\\x9e\\xcf\\x73\\x76\\xcf\\x6f\\x35\\xbb\\x67\\x97\\x58\\xd6\\xfe\\x99\\x3c\\x7d\\x62\\x58\\x7f\\x8b\\x59\\x3b\\x3d\\x2e\\x67\\xf7\\xec\\x92\\x3b\\xe7\\x94\\xf4\\x07\\x01\\xec\\x6f\\x4f\\xdb\\xa5\\x20\\x55\\x6c\\xb9\\x56\\x83\\xf4\\x49\\xe5\\x1e\\x7b\\xec\\xf0\\xd0\\x24\\xd0\\x62\\x56\\xbb\\x1b\\xf8\\x20\\x0a\\x09\\xeb\\xa1\\x8d\\x61\\xf7\\xba\\x4f\\x6d\\x48\\x6a\\xf3\\xd3\\x65\\xcb\\x31\\x13\\xbe\\x7e\\x1c\\x7f\\xcc\\xef\\xc1\\xe1\\xf1\\x5c\\xd3\\xe5\\x1b\\x31\\xb9\\x9b\\x0c\\xad\\xc5\\x5b\\x2b\\x80\\x04\\x00\\x23\\xd7\\xe3\\x14\\x25\\x32\\x5e\\x9d\\x93\\x8b\\x73\\xa7\\x83\\x43\\x1a\\x11\\xaf\\xcc\\x88\\xad\\xe1\\xf3\\xde\\x5c\\x4a\\x72\\x81\\xe7\\xef\\xdc\\x5a\\x31\\x5f\\xd8\\xee\\xbb\\xfe\\x6c\\x71\\x7f\\x74\\x8b\\xfb\\x1e\\x2d\\x80\\xb3\\x66\\xce\\xd5\\xd0\\xdd\\x28\\xb0\\xb9\\x67\\xde\\xba\\x16\\x65\\x1e\\x31\\xba\\x3b\\xc8\\x9e\\xc0\\x02\\x02\\xc9\\x05\\x79\\x61\\x63\\x9e\\x94\\xb9\\xbc\\x1f\\xb3\\x27\\xf4\\xbd\\xf3\\xcc\\x91\\xaf\\xb6\\x6e\\x5a\\xa1\\x57\\x02\\x5e\\x69\\x3a\\x61\\x15\\xfc\\xa5\\x4a\\x98\\x73\\xa6\\x86\\xdb\\x99\\x40\\x1e\\x7e\\x01\\x09\\x39\\xf1\\xa9\\x5c\\x92\\x46\\x51\\x9a\\x57\\x95\\xbe\\xc1\\x77\\xa7\\x7c\\xcd\\xad\\xbe\\x1b\\x0b\\x65\\x9a\\x8d\\x05\\x9b\\x4b\\xa7\\xa3\\x93\\x81\\x35\\x1d\\x0e\\xba\\x4c\\x9d\\x44\\x2e\\x6a\\x14\\x78\\x6b\\x72\\xb6\\x5d\\x0a\\x4b\\x1b\\x05\\x1b\\xed\\xf4\\x5b\\x85\\x01\\xe1\\xee\\xdf\\x3e\\xaa\\x08\\xde\\xed\\x69\\xc2\\x58\\xcc\\xf8\\xb5\\xd4\\x4d\\x8d\\xad\\xad\\x66\\x07\\xf4\\x13\\xf0\\x86\\xa5\\x6e\\x82\\xbd\\x0b\\x8b\\x61\\x86\\xd9\\x99\\x35\\xeb\\xf4\\x31\\xfe\\x08\\xaa\\x40\\xa9\\xbd\\x69\\x62\\x28\\xbe\\x4a\\x63\\x57\\xe7\\xe2\\x97\\xc8\\xc3\\xe0\\xed\\xeb\\xdc\\x5c\\x9b\\x85\\x63\\x0b\\xbd\\xab\\xda\\x65\\xed\\x72\\x79\\xe5\\xfa\\x12\\x7e\\xfa\\x86\\x6a\\xda\\x6d\\x45\\x77\\x7d\\x30\\x11\\xe8\\x77\\x28\\xfe\\x04\\x4f\\x58\\x25\\x8b\\x65\\xef\\x72\\x6f\\xad\\xd6\\x9e\\x68\\x9b\\xe0\\x43\\x73\\xdf\\xb3\\x37\\xdc\\x88\\x92\\x7d\\xe0\\x8a\\x4f\\x51\\xdf\\x3b\\xba\\xbc\\x78\\xf3\\xe1\\xd8\\xed\\x2b\\xe8\\x93\\xe7\\x67\\x6b\\x1d\\x6d\\x97\\x69\\xe7\\x1f\\xf7\\x99\\x2f\\xb2\\x32\\xf1\\x1d\\x58\\xd5\\x4a\\xfb\\x1d\\x27\\xbf\\xd7\\x44\\x18\\x16\\xf8\\x50\\x37\\xb0\\xde\\x35\\x2c\\xe8\\xa2\\x9d\\xc2\\xda\\xae\\xf9\\xd9\\x22\\x30\\xd7\\xf3\\xf2\\x8e\\x55\\x3e\\xa5\\x32\\x96\\x57\\xd5\\x45\\xc5\\xd5\\xc9\\x62\\x51\\xeb\\xeb\\xf5\\xda\\x78\\x36\\x56\\xff\\xa0\\x1f\\x29\\x86\\x79\\xf8\\x2f\\x17\\xb8\\xf4\\xe0\\xc2\\x56\\xec\\x3c\\xf6\\x3f\\x62\\xe7\\x36\\x68\\xe1\\x5a\\x01\\x4b\\x3d\\x38\\x69\\xac\\x9e\\x73\\x2b\\x8b\\x03\\xa7\\xac\\x1f\\x7c\\xe0\\xaa\\xe1\\xd5\\xda\\xa0\\xab\\x5b\\xa7\\xb1\\x49\\x44\\xbc\\xb5\\xd1\\x66\\xe8\\xba\\x0e\\xcd\\x6e\\x95\\x35\\x6e\\x6f\\x6f\\x79\\xed\\xa8\\xd3\\xe9\\xe5\\xcf\\xbd\\xda\\x1a\\xcb\\x6d\\xb3\\x42\\x85\\x6f\\xe1\\x0c\\x9b\\x79\\xc1\\x90\\x55\\xdc\\xd8\\x2f\\x8b\\xd2\\x5d\\xfa\\xd6\\xaf\\xb7\\x11\\xfc\\x82\\x5b\\x5e\\xe9\\xe9\\x5f\\x04\\xaf\\xd6\\x9f\\xf0\\xec\\x9c\\x9c\\xa6\\x4f\\x7b\\x03\\x14\\x39\\xfc\\x9b\\x71\\x78\\xf0\\xd0\\x30\\x27\\x60\\xfb\\x1c\\xf8\\x5a\\x54\\xe2\\x9a\\x2b\\xeb\\x9b\\x63\\x71\\x75\\x73\\x48\\xf3\\x87\\x53\\x24\\xa3\\xf1\\xb5\\x14\\x56\\xd4\\x73\\xa9\\xf2\\x3e\\x2f\\xe1\\xd9\\x53\\xad\\x4a\\x89\\x66\\x47\\x30\\xa8\\x61\\x8b\\xbc\\xdf\\xcd\\x47\\x6d\\x93\\xa7\\xe1\\x16\\xdf\\x42\\x8e\\xae\\x99\\x8c\\x27\\x5f\\x0a\\x7c\\x6c\\x4c\\xf2\\xe5\\x0c\\xbf\\x04\\x4f\\x7b\\x36\\xb6\\x95\\x95\\x62\\x57\\xca\\x09\\x86\\x80\\x23\\xb2\\x9e\\x6c\\x6d\\x95\\x13\\xb6\\xc9\\x07\\x43\\xbf\\xc7\\x38\\x84\\xcd\\x81\\xa3\\x43\\x1a\\xf7\\x26\\x1f\\xc4\\x6d\\x47\\x0c\\x3f\\xdb\\x25\\x8b\\xf6\\x50\\x36\\xd3\\xd4\\x75\\xe7\\x2e\\x34\\xc3\\x4c\\x96\\x56\\x41\\xfe\\xec\\xa1\\xcd\\x3c\\xa0\\x93\\xe0\\xd5\\x4d\\x46\\xea\\x8a\\x6a\\x9f\\xd3\\xda\\x88\\xc1\\xbe\\xa2\\xca\\x76\\x90\\x18\\xb7\\x32\\xad\\x8e\\xe0\\xf2\\xb9\\x62\\x7d\\x4e\\xf1\\x7f\\x35\\xa9\\x22\\x9c\\x2d\\xa4\\x40\\xf0\\x13\\xae\\x68\\xb1\\x80\\xb3\\x08\\x5e\\xd2\\x97\\x8e\\x83\\x39\\x95\\x10\\x7e\\x1b\\x90\\x33\\x1c\\x8d\\xcb\\x14\\x6b\\xe1\\x0d\\xd4\\x1c\\xc1\\x3f\\xc0\\x71\\xf1\\xe2\\x47\\x4d\\x46\\x5e\\x4a\\xd2\\x75\\x34\\x00\\x38\\xf9\\x80\\x99\\xa6\\x98\\x31\\x6e\\xdc\\xd0\\xdc\\x81\\x76\\x37\\x5e\\x8c\\xe6\\x5c\\xc9\\x89\\x30\\x76\\x14\\x50\\x82\\xcd\\xbf\\xff\\xf1\\x3f\\x47\\xec\\x9d\\xae\\x19\\x05\\xaa\\x0f\\x3c\\xaa\\x06\\x8d\\x33\\x9e\\x0b\\x69\\x70\\x32\\xa1\\x6d\\xd4\\x5a\\x17\\xba\\xa4\\x41\\xdf\\xc0\\x60\\x2d\\xbf\\x72\\x3c\\x0c\\x07\\xdb\\x08\\x70\\x5d\\xbc\\x66\\x07\\x4e\\x4c\\x4c\\x5e\\xfd\\x3f\\x8e\\x2d\\xfd\\xef\\x01\\x3b\\xba\\x01\\xa6\\x7d\\xe0\\xfe\\x3c\\xc0\\x17\\x86\\xb0\\xc9\\x54\\xa9\\x8e\\x2f\\xc6\\x64\\xc9\\x5a\\x4e\\xa7\\xa2\\x46\\xf5\\x91\\x41\\x52\\xe1\\x31\\xa1\\x82\\x28\\x9d\\x3c\\xec\\x9d\\xd2\\x51\\xdd\\x6c\\x0f\\xe4\\xdf\\xff\\xf8\\x9f\\x07\\xec\\x28\\x9f\\x17\\x93\\xaa\\x14\\x5f\\xd9\\x1f\\xd1\\xba\\x2c\\x8d\\x9b\\xe3\\x31\\x39\\x73\\xcc\\x52\\x59\\xfe\\xd5\\xf5\\x59\\xcc\\xb4\\x11\\x0a\\x55\\x79\\xab\\xd9\\x8c\\x5f\\x0b\\x66\\xb4\\xd3\\x80\\x45\\x55\\x0d\\xc9\\x96\\xce\\x6e\\x38\\x20\\xb5\\xf8\\xa5\\x84\\xc4\\x7a\\xb6\\xe0\\xb5\\xcd\\x8e\\xc4\\x88\\x2c\\x24\\xf0\\x36\\xb7\\x6d\\x53\\xe5\\x3d\\xd3\\x13\\xa9\\xc8\\x7f\\x45\\x9e\\x33\\xb7\\xe7\\x90\\x18\\x8a\\x9b\\x64\\x35\\x2b\\x66\\x5c\\x4d\\x43\\x6e\\xfa\\xa4\\xb1\\x4d\\x2d\\xb6\\xb8\\x7e\\x3a\\xde\\x81\\x2b\\xa9\\x7a\\xa5\\x30\\xff\\x55\\xaa\\x76\\x50\\xc1\\x7a\\xbb\\xd2\\x54\\x5a\\x9f\\x15\\x41\\xb1\\x8a\\x76\\xf9\\xc2\\xed\\x42\\x2d\\xc7\\x8d\\xd5\\xb5\\x79\\x51\\x8a\\x6b\\x51\\xbd\\x30\\x72\\x3a\\xe4\\x75\\x31\\x93\\x56\\x14\\x6e\\x5a\\x2f\\xf8\\x42\\x0e\\x0b\\xad\\xdc\\x8e\\x03\\x2a\\xc3\\xbc\\xfc\\x03\\x94\\x37\\x1d\\xba\\xa1\\x6e\\x41\\x9d\\xee\\x38\\xe9\\xed\\x46\\xb5\\x47\\x35\\xa6\\xed\\x6d\\x8e\\x1d\\xec\\x41\\xab\\x13\\x45\\xdb\\xcc\\x03\\xcc\\x16\\x0c\\x21\\x2f\\xf6\\x32\\x59\\x0f\\x9a\\xdc\\x9f\\xc7\\x1c\\x12\\x0e\\x78\\xd1\\xee\\xc3\\x5d\\x3b\\x0c\\x20\\x81\\x5b\\x99\\x51\\xca\\x39\\x2f\\x91\\x94\\x72\\xb5\\xbc\\xf7\\xc3\\xef\\x96\\x14\\xe0\\xf2\\x8b\\xe5\\x10\\xba\\xd0\\xd5\\x90\\xab\\xd2\\xfd\\x1b\\x13\\x76\\x8a\\xe5\\x5e\\xd6\\xb0\\x91\\xbd\\x08\\xc1\\x97\\xf3\\xb3\\x87\\xb9\\x12\\x8d\\xdc\\xc3\\xad\\x27\\x79\\xad\\xa3\\x10\\x85\\xa2\\x2a\\x06\\x6a\\xd4\\x8d\\xf0\\x4c\\x33\\x17\\x50\\xa5\\xf1\\xbd\\xfe\\x5f\\xf2\\xbf\\x04\\xb4\\xb3\\x6d\\x22\\xd5\\xed\\x5e\\x93\\x44\\x76\\xec\\x38\\xde\\xf7\\xb1\\x45\\x6a\\x93\\x83\\xc0\\x2b\\x6e\\x2c\\x41\\x6b\\x79\\x0c\\x82\\x6c\\x1a\\x5e\\x41\\x01\\x06\\xb3\\xd9\\x31\\xdc\\xe9\\x0c\\xf9\\x78\\x01\\x37\\x90\\xe1\\x5a\\xcc\\xa5\\x22\\x28\\x25\\xdb\\x15\\xa8\\xa8\\xbf\\x64\\x75\\xd0\\x70\\x52\\x56\\x18\\xcb\\xf8\\x35\\x97\\x15\\x58\\xe7\\xf5\\xd8\\x88\\xfa\\x1a\\x0b\\x52\\x11\\xd4\\x20\\x6f\\xeb\\x59\\x54\\x73\\x02\\xc5\\xa8\\x07\\xd2\\x7c\\xfc\\x1c\\x56\\x77\\xe5\\xb6\\x09\\x80\\x36\\xd4\\x1a\\xfd\\xc6\\x51\\xef\\x45\\xef\\x41\\xf5\\x72\\xe3\\xcf\\xee\\x0d\\x3b\\xaa\\x31\\xee\\xfc\\xfd\\x45\\xf0\\xda\\x8e\\x05\\xb7\\x9f\\xe5\\x6d\\x7c\\x77\\xe5\\x48\\x67\\xed\\x42\\x29\\xf7\\x70\\xa0\\x6f\\x04\\x9b\\x6a\\xeb\\x44\\xac\\x06\\xce\\x3e\\xca\\xa4\\x08\\xea\\x13\\x0e\\xda\\x7d\\x9f\\xe8\\x38\\xcb\\xcf\\x35\\x87\\x14\\x1f\\xad\\x7a\\x4e\\x33\\x6f\\xb8\\x3a\\x4f\\x92\\x8e\\xe9\\x24\\x59\\x7c\\x1a\\x81\\x34\\xb4\\x12\\xb4\\x77\\xe8\\xcd\\x00\\x0a\\xf4\\x30\\x53\\x9e\\x0b\\x63\\x6e\\x05\\xd8\\xc8\\xa3\\x0b\\xf1\\x69\\xbc\\xca\\x2d\\xd7\\xda\\xdc\\xff\\x86\\x69\\x21\\x4e\\x80\\x2e\\x85\\xe5\\xb2\\xf2\\x57\\x19\\x97\\x22\\xac\\xd2\\x36\\xea\\x7a\\xeb\\x04\\x6b\\xc1\\xcd\\x6d\\x02\\x42\\x36\\xea\\x4f\\xf0\\x30\\x0e\\x5a\\x2b\\x31\\xbc\\xd1\\x75\\xc9\\x4e\\xf9\\x5c\\x54\\xa7\\xdc\\x08\\xea\\x2b\\x4d\\xd1\\xc3\\x3d\\x3a\\x34\\x7b\\x1d\\xf2\\x7a\\xdb\\xd7\\x86\\x21\\xa3\\xf1\\x27\\x9a\\x84\\xe1\\xaf\\xa8\\x62\\xe1\\x00\\x07\\xde\\x04\\xf9\\xb9\\x6e\\xc4\\x80\\xbd\\x73\\xdc\\x6b\\xc0\\xbe\\xa8\\x2b\\xa5\\x6f\\xee\\x36\\x56\\x7b\\xab\\x17\\x24\\x1b\\x69\\x1a\\xfe\\xe1\\x61\\x75\\x32\\x83\\x4f\\x18\\xee\\x8e\\x23\\x22\\x82\\xbf\\xc1\\xd4\\x98\\x33\\x9b\\xf0\\xa8\\x1f\\x91\\xfb\\xe7\\x8a\\x09\\xca\\x29\\x8a\\xb5\\x9e\\xd6\\xc2\\x20\\x72\\xcd\\x5a\\x90\\xc4\\xae\\x26\\xe7\\x1f\\x85\\xa2\\xe4\\xbe\\xad\\xc3\\x3b\\x5f\\xd7\\xca\\x8f\\xd4\\xf3\\xb5\\x69\\xfc\\x85\\xf6\\x9b\\x5e\\xb6\\xa8\\xd6\\x8a\\x1a\\xb7\\x47\\x04\\x26\\x03\\xdd\\x60\\x7c\\xda\\x34\\xc2\\xf5\\x46\\xa7\\x84\\xeb\\x25\\xcf\\xa2\\x50\\x72\\x9b\\x75\\xd4\\xcf\\xee\\xf4\\xf2\\xe7\\xcd\\x8b\\xbd\\x91\\xf7\\x6d\\xe3\\x4f\\xdb\\xcd\\x52\\x77\\x35\\x48\\x6d\\xbd\\x33\\x5b\\x8d\\x50\\xcf\\xe6\\xa7\\x67\\xf3\\xd3\\xb7\\x64\\x7e\\xda\\x7a\\xe2\\x6f\\x33\\x39\\x7d\\x1b\\xc6\\xa6\\xad\\x53\\xbc\\xcd\\xc0\\xf4\\x24\\x4d\\x4b\\x9d\\x66\\x74\\xab\\x39\\xe9\\xc9\\x1a\\x92\\xb6\\x4e\\xad\\xa3\\xf1\\xe8\\xf7\\x63\\x36\\xda\\xba\\x62\\xb7\\x98\\x8a\\x9e\\xa0\\x91\\xa8\\x8b\\x40\\x26\\xca\\x2e\\x62\\xe2\\x79\\xf2\\x70\\x2a\\x28\\xc6\\x72\\x96\\xa1\\x3b\\x1f\\x94\\x93\\x8a\\x33\\xbb\\x4a\\x8b\\x4e\\x80\\xdb\\x3a\\xb6\\x43\\x1a\\x5c\\x77\\xd9\\x8b\\x04\\x46\\x2a\\xf6\\xb8\\x32\\x58\\x76\\xf6\\xf6\\xe2\\xd3\\xdb\\xd3\\x93\\xcf\\x6f\\xcf\\xda\\xf2\\xdd\\xba\\x95\\xde\\x22\\x89\\xdd\\x6e\\x83\\x18\\x26\\x92\\xd8\\x86\\x07\\x1c\\x41\\xde\\xf0\\x93\\x3b\\x03\\x1b\\x7e\\x6a\\x1a\\xb9\\xae\\xd5\\xdd\\xe5\\xc2\\x3b\\x71\\xb9\\x3b\\xf1\\x8f\\xed\\xb7\\xb3\\xeb\\xf5\\xfc\\x82\\x81\\x53\\x9c\\x62\\xce\\x9c\\xdc\\x33\\xd3\\x55\\x69\\x7c\\xdc\\xea\\xf9\\x59\\xc8\\xa4\\x92\\xaa\\xa8\\x9a\\xd2\\x09\\x17\\x5f\\xbe\\x9c\\x9f\\x99\\x11\\x63\\x6f\\x44\\xc1\\x1b\\x03\\x56\\x98\\x52\\xab\\x43\\xcb\\x7e\\xfa\\xf8\\xfe\\xdf\\x20\\x1e\\x1b\\x9e\\x18\\x04\\x5c\\x13\\x40\\xe5\\x95\\x1c\\x81\\x85\\x2d\\xc2\\xb5\\xb1\\x37\\x02\\x05\\x15\\x78\\x73\\xc1\\x17\\x8e\\x8a\\x19\\xac\\x5c\\x61\\x41\\x16\\x99\\x89\\x6a\\xe1\\x28\\xe6\\x95\\x60\\x11\\x41\\xd5\\x75\\x1c\\x2b\\xcc\\xfb\\xf0\\xc9\\xa9\\xb0\\x98\\x75\\x75\\x5b\\x84\\xe4\\xad\\xab\\xb6\\xc5\\xe2\\x7a\\x07\\x5b\\x6b\\xa6\\x3e\\x92\\x36\\x7e\\xc3\\x0d\\x59\\xac\\xd6\\x8e\\x76\\xcb\\xfe\\x6e\\xb7\\xcf\\x6c\\x36\\x71\\x6c\\x30\\x6e\\x20\\x79\\x86\\xbf\\x56\\xc6\\xec\\x06\\x1b\\xed\\x18\\x18\\x44\\x22\\x6d\\x67\\x6b\\xea\\xe6\\x30\\xa0\\xf5\\x75\\x00\\x56\\x6c\\x19\\xa2\\xbd\\xc8\\xd9\\x8b\\x43\\x44\\x76\\x32\\xe4\\x6e\\x63\\x81\\x22\\x22\\x65\\x56\\xfb\\x93\\xe2\\xe7\\xf2\\xef\\x9a\\x71\\xa8\\xfe\\x1a\\xc7\\x4b\\x16\\x19\\xf6\\x3f\\xff\\xfb\\x0f\\xff\\xf0\\xff\\x03\\x00\\x00\\xff\\xff\\x05\\x75\\x02\\xbb\\xcd\\xa1\\x0c\\x00\")\n\nfunc olmManifests0270CrdsYamlBytes() ([]byte, error) {\n\treturn bindataRead(\n\t\t_olmManifests0270CrdsYaml,\n\t\t\"olm-manifests/0.27.0-crds.yaml\",\n\t)\n}\n\nfunc olmManifests0270CrdsYaml() (*asset, error) {\n\tbytes, err := olmManifests0270CrdsYamlBytes()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tinfo := bindataFileInfo{name: \"olm-manifests/0.27.0-crds.yaml\", size: 827853, mode: os.FileMode(420), modTime: time.Unix(1730300878, 0)}\n\ta := &asset{bytes: bytes, info: info}\n\treturn a, nil\n}\n\nvar _olmManifests0270OlmYaml = []byte(\"\\x1f\\x8b\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xec\\x5a\\xdd\\x6f\\x1b\\xb9\\x11\\x7f\\xd7\\x5f\\x31\\x10\\x0a\\xb8\\x2d\\xb2\\x92\\xe5\\xef\\x2c\\x10\\xe0\\x5c\\x27\\x77\\x39\\xd4\\x76\\x04\\xcb\\xe9\\xcb\\x21\\x28\\xb8\\xdc\\xd1\\x8a\\x35\\x97\\xdc\\x23\\xb9\\x52\\x74\\x45\\xff\\xf7\\x82\\xcb\\xfd\\x16\\x25\\xcb\\x4a\\xee\\x52\\x14\\xe1\\x8b\\x24\\x72\\xc8\\x19\\xce\\xcc\\xce\\xc7\\x4f\\x1b\\x04\\xc1\\x80\\x64\\xec\\x1f\\xa8\\x34\\x93\\x22\\x84\\xe5\\x64\\xf0\\xc4\\x44\\x1c\\xc2\\x3d\\x49\\x51\\x67\\x84\\xe2\\x20\\x45\\x43\\x62\\x62\\x48\\x38\\x00\\x10\\x24\\xc5\\x10\\x24\\x4f\\x07\\x00\\x9c\\x44\\xc8\\xb5\\x9d\\x05\\xc8\\x64\\x1c\\x68\\xa4\\xb9\\x62\\x66\\x3d\\x7a\\xca\\x23\\x54\\x02\\x0d\\xea\\x11\\x93\\x63\\x14\\x73\\xa9\\x28\\x86\\xa0\\x50\\x1b\\xc5\\xa8\\xc1\\x78\\xcf\\x2d\\xc1\\xb2\\x92\\x8a\\x13\\x83\\xda\\x3c\\xb7\\x8d\\xe4\\x31\\x33\\x2f\\xe1\\x53\\x6c\\x78\\x29\\x97\\x15\\x51\\xe2\\x25\\x4c\\x2c\\xfd\\x06\\x8f\\xc3\\xd4\\x9e\\xa1\\x22\\x46\\x2a\\x7d\\x80\\xf2\\x23\\xa2\\x91\\x33\\x81\\xdf\\x55\\x6f\\x55\\xef\\x74\\x3d\\x43\\xb5\\x64\\x14\\xaf\\x29\\x95\\xb9\\x30\\x7d\\x7b\\x78\\xdd\\x3e\\xa8\\x6c\\x10\\x68\\xb7\\x99\\x94\\x9b\\x1d\\x4d\\x61\\x39\\xf7\\x7c\\xf4\\x2d\\xac\\x22\\x42\\x47\\x24\\x37\\x0b\\xa9\\xd8\\x6f\\xc4\\x30\\x29\\x46\\x4f\\x57\\x85\\x94\\xb5\\xed\\x6f\\x78\\xae\\x0d\\xaa\\x07\\xc9\\x7d\\xd6\\xd7\\x6b\\x6d\\x30\\x0d\\xa9\\x14\\x46\\x49\\xce\\x51\\x85\\xb5\\x2c\\x9c\\xcd\\x91\\xae\\x29\\xc7\\x20\\x25\\x82\\x24\\xa8\\x06\\x2a\\xe7\\xa8\\xc3\\x41\\x00\\x24\\x63\\x3f\\x29\\x99\\x67\\x3a\\x84\\x5f\\x86\\x7f\\x1d\\x7e\\x1a\\x80\\xd5\\x9f\\xcc\\x15\\xc5\\xd6\\xd4\\x12\\x55\\x54\\xfc\\x5c\\x11\\x43\\x17\\xc3\\x57\\x30\\xe4\\x4c\\x1b\\xfb\\x99\\x60\\xf1\\x41\\x15\\x12\\x83\\xf6\\x5b\\x9e\\xc5\\xe5\\xb7\\xac\\xa2\\x8d\\x91\\xa3\\x9b\\x72\\xdf\\xa8\\x15\\x8f\\xda\\x2b\\xda\\x39\\xd4\\x94\\xf0\\x72\\x4b\\xc4\\x44\\x3c\\xfc\\x34\\x08\\x40\\x48\\xf1\\x50\\x8a\\xf1\\xf1\\xe1\\xd6\\x27\\x89\\xfd\\xf9\\x65\\x3a\\xfc\\x1b\\x13\\x31\\x13\\xc9\\x73\\x86\\x8c\\x1c\\x59\\x60\\x8d\\xa6\\x24\\xc7\\x07\\x9c\\x5b\\xca\\x4a\\x71\\x3b\\xb8\\x0e\\x00\\x36\\x0d\\x77\\x90\\xb9\\x74\\x1e\\xfd\\x0b\\xa9\\x29\\x2c\\xe6\\xf5\\xcd\\xaf\\xe2\\x82\\x75\\xfc\\x18\\x51\\xa9\\x50\\xda\\x8f\\xb4\\xd1\\xdc\\x87\\xdb\\xbb\\x1b\\x29\\xe6\\xcc\\xa7\\x30\\xea\\x2e\\xb8\\x71\\x22\\xc9\\x32\\xdd\\x9c\\xf0\\x16\\x33\\x2e\\xd7\\x29\\x0a\\xf3\\x8c\\xce\\x37\\x45\\xed\\x06\\x34\\x92\\x65\\xbd\\x0d\\x3a\\x43\\x6a\\xd7\\xb4\\x51\\xc4\\x60\\xb2\\x76\\x74\\x66\\x9d\\x61\\x08\\x0f\\xe8\\xbc\\xb3\\x70\\xed\\x8c\\x33\\x4a\\x74\\x08\\x13\\x4b\\x8c\\xd6\\x0d\\xa5\\x72\\xc4\\xa9\\x75\\xd7\\xdb\\x16\\x17\\x1f\\x1f\\x00\\x83\\x69\\x66\\xdd\\xb5\\xdc\\xd4\\xba\\x87\\x1d\\xbc\\xb3\\xdf\\x7f\\x02\\x40\\x25\\x6d\\xf1\\xbd\\x0c\\x4d\\x37\\x52\\x18\\xfc\\x6c\\x9a\\xad\\x2a\\x17\\xd7\\xfa\\x5e\\x8a\\x07\\x29\\x4d\\x08\\x46\\xe5\\x58\\x2f\\x69\\xa4\\x54\\xa6\\xd9\\x54\\xc9\\x39\\xe3\\xd8\\x6c\\xa9\\x6f\\x9c\\x0b\\xc3\\x52\\x7c\\x8b\\x73\\x92\\x73\\x53\\x33\\x6a\\x7b\\xcc\\xfd\\x1e\\xee\\x62\\x87\\xf5\\x4f\\xc2\\x04\\xaa\\xd6\\xa5\\x02\\xbf\\xc9\\x5a\\xd2\\xf9\\x6f\\x54\\x28\\x84\\x73\\xb9\\x9a\\x2a\\xb6\\x64\\x1c\\x13\\x7c\\xe7\\x9e\\xfd\\xc2\\x57\\xe6\\x84\\x6b\\xec\\xd0\\x52\\x92\\x91\\x88\\x71\\x66\\x18\\xea\\xee\\x29\\x00\\xb1\\x92\\x59\\x08\\xbf\\xc0\\xf0\\xfa\\xf6\\x76\\x08\\x9f\\x5a\\xab\\x54\\xa6\\x29\\x11\\x71\\x7b\\x43\\x00\\xe3\\x88\\x89\\xb1\\x73\\xa4\\x5a\\x12\\x95\\xe8\\x2e\\x51\\x10\\xd4\\x5e\\xd7\\x99\\xff\\xd3\\x9f\\x3f\\x4c\\xdf\\x3d\\x5c\\x3f\\x7e\\x78\\xf8\\xe7\\xfd\\xf5\\xdd\\xbb\\xd9\\xf4\\xfa\\xe6\\xdd\\x5f\\x7a\\x3b\\x57\\x8a\\x19\\x9c\\x19\\x62\\x72\\x6d\\x55\\xdb\\x59\\x1d\\x0e\\x5b\\x3f\\x59\\x4a\\x12\\x0c\\xe1\\xd7\\x9c\\xac\\x6d\\x60\\xaa\\xb5\\x3f\\x57\\x24\\xc5\\x95\\x54\\x4f\\x56\\xcc\\x1f\\xf4\\x82\\x9c\\x9c\\x5f\\x84\\x93\\xe8\\xe2\\xf8\\xf8\\x64\\x72\\x7e\\x31\\x3f\\xbf\\xb8\\x8a\\x2f\\x4f\\x4e\\xe8\\xc9\\xeb\\xc9\\xe9\\xd5\\xf9\\xe5\\xf9\\xe5\\xe9\\xe9\\xf9\\xeb\\xc9\\xf1\\xe9\\x25\\x3d\\x39\\x8b\\xce\\xa2\\x39\\x89\\xe8\\xc5\\xe5\\xeb\\xb3\\x8b\\xf9\\xc9\\xc5\\x15\\xc5\\xb3\\xcb\\xf3\\x13\\x7a\\x8a\\x17\\x7d\\xbe\\xd3\\x9c\\xf3\\xa9\\xe4\\x8c\\xae\\x43\\xf8\\x79\\x7e\\x2f\\xcd\\x54\\xa1\\xc6\\xda\\xd8\\x50\\xa4\\x4b\\x65\\x7a\\xda\\x0e\\x1a\\x2f\\x98\\x4a\\x65\\x42\\xb8\\x3a\\xbe\\x3a\\xee\\xd9\\xc3\\x79\\x44\\x8a\\x36\\xf3\\xea\\xd6\\x1a\\x67\\x4b\\x14\\xa8\\xf5\\x54\\xc9\\x08\\xbb\\xc7\\x2e\\x8c\\xc9\\x7e\\x42\\xd3\\xb7\\x6c\\x46\\xcc\\x22\\x84\\xf1\\x02\\x09\\x37\\x8b\\xdf\\xfa\\x8b\\xdb\\xf8\\x6b\\xba\\x40\\x2b\\xc1\\xfb\\xc7\\xc7\\x69\\x6b\\x49\\x21\\x89\\xd9\\x37\\xe4\\x6f\\x50\\xa5\\x4c\\x14\\x1e\\x7e\\x87\\x5a\\x5b\\x13\\x94\\xea\\xff\\x91\\x70\\x1e\\x11\\xfa\\xf4\\x28\\x6f\\x65\\xa2\\x3f\\x88\\x77\\x4a\\x75\\x9e\\x22\\x14\\xcb\\xae\\x77\\x3a\\x0d\\x6f\\x7a\\x62\\x47\\x90\\x25\\xe1\\x39\\xfe\\xa8\\x64\\xda\\xbf\\xd5\\x9c\\x21\\x8f\\xcb\\xd4\\xe5\\x59\\x99\\x16\\x97\\xae\\xa2\\xd9\\xc8\\xff\\x1c\\x78\\x24\\xd8\\x64\\xbe\\x35\\x2c\\x34\\x65\\x45\\x67\\x93\\xc2\\x5f\\x73\\xd4\\x7d\\x97\\x03\\xa0\\x59\\x1e\\xc2\\xe4\\x38\\xed\\x4d\\xa7\\x98\\x4a\\xb5\\x0e\\x61\\x72\\x71\\x7c\\xc7\\xca\\x35\\x21\\x63\\x9c\\x75\\x62\\xb9\\x1d\\xdd\\x52\\x4f\\xea\\x10\\x38\\x13\\xf9\\xe7\\x2f\\xc9\\x51\\x94\\x18\\xc2\\x65\\xf2\\xb2\\x3c\\xb5\\xb1\\xe9\\x77\\xcc\\x55\\x1e\\x01\\x0f\\xc8\\x57\\x9e\\x53\\xfe\\x6f\\x72\\x96\\xf7\\x6e\\xcf\\xdc\\x0a\\xbe\\x71\\xde\\x2a\\x65\\xde\\x99\\xbb\\x8e\\x5a\\xc9\\xeb\\xa8\\xb3\\xd2\\xcd\\x7a\\x36\\x57\\xd1\\xa2\\x8c\\x4b\\x49\\x66\\x8b\\x48\\x54\\x3f\\xdb\\xcc\\xf0\\x66\\x47\\x42\\xaa\\xe9\\x1b\\xbd\\x2b\\x4c\\x98\\x36\\x6a\\x1d\\xb6\\x1a\\xb3\\x86\\x41\\x6e\\x18\\x0f\\x8a\\x84\\xd3\\x59\\xf8\\xe3\\x93\\x9e\\x15\\x46\\xa3\\x09\\x2c\\x0b\\x2e\\x49\\x1c\\xe4\\x1a\\x55\\xc0\\xe2\\x37\\x1d\\xd7\\xfc\\x9e\\x94\\x9b\\xf1\\x3d\\x29\\xef\\x4a\\xca\\x5f\\x37\\x87\\x5d\\x7d\\x49\\x0a\\xdb\\xec\\x2c\\xf7\\xee\\x84\\x37\\x13\\x1b\\x49\\x12\\x85\\x09\\x31\\x68\\xbb\\xdc\\x00\\x63\\x66\\x7a\\x99\\x6c\\xfb\\x79\\xcd\\x56\\x23\\x03\\x12\\xa7\\x4c\\x84\\x30\\xb4\\x8f\\xd7\\xf0\\x25\\x1b\\xb1\\x80\\x87\\xca\\x7d\\x7e\\x70\\xc2\\xd7\\x9d\\x6e\\xe2\\x15\\x3a\\x8f\\x34\\x55\\x2c\\xb3\\x9c\\x74\\x17\\x31\\xd8\\x07\\xa3\\xf8\\x74\\x18\\xd7\\xb2\\xff\\x2d\\xb3\\x51\\x89\\x28\\xe9\\x02\\x18\\x71\\xb1\\xbb\\xa4\\xb5\\x33\\x4c\\x68\\x43\\x38\\xcf\\x38\\x71\\x14\\x3b\\x24\\x6e\\x84\\xfa\\x7d\\x0d\\xbe\\x64\\xb8\\xfa\\x96\\x06\\x7f\\xc1\\x3e\\x2b\\xea\\x57\\x71\\x94\\xaf\\x67\\xb2\\x57\\x50\\xb3\\x4c\\x0a\\x21\\xba\\x46\\x2c\\x11\\xb2\\x0a\\x30\\x73\\x08\\xda\\x86\\x9f\\x65\\x84\\x3e\\x91\\x04\\xf5\\x68\\x3f\\xe9\\x4b\\xf2\\x94\\x08\\x36\\xb7\\x91\\xc7\\xf9\\x72\\x77\\x6e\\xcc\\xa8\\x14\\xfb\\xc9\\xf2\\x32\\x20\\xa8\\x5c\\x2d\\x84\\xf7\\xf8\\x56\\xc2\\x65\\x44\\x78\\xd0\\x46\\xa3\\xdb\\x55\\x72\\x3d\\xfd\\x75\\xb9\\xb6\\xcb\\xc2\\x3e\\x4b\\x9e\\xd6\\x45\\xb7\\x21\\x2a\\x41\\x53\\xa3\\xe8\\xa5\\xb7\\x07\\x2f\\xc1\\xc3\\x08\\xcf\\x16\\xa4\\x87\\x27\\x96\\x70\\x5c\\xb9\\xd5\\x23\\x5e\\x65\\xdf\\xa2\\xe2\\x7a\\xae\\x6f\\x90\\x3c\\x1d\\xd5\\xb0\\xf4\\xf2\\x78\\x74\\x72\\x39\\x3a\\xae\\x6f\\x10\\x33\\x9d\\x71\\xb2\\x76\\xc5\\xf0\\xd4\\x1d\\x0b\\xb3\\xea\\xdc\\x18\\x6b\\xcf\\xb4\\xdd\\x44\\xe6\\x4a\\x09\\x0d\\x44\\xd4\\x1a\\xac\\x64\\x01\\xb3\\x20\\x06\\x98\\x06\\xb2\\x24\\x8c\\x93\\x88\\x23\\xcc\\x95\\x4c\\x81\\x40\\x62\\xeb\\x03\\xb8\\x71\\xcf\\xc1\\xac\\xf0\\x3a\\x58\\x2d\\x18\\x5d\\xc0\\x8a\\x71\\x5e\\x78\\x22\\x5f\\x22\\x18\\x09\\xc4\\xaf\\x80\\xd1\\x00\\x20\\x65\\xe2\\xef\\x79\\x84\\xb5\\x36\\x27\\xa3\\xc9\\x64\\x64\\x33\\xf4\\x13\\xae\\x57\\x52\\xc5\\xd6\\x21\\x8f\\xfa\\x3e\\x7b\\xf4\\x0a\\x8e\\x24\\x4f\\xed\\x47\\xa5\\xb1\\x23\\xeb\\xc1\\x29\\x61\\xed\\x9a\\xbe\\xaa\\xe6\\x1f\\x30\\x86\\xf7\\xc4\\x55\\x4a\\x98\\x12\\xc6\\x0b\\xa3\\x09\\xbd\\x60\\x73\\xd3\\x78\\xc3\\x0f\\x0a\\xe3\\x05\\x31\\xd6\\x7c\\x03\\x80\\x4c\\xc9\\x25\\x8b\\xb1\\x4c\\xb3\\xfd\\x73\\x38\\x13\\x4f\\x1d\\x16\\x1b\\x1a\\x06\\xc8\\x15\\x0f\\x8b\\x42\\x45\\x87\\xe3\\x71\\xc2\\xcc\\x22\\x8f\\x0a\\xd7\\xf0\\x95\\x8d\\x5b\\x31\\xdd\\xb1\\x51\\x88\\xe3\\x94\\x58\\xe5\\x8d\\xb3\\xa7\\x64\\x5c\\xde\\x37\\xa8\\x5d\\xa4\\x8c\\x3a\\x77\\x32\\xc6\\x52\\x22\\xd7\\x29\\x7d\\x58\\x89\\xfb\\x4e\\x7f\\xae\\xf3\\xcc\\x96\\x40\\x18\\xd7\\x2d\\x57\\x45\\x3a\\x63\\x22\\xe1\\xb8\\x2f\\xf5\\x5d\\xce\\x0d\\xdb\\x97\\xf8\\x9a\\xf3\\xe6\\x29\\xda\\x42\\x5b\\xde\\xc0\\x69\\xba\\x6e\\x77\\x21\\x6e\\x7a\\x6c\\xe8\\x75\\x96\\x65\\x54\\x9e\\xda\\x0a\\x4d\\x17\\x11\\xb9\\x5a\\x09\\x0e\\x6c\\x06\\x6d\\x53\\xca\\xb1\\xd3\\x09\\x36\\x81\\xb7\\x57\\x51\\x6f\\x01\\xf1\\x9f\\xa9\\xfe\\x02\\x28\\xe1\\x79\\x42\\x29\\x6a\\xad\\xd0\\xe6\\xa8\\x76\\xb9\\xed\\xc2\\x6f\\xbf\\x7a\\xaf\\xfa\\xfc\\xf6\\x64\\x82\\xe6\\x39\\x39\\x7b\\x70\\xa2\\x57\\xa6\\xa2\\x37\\x70\\x2d\\xdb\\x4e\\x39\\xba\\x0c\\xed\\x6f\\x9b\\x19\\x3a\\x13\\x45\\x8a\\xd8\\x43\\x26\\x6f\\xda\\xda\\x43\\xce\\x4e\\xae\\xfd\\x83\\x64\\xdd\\x9d\\x6b\\x9f\\x17\\xba\\x1f\\xb4\\x0e\\x16\\xbb\\x79\\x10\\x5a\\x6e\\xee\\xcf\\x17\\x6e\\xb4\\x1f\\x15\\x80\\x3e\\x84\\x54\\x8d\\x12\\x50\\x91\\x9c\\x33\\x91\\x7c\\x2c\\x6a\\xdd\\x6e\\xbb\\xd2\\x5e\\xe9\\xf7\\x2c\\x29\\xf9\\xfc\\x51\\xd4\\x19\\xc1\\x81\\x4f\\xbd\\xf5\\x59\\xae\\x92\\xde\\x4a\\x03\\x56\\x9d\\x74\\x10\\x95\\x7e\\x47\\x03\\x7e\\xf0\\xaa\\x1a\\x05\\xfc\\xe4\\xbf\\x7a\\x1f\\xc9\\xaa\\x4f\\xeb\\x21\\x5a\\xd5\\xe8\\x23\\x5b\\x7b\\xb1\\xd8\\xd4\\x30\\x3c\\x07\\x0c\\xc1\\x6e\\xd8\\xab\\x75\\xc6\\x16\\xf8\\xab\\xbe\\xde\\x76\\x18\\xac\\x39\\xe4\\xb0\\x08\\xe8\\x86\\xbf\\xc7\\xac\\xc6\\xb6\\x5e\\xb3\\x4b\\xe5\\x83\\xd6\\xdc\\xd8\\xed\\xb8\\x7b\\xab\\xf2\\x65\\x48\\x5b\\x29\\xd4\\x0e\\xbc\\xcd\\x8d\\xed\\xa8\\x5b\\x75\\xad\\x0d\\xec\\xad\\xba\\x55\\x81\\xc0\\x6d\\xe4\\xe6\\x3e\\x55\\xb0\\x7c\\x73\\xe6\\x9b\\x76\\x6f\\x1e\\x60\\x60\\x13\\xa3\\x67\\x7d\\x78\\x7e\\x76\\x76\\x3a\\xf4\\x6e\\x2c\\xab\\x68\\x1f\\x12\\x5f\\x11\\x75\\x91\\x3d\\x37\\xbe\\x15\\x92\\xd5\\xe2\\xde\\xc6\\xb3\\xae\\xf9\\x8a\\xac\\xf5\\x06\\x9d\\x07\\xcf\\x02\\x1f\\xa6\\x65\\xd5\\xe3\\x31\\x68\\xa6\\xa4\\x91\\x54\\xf2\\x10\\x1e\\x6f\\xa6\\x1b\\xeb\\x3b\\xd0\\x2d\\x37\\xb6\\x60\\x4c\\x6e\\xb4\\x31\\xa3\\x99\\x97\\x62\\x27\\x16\\xd5\\xdc\\x6f\\x8b\\xf4\\xbb\\xc0\\xaf\\xff\\x01\\xf1\\x0e\\xc7\\xc6\\xaa\\xeb\\x79\\x6b\\xa4\\x6a\\xd1\\x8f\\x93\\xb9\\xb1\\x05\\x2d\\x73\\xa3\\xc2\\xcc\\xce\\x1b\\xcc\\xac\\x19\\x4b\\xc9\\xf3\\x14\\xef\\x6c\\xcc\\xf3\\x7a\\x95\\x8b\\x4c\\x26\\xcd\\xe6\\x9b\\xae\\x08\\x90\\xda\\x7d\\xee\\x0f\\xb0\\xb1\\x49\\xb3\\x81\\xef\\xec\\xad\\xe1\\xce\\x7f\\x28\\xa6\\x99\\x59\\xbf\\x65\\x2a\\x84\\x7f\\xff\\xa7\\xe8\\x5e\\x4c\\x11\\xf5\\x42\\x28\\x7a\\x47\\xd7\\x91\\x77\\xbb\\xbb\\xe2\\x85\\x92\\x32\\x7c\\xc7\\x38\\x67\\x82\\x99\\xa6\\xfa\\x95\\x2b\\x81\\x71\\xd5\\xa9\\x26\\xee\\xad\\x93\\x9d\\x45\\x4c\\x29\\xd0\\xb2\\xf5\\xba\\x92\\x9b\\x71\\x4d\\x6b\\xd9\\xd3\\xdc\\x95\\x05\\x4c\\x85\\x41\\xb6\\xe3\\x77\\xbf\\xb8\\xf1\\x75\\x9d\\xbd\\xfd\\x9d\\xd6\\xf3\\xba\\x4f\\x54\\x34\\x9a\\xb5\\x7b\\x40\\x82\\xc2\\x8a\\x8d\\xb1\\xeb\\x39\\xf1\\x33\\xd3\\x86\\x89\\xa4\\xdb\\x74\\xda\\xb6\\x35\\x06\\xb3\\x40\\xa6\\xc0\\xbd\\x7b\\x72\\xd7\\x54\\xb4\\x4d\\xf1\\x74\\xbf\\x35\\xf1\\xf8\\xc2\\xc9\\x41\\x5d\\x7e\\x5b\\xaa\\x1d\\x6f\\xde\\x2d\\xf2\\x88\\xc9\\xa0\\xf9\\xbf\\x66\\x0b\\x08\\xe1\\x74\\xf0\\x58\\x24\\xfc\\x44\\x65\\x74\\xb0\\x35\\x6e\\x17\\x07\\x56\\x7f\\x00\\x35\\x7f\\xb6\\x74\\xac\\x71\\x23\\xd3\\x34\\x17\\xcc\\xac\\xeb\\x0e\\xdf\\xaa\\x28\\xcb\\x23\\xce\\xf4\\x02\\x55\\x03\\x9d\\xbc\\xcf\\x23\\xd7\\xd0\\x58\\x9e\\x53\\x19\\x3b\\x95\\x96\\xdd\\x59\\x37\\x31\\x97\\x4b\\xdd\\x77\\xe9\\x1c\\x6c\\x3a\\xeb\\xd4\\x9c\\xd5\\x1f\\x41\\x53\\x59\\xf5\\x79\\xb6\\xed\\x33\\xa8\\x96\\x84\\x87\\x70\\x71\\x9c\\x0e\\xfe\\x1b\\x00\\x00\\xff\\xff\\xa1\\x41\\x61\\x14\\x42\\x2a\\x00\\x00\")\n\nfunc olmManifests0270OlmYamlBytes() ([]byte, error) {\n\treturn bindataRead(\n\t\t_olmManifests0270OlmYaml,\n\t\t\"olm-manifests/0.27.0-olm.yaml\",\n\t)\n}\n\nfunc olmManifests0270OlmYaml() (*asset, error) {\n\tbytes, err := olmManifests0270OlmYamlBytes()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tinfo := bindataFileInfo{name: \"olm-manifests/0.27.0-olm.yaml\", size: 10818, mode: os.FileMode(420), modTime: time.Unix(1730300878, 0)}\n\ta := &asset{bytes: bytes, info: info}\n\treturn a, nil\n}\n\nvar _olmManifests0280CrdsYaml = []byte(\"\\x1f\\x8b\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xec\\xfd\\x79\\x77\\x23\\xb7\\x95\\x30\\x0e\\xff\\xfd\\xf8\\x53\\xe0\\x28\\x99\\xd3\\x92\\x43\\x52\\xdd\\x71\\x26\\xcf\\x4c\\x4f\\x12\\x1f\\x8d\\xd4\\x76\\xf4\\xba\\x17\\x1d\\x49\\x76\\xde\\x79\\x1c\\x4f\\x0c\\x56\\x5d\\x92\\x88\\xaa\\x80\\x0a\\x80\\xa2\\x44\\xc7\\xf9\\xee\\xbf\\x83\\x0b\\xa0\\x16\\xee\\xb5\\x48\\x62\\xb7\\x81\\x9c\\x13\\xb7\\x58\\x55\\x58\\x2f\\xee\\xbe\\x0c\\x87\\xc3\\xcf\\x68\\xc6\\xbe\\x03\\xa9\\x98\\xe0\\xaf\\x09\\xcd\\x18\\x3c\\x68\\xe0\\xe6\\x2f\\x35\\xba\\xfb\\x0f\\x35\\x62\\xe2\\x74\\xfe\\xea\\xb3\\x3b\\xc6\\xe3\\xd7\\xe4\\x3c\\x57\\x5a\\xa4\\xd7\\xa0\\x44\\x2e\\x23\\xb8\\x80\\x09\\xe3\\x4c\\x33\\xc1\\x3f\\x4b\\x41\\xd3\\x98\\x6a\\xfa\\xfa\\x33\\x42\\x28\\xe7\\x42\\x53\\xf3\\xb3\\x32\\x7f\\x12\\x12\\x09\\xae\\xa5\\x48\\x12\\x90\\xc3\\x29\\xf0\\xd1\\x5d\\x3e\\x86\\x71\\xce\\x92\\x18\\x24\\x76\\xee\\x87\\x9e\\xbf\\x1c\\xbd\\xfa\\xdd\\xe8\\xe5\\x67\\x84\\x70\\x9a\\xc2\\x6b\\x12\\x51\\x4d\\x13\\x31\\xb5\\x63\\xa9\\x91\\xc8\\x40\\x52\\x2d\\xa4\\x1a\\x45\\x42\\x82\\x30\\xff\\x49\\x3f\\x53\\x19\\x44\\x66\\x90\\xa9\\x14\\x79\\xf6\\x9a\\xac\\x7d\\xc7\\xf6\\xe7\\xe7\\x42\\x35\\x4c\\x85\\x64\\xfe\\x6f\\x42\\x86\\x44\\x24\\x29\\xfe\\xdb\\xad\\xd1\\x0e\\x7b\\x83\\xc3\\xe2\\xef\\x09\\x53\\xfa\\x9b\\xd5\\x67\\x6f\\x99\\xd2\\xf8\\x3c\\x4b\\x72\\x49\\x93\\xe5\\x09\\xe3\\x23\\x35\\x13\\x52\\xbf\\x2f\\x87\\x37\\xc3\\x45\\x54\\x2b\\x19\\xd9\\xc7\\x8c\\x4f\\xf3\\x84\\xca\\xa5\\x6f\\x3f\\x23\\x44\\x45\\x22\\x83\\xd7\\x04\\x3f\\xcd\\x68\\x04\\xf1\\x67\\x84\\xb8\\x9d\\x72\\x5d\\x0d\\x09\\x8d\\x63\\xdc\\x7d\\x9a\\x5c\\x49\\xc6\\x35\\xc8\\x73\\x91\\xe4\\x29\\x2f\\x86\\x32\\xef\\xc4\\xa0\\x22\\xc9\\x32\\x8d\\x3b\\x7c\\x3b\\x03\\x92\\x49\\xd0\\x7a\\x81\\x5b\\x42\\xc4\\x84\\xe8\\x19\\xf8\\xb1\\x8b\\xaf\\x08\\xf9\\xbb\\x12\\xfc\\x8a\\xea\\xd9\\x6b\\x32\\x32\\x3b\\x3c\\x8a\\x99\\xca\\x12\\xba\\x30\\xb3\\xa9\\xbc\\x65\\x8f\\xe9\\xc2\\x3e\\xab\\xfc\\xae\\x17\\x66\\xea\\x4a\\x4b\\xc6\\xa7\\xdb\\xa6\\x62\\xde\\xdb\\x7f\\x0e\\x76\\x6b\\x6e\\x17\\xd9\\xea\\x14\\x96\\x7e\\xdc\\x77\\xfc\\x2c\\x1f\\x27\\x4c\\xcd\\x40\\xee\\x3f\\x89\\xe2\\x93\\x95\\x39\\x5c\\xad\\x79\\xb2\\x61\\x22\\x95\\x4e\\xfd\\xbd\\x19\\x45\\x12\\xf0\\xca\\xdc\\xb2\\x14\\x94\\xa6\\x69\\xb6\\x32\\xc0\\xd9\\x74\\x75\\x8d\\x31\\xd5\\xfe\\x47\\xfb\\xd2\\xfc\\x15\\x4d\\xb2\\x19\\x7d\\xe5\\x7e\\x54\\xd1\\x0c\\x52\\x5a\\xc2\\x83\\xc8\\x80\\x9f\\x5d\\x5d\\x7e\\xf7\\xc5\\xcd\\xd2\\x03\\x52\\xdf\\x9d\\x1a\\x9c\\x13\\xa6\\x08\\x25\\x12\\x32\\xa1\\x98\\x16\\x72\\x61\\x76\\xeb\\xfc\\xe6\\x3b\\x35\\x20\\xe7\\xd7\\x17\\x6a\\x40\\x28\\x8f\\x8b\\x8b\\x47\\x32\\x1a\\xdd\\xd1\\x29\\xa8\\xd1\\xca\\x5c\\xc5\\xf8\\xef\\x10\\xe9\\xca\\xcf\\x12\\xfe\\x91\\x33\\x09\\x71\\x75\\x16\\x66\\x7b\\xfc\\x9e\\x2c\\xfd\\x6c\\xf6\\xbf\\xf2\\x53\\x26\\xcd\\x98\\xba\\x72\\x91\\x6d\\xab\\x20\\xb3\\xda\\xef\\x4b\\x2b\\xfc\\x79\\xb8\\xf4\\x94\\x10\\xb3\\x31\\xf6\\x4b\\x12\\x1b\\xcc\\x06\\x0a\\x81\\xc2\\xdd\\x3a\\x88\\xdd\\x6e\\x5a\\x60\\x61\\xca\\xec\\x88\\x04\\x05\\xdc\\xe2\\x3a\\xf3\\x33\\xe5\\x6e\\x95\\xa3\\x95\\xce\\x6f\\x40\\x9a\\x8e\\x0c\\x42\\xc8\\x93\\xd8\\xa0\\xc4\\x39\\x48\\x4d\\x24\\x44\\x62\\xca\\xd9\\x4f\\x45\\xef\\x8a\\x68\\x81\\xc3\\x26\\x54\\x83\\xd2\\x04\\xef\\x35\\xa7\\x09\\x99\\xd3\\x24\\x07\\xdc\\xec\\x95\\xbe\\x53\\xba\\x20\\x12\\xcc\\xb8\\x24\\xe7\\x95\\x1e\\xf1\\x13\\xb5\\x3a\\x97\\x77\\x42\\x02\\x61\\x7c\\x22\\x5e\\x93\\x99\\xd6\\x99\\x7a\\x7d\\x7a\\x3a\\x65\\xda\\x23\\xfb\\x48\\xa4\\x69\\xce\\x99\\x5e\\x9c\\x22\\xde\\x66\\xe3\\xdc\\x20\\xd4\\xd3\\x18\\xe6\\x90\\x9c\\x2a\\x36\\x1d\\x52\\x19\\xcd\\x98\\x86\\x48\\xe7\\x12\\x4e\\x69\\xc6\\x86\\xb8\\x18\\x8e\\x08\\x7f\\x94\\xc6\\xbf\\x92\\x50\\xc5\\x80\\xcb\\x60\\xb0\\x74\\x1b\\x88\\xc7\\xbb\\x0d\\x0f\\xcb\\xe0\\x63\\x0b\\x98\\xb6\\x43\\xbb\\xd8\\xf2\\x4c\\xcc\\x4f\\x66\\x1b\\xaf\\xdf\\xdc\\xdc\\x12\\x3f\\x23\\x7b\\x6e\\xf6\\x88\\xca\\x57\\xd7\\xec\\x90\\x3f\\x2d\\xb3\\xb3\\x8c\\x4f\\x40\\xda\\x2f\\x27\\x52\\xa4\\xd8\\x2b\\xf0\\x38\\x13\\x8c\\x6b\\x8b\\x35\\x12\\x06\\x5c\\x13\\x95\\x8f\\x53\\xa6\\x15\\x82\\x35\\x28\\x6d\\x0e\\x72\\xb5\\xe3\\x73\\x24\\x8e\\x64\\x0c\\x24\\xcf\\xcc\\xe5\\x8d\\x57\\x5f\\xb9\\xe4\\xe4\\x9c\\xa6\\x90\\x9c\\x53\\x05\\x4f\\x7e\\x76\\xe6\\x8c\\xd4\\xd0\\x1c\\xc8\\xde\\xa7\\x57\\x25\\xfd\\xab\\x1f\\xac\\xdc\\x7a\\x42\\x3c\\xcd\\xde\\xeb\\xe5\\x4d\\x68\\x82\\x58\\x9c\\xb0\\x8e\\x26\\x90\\x2d\\xd8\\xc1\\x34\\x1a\\xc7\\x12\\xd4\\x9a\\x07\\xbb\\xa1\\xce\\xb4\\x33\\xfb\\xb9\\x05\\xbe\\x99\\x50\\x06\\x08\\xa8\\x26\\x1f\\xde\\xbe\\x23\\x11\\xe5\\x24\\x57\\x60\\xae\\x70\\x24\\x38\\x37\\x50\\xa6\\x05\\xa1\\x86\\xe6\\x0e\\xe1\\x81\\x29\\x84\\x4a\\x09\\x53\\xa6\\xb4\\x5c\\xac\\x9e\\xad\\x69\\x5f\\x09\\x99\\x52\\xfd\\x9a\\xfc\\xc1\\xbf\\x36\\xc4\\x21\\x84\\x24\\x2c\\xfb\\xd3\\xeb\\x3f\\x64\\x42\\xea\\x3f\\xad\\xfd\\xf0\\x03\\x4f\\x16\\x66\\xf0\\x98\\xdc\\xcf\\x80\\x93\\x9b\\x62\\x67\\xc8\\x1f\\x2b\\x7f\\x7c\\x2d\\xb3\\x68\\xfd\\xc0\\x97\\x53\\x2e\\xa4\\xff\\xda\\x80\\xf5\\x65\\x4a\\xa7\\x40\\x26\\x0c\\x12\\xbc\\x68\\x0a\\xd6\\x60\\xb5\\x2d\\x60\\x41\\x2c\\xe3\\x37\\x61\\xd3\\x77\\x34\\x6b\\xbb\\xd7\\xe7\\xbe\\x03\\x33\\x03\\x33\\xa9\\x2a\\xdb\\x52\\x3e\\xd4\\x02\\x6f\\x94\\x59\\xbc\\xf9\\x27\\x8d\\xee\\x08\\x75\\x83\\xa7\\x34\\x1b\\x2a\\xbc\\xcd\\x3b\\x36\\x7e\\xbf\\xfd\\x3b\\xf7\\x9d\\x9a\\x13\\x29\\x7f\\xbe\\x74\\x58\\xba\\xf1\\x0e\\x55\\x37\\xa1\\xf1\\xb7\\x25\\x53\\xb6\\x73\\x7f\\xdf\\xad\\xa3\\xa9\\x7b\\x8c\\x31\\x95\\x59\\x74\\x25\\x62\\xbb\\xec\\xb6\\xa7\\xf8\\x75\\xb5\\x13\\x02\\x0f\\x99\\x50\\xa0\\x48\\xcc\\x26\\x13\\x90\\x06\\x73\\x8a\\x39\\x48\\xc9\\x62\\x50\\x64\\x22\\x24\\x1e\\x6d\\x26\\x62\\x44\\x13\\xc5\\x51\\xd7\\xf8\\x91\\x2b\\xb1\\x06\\x6d\\x92\\x46\\x77\\x00\\x99\\x16\\x0b\\xe1\\xbb\\x60\\x7b\\x2d\\x52\\x22\\x3b\\x70\\x8c\\x69\\x74\\x82\\xe2\\xd1\\x62\\xfd\\xd3\\xa5\\xad\\x3b\\x73\\x2f\\x7b\\x40\\x77\\xac\\xa8\\xc3\\x70\\x2f\\x94\\xd9\\x92\\x17\\xaa\\xe8\\x73\\xfd\\xfa\\x77\\x4e\\x79\\x9f\\x69\\x9b\\xc6\\x45\\x0c\\x67\\x3b\\xa6\\xbf\\xb2\\x84\\x0b\\xfc\\x63\\x0c\\x0a\\x3f\\x2f\\xa6\\x8a\\x8c\\x4d\\x9c\\x27\\x88\\xfb\\xf2\\xa4\\x7e\\xca\\x9b\\xd6\\xb1\\xe7\\x5a\\xf6\\x5d\\x8f\\x7d\\x0f\\x26\\x20\\x25\\xc4\\x17\\xb9\\x01\\xf5\\x9b\\x62\\x56\\x0e\\xf3\\xd9\\x9f\\xdf\\x3c\\x40\\x94\\x6f\\xba\\x8e\\x1b\\x97\\xbe\\x01\\xf0\\xab\\xcd\\x08\\x1c\\x6e\\x27\\x40\\x92\\x7b\\x96\\x24\\x6e\\x46\\x06\\x65\\xf9\\x07\\x66\\x4b\\x90\\x03\\x34\\x3b\\xa8\\x2c\\x61\\x51\\x54\\x33\\x35\\x59\\xec\\x1c\\xc0\\xec\\x68\\xb1\\xe7\\xf0\\x60\\x98\\x1b\\x94\\x16\\xf1\\x22\\xb1\\x09\\x83\\x98\\x8c\\x17\\x8e\\x8f\\x31\\x48\\x7d\\x40\\xc6\\xb9\\x26\\x4c\\x23\\x93\\x13\\xcd\\x84\\x50\\xcb\\x44\\x74\\xb5\\x51\\x7b\\xb4\\x38\\xaf\\x39\\x13\\xc8\\xa3\\x12\\xc1\\xc1\\x60\\xc3\\xd4\\x70\\x26\\xee\\xbe\\x56\\x86\\x1f\\xe1\\xca\\xcb\\xcf\\xd8\\x32\\x63\\xb1\\xda\\x52\\x43\\xf1\\x8a\\xe3\\xf2\\x37\\xc2\\x0c\\x73\\xcf\\xf4\\x0c\\xff\\x98\\x1a\\x71\\xc9\\xf0\\xc7\\x2a\\x4f\\xcd\\xa0\\xf7\\xc0\\xa6\\x33\\xad\\x06\\x84\\x8d\\xd6\\x30\\x4d\\xcb\\xcd\\x00\\x20\\xd0\\x68\\x56\\x99\\x56\\x0a\\xa0\\x15\\xa1\\x49\\xe2\\x97\\x50\\x85\\x5a\\xcb\\x81\\xa4\\x86\\x57\\x24\\xc7\\x9e\\x99\\xdc\\x39\\x8a\\x63\\x04\\x07\\x05\\x07\\xb3\\x0c\\x78\\x6b\\x8f\\x6b\\x40\\x40\\x47\\xa3\\x93\\xc1\\xce\\xee\\x23\\x91\\x66\\xb9\\x06\\xc3\\x01\\xe7\\xa9\\x39\\x5a\\xa6\\x8d\\x0c\\x66\\x19\\x5f\\x29\\xf2\\xa9\\xdd\\x29\\x48\\xdc\\xc4\\xbd\\xd8\\x62\\x29\\xba\\xc1\\x7f\\x34\\x8e\\xd7\\xe1\\xfc\\xe5\\x76\\x64\\x37\\xf7\\xc8\\x4b\\x26\\x66\\x38\\x66\\x37\\x09\\xf7\\x2f\\xa5\\x3a\\x9a\\x39\\x61\\x29\\x12\\x52\\x82\\xca\\x04\\x37\\x3d\\xdb\\x27\\x6f\\xca\\xb5\\xfd\\x97\\x79\\x67\\xe7\\x78\\xa6\\xd3\\x63\\x75\\x52\\x1e\\xf6\\x8c\\x4d\\x67\\xfe\\xac\\xa9\\x04\\xfc\\xad\\x0e\\x23\\xbb\\x8e\\xdc\\xa2\\x12\\x2a\\x25\\xdd\\x75\\x8f\\x98\\x86\\x74\\x07\\x22\\x21\\x2d\\x6e\\x3f\\x21\\x67\\x9c\\x40\\x9a\\xe9\\x45\\x05\\xb0\\x2b\\x20\\xa6\\x41\\xa6\\xc5\\x46\\x22\\x14\\x22\\xda\\x53\\x76\\x13\\x58\\x9a\\x25\\x2c\\x62\\xda\\x81\\x39\\x79\\xb9\\xc7\\x78\\xc7\\xe6\\x26\\x10\\xa6\\x0d\\xd1\\x20\\x5c\\x0c\\x45\\x76\\x32\\x22\\x67\\x84\\xe7\\x05\\xe2\\xd9\\x36\\x05\\x2e\\x8a\\x19\\xb8\\x8e\\xcc\\xb4\\x94\\x28\\xfb\\xda\\x8d\\x8f\\xf6\\x43\\xdf\\xb6\\x6d\\x66\\xf2\\x57\\xdb\\xd0\\xcd\\x1f\\xf8\\x1e\\x97\\xd0\\xbc\\x6e\\x77\\x6d\\xe7\\xab\\xfb\\x12\\x12\\xff\\xb6\\x9f\\xc3\\x3e\\x6f\\x2f\\x53\\x7b\\x7b\\x73\\x14\\x24\\x10\\x69\\x43\\x0d\\x41\\xa6\\x03\\x42\\x95\\x12\\x11\\x33\\x52\\x61\\x09\\xfb\\xf5\\x0b\\x65\\x57\\xb2\\x7b\\xef\\x49\\xd3\\xfd\\x27\\x8d\\xd7\\x4f\\x50\\xf1\\x50\\xbf\\xdf\\xfb\\x7e\\xb7\\xb2\\x1b\\x09\\x33\\x32\\xce\\x64\\x69\\x57\\x6a\\x78\\x77\\xbc\\xc0\\xa7\\x2f\\x14\\x49\\xe8\\x18\\x92\\x35\\x42\\xfb\\xa6\\xb6\\xff\\xe5\\x2f\\xdb\\x9e\\x68\\x60\\xc3\\x82\\xf6\\x42\\x08\\x65\\x5b\\x86\\x86\\xca\\xba\\x9d\\x8a\\xa3\\x80\\x13\\x43\\xaa\\x8c\\x68\\x4f\\x19\\x57\\x4e\\xbf\\x33\\x20\\x94\\xdc\\xc1\\xc2\\xea\\xe1\\x28\\x2f\\x54\\x71\\x8d\\xa6\\x80\\x1d\\x4b\\xb0\\x04\\xdd\\xc0\\xdd\\x1d\\x2c\\xb0\\xc3\\x4d\\x3a\\xa4\\x2d\\x5d\\x35\\x85\\x3b\\xdb\\x9a\\x60\\x80\\xb2\\x0d\\xcd\\x44\\x1b\\x7e\\xd1\\x62\\x83\\x9a\\x5f\\x0d\\xdb\\xee\\x60\\x2b\\xfb\\xbc\\xae\\xad\\x68\\xa9\\x11\\xdc\\xf1\\x3c\\xf0\\x90\\x90\\x02\\x7b\\x78\\xa0\\x59\\x96\\x30\\x58\\xaf\\x6a\\xda\\xde\\xb6\\x4a\\x7d\\xdb\\x9a\\xdf\\xbd\\x4e\\xeb\\x6a\\x78\\x41\\x4c\\xbb\\x2e\\xd4\\x75\\x16\\xde\\x5f\\x28\\x0b\\xaf\\x06\\xef\\xcc\\x58\\x66\\x15\\x2d\\x0a\\x10\\x8d\\x34\\x07\\x5a\\xdb\\xbe\\xa3\\x09\\x2b\\x75\\xd9\\x0a\\x99\\x8d\\x4b\\x3e\\x20\\xef\\x85\\x36\\xff\\x79\\xf3\\xc0\\x94\\xe1\\x31\\x2f\\x04\\xa8\\xf7\\x42\\xe3\\x9f\\x23\\xf2\\xb5\\xb6\\x57\\xef\\xed\\x9e\\x78\\xb9\\x6c\\xad\\xcf\\xc0\\xae\\xef\\xa9\\x4f\\xe0\\x8c\\x5b\\x24\\x6a\\x76\\xb8\\xaa\\x74\\x55\\x23\\x72\\x69\\xd9\\xc1\\xc2\\x0a\\xc0\\x14\\xb9\\xe4\\x46\\x28\\xb0\\x3b\\xd7\\x78\\x28\\xd4\\xbb\\x63\\xdf\\x6e\\xc8\\x34\\x57\\xa8\\x35\\xe5\\x82\\x0f\\x91\\x8d\\x5a\\x3b\\xa6\\x3d\\x20\\x33\\x6e\\xf5\\x88\\x7a\\x1c\\x7e\\xf3\\xd0\\x5f\\xa3\\x8e\\xee\\xad\\x1e\\x54\\x3e\\x6e\\x3c\\x6e\\x65\\xb0\\x19\\x9d\\x23\\x6b\\xcf\\xf8\\x34\\x29\\x98\\xf8\\x01\\xb9\\x9f\\xb1\\x68\\x66\\xa5\\xc7\\x31\\x58\\xe3\\x40\\x26\\xc1\\x70\\x0c\\x54\\x19\\xe4\\x6f\\x7e\\x99\\x82\\x6c\\x0e\\xfa\\xb7\\x46\\x34\\xb0\\xe3\\x5b\\xd3\\x46\\x42\\x23\\x88\\x49\\x8c\\x22\\x8b\\xd5\\xb2\\x53\\x0d\\x53\\x16\\x91\\x14\\xe4\\x14\\x48\\x66\\x48\\x7f\\x3b\\x80\\x6f\\x46\\x89\\x6d\\x6b\\x4c\\x8f\\xab\\x03\\x36\\xba\\x61\\xc8\\xd3\\x7c\\x65\\x64\\xa4\\x27\\x62\\x67\\x50\\x1e\\x0b\\xec\\x4c\\x60\\x67\\x02\\x3b\\x13\\xd8\\x99\\xc0\\xce\\xec\\xdd\\x02\\x3b\\xd3\\x79\\xf8\\xc0\\xce\\x7c\\xe2\\xec\\xcc\\xc3\\xf0\\x2e\\x1f\\x83\\xe4\\xa0\\x41\\x0d\\x53\\x9a\\x0d\\xdd\\x94\\xb5\\x48\\x59\\xb4\\x47\\x0f\\x56\\xdf\\xd4\\x42\\xc1\\xf5\\x17\\xab\\xa8\\x5c\\xd6\\x68\\x21\\x73\\xe5\\x5d\\x33\\xea\\xaa\\x2d\\xc3\\x33\\xdc\\x38\\x42\\x70\\x8b\\xea\\x30\\x66\\xed\\xd0\\x92\\xf2\\x29\\x90\\x57\\xc3\\x57\\x2f\\x5f\\x36\\x51\\x7c\\x39\\xd0\\xd9\\xeb\\x8b\\x89\\x33\\xba\\x33\\xae\\xbf\\xf8\\xed\\xd6\\x2f\\x36\\xa9\\xf2\\x9f\\xc6\\x86\\xe4\\x2e\\x6a\\x61\\x36\\xa8\\x71\\x94\\x1b\\xcc\\x3c\\x88\\xf5\\xb9\\xd0\\x24\\x05\\x4d\\xe8\\x6e\\x16\\xa6\\xaa\\x11\\x66\\x29\\x0c\\x0a\\x7b\\x2c\\xde\\x52\\xe7\\xbc\\xe2\\xed\\x55\\x31\\x11\\xdc\\x59\\x05\\xcc\\xf9\\xed\\x3e\\x9f\\x56\\x2b\\x88\\x80\\x5a\\xa7\\x8a\\x31\\x98\\x55\\xec\\xb6\\x52\\x69\\xa2\\x44\\x6a\\x66\\xcd\\xb8\\xf6\\x77\\xde\\x2c\\x01\\xfc\\xc1\\x90\\x63\\x18\\x4d\\x47\\x24\\xce\\xb1\\x5b\\xca\\x9d\\x37\\xce\\x89\\x5d\\xad\\x5a\\x28\\x0d\\xe9\\x6e\\x33\\x95\\xa1\\x1d\\x12\\xff\\x63\\xb6\\x45\\xcb\\x85\\xe9\\x0c\\xe6\\xc0\\x75\\x4e\\x93\\x64\\x41\\x60\\xce\\x22\\x5d\\xec\\x1f\\x3a\\x0f\\x31\\xad\\xf6\\xda\\xa9\\x06\\x5c\\xe7\\xfe\\x9c\\xe6\\x70\\xe5\\x92\\xed\\xc2\\xe9\\x4d\\x18\\xc5\\x95\\xbe\\xf7\\x41\\x1b\\xb5\\x1b\\x70\\xed\\x56\\x32\\xda\\x28\\x42\\x69\\xd3\\xaf\\xb5\\x28\\xe2\\x3f\\x11\\xb8\\x3f\\x5c\\xef\\x36\\x00\\x91\\xc6\\xe8\\xba\\x01\\x8a\\x6e\\xc7\\x89\\x38\\x5b\\x8c\\x90\\xce\\x2e\\xb4\\xba\\xd2\\x35\\xd6\\x18\\xbb\\xf6\\xda\\xad\\x11\\x93\\x3d\\x07\\xd4\\x33\\xb0\\xf6\\xb3\\xb3\\xf7\\x17\\xfb\\xed\\x18\\x71\\x76\\xeb\\x5b\\x91\\x89\\x44\\x4c\\x17\\xd5\\xe3\\xb5\\xde\\xbb\\x2c\\xcd\\xbc\\x7d\\x91\\x12\\x95\\x8f\\x1d\\xc7\\x6a\\x60\\xfe\\xfd\\x12\\x3c\\x04\\xab\\x45\\xb0\\x5a\\x04\\x31\\x1f\\x5b\\x10\\xf3\\x83\\x98\\x1f\\xc4\\xfc\\xfd\\x5a\\x10\\xf3\\x3b\\x0f\\x1f\\xc4\\xfc\\x4f\\x5c\\xcc\\x0f\\x56\\x8b\\x35\\x0b\\x0a\\xec\\x4c\\x60\\x67\\xb0\\x05\\x76\\x66\\xfd\\xba\\x02\\x3b\\x43\\x02\\x3b\\xb3\\xa5\\x05\\x76\\x26\\xb0\\x33\\xb5\\xf6\\x31\\x58\\x2d\\xda\\x7d\\x9b\\x89\\xb8\\x43\\xb8\\x4b\\x26\\xe2\\x2d\\xd1\\x2e\\x56\\xd5\\x1c\\x89\\x61\\x22\\x22\\xaa\\x5d\\x0c\\xaa\\xf9\\xc4\\xd9\\x37\\x14\\x4d\\xad\\xf6\\x7c\\x40\\x7e\\x12\\x1c\\xac\\xff\\xbf\\x81\\x24\\xd4\\x61\\x0b\\x3d\\x03\\x69\\x5e\\x3f\\x56\\x27\\x5b\\x9d\\xae\\x43\\xb4\\x4c\\x88\\x96\\x09\\xd1\\x32\\x1b\\xdb\\xc1\\x44\\xcb\\xcc\\xa8\\xb2\\x70\\x6b\\xa9\\xc8\\xe6\\xe0\\x99\\x0a\\x4e\\xba\\x05\\x99\\x7e\\xa2\\xb1\\x33\\x06\\xdc\\x1d\\x38\\x62\\x06\\x85\\x12\\xa4\\xec\\xce\\xc4\\xce\\x94\\x0c\\xf1\\x55\\x7d\\x3f\\x9c\\x04\\x8a\\x8b\\xa2\\x71\\x0c\\x31\\xc9\\x40\\x0e\\x2d\\x88\\x0a\\x32\\x61\\x3c\\x5e\\xb3\\x56\\xbf\\x3f\\xbb\\xd1\\xc3\\x23\\x06\\xaf\\xd4\\xd7\\xb1\\xd7\\x37\\x8f\\x13\\xc1\\x52\\x9f\\x48\\x0b\\x5b\\x57\\xd5\\x60\\x57\\x23\\x82\\x07\\x11\\xcf\\xd2\\x54\\x98\\x1d\\x12\\xed\\xec\\x5c\\xdf\\xec\\x29\\xce\\x36\\x97\\x48\\x51\\x8e\\xf4\\x56\\xb1\\x96\\x9a\\x9a\\x46\\x52\\xc3\\x99\\x13\\x5d\\xff\\x91\\x83\\x5c\\x60\\xa4\\x75\\x29\\xa1\\x15\\x89\\x3a\\x9c\\xaf\\x05\\x53\\x24\\xa2\\xca\\x92\\xd5\\x26\\x5c\\xe5\\xe5\\xc4\\xc6\\x99\\xf1\\x3c\\x49\\x06\\xb6\\x9f\\xe5\\xcb\\xea\\xd1\\x1c\\xc2\\x01\\x17\\xe6\\x79\\x63\\xe5\\x51\\x43\\x6d\\x46\\x3b\\x75\\x41\\x7b\\xe3\\x20\\x59\\x3e\\xa7\\xe5\\xae\\xac\\x1a\\xc9\\x6b\\xd9\\xec\\xb1\\xac\\x55\\xb3\\xad\\x31\\xf2\\x36\\x36\\xdb\\xda\\xd6\\x96\\xd7\\x6f\\xc5\\xe9\\x77\\x16\\x6d\\xb7\\xec\\x49\\x07\\x15\\x1c\\xbe\\xdc\\x78\\x32\\xfd\\xa8\\xe1\\x48\\x7b\\x55\\x1c\\x69\\xad\\x8e\\x23\\xad\\x54\\x72\\xa4\\xad\\x5a\\x8e\\x74\\x50\\xcd\\x91\\x76\\xea\\x39\\xb2\\x0c\\x6d\\xe6\\x84\\x1c\\xe3\\xfb\\x38\\x9a\\x3a\\xd2\\x45\\x53\\x44\\x3a\\x68\\xec\\x48\\x0f\\x17\\xab\\x3a\\x7e\\x25\\xed\\xd1\\xe3\\xa9\\xf0\\xc8\\xbe\\x6a\\x3c\\xbc\\x56\\x35\\x4d\\xde\\x53\\x9f\\x4b\\x3b\\x2d\\x1e\\xe9\\xe9\\x54\\x9c\\x7e\\x8b\\xa1\\xda\\xe8\\xa9\\xf4\\x7a\\xe4\\xf9\\x75\\x7b\\x5b\\xa7\\xe0\\x86\\xdf\\x5b\\x19\\xd6\\x6a\\xf4\\x0e\\x0a\\x34\\xd2\\x49\\x89\\x46\\xda\\x2b\\xd2\\x48\\x7b\\x60\\x47\\x5e\\xe4\\x2d\\xba\\x20\\x75\\xe0\\x68\\x1a\\x43\\x79\\x65\\x58\\x4b\\xc1\\x31\\x73\\xd2\\x84\\xfc\\xd3\\x10\\x6a\\x3c\\xfc\\x7f\\x91\\x8c\\x32\\xa9\\x8c\\x04\\xe1\\xd4\\xac\\xd5\\x67\\x4e\\x45\\x56\\xe9\\xa6\\xf1\\x04\\x30\\x75\\x94\\xa1\\xa3\\x73\\x9a\\x18\\x46\\xc2\\xfa\\x7b\\x3a\\x39\\xdf\\xcc\\x65\\x99\\x4d\\x1b\\x90\\xfb\\x99\\x50\\x96\\xea\\x17\\xd9\\xaf\\x8e\\xee\\x60\\x71\\x34\\xd8\\x4b\\x04\\xaf\\xb7\\xea\\xed\\x39\\xba\\xe4\\x47\\x96\\x3d\\x59\\x81\\xfd\\x82\\x97\\x11\\x3c\\x59\\x90\\x23\\x7c\\x76\\xd4\\x37\\x1f\\xd8\\x82\\x07\\xa9\\xa6\\x18\\x6d\\x4b\\xe2\\x5b\\x81\\x6c\\x57\\xcf\\x75\\x52\\x83\\xbe\\x6f\\x60\\xd1\\xd6\\x2e\\xde\\x08\\xe6\\xdf\\xd5\\x46\\xf4\\x4c\\x2b\\x82\\x99\\x91\\x8f\\x0b\\xde\\x04\\xb5\\x96\\x96\\x2d\\x71\\x7a\\x20\\xab\\x12\\x62\\x49\\xd2\\x60\\xb4\\x31\\x10\\x4d\\xef\\x00\\x0d\\x0e\\x98\\x71\\x4e\\xb1\\x18\\x95\\x5a\\x82\\x5b\\xd0\\xc1\\x91\\x0c\\xc8\\xf8\\xd4\\x68\\x89\\x10\\x77\\x79\\xe6\\x41\\xcf\\xa7\\x33\\x6c\\x30\\x24\\xe3\\x91\\x48\\xbd\\x3b\\xb5\\x75\\x69\\x34\\xb7\\xc2\\xdd\\x97\\xa1\\x4d\\xc2\\x68\\x7f\\xc7\\x81\\x11\\xcd\\x3a\\xf1\\xff\\xc7\\xb7\\x55\\xe1\\xf7\\x47\\x42\\x15\\xf9\\x11\\x19\\x37\\x4e\\x8e\\xf1\\xc3\\x93\\x1f\\x9b\\x58\\xb8\\x8b\\x0d\\xb4\\x1a\\x4e\\x91\\x23\\x66\\x29\\xd2\\xec\\x55\\x74\\x6c\\xc5\\xde\\x6e\\xdb\\xb1\\x06\\x43\\xfb\\xfc\\x55\\xd5\\xcd\\xb0\\x19\\xba\\xc8\\x31\\xe5\\x9a\\x9d\\x94\\x69\\xba\\x08\\xc2\\x01\\x72\\xa2\\xb1\\xe0\\x2f\\xb4\\x9d\\x9f\\xc7\\x6b\\xbe\\x83\\x26\\x46\\xf0\\x62\\xdf\\x4b\\x03\\x94\\xd5\\xc8\\xdb\\x23\\x8f\\x61\\x42\\xf3\\x44\\xbb\\x74\\x98\\x06\\xf5\\x21\\x35\\x6d\\x30\\xc2\\xad\\xb7\\x49\\x38\\xa6\\x7a\\x22\\xe4\\x98\\xc5\\x31\\x70\\xf4\\x6e\\xf7\\xd3\\x1f\\x0b\\x3d\\x5b\\x06\\x77\\x34\\xc0\\x56\\xcf\\xb8\\xc9\\xb0\\x67\\x89\\x12\\x83\\xe5\\x1e\\xa3\\x22\\x5d\\xa6\\xb9\\x45\\x98\\xd4\\xad\\x36\\x00\\x61\\xca\\x6c\\xea\\x86\\xfc\\x6d\\x9b\\x57\\xc8\\x0a\\x9e\\x2b\\xc9\\x66\\xb4\\xa2\\xe4\\x75\\xc8\\x56\\x11\\xe0\\x74\\x8c\\x5a\\xe7\\xfa\\x8c\\x2e\\x79\\x45\\xb3\\x41\\x26\\x40\\x75\\x2e\\x81\\x4c\\xa9\\xde\\x43\\x8f\\xee\\xdb\\x93\\xb8\\xc2\\x74\\x47\\xba\\x09\\x53\\xba\\x15\\xd6\\x65\\xea\\x19\\x10\\xef\\xf2\\xa0\\x01\\xf7\\xee\\x85\\x7b\\xb9\\xd0\\x01\\xfd\\x7e\\xb4\\xe8\\x77\\x05\\xe8\\xfb\\xc0\\xc0\\x2b\\x9d\\x06\\x24\\xec\\xda\\x47\\x84\\x84\\xb9\\xaf\\x1b\\xf0\\xcc\\xb6\\x06\\xab\\x7e\\xb3\\x6e\\xa5\\x7e\\x4a\\xaa\\xd4\\xcc\\x61\\x94\\x53\\x3b\\xad\\x9c\\x8f\\x01\\x43\\x18\\xc2\\x1e\\x62\\x6f\\x72\\xcd\\xb9\\xcb\\xc7\\xee\\x33\\x06\\xbb\\x61\\x2d\\xc2\\x5a\\xb6\\xec\\x37\\x18\\xd3\\x8b\\x6e\\x82\\x83\\x42\\x45\\x3e\\x14\\x5e\\x1c\\x95\\x61\\xb0\\xd7\\x26\\x4b\\xc1\\x38\\xb0\\x52\\x49\\xc9\\xe3\\xe5\\xc8\\xb0\\xb2\\x6f\\xb4\\x1e\\xa4\\x40\\xb9\\x22\\x47\\xde\\x91\\xe4\\x85\\x2a\\xdf\\x38\\x6a\\x74\\xe1\\x7d\\x4a\\xc2\\x62\\xec\\xe3\\x7f\\xfe\\xeb\\xa4\\x96\\x86\\xb0\\x1c\\x3a\\x58\\x6b\\x82\\xb5\\xa6\\xda\\x82\\xb5\\x66\\x75\\x12\\xc1\\x5a\\xb3\\xa9\\x05\\x6b\\x4d\\xab\\xf1\\x83\\xb5\\xa6\\xde\\x82\\xb5\\x26\\x58\\x6b\\x82\\xb5\\x66\\x73\\x0b\\xd6\\x9a\\x60\\xad\\xf9\\x58\\xad\\x35\\xa5\\xa8\\xf1\\x14\\xb2\\x6a\\x55\\x2c\\x74\\x1e\\xdf\\xb6\\x98\\x14\\xd5\\x2c\\x2a\\x43\\x21\\xfd\\x5b\\xf6\\x5f\\xcf\\x25\\xb8\\x56\\x45\\xcd\\xae\\x62\\x6b\\x55\\x08\\x5e\\xd1\\x12\\x34\\x96\\x5a\\x37\\xca\\xa8\\x85\\x14\\xbb\\x32\\x46\\x4f\\xe2\\xeb\\xa1\\x2a\\x70\\x2a\\x3e\\xa4\\x4f\\x01\\xc7\\xb7\\x3e\\x9a\\xc4\\x15\\x96\\x1b\\x43\\x19\\x6a\\x12\\x93\\x63\\xaf\\x09\\x3d\\x31\\x27\\xc5\\x85\\xae\\x3f\\xe4\\x9a\\x0d\\xcb\\x37\\x0a\\x1f\\x5d\\x54\\xd8\\xfa\\x54\\x5d\\x4d\\x76\\xcb\\x33\\xf4\\xa5\\x66\\xd0\\x85\\xb8\\x14\\x31\\x15\\x25\\x98\\x18\\xc4\\x0d\\xb2\\x36\\x5b\\xa6\\x5c\\xe1\\x3d\\x0c\\xa4\\x92\\x39\\xe7\\x86\\x77\\x10\\xdc\\x05\\x52\\x34\\x98\\x89\\xa5\\x09\\x56\\x09\\xeb\\xae\\x93\\x95\\x34\\x70\\x8d\\x28\\x6e\\x94\\xc7\\x54\\xf1\\xc1\\xa7\\xda\\x96\\xf1\\x73\\xd9\\x78\\x04\\x77\\x2a\\x6c\\xf3\\x8b\\xed\\xa7\\xc1\\x24\\x8a\\x9b\\x86\\xfb\\xc9\\x8a\\x15\\x35\\xb9\\x64\\x6f\\xf0\\x72\\x55\\x27\\xcb\\x14\\x9e\\x23\\x4d\\x12\\x71\\xdf\\x84\\xb0\\x34\\x04\\xe5\\xd6\\x99\\xdf\\xf6\\x86\\xde\\xfb\\xc6\\x29\\xe2\\x96\\x1c\\xd6\\xf7\\x65\\x64\\x43\\x1e\\xb9\\xe5\\x16\\xf2\\xc8\\x3d\\x4e\\x1e\\xb9\\x8a\\xa1\\xb1\\x9a\\x50\\x6e\\xf7\\x5e\\x61\\xc2\\xb9\\x47\\x4d\\x28\\x47\\xc8\\x5f\\x5c\\x61\\x3f\\x09\\xd6\\x3a\\x98\\x27\\x9a\\x65\\x65\\x58\\xab\\xb2\\x27\\x94\\x58\\x91\\x71\\xe2\\x62\\xea\\xea\\x17\\xd0\\xcc\\x86\\x46\\xb3\\x9d\\x43\\x2d\\x5d\\x54\\x1c\\x0f\\xc3\\x64\\x15\\x22\\x44\\x1b\\x77\\x86\\xfa\\x65\\x9b\\xc5\\xcd\\xcb\\x92\\x36\\x78\\x8f\\x3d\\x77\\x4c\\xd2\\x5e\\x28\\xec\\xc2\\x95\\x88\\xad\\x1a\\x99\\x15\\x39\\x36\\x04\\x2e\\x59\\x38\\xb3\\x6c\\x0d\\x97\\xd5\\x28\\xe3\\x1e\\x03\\x58\\x3d\\xcf\\x1c\\x3c\\x73\\x38\\x65\\x73\\xe0\\x25\\x01\\x3d\\x56\\x27\\x27\\x9e\\x1f\\x5d\\x66\\x01\\xf6\\xe8\\xbd\\x0b\\x93\\xb0\\x0f\\xe2\\x6d\\x4a\\xdc\\x97\\x48\\xf6\\x1e\\x23\\xac\\x21\\xea\\x7f\\xa8\\x10\\xca\\x3f\\xed\\x26\\xeb\\x7b\\x0c\\x62\\xaf\\xb4\\x0f\\x72\\xac\\x1c\\x74\\x49\\xce\\x77\\xf6\\xf2\\x88\\xb1\\x64\\x4d\\x02\\x96\\x9a\\x69\\x7d\\x5b\\x04\\x2a\\xb5\\x4d\\x83\\xf8\\xb8\\x01\\x4a\\x8f\\x1a\\x9c\\xf4\\xf1\\x64\\x2b\\x7c\\x66\\xf3\\xd6\\x47\\x90\\xfe\\xe7\\x40\\xcc\\x59\\x21\\xff\\xcf\\xa6\\xf6\\x5c\\xf9\\x7f\\x1e\\xdd\\x5c\\xf5\\xd1\\xa5\\x01\\x7a\\x52\\xf3\\xd4\\xd3\\x98\\xa6\\x3e\\xb2\\x34\\x40\\xcf\\x62\\x8a\\x3a\\xf0\\x84\\x40\\x8f\\x67\\x82\\xfa\\xa4\\xb3\\xed\\xb4\\x34\\x37\\xb5\\x87\\xe0\\x67\\x35\\x33\\x3d\\xab\\x89\\xe9\\xf9\\xcd\\x4b\\xad\\xf8\\x82\\xae\\x66\\xa5\\x27\\x2f\\x5b\\xd1\\xc6\\xff\\xbc\\x1d\\x3c\\x3f\\x5d\\xc0\\xcf\\x13\\x3b\\x9c\\x1f\\x46\\xa0\\xcf\\x33\\x79\\x99\\x3f\\x97\\x87\\xf9\\xe3\\x7a\\x97\\x3f\\x43\\x60\\xcf\\x13\\x05\\xf5\\x3c\\xa3\\x2f\\x79\\x53\\xfa\\xde\\x88\\xaa\\x77\\x43\\x9c\\x6d\\x7c\\xc7\\x5b\\x06\\xef\\xb4\\x44\\x9e\\x4f\\x19\\xb4\\xf3\\x09\\xe0\\xcf\\x56\\xc1\\x3a\\x01\\x85\\x3e\\x13\\x0a\\xed\\x2f\\x38\\xe7\\xe9\\x02\\x73\\x02\\x22\\x75\\xad\\x33\\x22\\x6d\\x19\\x80\\xd3\\x9b\\x0e\\xfd\\x71\\x02\\x6f\\x9e\\x3a\\xe8\\xe6\\x11\\x02\\x6e\\x9e\\x23\\xd8\\xe6\\x11\\x02\\x6d\\x82\\xe5\\x61\\xcf\\x16\\x2c\\x0f\\xfb\\xb6\\x60\\x79\\xd8\\xd4\\x82\\xe5\\x61\\xb9\\x05\\xcb\\x43\\xb0\\x3c\\x04\\xcb\\x43\\xb0\\x3c\\xac\\x0e\\x18\\x2c\\x0f\\x1b\\x07\\x0f\\x96\\x87\\x4f\\xde\\xf2\\xd0\\x34\\x88\\xa5\\x1d\\x2c\\x3f\\x4f\\xf0\\xca\\xd3\\x06\\xae\\xf4\\x1f\\xb4\\xf2\\x8c\\x01\\x2b\\x87\\xa4\\xdc\\x68\\x1c\\xa0\\xd2\\x0e\\x46\\x0f\\x25\\x30\\xe5\\x30\\x82\\x52\\x9e\\x3d\\x20\\xa5\\x6b\\x30\\x4a\\x3f\\x81\\x28\\x7b\\x81\\x6a\\x26\\xe2\\x33\\xae\\x59\\xd7\\x82\\x3c\\x55\\x18\\xda\\x54\\x95\\x87\\xce\\x05\\x8b\\x49\\x96\\x6b\\x57\\x08\\x24\\x54\\xe6\\xd9\\x79\\x8c\\x4f\\x53\\x99\\xa7\\x76\\x78\\xa1\\x3c\\xcf\\xb6\\x76\\x30\\xe5\\x79\\x36\\x9d\\x59\\xa8\\xd1\\x53\\x6f\\xa1\\x46\\x4f\\xa8\\xd1\\x13\\x6a\\xf4\\xd8\\x16\\x6a\\xf4\\x84\\x1a\\x3d\\x21\\xeb\\x5b\\xc8\\xfa\\x16\\xb2\\xbe\\xed\\xff\\x55\\xc8\\xfa\\xb6\\xb9\\x85\\xac\\x6f\\x4d\\x5a\\xc8\\xfa\\xb6\\xf7\\xe8\\x21\\xeb\\x5b\\xc8\\xfa\\xd6\\x6c\\xe0\\x90\\xf5\\x6d\\xef\\x09\\x84\\xac\\x6f\\xbf\\xd8\\xac\\x6f\\xa1\\x46\\xcf\\x47\\x51\\x27\\x22\\x14\\x89\\x68\\xe2\\x2e\\x76\\x50\\x45\\x22\\x42\\x8d\\x9e\\x50\\x1e\\x62\\xb9\\x85\\x1a\\x3d\\x1f\\x11\\xee\\x0d\\x35\\x7a\\x3e\\x66\\xf4\\x1b\\x6a\\xf4\\x04\\x24\\xbc\\xbe\\x85\\x1a\\x3d\\xa1\\x46\\xcf\\xce\\x16\\x6a\\xf4\\x04\\x6b\\x4d\\xb0\\xd6\\xd4\\x5b\\xb0\\xd6\\x6c\\x6f\\xc1\\x5a\\xb3\\xab\\x05\\x6b\\xcd\\xd6\\x16\\xac\\x35\\xcd\\x5b\\xb0\\xd6\\x04\\x6b\\xcd\\x5e\\x2d\\x58\\x6b\\x82\\xb5\\xe6\\x63\\xb5\\xd6\\x84\\x1a\\x3d\\xa1\\x46\\x4f\\xa8\\xd1\\x13\\x6a\\xf4\\x84\\x1a\\x3d\\x95\\x16\\x6a\\xf4\\x84\\x1a\\x3d\\x8f\\x57\\xa3\\xa7\\x16\\x55\\xf3\\xf1\\x16\\xea\\x69\\xbe\\x8c\\x50\\xad\\x27\\x54\\xeb\\xd9\\xd0\\x42\\xb5\\x9e\\x50\\xad\\x67\\x5d\\x0b\\xd5\\x7a\\x42\\xb5\\x9e\\x2d\\x2d\\xe4\\xcc\\xdb\\xb3\\x85\\x9c\\x79\\xfb\\xb6\\x90\\x33\\x6f\\x53\\x0b\\x39\\xf3\\x96\\x5b\\xc8\\x99\\x17\\x72\\xe6\\x85\\x9c\\x79\\x21\\x67\\xde\\xea\\x80\\x21\\x67\\xde\\xc6\\xc1\\x43\\xce\\xbc\\x4f\\x3e\\x67\\x5e\\xa8\\xd6\\x73\\x90\\xd5\\x26\\x42\\xa9\\x89\\x1d\\xed\\x70\\x4a\\x4d\\x84\\x6a\\x3d\\xbf\\xcc\\x22\\x13\\xa1\\x5a\\xcf\\x01\\xe3\\xcf\\x50\\xad\\x67\\x77\\x3b\\x1c\\x14\\x1a\\xaa\\xf5\\xfc\\x92\\x11\\x69\\xa8\\xd6\\x13\\xaa\\xf5\\x14\\x2d\\x54\\xeb\\x09\\x96\\x87\\x8d\\x2d\\x58\\x1e\\x48\\xb0\\x3c\\x14\\x2d\\x58\\x1e\\xf6\\x1a\\x37\\x58\\x1e\\x82\\xe5\\x21\\x58\\x1e\\xb6\\x4f\\x3a\\x58\\x1e\\xb6\\x0c\\x17\\x2c\\x0f\\xc1\\xf2\\xb0\\xa6\\x85\\x6a\\x3d\\x9b\\x5b\\xa8\\xd6\\x13\\xaa\\xf5\\x84\\x6a\\x3d\\xa1\\x5a\\xcf\\x63\\x56\\xeb\\x81\\x07\\x2d\\x69\\xa4\\xcf\\x05\\xd7\\xc0\\x37\\x06\\xa2\\xec\\x0b\\x91\\x6f\\x6a\\xbd\\x19\\xea\\x36\\x61\\xd3\\x5c\\x3a\\x19\\x77\\x7a\\x7d\\x75\\x4e\\x22\\xaa\\x69\\x22\\xa6\\xe4\\x4a\\xc4\\x56\\x87\\x8b\\x5f\\x14\\x3f\\xa7\\xa0\\x69\\x4c\\x35\\x2d\\xd4\\xff\\x46\\x16\\x9c\\xb3\\x18\\x91\\x5a\\x0c\\x0f\\x84\\xa5\\x74\\x0a\\x06\\x79\\x6c\\x9c\\x44\\xae\\x80\\x50\\x72\\x0f\\x49\\x32\\xbc\\xe3\\xe2\\x9e\\x93\\x39\\x48\\x55\\x41\\x97\\x3f\\x8a\\x2c\\xfd\\x91\\x28\\x90\\x73\\x5b\\xf1\\x06\\x1e\\x32\\x03\\x2b\\x4c\\x5b\\xba\\xeb\\x67\\x52\\x1d\\xae\\x74\\xfb\\x3e\\xb7\\x4f\\x6f\\xd0\\x4d\\x76\\x5b\\xf1\\x98\\x62\\xed\\xb8\\x4c\\x33\\xa7\\xcf\\x0d\\x13\\xfb\\xb9\\xb9\\x97\\xb9\\xf2\\x3e\\xea\\x13\\x96\\xc0\\x70\\x4c\\x15\\xc4\\x7e\\x5c\\x65\\xae\\x8b\\x90\\xb1\\x9d\\x5b\\xae\\x59\\xc2\\x7e\\x02\\x87\\xcd\\xad\\x8e\\x77\\xd3\\xc9\\xef\\x41\\xf0\\x77\\x0b\\xfd\\x43\\x12\\xd1\\x68\\x06\\x17\\x6c\\xb3\\xb8\\x3e\\xf4\\x53\\xdd\\xfc\\xd2\\x3e\\xf2\\xbb\\x1f\\x67\\xef\\xe2\\x50\\xe7\\xee\\x03\\x2f\\xa1\\xc7\\x4c\\x22\\x7e\\x59\\x10\\xa5\\x85\\xf4\\x3b\\x9a\\x49\\x18\\x46\\x34\\x89\\xf2\\x04\\xb1\\xc9\\xd9\\xd5\\xa5\\x1d\\x69\\x77\\x79\\xa7\\x1d\\x08\\xbd\\x5c\\x74\\x83\\x19\\xfb\\x4f\\xb6\\xcf\\x79\\x15\\x0a\\x90\\x31\\x44\\x9d\\x5c\\x97\\x69\\xa7\\x90\\x0a\\xb9\\xb8\\xa5\\x72\\x0a\\x9d\\xaf\\xf6\\xbb\\x4a\\x5f\\xcb\\x17\\xfb\\xd7\\x5f\\x7f\\x78\\xf7\\xe6\\xdd\\xdb\\xcb\\x77\\x97\\xb7\\x0e\\xe5\\x7a\\x6b\\xd4\\xf2\\x95\\x1f\\x95\\x16\\x0f\\xa2\\xc4\\x44\\xbb\\x29\\x92\\x84\\xa5\\x4c\\x17\\x5f\\xd9\\xbb\\xb9\\x59\\x6c\\xb4\\x28\\x19\\xa3\\xcd\\x72\\xae\\x59\\x0a\\xd6\\xf4\\x44\\xb5\\x36\\xac\\x86\\xb9\\x37\\x29\\x80\\xc6\\x7a\\x52\\x29\\xbd\\x03\\x83\\x37\\xc9\\x34\\xa7\\x92\\x72\\x0d\\x1e\\xcb\\x33\\x6d\\x3f\\x8a\\x05\\x51\\xc2\\x09\\xb3\\x4c\\x95\\x66\\x2a\\x05\\xda\\x06\\xe8\\x5c\\x89\\xcd\\xa8\\x06\\x7b\\x98\\xd1\\xb9\\x2d\\xf8\\x33\\x11\\x06\\x35\\x9b\\x43\\x4d\\x45\\xcc\\x26\\x2c\\xb2\\xda\\x11\\x92\\xd2\\xb8\\x08\\x2a\\x71\\x0c\\x3f\\xc8\\x82\\xb2\\x95\\x0b\\xde\\x76\\x2b\\x97\\xb7\\x19\\xf8\\x9c\\x49\\xc1\\x51\\x90\\x99\\x53\\xc9\\xe8\\x38\\x81\\xc2\\x00\\xa7\\x40\\xdb\\xf1\\xca\\x05\\x71\\x32\\x5e\\x68\\xd8\\x8c\\xae\\xec\\x08\\xee\\x34\\x5c\\xa5\\xa8\\xcd\\xfd\\x7d\\xf6\\xd9\\xc6\\x8e\\x6e\\xcb\\xf0\\xaf\\x92\\x11\\x31\\x1d\\x30\\x17\\x17\\x10\\x83\\x62\\x0e\\x2b\\x4a\\x88\\xf3\\xc8\\xef\\x9d\\xd0\\x99\\x64\\x56\\x2c\\xa3\\x05\\xc8\\x38\\x2c\\x4d\\x15\\x49\\x73\\x43\\x85\\x0d\\x87\\xa3\\x14\\x1b\\x27\\x30\\x30\\x7c\\x0c\\xdb\\x1c\\xb7\\x52\\xf6\\x31\\x06\\xb3\\xcd\\xd8\\x13\\x72\\x17\\x73\\x30\\x00\\x67\\x00\\xd9\\xf2\\xa0\\x00\\x86\\xc9\\x11\\x58\\xb5\\x89\\x5a\\x56\\xc5\\x1b\\x2d\\x0d\\xad\\x8d\\x9c\\xc9\\xfa\\x72\\x42\\x16\\x22\\x97\\x35\\xba\\x30\\xa3\\x06\\x90\\xf1\\xfa\\x6e\\x9c\\x88\\x8b\\x35\\x43\\x24\\x34\\x20\\x31\\x18\\x8e\\x9e\\x71\\x43\\xa2\\xa6\\x42\\xc4\\x86\\xb1\\x97\\xe2\\x81\\xa5\\x38\\x8a\\xbb\\x01\\xc5\\xb1\\x8d\\x17\\x24\\x16\\xb9\\xb5\\xfe\\x21\\x9c\\x18\\x5a\\xe0\\xc8\\x58\\x46\\xa3\\x3b\\x33\\x07\\xec\\x78\\x5b\\x94\\xe0\\xa9\\x4e\\xb3\\x53\\x7c\\xcb\\xfd\\xbf\\xfb\\x52\\x8d\\xfe\\xae\\x04\\x2f\\xcd\\xbe\\xc5\\xb2\\x46\\xfb\\x1d\\x2f\\x53\\x64\\x0c\\x4a\\x0f\\x61\\x32\\x11\\x52\\xff\\x97\\x39\\xe0\\x9c\\xe3\\xb5\\xe1\\xa2\\xd8\\x41\\x0f\\x42\\x68\\xe3\\xc7\\xed\\xc6\\x70\\x8f\\xfa\\xbd\\x17\\x72\\x0d\\x0a\\xa9\\x00\\xdf\\x26\\x24\\x98\\x99\\x1b\\x2f\\xf9\\x6b\\xf2\\xbf\\xc7\\x7f\\xfd\\xcd\\xcf\\xc3\\x93\\x2f\\x8f\\x8f\\xbf\\x7f\\x39\\xfc\\xcf\\x1f\\x7e\\x73\\xfc\\xd7\\x11\\xfe\\xe3\\xf3\\x93\\x2f\\x4f\\x7e\\xf6\\x7f\\xfc\\xe6\\xe4\\xe4\\xf8\\xf8\\xfb\\x6f\\xde\\x7d\\x7d\\x7b\\xf5\\xe6\\x07\\x76\\xf2\\xf3\\xf7\\x3c\\x4f\\xef\\xec\\x5f\\x3f\\x1f\\x7f\\x0f\\x6f\\x7e\\xd8\\xb3\\x93\\x93\\x93\\x2f\\x7f\\xbd\\x61\\x42\\x94\\x2f\\x3e\\x4c\\xb6\\x5e\\xe3\\xbd\\x82\\x5d\\x87\\xfb\\x50\\xa4\\x9a\\xe4\\xcc\\xb8\\x1e\\x0a\\x39\\xb4\\x1f\\xbc\\x26\\x5a\\xe6\\xeb\\xf9\\x54\\xc3\\xd4\\xee\\x32\\x90\\xee\\x4b\\x11\\xde\\x57\\xfa\\x5a\\xb2\\x9b\\xb8\\xa2\\x6b\\x4e\\x69\\x67\\x66\\x53\\xe0\\xf6\\xcc\\xf2\\x7d\\x13\\x73\\xec\\x9e\\xa7\\xdf\\x4c\\xe4\\x6e\\xd6\\xf4\\x88\\xcc\\xba\\xfb\\xf2\\x85\\xf2\\xce\\x07\\x4b\\xfd\\x2f\\x05\\xbc\\x5a\\x9c\\xbf\\x6d\\xac\\x3d\\xb8\\xa7\\x66\\xca\\x91\\x9d\\x47\\x98\\x49\\x26\\x24\\xd3\\x8b\\xf3\\x84\\x2a\\xf5\\x9e\\xa6\\xd0\\xf5\\x40\\x2e\\x27\\xa5\\x8c\\x35\\x30\\x17\\xda\\x50\\x20\\x47\\xa2\\x9d\\x37\\x88\\x1b\\x72\\xf3\\x86\\x5f\\x4e\\x50\\xc8\\xa8\\xf4\\xe3\\x37\\xd5\\x7f\\x5b\\x5c\\x4c\\x7f\\xc5\\x85\\x24\\x3f\\x81\\x14\\xae\\xfc\\x9e\\x04\\x2b\\xa8\\x6c\\x1c\\xc1\\x7d\\xb6\\xfd\\x1c\\xb6\\x6c\\x9b\\x82\\x28\\xc7\\x6d\\x33\\x1c\\xd2\\x83\\x91\\x35\\x26\\x6c\\xda\\x75\\xeb\\x6e\\xd6\\x75\\x4a\\x22\\xca\\xcd\\x42\\xb1\\xa0\\xe4\\x84\\xfc\\x98\\xc0\\x94\\x46\\x8b\\x1f\\xcd\\x82\\x7f\\x94\\x60\\xa6\\x68\\x04\\xbc\\x1f\\xad\\xd8\\x50\\x13\\x0c\\x9c\\xe3\\x0d\\x53\\x04\\x18\\xd6\\x18\\x65\\xfc\\xef\\x56\\x1a\\xf4\\xa2\\xf5\\xc6\\x99\\x48\\x0c\\xd7\\xcf\\x44\\x3c\\x32\\x67\\x30\\x5a\\x5a\\x2d\\xa2\\xd0\\xe2\\x61\\xc1\\x4c\\x7c\\xff\\xf9\\x0f\\x2b\\x6f\\x3a\\x3d\\xa3\\x16\\x56\\x62\\xac\\x5e\\x0e\\x99\\x23\\xda\\xdf\\xc6\\xd9\\xf8\\x0d\\x21\\x67\\x71\\xca\\x50\\x39\\x4a\\x8e\\xaf\\x6e\\xce\\x4e\\x6a\\x2b\\x37\\x7c\\x8e\\x25\\xc4\\xb1\\x00\\xef\\xfa\\x62\\x06\\x52\\xa5\\x9a\\x13\\x89\\x28\\x86\\x13\\xda\\x2b\\x8c\\xf1\\x84\\x7e\\x2e\\x66\\x83\\x51\\xf3\\xb9\\x25\\x84\\xd6\\x4f\\xf6\\xe6\\x8c\\xfc\\x68\\x78\\xe4\\x84\\x71\\xb0\\x67\\x90\\x49\\x36\\x67\\x09\\x4c\\xcd\\x4c\\x2a\\xe6\\x7c\\x72\\x9e\\x4b\\x09\\x5c\\x27\\x0b\\x5f\\x11\\x72\\xfd\\xe9\\x32\\x65\\xe8\\x55\\x1d\\xd0\\x1d\\x70\\x6e\\x9c\\x4c\\xa1\\x50\\x28\\x80\\xc1\\xf4\\xa2\\x20\\x1e\\x91\\x1b\\xec\\x69\\x61\\x0d\\x10\\xee\\x3d\\x3c\\x7b\\xe4\\x2a\\x36\\x01\\x0f\\x91\\xa0\\xcc\\x25\\x62\\xdc\\x7e\\xc5\\x62\\xcb\\x08\\x80\\x94\\xdb\\x14\\x6d\\x18\\x5b\\x6e\\xc5\\x48\\x91\\x18\\x59\\xb1\\x90\\x5a\\x0d\\x01\\x47\\xb5\\x0a\\x6e\\x36\\x32\\x60\\xce\\x67\\xc9\\x6d\\xe4\\x9a\\x03\\xdc\\xbc\\x47\\xbb\\x23\\x9c\\x1d\\x6f\\xe8\\xd7\\xb7\\x8d\\x77\\xb8\\x34\\x6b\\x9c\\xe4\\xe8\\xa7\\xe4\\x65\\x72\\x44\\x26\\x55\\x96\\x6b\\x89\\xe7\\xac\\xce\\x76\\x50\\x6a\\x09\\x28\\x73\\x90\\xaf\\xfc\\x14\\x25\\x8c\\x73\\x96\\xa0\\x0a\\x93\\x15\\xdb\\xb1\\x99\\xdf\\xc5\\x7b\\x48\\xab\\xaa\\x01\\x91\\xa5\\xae\\xca\\x6d\\x9e\\x65\\x42\\xea\\x52\\xf7\\x14\\xd5\\x64\\x7e\\xab\\xcf\\x59\\xb3\\x8f\\x66\\xba\\x99\\x84\\x8c\\xca\\x82\\xda\\x29\\x20\\xd1\\x8c\\x72\\xc3\\x6b\\x6d\\xd9\\x97\\x77\\x02\\xc3\\xf5\\x6d\\x5a\\x0b\\x33\\x1b\\x3a\\x16\\xb9\\x46\\x88\\x77\\x18\\x68\\x22\\x72\\x1e\\x13\\x83\\x5c\\x5f\\x93\\x99\\xd6\\x99\\x7a\\x7d\\x7a\\x5a\\x52\\xff\\x11\\x13\\xa7\\xb1\\x88\\xd4\\x69\\x24\\x78\\x04\\x99\\x56\\xa7\\x1e\\x17\\x9c\\x66\\x22\\x1e\\xfa\\x3f\\x86\\xd4\\x5f\\xe5\\xd3\\x17\\x6d\\x91\\x6f\\x81\\xbe\\x5f\\x13\\x7b\\xe0\\x1b\\xde\\x02\\x9e\\x6f\\xa9\\x74\\x39\\xdc\\xfe\\xb1\\x79\\xa1\\xdc\\xdc\\xb5\\x2f\\x69\\x91\\x38\\xf7\\xc8\\x8d\\x14\\xb8\\x5e\\xff\\xb4\\x7c\\xbf\\xa8\\xcf\\x5a\\xc8\\x18\\x15\\x94\\xfd\\x42\\x55\\xbb\\xde\\x4e\\xa3\\xb6\\x69\\x97\\x77\\xe8\\x93\\xf7\\xd7\\xf0\\xde\\x7a\\xac\\x6d\\xf8\\xee\\x72\\x15\\xc8\\x6f\\x69\\x4d\\xb1\\x74\\xab\\x11\\xcd\\xec\\x13\\x83\\x70\\xf9\\x82\\x98\\xab\\xa1\\x5d\\x1d\\x61\\xab\\xd9\\xdc\\xa6\\x45\\x98\\x19\\x0e\\x0d\\x33\\x53\\xfc\\xa1\\x30\\xbd\\x0d\\x60\\x32\\x81\\x48\\xff\\xa9\\xa2\\xaa\\x2a\\x72\\x2b\\x14\\xa6\\xad\\x3f\\xf8\\x7f\\xfd\\x69\\x33\\xa2\\xda\\xcb\\x0a\\xb5\\x9f\\xbb\\x87\\x9d\\xd2\\x76\\x15\\x7a\\x33\\xd5\\xf9\\x1b\\xec\\x71\\x89\\x53\\xb2\\x9b\\x67\\x07\\x43\\x55\\x02\\xda\\x82\\x9d\\x3e\\xd6\\x5a\\x26\\x1c\\x07\\x6a\\x30\\x57\\xe5\\xe5\\x9d\\x0e\\x0f\\x88\\xb4\\x2b\\x04\\xc7\\x69\\x72\\x4b\\x8b\\x20\\x90\\xf7\\xc2\\x25\\xa9\\x81\\x01\\xb9\\xc2\\x72\\xba\\xe5\\x2f\\x48\\xfb\\xdf\\x0b\\x9b\\xae\\x66\\x87\\x93\\xe7\\x9e\\x26\\x8a\\x9d\\xfe\\x32\\xcd\\xf6\\xf3\\x9b\\xd2\\x7d\\xc6\\x6e\\x4c\\xcd\\x7d\\xa6\\xbc\\x58\\x55\\x5b\\xd8\\xd6\\x8d\\xbd\\x83\\xc5\\xce\\x5d\\x75\\x6e\\x08\\xce\\x75\\x07\\x6d\\x4d\\x83\\x12\\x46\\xbd\\x0c\\x62\\x3d\\x13\\xfe\\xcb\\xe5\\x34\\x10\\xe9\\x98\\x71\\x3b\\x15\\x3b\\xb0\\x3f\\x67\\x1c\\xdb\\x9f\\x07\\x8f\\xf1\\xcf\\xdd\\x93\\xd8\\x73\\xb7\\xf7\\xf3\\xe1\\x69\\xb6\\xe5\\x1f\\x1a\\xf8\\xe7\\x14\\xd6\\xe7\\x5d\\x5b\\xba\\xce\\x0f\\xa7\\xe2\\x7c\\xf3\\xe6\\x1f\\x39\\x4d\\x46\\xe4\\xc2\\x52\\x02\\xdc\\x3c\\xfb\\xd3\\xae\\xeb\\x66\\xbb\\x58\\xb1\\xc9\\xdf\\xb3\\x24\\x8e\\xa8\\x8c\\x91\\x6a\\x5a\\xf4\\x43\\x94\\xb0\\x80\\x43\\x3d\\x9f\\xb8\\xa3\\x6f\\x8f\\x00\\x4b\\xe0\\xb1\\x85\\xae\\x49\\x46\\xa5\\x66\\x51\\x9e\\x50\\x64\\x0a\\x60\\x2a\\xe4\\x0e\\xe7\\xf3\\x3d\\x0f\\xb3\\x84\\xe6\\x1b\\x88\\x04\\x8f\\x77\\x58\\x0f\\x9b\\x9d\\xea\\xed\\x72\\xe7\\xd5\\xe3\\x45\\xe6\\x19\\x24\\x73\\x79\\x52\\x58\\x0a\\xcb\\xd7\\xeb\\xb8\\x26\\x7f\\xef\\x18\\x4b\\x4c\\x3c\\xb2\\x2b\\x70\\xcb\\xc0\\x72\\xae\\xf7\\x4c\\x41\\x35\\x9d\\x13\\x53\\xde\\xb5\\xff\\xa4\\x42\\x70\\x8a\\xdb\\x3e\\x22\\xff\\xbd\\xf0\\xec\\xc1\\x2e\\x97\\x1f\\xa6\\xbd\\x39\\x0b\\x15\\x46\\x6e\\xbe\\xee\\x2a\\xba\\x93\\x2c\\xd1\\xc8\\x44\\x48\\x98\\x83\\x24\\xc7\\xb1\\xc0\\x6f\\x30\\x2d\\xd3\\xc9\\x88\\xfc\\x3f\\x23\\x76\\x6e\\x33\\x05\\xd9\\xc6\\x61\\x6a\\x13\\xfb\\xb8\\x8b\\x5d\\x44\\x5c\\x60\\xd1\\x7e\\x34\\x33\\xbe\\x24\\xc7\\x36\\xd7\\x13\\x4b\\x53\\x88\\x19\\xd5\\x90\\x2c\\x4e\\xac\\x07\\x35\\x38\\x0d\\xde\\x3e\\x50\\xb3\\x4f\\x16\\xb3\\x4a\\xf6\\xb2\\xdf\\xff\\x6e\\xcb\\x9b\\x38\\xd9\\x3e\\x81\\xea\\x3b\\xaf\\xda\\x2e\\x37\\xd6\\x8a\\x29\\x4b\\xd0\\x53\\x18\\x43\\x77\\x3a\\x2a\\x6c\\xf4\\x00\\x1b\\x94\\xb8\\xa6\\xa2\\x05\\xf6\\xb8\\xb9\\x80\\xad\\xbf\\x1b\\x00\\xa5\\x44\\xc2\\x14\\xef\\xa7\\xbd\\x73\\x1d\\x6e\\x27\\x8b\\xd6\\x27\\x71\\xdb\\xc1\\x84\\x6c\\xb7\\x8a\\x0d\\x89\\x91\\x3a\\x7f\\xff\\xbb\\x98\\x6a\\xba\\xe1\\x05\\x0b\\x32\\x8b\\x6c\\xdd\\x55\\xdb\\xc5\\xdb\\x94\\x9d\\x6f\\x3a\\xeb\\x3d\\xcc\\x3c\\x6e\\xf8\\x56\\x3d\\xa0\\xc4\\xb8\\xee\\xcb\\x7d\\xa0\\xeb\\x12\\xd5\\xe0\\xd6\\x37\\xd1\\x83\\xc1\\x50\\xc2\\x94\\x29\\x2d\\x17\\x15\\x63\\x87\\x33\\xa3\\x0a\\xc2\\xb8\\xd2\\x94\\x6b\\x86\\xa8\\x9a\\xf8\\x37\\x87\\x4e\\xcf\\x6f\\xa4\\xb2\\xf5\\xe7\\xff\\x81\\x27\\x0b\\xab\\x44\\xc6\\xb0\\x1b\\x2b\\x8b\\xdd\\x2e\\x32\\x20\\x7f\\xac\\xfc\\xf1\\xb5\\xcc\\xa2\\xf5\\xdf\\x5f\\x4e\\x88\\x43\\xa0\\x16\\x36\\x69\\x1c\\x4b\\x50\\xab\\x98\\x6d\\xdd\\xd7\\x5b\\xb7\\xcf\\xab\\xc5\\xda\\xee\\xe0\\x95\\x57\\xab\\xb9\\xc8\\x1f\\xa5\\xd8\\xd4\\x08\\x29\\x3e\\x71\\xa3\\xb7\\x1b\\xd5\\x84\\x15\\x2b\\x6a\\xe2\\x87\\xd6\\x3a\\x0c\\x69\\x41\\x31\\x99\\xf6\\x52\\x63\\x24\\xb8\\xca\\x53\\x1f\\x09\\x62\\x44\\xec\\x0c\\x78\\x0c\\x3c\\x5a\\x60\\xa2\\xa7\\x64\\x0e\\x1b\\x34\\x0c\\xdf\\xaa\\x0d\\x20\\x41\\xc8\\x9f\\xd9\\x74\\x66\\x0e\\xca\\x4e\\xae\\xca\\x39\\x7b\\x0b\\xf9\\xd2\\x4c\\x99\\x32\\x1b\\x3f\\x01\\x29\\x21\\xb6\\x91\\x32\\x86\\xe9\\xf5\\x3d\\x54\\x2c\\x9e\\x2e\\xf3\\x94\\x77\\xe2\\x5c\\x9e\\x2c\\xa6\\xff\\x5b\\x3f\\xdd\\xdb\\x22\\xed\\xa4\\x37\\x8d\\xf8\\x3d\\xb5\\x18\\xc8\\x6c\\xc7\\x54\\x58\\x8f\\x82\\x4c\\x28\\xe6\\x93\\xbc\\x15\\x74\\xa1\\x96\\xba\\x52\\x4c\\x6c\\x62\\xc9\\xcd\\x63\\xd5\\x43\\xda\\xd0\\xf1\\x79\\x69\\xd1\\xa8\\x5d\\xc8\\xb9\\x3d\\x4c\\xa8\\xea\\x4e\\x3d\\x2e\\xdc\\x90\\x1c\\xf3\\x76\\xf5\\xa8\\x0b\\x67\\x1c\\x8c\\x83\\xab\\x2f\\xad\\xa4\\x65\\x92\\xf2\\x3b\\x88\\x49\\x02\\x0f\\x2c\\x12\\x53\\x49\\xb3\\x19\\x8b\\x30\\x85\\xa1\\x35\\x2b\\x1b\\x89\\x51\\x5b\\x37\\xaa\\xcd\\x10\\xbe\\x89\\x7a\\x65\\xf9\\x38\\x61\\x6a\\xb6\\xde\\x40\\xb9\\xf5\\x72\\x28\\x88\\x24\\xe8\\xb5\\x98\\x6f\\x9f\\xbb\\x71\\x63\\x3f\\x2f\\x99\\x1f\\xef\\x60\\xee\\xfa\\x75\\xf1\\x19\\x16\\xda\\x7d\\x14\\x29\\x8d\\x22\\x73\\xb1\\xbd\\xb1\\x15\\x1c\\x27\\x58\\xb9\\x44\\x1b\\x30\\x84\\xf6\\x16\\x2d\\xd3\\xcb\\x1d\\x40\\x66\\xe1\\x19\\x9d\\xd5\\x54\\x8a\\x5a\\x4c\\xc5\\x78\\x04\\x98\\x92\\xd1\\xa5\\xd6\\x04\\xf0\\xd6\\x06\\x2d\\x19\\x58\\x0e\\x16\\xd0\\xc0\\xe8\\x4f\\x11\\xb8\\x5e\\xcf\\x71\\x6e\\x57\\x22\\x6c\\x51\\x20\\x6c\\xdf\\xf1\\x02\\x17\\xee\\xdc\\xf4\\x0a\\x0e\\xf5\\x4c\\x81\\xf9\\xb7\\xd9\\x5e\\x7c\\xd2\\xf4\\xb0\\x6d\\x06\\xce\\x1b\\xeb\\x7a\\xdd\\x1a\\x1f\\x7e\\x5b\\xeb\\xc5\\xb9\\x82\\x29\\x32\\x13\\xf7\\x6e\\x80\\x65\\x8c\\xe1\\x54\\x9e\\x1e\\x0c\\x62\\xa6\\x22\\x83\\x66\\x36\\x28\\x8e\\xce\\x05\\x57\\x3e\\xe3\\x26\\xe5\\x36\\x49\\xe6\\x9c\\x26\\x2e\\x1a\\xd6\\x0d\\x96\\x89\\x04\\x4d\\xae\\x71\\xee\\xe5\\x55\\x1b\\xea\\x03\\xe9\\x18\\xe2\\x18\\x62\\xef\\x5f\\xbe\\x20\\x1b\\x88\\xfe\\x0e\\x86\\x63\\x17\\x4f\\xe0\\xc9\\xe2\\x95\\x48\\x92\\xed\\x34\\x7d\\xab\\x62\\x65\\x1f\\xb5\\x8a\\xdf\\x80\\xbd\\x7d\\x5a\\x76\\xb0\\x99\\x97\\x7e\\x43\\x9d\\x5e\\xdc\\xdc\\x8e\\xd2\\xe6\\x8d\\x40\\x66\\x04\\x96\\x62\\xdf\\xc7\\xa0\\xef\\x01\\x38\\x89\\x66\\x10\\xdd\\xa9\\xd2\\x55\\x4f\\x9b\\x7b\\xb8\\x74\\xd0\\x4e\\x59\\xbb\\x9d\\x41\\xac\\x62\\xd0\\x82\\x31\\x35\\x07\\xea\\x22\\xda\\x81\\x30\\x23\\x16\\x72\\xb8\\x5f\\xf6\\x0b\\x5b\\x25\\x5c\\x74\\x4e\\x59\\x42\\xc7\\xc9\\x0e\\x81\\xf9\\x72\\x52\\xbe\\x39\\xa8\\xce\\x9f\\x79\\xee\\x28\\xcb\\x93\\xc4\\xd9\\xbf\\xd1\\x23\\x46\\x4b\\x3a\\x99\\xb0\\x08\\x7d\\x1d\\xd1\\x23\\xa8\\xf4\\xec\\x5d\\xbb\\xf4\\x56\\x5e\\x40\\x4a\\x53\\x9d\\xaf\\x1c\\xfd\\x16\\xb8\\xd9\\x06\\x2f\\x46\\x0a\\x65\\x1b\\xf5\\xad\\xfb\\x40\\xc8\\x75\\x5d\\x82\\x35\\xb3\\x03\\x2b\\xa2\\xd7\\x4c\\x67\\x23\\xf2\\x5e\\x68\\xe7\\x71\\xf7\\x0e\\x94\\x72\\xde\\x7e\\xe4\\x1a\\xa8\\x12\\xbc\\x42\\x0a\\x50\\xf2\\x90\\x6c\\xca\\x38\\x5d\\x9f\\x92\\xc0\\xae\\xbf\\xaa\\x58\\x2f\\x04\\x4d\\xba\\xc0\\x94\\xc4\\x6c\\x2a\\xa9\\x2e\\x30\\x78\\xb9\\x44\\x47\\x34\\x1d\\x5b\\x60\\x2d\\x16\\x23\\x72\\xc6\\x17\\x08\\x36\\xce\\x0d\\x6f\\xbd\\x4e\\x95\\x71\\x2d\\x45\\x9c\\x47\\xe0\\x92\\x2f\\xe7\\xaa\\xda\\x71\\xaf\\x74\\x60\\xbf\\x6b\\x79\\xee\\x07\\x2f\\x63\\x0d\\x62\\xd0\\x94\\x39\\x93\\xb9\\xe0\\x40\\xa8\\xca\\x8c\\xf8\\xef\\xaf\\x81\\xb5\\x9e\\x95\\x07\\x84\\x54\\xf0\\xec\\xea\\x92\\x5c\\xc3\\x76\\x68\\x1c\\x0e\\x37\\x4d\\x02\\xbd\\x46\\x94\\x96\\x79\\x84\\x44\\xd6\\xdc\\x7e\\x1e\\x3b\\x72\\x69\\x2f\\x80\\xf5\\xda\\xac\\xc4\\x38\\x39\\xa5\\xa1\\xe5\\x8a\\x33\\xaa\\x67\\x64\\x64\\x0f\\x74\\x54\\xd9\\x4e\\x42\\xbe\\x32\\x04\\xf7\\x81\\xa6\\x59\\x02\\x83\\x8d\\x26\\x96\\xff\\x83\\x84\\xed\\x2b\\x21\\x6e\\x2c\\x48\\xd8\\x99\\xfc\\x73\\xd3\\xdb\\xe6\\xff\\x4e\\x4f\\x97\\x01\\x56\\x8c\\x8d\\x90\\xe2\\x6c\\x08\\x08\\xb7\\x13\\x21\\x5e\\xa8\\xfa\\x7e\\x6d\\xda\\x1a\\xdf\\xe7\\x37\\xe8\\x90\\xba\\x66\\x25\\x38\\x43\\x2a\\xe1\\x35\\x39\\x3a\\xf3\\xb8\\xe4\\x68\\x40\\x8e\\xae\\xa4\\x98\\x62\\x74\\x0a\\x9f\\xba\\x18\\x92\\xa3\\x0b\\x98\\x4a\\x1a\\x43\\x7c\\xb4\\x63\\xac\\xdf\\x60\\x14\\xd3\\x3b\\x90\\x53\\xf8\\x06\\x16\\x7f\\xdc\\x40\\xaa\\x56\\xbf\\xf0\\xb4\\xf7\\x8f\\x18\\x0b\\xb5\\xeb\\x13\\xc3\\x1e\\x19\\x1e\\xe2\\x8f\\x29\\xcd\\xf6\\x79\\xf7\\x1d\\xcd\\xf6\\x99\\xcd\\x79\\x79\\x19\\xbf\\xff\\x21\\x05\\x4d\\xe7\\xaf\\x46\\x25\\x28\\xff\\xf8\\x77\\x25\\xf8\\xeb\\xa3\\x72\\xff\\x06\\x22\\x65\\xe8\\xfc\\xb7\\x38\\x22\\xb5\\x45\\xbc\\x3e\\xc2\\x55\\xb8\\x5f\\xfd\\x66\\xbc\\x3e\\x32\\xe3\\x1f\\x19\\x8c\\xa7\\xc5\\x38\\x9f\\xbc\\x3e\\x42\\xef\\xb8\\xc1\\xab\\x81\\x84\\x6c\\x60\\xb8\\xe4\\x3f\\x96\\x7d\\x1f\\xfd\\xb8\\x19\\xb0\\xdc\\xca\\xac\\xa1\\x17\\x61\\x75\\x93\\xa9\\xe5\\xff\\xfc\\x6b\\x0b\\x33\\xb7\\x85\\x8c\\xef\\x72\\xd9\\x1d\\x92\\x84\\x2a\\x7d\\x2b\\x29\\x57\\x38\\xdd\\x5b\\x96\\x6e\\xda\\xd8\\x21\\x49\\x2d\\x42\\xdd\\xf8\\x5c\\x22\\x92\\xdd\\xf8\\xd8\\x82\\xed\\xc6\\xc7\\x1b\\xcf\\x74\\x37\\x23\\xb2\\xba\\x86\\x3e\\x8c\\x67\\xab\\xbd\\x96\\xd1\\xbd\\x86\\xcd\\xf7\\xaa\\xd3\\xe2\\xac\\x0d\\x61\\x76\\x6f\\x83\\xcb\\xf7\\x6e\\x10\\xa4\\xa3\\x24\\x18\\x3e\\x86\\x47\\xbd\\x8d\\x1e\\x5b\\x5c\\x57\\x28\\xbd\\xee\\x5d\\x16\\x78\\x92\\xf3\\x18\\x64\\x82\\xfe\\x01\\xe5\\x78\\xd6\\x3a\\x1c\\x8f\\x9c\\x2e\\x8d\\x16\\x6a\\x51\\xf4\\x5c\\x47\\x66\\x82\\x57\\x6c\\x70\\xd6\\xd7\\xd5\\xf7\\x68\\x70\\xb2\\x4b\\xb4\\x6f\\xbb\\x41\\x9e\\x25\\x8a\\x20\\xd3\\xdb\\x99\\x96\\xbd\\x54\\xdc\\x5e\\x4f\\x69\\x78\\xee\\xa1\\xde\\x0c\\x55\\x0e\\xa6\\xfa\\x38\\x2f\\xd7\\x95\\x75\\x26\\x9b\\xe5\\x29\\x35\\xf4\\x9e\\xc6\\xe8\\xdb\\x5a\\x3c\\xb3\\x2a\\x07\\xab\\x22\\xb0\\x74\\xcc\\x9a\\xcb\\xad\\x1d\\xd3\\x1f\\xdf\\xce\\x13\\x72\\x3c\\x00\\x2d\\x32\\x45\\xec\\x50\\x3e\\xee\\xb5\\x67\\x29\\x7d\\x78\\x0b\\x7c\\xaa\\x67\\xaf\\xc9\\x17\\xbf\\xfd\\xbf\\xbf\\xff\\x8f\\x0d\\x2f\\x5a\\x52\\x02\\xf1\\xd7\\xc0\\x9d\\xd2\\xb5\\x8f\\xdd\\x5b\\xed\\x75\\xd9\\x6a\\x30\\xf2\\xd1\\x15\\xa3\\x69\\xf9\\x4e\\x61\\x9f\\x2b\\xa1\\xf2\\x9e\\xa2\\xff\\xb3\\x63\\x83\\xf2\\x6c\\xfb\\x76\\x7e\\x85\\x21\\x3e\\x4a\\x53\\x1e\\xc1\\xc0\\x70\\xd7\\x6b\\x87\\x61\\x05\\xa5\\x4c\\x16\\xe4\\xd5\\x6f\\x07\\xe8\\x9d\\x8d\\x93\\x5a\\x21\\x86\\xdf\\x3f\\xfc\\x30\\x5a\\xb3\\x18\\xa6\\xc8\\x7f\\x0e\\x96\\x66\\xca\\x14\\x31\\x67\\x2f\\x26\\x08\\xa6\\x5b\\x26\\x89\\x5a\\x14\\x09\\x96\\xd3\\xf1\\x3a\\xb5\\x55\\x4e\\x07\\x8a\\x95\\xec\\x82\\x84\\x5d\\xaa\\xfe\\xfd\\xd4\\xfc\\x29\\xe3\\x2c\\xcd\\xd3\\xd7\\xe4\\xe5\\x86\\x57\\x2c\\x46\\xee\\x03\\x3c\\x6c\\x4f\\x25\\x17\\x48\\x0d\\x5a\\x9e\\x4a\\x9a\\xa6\\x18\\xc4\\xc8\\x62\\xe0\\x9a\\x4d\\x18\\x3a\\xab\\x15\\x57\\x0c\\xd5\\x62\\xf6\\x43\\xef\\x60\\x59\\x6c\\x3e\\xfa\\x5e\\x1a\\x34\\xba\\xd7\\xa5\\xbb\\xb2\\x6c\\xb1\\x44\\xde\\xc9\\x19\\xc1\\xa3\\x2a\\xe6\\x5d\\x64\\x60\\x6f\\xa5\\x95\\xc2\\x09\\x3c\\x64\\x56\\x30\\xaa\\x98\\x63\\x53\\xa0\\x9c\\xf1\\xa9\\x2a\\xfd\\xa4\\x11\\xff\\x6d\\xb3\\x36\\x99\\xcf\\xee\\x67\\xe0\\x3c\\xb1\\xa0\\x6a\\x6c\\xf7\\x69\\xb6\\x8c\\x64\\x56\\xc6\\x07\\x60\\xcc\\xc8\\x76\\xf4\\xb1\\x6a\\xda\\x30\\x42\\x4c\\x0a\\xc9\\x39\\x55\\xb0\\x87\\x19\\xa3\\xe2\\x44\\xed\\x6b\\x8f\\x14\\xb1\\xed\\xbd\\x21\\xa0\\x57\\x2f\\x7f\\xbb\\x15\\xee\\x8a\\xf7\\x36\\xbe\\x54\\xba\\x57\\x7f\\x7f\\x36\\xfc\\x7f\\x74\\xf8\\xd3\\x0f\\xc7\\xee\\x1f\\x2f\\x87\\xff\\xf9\\xb7\\xc1\\xeb\\x1f\\x3e\\xaf\\xfc\\xf9\\xc3\\x66\\xaf\\xe8\\xf5\\x82\\x68\\xd9\\x6a\\x30\\xec\\x68\\xad\\x17\\x46\\x3c\\x7c\\x0c\\xbc\\x17\\xe6\\xad\\xcc\\x61\\x40\\xbe\\xa2\\x89\\x82\\x01\\xf9\\x96\\x23\\x9d\\xec\\xb8\\x69\\xdb\\x9d\\x95\\x0c\\x67\\x73\\x64\\x46\\xdd\\xc4\\x6f\\xbb\\x57\\x70\\x4a\\xdb\\xdf\\x71\\xd3\\xdd\\xa6\\xd1\\xe9\\xe1\\xa2\\x7b\\x2d\\x5e\\x05\\x4b\\xf2\\x0a\\x78\\xda\\x80\\xcc\\x89\\x10\\x23\\x27\\x37\\x8d\\x22\\x91\\x9e\\x16\\xcf\\xb7\\xc1\\xed\\x66\\x01\\x8f\\x60\\x6a\\x56\\xbe\\x20\\x25\\x1a\\xb7\\x22\\xcd\\xf2\\x75\\x53\\x18\\x18\\x48\\x23\\x29\\x94\\x2a\\xcb\\x4d\\x90\\x84\\xdd\\x01\\x39\\x2b\\x95\\x28\\x86\\x38\\x8c\\x21\\xa2\\x28\\x15\\xca\\x31\\xd3\\x92\\x5a\\x7b\\x92\\x17\\x0a\\xac\\xb6\\x6f\\xcb\\x6c\\x72\\x05\\x93\\x3c\\x21\\xc7\\x0a\\x80\\x8c\\xd0\\xf1\\x7b\\x85\\xce\\x9c\\x38\\x53\\xd0\\x98\\x25\\x0c\\x63\\x2d\\x49\\x0c\\x91\\xe0\\x93\\x84\\x39\\x31\\x35\\xcd\\x84\\xd4\\x94\\x6f\\xcd\\x30\\x62\\x43\\xf5\\xa7\\xf0\\x40\\x58\\xe1\\x6d\\x65\\x3e\\x3e\\x8e\\xb9\\x7a\\xf5\\xea\\xb7\\x5f\\xdc\\xe4\\xe3\\x58\\xa4\\x94\\xf1\\xaf\\x52\\x7d\\x7a\\xf2\\xe5\\xf1\\x3f\\x72\\x9a\\xa0\\xff\\xcf\\x7b\\x9a\\xc2\\x57\\xa9\\x3e\\xe9\\x8f\\xe3\\x78\\xf5\\xfb\\x3d\\xae\\xf2\\xf1\\xf7\\xf6\\xc2\\xfe\\x70\\xfc\\xfd\\xd0\\xfd\\xeb\\x73\\xff\\xd3\\xc9\\x97\\xc7\\x7f\\x1d\\x6d\\x7d\\x7e\\xf2\\xf9\\x29\\x06\\x48\\x14\\xf7\\xfe\\x87\\xef\\x87\\x25\\x0e\\x18\\xfd\\xf0\\xf9\\xc9\\x97\\x95\\x67\\x27\\xeb\\x30\\xc2\\x6a\\xa6\\xb7\\x94\\x66\\xc3\\xbb\\x8d\\xa9\\x2f\\x37\\xca\\x15\\x9b\\x52\\xc6\\xad\\x13\\x44\\x6d\\xc0\\xda\\x3b\\x9a\\x5d\\xc3\\x04\\x24\\xf0\\x68\\xb7\\x7a\\xfc\\x7c\\xe5\\x13\\x72\\x1c\\x1b\\x7e\\x0a\\xc3\\x94\\x4f\\xbc\\x24\\x21\\x8b\\xa7\\x8e\\xab\\x28\\xbe\\xf3\\xa4\\xb6\\xa8\\xb2\\xb6\\xec\\x6f\\xe8\\xa3\\xe8\\x0a\\xdd\\x94\\xe3\\xeb\\xd7\\x28\\x22\\xcb\\x5e\\x9b\\x6b\\x9b\\x77\\x99\\xb7\\x8d\\xb8\\xbb\\xe5\\x11\\x7a\\x55\\xb7\\x50\\x62\\x1b\\xde\\xc0\\x2a\\xf3\\xb7\\x89\\x73\\x7b\\x00\\xf9\\x7e\\x82\\x08\\xdf\\x12\\x40\\xb1\\x73\\x90\\x62\\x9d\\xad\\x7b\\xf0\\xa8\\xec\\x3b\\xab\\x53\\x6e\\xdd\\x4f\\xce\\x36\\x4a\\xfa\\xfb\\x52\\x80\\x6f\\x2f\\x2f\\x2c\\xcc\\x20\\x02\\x46\\xf6\\x7e\\x26\\x92\\x58\\x91\\x9c\\xb3\\x7f\\xe4\\x40\\x2e\\x2f\\x8a\\x4c\\x66\\x8c\\x47\\x49\\x8e\\x95\\xc6\\xbe\\xfd\\xf6\\xf2\\x42\\x8d\\x08\\xf9\\x6f\\x87\\x74\\xef\\x37\\xe3\\x56\\x9b\\x33\\xf4\\xc3\\xfb\\xb7\\xff\\x83\\x4a\\x3b\\xfc\\xd2\\x15\\xfa\\xf1\\x99\\x2c\\x19\\xb5\\xda\\x76\\xcb\\x09\\x99\\x5e\\xad\\x5b\\x3c\\xce\\x28\\xa2\\xd9\\x66\\xfd\\x29\\x71\\x36\\x09\\x6e\\x43\\x1d\\x66\\x90\\x64\\x0a\\x83\\x38\\x89\\xca\\xa5\\x5b\\x8d\\x19\\xd0\\xc6\\x92\\x61\\x9a\\x0d\\xe7\\x14\\xe4\\xe3\\x52\\x31\\xee\\xb7\\x55\\x74\\x49\\x24\\x38\\x87\\x08\\xbd\\xae\\x8c\\x44\\xb0\\x0f\\x86\\xa8\\xbe\\xbf\\x2c\\x6d\\xad\\x15\\x2f\\x96\\xc3\\x44\\xca\\x31\\x3d\\xfe\\xf0\\xc6\\x9f\\xfe\\x2f\\xba\\xb9\\x91\\x1f\\x9c\\x5c\\x85\\x33\\x6e\\x71\\xab\\x9d\\xdf\\x44\\x6b\\xf8\\x36\\x73\\x70\\xfb\\xf6\\xe8\\x28\\x61\\x65\\xbd\\xad\\x46\\xb4\\x06\\x19\\x74\\x74\\xb9\\xde\\x61\\x97\\xab\\xbb\\x9c\\xaf\\xa8\\x99\\x96\\x72\\x07\\xa0\\x71\\xa8\\xf0\\x95\\x99\\x51\\x45\\xc6\\x00\\x1c\\x6d\\x55\\xd6\\x26\\x01\\xdc\\xc1\\x3c\\x94\\x96\\xa4\\x3c\\x1b\\x6a\\x31\\xdc\\x20\\xec\\xee\\xd8\\xb9\\xdd\\xbb\\xb6\\x45\\x97\\x53\\x5b\\xdb\\x59\\x63\\xed\\xcc\\xfd\\x6c\\xb1\\x6e\\x0f\\x54\\x59\\x67\\xac\\xe0\\x1b\\x9b\\x2e\\x6c\\xb3\\x88\\x5c\\x9b\\xb3\\x33\\x20\\x15\\x64\\x1b\\xff\\x5a\\x9d\\xd2\\xbd\\x41\\x5d\\x55\\x2d\\xa0\\x16\\xe8\\x3a\\xb1\\x53\\xcd\\xbf\\x63\\x8e\\xf6\\x98\\x6f\\x40\\xce\\xd9\\x1e\\xcc\\xc7\\x75\\xfd\\xfd\\xbd\\x50\\xcb\\xd7\\xd7\\x57\\xe7\\x18\\xe6\\x6c\\x3e\\xf0\\xb6\\x57\\x84\\xfe\\x2a\\x57\\xd1\\x1c\\xad\\xec\\x42\\x09\\x91\\x75\\xa3\\x3c\\x7b\\xfc\\x0b\\x6d\\xd8\\xf1\\xd6\\x83\\xa0\\xae\\x3f\\x12\\x3b\\x0c\\xea\\x5b\\x03\\x0f\\x71\\x6b\\xb7\\x45\\x6a\\x36\\xe9\\xa3\\x29\\xbf\\x61\\xf1\\x58\\x2d\\xb6\\x57\\x69\\x21\\xcd\\x75\\xad\\xfd\\x96\\x8f\\x0b\\xb1\\xaa\\xec\\xdd\\x89\\xe0\\xe4\\x9f\\xff\\xfa\\xec\\x33\\x23\\xc5\\xd1\\x8c\\x79\\x4e\\x85\\xd0\\x8c\\xc1\\x83\\x06\\x8e\\x19\\xd0\\x46\\x77\\xff\\x81\\xf1\\x44\\xf3\\x57\\x9f\\xdd\\x31\\x1e\\xbf\\x26\\xe7\\xb9\\xd2\\x22\\xf5\\xa6\\x3f\\x2c\\xc2\\x89\\x37\\xe3\\x33\\xaf\\xe4\\x33\\x83\\x60\\x5e\\xec\\x6a\\x38\\x8e\\x61\\x7d\\xa5\\x41\\x64\\x72\\x38\\x05\\x3e\\x32\\x8c\\x3a\\x86\\x67\\x81\\xc4\\xce\\xfd\\xd0\\xf3\\x97\\xa3\\x57\\xbf\\x1b\\xbd\\xfc\\xcc\\xb1\\x6f\\x24\\x4a\\x72\\x85\\x55\\x4b\\x71\\x97\\xdc\\x6b\\x6a\\x54\\x78\\xa2\\x8f\\x22\\x21\\x41\\x98\\xff\\xa4\\x9f\\xa9\\x0c\\x22\\x33\\x18\\x66\\x58\\x7f\\x4d\\xd6\\xbe\\xe3\\x38\\x3b\\x37\\x27\\xeb\\xfe\\x5d\\x81\\xe3\\x21\\x11\\x49\\x8a\\xff\\x76\\x6b\\xb5\\xc3\\xbb\\x4b\\xe7\\x36\\x08\\x9f\\x1b\\xf1\\xe2\\x9b\\xcd\\xef\\xbc\\x65\\xca\\xde\\x9c\\x2c\\xc9\\x25\\x4d\\x36\\x2d\\x04\\x5f\\x51\\x33\\x21\\xf5\\xfb\\x72\\x5a\\x98\\x50\\x45\\xcd\\xab\\xff\\x76\\x2f\\x32\\x8e\\x7e\\xb1\\x1b\\x7a\\xfb\\x8c\\x10\\x15\\x09\\x03\\x26\\x05\\x34\\xc5\\x9f\\x11\\xef\\xd4\\xe0\\x3a\\x1f\\xd6\\x82\\x96\\xd1\\xeb\\xe2\\x5c\\x24\\x79\\x5a\\x35\\xe3\\x0f\\x57\\xe9\\x96\\xd9\\xb5\\x82\\x63\\xb9\\xf9\\xae\\x02\\xa4\\x7f\\x57\\x82\\x5f\\x51\\x23\\x6e\\xda\\x10\\xd4\\x98\\xa9\\x2c\\xa1\\x8b\\xf7\\x75\\x19\\xc2\\x9e\\xe6\\x85\\x7d\\xf6\\xd9\\x8e\\xfb\\xb1\\x66\\xfc\\x25\\xcf\\x8c\\xed\\x53\\x98\\x57\\xce\\xa9\\x3a\\xfc\\x77\\x2b\\xbf\\xef\\x3b\\xbc\\x5f\\x3e\\x35\\x23\\x57\\x5c\\x1b\\x05\\x07\\x9f\\x6c\\x52\\x6d\\x99\\xd0\\x9a\\x57\\xec\\x8c\\xae\\x57\\x1f\\x6c\\x98\\x52\\xb5\\x4b\\xab\\xb6\\xc8\\x66\\x54\\xad\\x6e\\xf1\\xd5\\xd2\\xaf\\x6b\\xba\\xb3\\x2f\\xce\\x5f\\x61\\x7e\\x79\\xaf\\xec\\x53\\xd1\\x0c\\xd2\\x8a\\xc7\\xb1\\xc8\\x80\\x9f\\x5d\\x5d\\x7e\\xf7\\xc5\\xcd\\xd2\\x83\\x65\\x96\\x77\\x1d\\xf4\\x3b\\x09\\x15\\x11\\x45\\xe1\\x24\\x80\\x67\\x67\\xd8\\xfd\\x1f\\xd7\\x7e\\x73\\x93\\x41\\xf4\\xe3\\x68\\x65\\xe6\\x2b\\x44\\x68\\x3d\\x4f\\x3b\\x2c\\xf2\\x44\\x2d\\xfd\\x6c\\xf6\\xbf\\xf2\\xd3\\x26\\xd2\\x55\\x41\\x7f\\x4b\\x08\\x78\\x97\\x90\\x65\\x36\\xc9\\xad\\xda\\x7b\\x8b\\xe9\\x12\\x60\\x21\\x76\\x3b\\x5b\\xf8\\x4d\\x14\\x84\\xdb\\xda\\x30\\xac\\xd7\\x99\\x5d\\xe5\\x2a\\x13\\x71\\x83\\x5e\\xd0\\x85\\xf5\\x30\\x12\\x7c\\x0e\\x52\\x13\\x09\\x91\\x98\\x72\\xf6\\x53\\xd1\\xbb\\x5a\\x72\\x16\\xc2\\x7b\\xcd\\x69\\xe2\\x83\\x67\\xd6\\x85\\x44\\xa4\\x74\\x41\\x24\\xfc\\x1d\\x5d\\x2d\\x78\\xa5\\xc7\\x4d\\xb9\\x7a\\x8b\\xa0\\xd4\\x32\\xe2\\x74\\xca\\xb4\\x27\\x0f\\x91\\x48\\xd3\\x9c\\x33\\xbd\\x38\\x45\\x4c\\xcf\\xc6\\xb9\\x41\\xbd\\xa7\\x31\\xcc\\x21\\x39\\x55\\x6c\\x3a\\xa4\\x32\\x9a\\x31\\x0d\\x91\\x91\\xf4\\x4e\\x69\\xc6\\x86\\xb8\\x18\\x6e\\x9d\\x1d\\xd2\\xf8\\x57\\x05\\x8d\\x5a\\x1a\\x78\\x23\\x05\\x45\\x0c\\xdd\\xf0\\xb0\\x0c\\xc6\\x76\\x99\\x29\\x2a\\xe9\\x72\\xcb\\x33\\xf1\\x9a\\x99\\xeb\\x37\\x37\\xb7\\x85\\x04\\xef\\xae\\x3a\\x1e\\x51\\x85\\xef\\xda\\x7c\\x5a\\x66\\x67\\x19\\x9f\\x80\\xb7\\x48\\xf8\\xc4\\x65\\xc0\\x63\\x5b\\xc8\\x1c\\xb9\\xaf\\x84\\x21\\xc3\\x96\\x8f\\x53\\x86\\x1e\\xad\\x98\\x61\\x67\\x7d\\x90\\xc5\\x79\\x51\\x66\\xc2\\x79\\x3c\\xae\\xbe\\x72\\x59\\xd1\\xe8\\x3e\\xf9\\xd9\\xa1\\xa9\\x66\\x68\\x0e\\x64\\xef\\xd3\\xab\\x32\\x0b\\xab\\x1f\\xac\\x61\\x3d\\x3d\\x75\\x6f\\x72\\xdc\\x1b\\x11\\x0d\\x89\\x21\\x4a\\xa8\\x8f\\xff\\xd5\\x90\\x24\\xe4\\xc3\\xdb\\x77\\xe8\\x53\\xea\\x43\\x12\\x92\\xa4\\x1a\\xc2\\xb0\\xd2\\x75\\xe1\\x68\\x9c\\x52\\x8e\\x1e\\x69\\x59\\x66\\x8d\\x50\\xd4\\x95\\x09\\xdf\\xe0\\x9b\\xb8\\x85\\xb5\\xde\\x2c\\xad\\x0f\\xc9\\x7a\\xaa\\xea\\x9f\\xba\\x09\\x2f\\x3d\\xd9\\xc6\\xa6\\xaf\\xf0\\x67\\xcd\\x36\\x96\\x60\\x49\\x85\\xa2\\x0b\\xa7\\xe6\\xc9\\xb9\\xf5\\xa3\\xc2\\x1c\\x77\\x77\\xe0\\xbd\\xed\\x53\\x9a\\x21\\x63\\xea\\x93\\x5d\\xd0\\xea\\xcd\\xc2\\x88\\xe4\\x8d\\xe9\\x1e\\xd0\\xe6\\xbc\\x20\\x86\\x1b\\x45\\x74\\xa6\\x85\\x70\\x6e\\x9b\\xa6\\x3f\\x57\\x15\\x45\\x4b\\x06\\xf3\\xaa\\x55\\xa0\\xb0\\x36\\x37\\x17\\x6d\\xf6\\xcf\\xe8\\xb2\\x95\\xb3\\xa7\\x19\\x73\\xbc\\x59\\x5c\\xf0\\xc7\\xed\\x37\\xfa\\xea\\xd2\\x41\\x70\\xc9\\x6c\\x2b\\x07\\xc1\\xae\\x76\\x85\\x63\\x8b\\x0a\\xae\\x1d\\x27\\xe0\\x40\\x33\\x26\\x65\\x45\\x83\\x98\\x8c\\xd7\\x07\\xa8\\x57\\xcb\\x16\\xd8\\xf4\\x58\\x92\\x72\\xb3\\xf5\\x6b\\xaf\\x50\\x8b\\x8d\\xdd\\x25\\x33\\x8a\\x7b\\xbe\\xd9\\xa5\\xa9\\xdf\\xf0\\xfa\\xea\\x7e\\x16\\x3f\\xfb\\xac\\x92\\xa5\\x33\\xa4\\x16\\x88\\x13\\xac\\xb6\\x02\\xf7\\xb3\\x48\\x3c\\x39\\x67\\x94\\xd0\\xe9\\x54\\x62\\xb8\\xc8\\x96\\x82\\x4c\\x7b\\xc5\\xba\\xef\\x53\\x77\\x61\\x68\\x85\\x9a\\xad\\x6f\\x18\\xf4\\xbb\\xf5\\x85\\x8d\\x6a\\x7d\\xff\\xc2\\x2a\\xdf\\x5c\\x6f\\xfb\\x45\\xe5\\x53\\x54\\x5e\\xfa\\xad\\x15\\x72\\x47\\x1c\\xec\\xbe\\x89\\x79\\xf7\\x4a\\xc8\\x5b\\x3f\\xe7\\xa5\\x89\\xb8\\xa7\\x63\\xcc\\xd4\\x5c\\x10\\x00\\x83\\x39\\xa2\\xd2\\xef\\xc5\\x05\\x0d\\x64\\x20\\x27\\x42\\xa6\\x36\\x50\\x86\\x92\\xc8\\xb2\\xb2\\x05\\xde\\xf2\\x3e\\x21\\x3b\\xa6\\xd3\\x20\\xe3\\xf6\\xfe\\xd5\\x37\\x86\\xe8\\xfc\\xba\\xe3\\xb5\\x26\\xf5\\x32\\xaa\\x9b\\xb6\\xf3\\xe5\\x86\\xc9\\x8e\\x2b\\x74\\xab\\xf7\\xbe\\xcd\\x36\\xf4\\xde\\xe9\\x1e\\x41\\xb6\\xb6\\xb5\\xc9\\xc9\\x7c\\x4d\\xef\\xdf\\x55\\x3d\\xda\\x24\\xbd\\x27\\xc0\\x23\\x61\\x70\\xca\\xff\\xef\\xe6\\xc3\\xfb\\xfd\\x82\\xf1\\x6d\\xbb\\xd4\\x84\\xa5\\x59\\xe2\\xd2\\xc1\\xbf\\xa3\\x52\\xcd\\x68\\x02\\xb6\\x9e\\xd2\\xb7\\x3c\\xad\\xfd\\xbd\\x3b\\x5a\\xde\\xb6\\x4a\\xd0\\x54\\x0c\\x09\\x5d\\xd8\\x49\\xc5\\x10\\x09\\x34\\x09\\x09\\x49\\x32\\x23\\x28\\xa4\\x59\\x8e\\xc1\\x9a\\xf8\\x14\\xe7\\xbf\\x67\\x1a\\xe3\\x86\\x79\\xb2\\xbd\\x0e\\x70\\xbc\\xd8\\xea\\xc9\\x65\\xdb\\xc3\\x30\\xde\\x17\\xe5\\x54\\x27\\xb3\\x6f\\x46\\xf0\\x06\\xf9\\xc0\\xf7\\x5c\\x65\\x11\\x0b\\x7b\\xb5\\x45\\x89\\x59\\xed\\xb1\\x61\\x2c\\xf9\\x17\\xbf\\xdd\\xf2\\x66\\x0c\\x59\\x22\\x16\\x06\\x76\\x76\\x5f\\xcd\\x3d\\xd7\\xb3\\x37\\x1a\\xd9\\xb7\\xbf\\x7d\\x51\\xc7\\x9e\\xfd\\x59\\xb5\\x60\\x1f\\x3d\\xad\\x93\\x3c\\x5b\\x75\\xb4\\xcd\\x44\\xdd\\xa8\\xa3\\x35\\x0a\\xde\\xcd\\xbd\\x3d\\x0a\\xad\\xbd\\xba\\xf4\\x7a\\x9e\\xd2\\x3b\\xc2\\xe2\\xb8\\xaa\\x3b\\x04\\x25\\xdf\\x14\\x1e\\x1a\\x15\\x29\\xa0\\x30\\x4b\\x17\\xfe\\x13\\x12\\xa4\\x4f\\x75\\xbd\\x33\\xdf\\xcb\\x23\\x51\\xd9\\x1d\\xfc\\x94\\x7f\\x6d\\x07\\x57\\xe5\\x5f\\xdb\\xc5\\x5b\\xd9\\xd6\\x84\\x6c\\xef\\x86\\x42\\xdb\\x6a\\xe7\\x84\\x0a\\x10\\x27\\x2d\\x14\\x27\\x13\\xd7\\x8f\\xa2\\x77\\x4c\\xbe\\x1b\\xcc\\xd7\\xcc\\xf4\\x0a\\x15\\xe7\\x35\\xc5\\xf3\\xa6\\x09\\x93\\xe3\\x4d\\x36\\x89\\x91\\x11\\xf6\\x47\\xa8\\x0e\\xff\\xfe\\x87\\x91\\xed\\xf2\\xc4\\x67\\x18\\x72\\x2a\\x20\\xb6\\xa3\\x73\\x9f\\x65\\x7f\\x99\\x09\\xec\\x7d\\x9b\\xe6\\xdb\\x3d\\x45\\x36\\xee\\xd4\\xd9\\xd5\\xa5\\x57\\x6d\\x3f\\xe1\\xd1\\xaa\\x0c\\xa2\\x03\\x60\\xf2\\x6f\\x6a\\xd3\\xa8\\xb1\\xf8\\x2e\\x93\\x83\\xe1\\xdf\\xcd\\x64\\xc9\\x38\\x11\\xd1\\x9d\\xd3\\xe2\\x5f\\x5f\\x14\\xe9\\x11\\x8c\\x90\\x67\\xb8\\x7e\\x97\\x1c\\x81\\xb0\\x5d\\x48\\x24\\x70\\xf5\\x81\\xab\\xaf\\xb6\\xc0\\xd5\\x07\\xae\\xbe\\x68\\xd6\\x38\\x77\\x08\\x88\\x71\\x69\\x22\\x1b\\x51\\xa3\\x75\\xaf\\x0f\\xc8\\x71\\x4b\\x0b\\xc8\\x11\\x5b\\x40\\x8e\\x01\\x39\\x6e\\xeb\\x78\\xe7\\x2a\\xf7\\xe2\\x70\\xf7\\xf0\\xac\\xde\\x8e\\x37\\x82\\xb5\\x20\\x58\\x0b\\x82\\xb5\\xc0\\xb5\\x40\\x3a\\x5d\\x0b\\xa4\\x33\\x90\\xce\\xb2\\x7d\\x74\\xa4\\x33\\x58\\x0b\\x82\\xb5\\x20\\x58\\x0b\\x82\\xb5\\xa0\\xda\\x82\\xb5\\x20\\x58\\x0b\\x82\\xb5\\x20\\x58\\x0b\\x36\\xb4\\xc0\\xd5\\xb7\\xec\\x34\\x70\\xf5\\x81\\xab\\x5f\\xd7\\x82\\xb5\\x20\\x58\\x0b\\x02\\x72\\x0c\\xc8\\x31\\x20\\xc7\\x35\\xed\\x10\\xad\\x05\\x51\\x02\\x94\\xaf\\x17\\xe3\\x97\\x82\\x18\\xf1\\xbd\\xa2\\x14\\x9b\\x8b\\xa9\\x77\\xbf\\x8e\\x61\\x46\\xe7\\x4c\\xe4\\xb2\\x4c\\xc8\\x73\\x7e\\xf3\\x1d\\x99\\x82\\x56\\x06\\x0a\\x60\\x7d\\x49\\xc2\\x8e\\xa9\\x39\\x80\\xd3\\x71\\xb2\\xb6\\xe3\\x5d\\x98\\xcb\\x7d\\xb9\\xdd\\x3a\\x32\\x16\\xc2\\xac\\x6e\\x75\\xc7\\x50\\x6a\\xf1\\x52\\x40\\x0f\\xc1\\x2b\\x9b\\x64\\xad\\xf5\\x01\\x2c\\xe7\\xd7\\x17\\x8f\\x1a\\xb6\\xb2\\x3e\\x6d\\xef\\x65\\x31\\xb8\\x2b\\x4e\\x82\\xe9\\xc4\\x5d\\xb2\\xef\\x0f\\xf7\\x1c\\x62\\x0c\\xf7\\x1e\\xb8\\x22\\x55\\x06\\xab\\xb0\\x88\\xe9\\x64\\x51\\xcc\\xef\\xe3\\x0e\\x88\\x39\\xbf\\xbe\\xd8\\xdf\\xb6\\xe5\\x8f\\x69\\x63\\xd7\\x3d\\x9a\\xb1\\x82\\x91\\x2a\\x18\\xa9\\x8a\\x16\\x38\\xb6\\x96\\x9d\\x06\\x8e\\x2d\\x70\\x6c\\xeb\\x5a\\xff\\x1c\\xdb\\xa1\\x1b\\x75\\x82\\x29\\x86\\x04\\x53\\x8c\\x7f\\x2d\\x98\\x62\\x76\\xbe\\x1e\\x4c\\x31\\xc1\\x14\\x13\\x4c\\x31\\xdb\\x5b\\xe0\\x5d\\x5d\\x0b\\xbc\\x6b\\xe0\\x5d\\xcb\\xf6\\xd1\\xf1\\xae\\xc1\\x14\\x13\\x90\\x63\\x40\\x8e\\x65\\x0b\\xc8\\x31\\x20\\xc7\\xa2\\x7d\\x8c\\x81\\x1b\\x41\\xab\\x1d\\xb4\\xda\\x41\\xab\\x1d\\x88\\x5f\\x20\\x7e\\x81\\xf8\\x6d\\xeb\\x38\\x68\\xb5\\x7d\\x0b\\x5a\\xed\\xa0\\xd5\\xae\\xb5\\xa0\\xd5\\x0e\\x5a\\xed\\xa0\\xd5\\x0e\\x5a\\xed\\x0d\\x2d\\xf0\\xae\\x2d\\x3b\\x0d\\xbc\\x6b\\xe0\\x5d\\xd7\\xb5\\xa0\\xd5\\x0e\\x5a\\xed\\x80\\x1c\\x03\\x72\\x0c\\xc8\\x71\\x4d\\x3b\\x44\\xad\\xf6\\x8e\\x8b\\xbb\\x0f\\x84\\x56\\x75\\xd4\\x8e\\x5d\\xf6\\x2e\\xed\\x23\\x72\\x4e\\xb9\\x2b\\xc9\\x6a\\x4b\\xf6\\x4d\\x80\\x62\\xa5\\xd4\\x01\\x49\\x58\\xca\\x7c\\xf5\\x0d\\x21\\x0d\\xd0\\x0c\\x23\\xaa\\xc0\\xd7\\x49\\x5f\\x3b\\x54\\xd1\\xef\\x9a\\xa7\\xdb\\x97\\xb9\\x1d\\x87\\x6c\\xad\\x16\\x56\\xf8\\xe7\\x33\\xee\\xfb\\x71\\x60\\xd5\\x78\\x1a\\x2c\\xda\\x63\\x9b\\xcd\\xf8\\xe6\\x45\\x2c\\xc6\\x62\\x2b\\xf7\\xec\\x5c\\xf6\\x26\\x10\\xdc\\x02\\x72\\x3b\\x09\\xcb\\x2e\\x72\\x32\\x24\\x63\\xaa\\xe0\\xf7\\xbf\\x5b\\xa9\\x59\\x55\\x7d\\x25\\x85\\x98\\x51\\xbd\\xbe\\xda\\xf5\\x3e\\x24\\xa6\\x1c\\x62\\x33\\x90\\xef\\x71\\x59\\x8a\\x69\\xb4\\xec\\xc5\\xd5\\xa7\\x69\\x7b\\x45\\x0c\\xdc\\xc5\\x97\\xb6\\x8f\\x1b\\x2d\\xa9\\x86\\xe9\\x62\\xb9\\x00\\x66\\xc9\\x30\\xf0\\x0d\\x35\\xc9\\xbc\\xe4\\xb9\\x76\\x88\\xfb\\x19\\xf8\\xc2\\xaa\\xae\\xf8\\x8f\\xf2\\x03\\x31\\x55\\xc4\\x05\\xb5\\x89\\xf3\\xd8\\x15\\xe8\\xe3\\xc7\\x59\\xf3\\x78\\xd7\\xf9\\xae\\x2b\\x89\\xe4\\xdb\\xbe\\xc4\\xd1\\xef\\xe7\\x85\\xb5\\x8a\\x5d\\x14\\x99\\x5e\\x96\\x37\\x38\\xa3\\xd2\\x10\\x26\\x6f\\x3d\\x43\\xd6\\xac\\x7c\\x7b\\x63\\xff\\x4b\\xc7\\xb6\\xbd\\x0c\\xf3\\x56\\x3e\\x6d\\x37\\x7f\\x36\\xac\\x24\\xaa\\xd9\\x64\\xc9\\xdb\\x87\\x2d\\x73\\xd5\\x15\\xaf\\x40\\xa6\\x4c\\xa9\\x4d\\xd1\\x4f\\xf5\\xa9\\xef\\xa2\\x62\\x7b\\x50\\xaf\\x25\\x7e\\xd9\\x9f\\x8b\\x5f\\x51\\x65\\x3a\\x05\\xf3\\x6c\\xb5\\x2b\\x63\\x1a\\x11\\x99\\x27\\x60\\x6b\\x60\\xfb\\x82\\xaf\\x34\\x8a\\x44\\xce\\x35\\xe1\\x00\\x31\\x46\\x50\\xad\\x05\\xef\\x3d\\x68\\xdf\\x1e\\xdc\\xf3\\xbe\\xbc\\xf3\\xd0\\xce\\x73\\xe7\\x5b\\x6e\\x0d\\x67\\x76\\x09\\x6b\\xab\\x5e\\x55\\xdb\\xfe\\xbc\\x36\\x0e\\xbf\\x9b\\x89\\x68\\xc2\\x99\\xec\\xcd\\x97\\xb4\\xe1\\x57\\xaf\\x44\\xc2\\xa2\\xc5\\x75\\x9e\\x80\\x2b\\xd9\\xce\\xb8\\x25\\x9e\\x85\\x1d\\xb4\\x2a\\x47\\x65\\xf8\\x36\\x2e\\x72\\x40\\xc6\\xb9\\x26\\xb1\\x00\\xab\\x2e\\x74\\xe9\\xa3\\xaa\\x9f\\xef\\x35\\xbe\\xaf\\xd5\\xec\\x2a\\x91\\x9b\\x79\\xd0\\x2c\\x4b\\x30\\x44\\x52\\x18\\xc6\\xe3\\x7e\\xc6\\xa2\\x59\\x59\\x2e\\x7f\\xdd\\x6b\\xfb\\xf3\\xa5\\x7b\\xc9\\x69\\xa4\\x91\\xac\\x46\\xbc\\xba\\x7b\\xbc\\x0b\\xea\\x48\\x43\\xa1\\x8d\\xd8\\x3a\\x5f\\x5f\\x4b\\x91\\x67\\x7b\\xbe\\xde\\x0e\\x06\\x88\\xad\\x01\\x66\\x07\\xf2\\xe5\\xaa\\xab\\x2c\\x96\\x7f\\xe8\\x0c\\xe3\\xf6\\xa8\\x7d\\x55\\x6b\\x67\\x89\\x19\\x61\\x98\\x63\\x9a\\x27\\x9a\\x65\\x09\\x7e\\x62\\x53\\x5c\\x29\\x42\\x25\\x94\\x04\\x6e\\x40\\x28\\x5f\\x78\\x3b\\xbb\\xab\\x49\\x08\\x31\\xa1\\x53\\xd3\\xa3\\xc6\\x7a\\xa7\\x62\\xb2\\xf7\\xac\\x6d\\xd1\\xc3\\x3c\\x35\\xfc\\x57\\x45\\xf7\\x8b\\x35\\xbe\\xcd\\x38\\xc5\\x2c\\xc8\\x3d\\x4b\\x12\\x23\\xfc\\xd0\\x24\\x11\\xf7\\x10\\x8f\\xc8\\xd1\\xd1\\x4a\\x89\\x6b\\x21\\x2b\\xf3\\x46\\x54\\x77\\xf4\\x79\\xed\\x2d\\x83\\xd7\\xca\\x85\\xed\\x27\\xc4\\x35\\x95\\x42\\x48\\x33\\x49\\x84\\x34\\x97\\xb9\\x08\\xe1\\x82\\x7b\\xdb\\xc1\\xb7\\xd7\\x6f\\x1f\\x1d\\xb6\\xde\\xd7\\x87\\x73\\xf5\\x31\\x41\\x1b\\xf0\\xca\\xa8\\xd4\\x8c\\x26\\x24\\x97\\x89\\xb2\\xe0\\x45\\x8d\\xac\\x21\\x7d\\x45\\xd2\\x19\\x45\\xb7\\x8c\\x08\\x14\\xde\\x74\\x42\\x3e\\xb7\\x00\\xe5\\xce\\xd1\\x62\\x21\\xc1\\x93\\x05\\xa1\\xf6\\x14\\x27\\x79\\x92\\x0c\\xc8\\x84\\x71\\x6a\\x68\\x10\\x64\\x3e\\xcc\\x76\\x0f\\x8d\\x4a\\xd9\\x6e\\x18\\x8f\\xc0\\x6c\\xd3\\xb0\\x30\\x27\\xe0\\xcc\\xcd\\xc8\\x06\\xdb\\x15\\xe8\\x28\\x1e\\xb8\\x12\\x9c\\x56\\xc1\\xa4\\xdc\\x54\\x0c\\x6a\\x8a\\xb0\\x4c\\xbd\\x11\\x12\\x1c\\xbb\\x78\\x2d\\x12\\xb4\\x02\\x16\\xa6\\x0a\\xac\\xdb\\x49\\xab\\x8f\\xff\\x9b\\xf1\\x7d\\x05\\x6d\\xdb\\xae\\x91\\x2a\\x47\\x94\\x13\\x60\\x7a\\x06\\x12\\x87\\x5e\\x18\\xd4\\x69\\xe0\\xb4\\xbc\\x0f\\xc7\\x2a\\x8f\\x66\\x66\\x8b\\x8e\\x32\\x11\\xab\\x23\\x83\\x58\\x8f\\x14\\x44\\x12\\xb4\\x3a\\x3a\\x31\\x7f\\x2d\\xaf\\x15\\xf7\\xab\\xfa\\xdd\\x29\\xcd\\xd8\\xd1\\xc9\\x80\\xe0\\x86\\x63\\xb1\\x50\\xa1\\x67\\x1f\\xef\\x15\\xf0\\x6b\\xad\\x95\\xc5\\xde\\xd5\\x96\\x0a\\xe6\\x57\\x7a\\x70\\x05\\x2a\\x45\\x66\\x6b\\x3b\\x1a\\xaa\\xa5\\x01\\x83\\xba\\x0d\\x90\\x23\\xb8\\x54\\x2c\\xbe\\x4b\\xe4\\x8b\\x90\\x33\\x4e\\xc0\\xda\\xe8\\x40\\x93\\x14\\x28\\x77\\x6f\\xc3\\x1c\\xe4\\x42\\xcf\\xd0\\x6c\\xa7\\x0a\\xdc\\xf5\\xd1\\x6f\\x7a\\xb7\\x0d\\x77\\x08\\xc4\\x6f\\x6e\\x09\\xe4\\xb6\\xfc\\xf1\\xf2\\xe6\\xbe\\xf8\\xfc\\xc5\\x32\\x0e\\x2f\\x89\\xd6\\x47\\xbb\\x95\\xc8\\x70\\xb4\\xda\\xc6\\xef\\xcc\\x97\\xf5\\x2d\\xb4\\x3f\\x59\\xec\\x5b\\xe0\\x8f\\xb7\\x6f\\x6d\\xa5\\x62\\xb7\\x57\\xdf\\x30\\x1e\\xab\\x22\\x4b\\x68\\x6c\\xd1\\xaa\\xdb\\xef\\xb5\\x9b\\x8c\\x33\\xfc\\x18\\x37\\x78\\x55\\x36\\xd8\\x97\\x9f\\xdf\\xd1\\x7d\\x45\\x78\\x3c\\x04\\x79\\x0f\\xeb\\x14\\xd7\\x98\\x39\\x83\\xa7\\x06\\xd6\\x78\\x6c\\xb8\\x9f\\x84\\x8e\\x21\\x51\\x4e\\xcf\\x05\\x95\\xe9\\x93\\xb3\\xb7\\xef\\x8a\\x92\\xe1\\x12\\xe8\\x0e\\xdd\\xed\\x23\\x48\\x79\\x7b\\x78\\xa1\\xac\\x94\\x66\\x5f\\x6d\\xfb\\x73\\xe3\\xb8\\x15\\xcd\\xec\\x2c\\xe4\\x06\\xb4\\xbd\\x66\\x29\\xcd\\xcc\\x2d\\xb3\\x7d\\x58\\xfd\\xff\\x92\\x6e\\xff\\x2d\\xee\\xf4\\xee\\xcb\\xd2\\x48\\x8a\\xd9\\xbf\\xd4\\xf0\\xba\\x41\\xf6\\xba\\x2a\\xfb\\x79\\xba\\x34\\xb9\\x7b\\x5b\\x34\\x4e\\x65\\xab\\x6d\\xf3\\x12\\x40\\x3b\\xf1\\xc5\\x09\\x1c\\x11\\xad\\xea\\xbd\\x63\\x50\\x36\\xd9\\x8b\\x4d\\xb8\\x23\\xfd\\xef\\x65\\x17\\x3d\\x1f\\x41\\x13\\x31\\x72\\x48\\x14\\x24\\x10\\xad\\xab\\x05\\xbe\\xee\\x65\\x0d\\x69\\x96\\xec\\xba\\x79\\xa4\\xb1\\xc8\\x99\\x32\\x7e\\x0d\\x34\\x5e\\xdc\\x40\\x24\\x78\\xbc\\x27\\x82\\x6d\\x27\\x18\\xbc\\x63\\x9c\\xa5\\x79\\x4a\\x78\\x9e\\x8e\\x01\\xcf\\x42\\xd9\\x41\\x11\\xe3\\x58\\xb9\\x9f\\x12\\x0e\\xf7\\xc9\\xc2\\x61\\x99\\x98\\x64\\x22\\xf6\\x88\\x67\\x6c\\x84\\x4f\\x1a\\xef\\x4b\\x2f\\xee\\x99\\x9e\\x61\\xe9\\x04\\xbe\\x30\\x43\\x31\\x5d\\x12\\x33\\x49\\x22\\x49\\x95\\xe1\\xb2\\x06\\x38\\x34\\xd3\\x86\\x00\\x8e\\x01\\xad\\xc0\\x2c\\x06\\x03\\x32\\x74\\x4e\\x59\\x62\\x38\\xfa\\x7d\\x29\\xda\\x05\\x4c\\x68\\x9e\\x60\\xbd\\x7d\\xf2\\x92\\x1c\\x9b\\x89\\x7b\\x19\\x74\\x5d\\xb7\\x86\\xc7\\x56\\x42\\x70\\xf3\\x5f\\x9b\\x05\\x08\\x17\\x77\\xd2\\xc0\\x1c\\xb5\\x4f\\x42\\x6e\\xdf\\xf6\\x4d\\xcc\\xed\\x5b\\x46\\x73\\xb5\\xaf\\x36\\xa4\\x06\\x0d\\x97\\x3c\\x36\\x97\\xb0\\xca\\xfe\\x56\\xe8\\x08\\x53\\xae\\xe7\\xfd\\x76\\x75\\x7b\\x6a\\xa9\\x35\\xb3\\x96\\x62\\x2a\\x41\\xa9\\x0b\\xa0\\x71\\xc2\\x38\\x3c\\x01\\x50\\xdf\\xce\\x80\\xa4\\xf4\\x01\\x01\\x5b\\xb3\\x14\\x0c\\x9f\\x54\\x05\\x6b\\x5a\\x5d\\xbe\\x16\\x24\\xa5\\x77\\x50\\xcc\\x93\\x8c\\x61\\x22\\xe4\\x1e\\x5e\\x07\\xbe\\x31\\x55\\x05\\x26\\x0b\\xb4\\x13\\xca\\x12\\x88\\x47\\x38\\x93\\xca\\x58\\x06\\xd8\\xa5\\x48\\x12\\x90\\x16\\x0e\\xcd\\xdf\\x8c\\xe7\\x40\\xb4\\xd8\\x73\\xb0\\x4c\\x0a\\x14\\xc3\\xed\\x00\\x55\\x6e\\x06\\xb9\\x05\\x6a\\xba\\xb4\\x14\\xc7\\x97\\xe1\\xbf\\x5a\\xda\\xff\\x37\\x0f\\x11\\xea\\x8a\\xf7\\x1c\\x50\\x02\\x55\\xd8\\x99\\xbd\\x36\\x2a\\x97\\x13\\x23\\x72\\x7b\\x89\\xbe\\xb2\\x38\\xeb\\xd4\\x31\\x22\\xef\\x85\\x76\\x9e\\xb5\\xc5\\x96\\x9a\\xaf\\xf7\\x1c\\x0f\\xa5\\x5a\\x20\\xa0\\x34\\x4b\\x11\\xdb\\xc4\\x39\\x7a\\x4c\\x9a\\xc1\\xf0\\x2c\\xe9\\x7a\\xd8\\xad\\xdd\\xf5\\xdf\\xbf\\x7c\\xb9\\x27\\xd7\\xfb\\xf8\\xb7\\x56\\x02\\xea\\x21\\x1e\\x15\\xe0\\xdf\\x17\\xd8\\xdb\\x53\\xd7\\x4c\\xc4\\xca\\x80\\x1f\\x73\\x52\\x46\\x26\\xcc\\x1a\\x25\\xba\\x1c\\x30\\xa5\\x19\\x9f\\xe6\\x4c\\xcd\\xc8\\x18\\xf4\\x3d\\x00\\x27\\xf0\\x60\\xb3\\x9d\\xed\\x39\\xde\\x4f\\x20\\x05\\xc2\\x9b\\x39\\xad\\xd2\\x6e\\x56\\x3b\\x83\\x57\\x87\\x73\\x00\\x73\\xa6\\x98\\xe0\\x7f\\x66\\x4a\\x0b\\xb9\\x78\\xcb\\x52\\xb6\\xa3\\xb6\\x82\\x6f\\xed\\xb1\\x4f\\x49\\x4e\\x45\\x12\\x93\\x6b\\x0b\\x02\\x37\\x60\\x77\\x46\\x02\\x6a\\xe9\\xb5\\xb0\\xca\\x04\\x62\\x30\\xc2\\x98\\x46\\x77\\xfb\\x52\\xb5\\xc6\\xa7\\xba\\xe9\\xbc\\x5a\\x50\\xd1\\x57\\x2f\\x0f\\xe5\\x58\\x3d\\xa3\\xf6\\x98\\x47\\x89\\x22\\x41\\x31\\x12\\xd2\\x0e\\x7b\\xb1\\xde\\x3c\\xd8\\xed\\xae\\x1d\\xed\\xfd\\x4c\\x28\\xc0\\x17\\x08\\x95\\xbb\\x79\\xc2\\xea\\x32\\xbc\\xe9\\x8e\\xa9\\x02\\xd3\\xa2\\x5b\\x05\\x07\\x45\\xe8\\x64\\x52\\x7f\\x23\\x6e\\xc0\\x29\\xdb\\x76\\xa9\\x49\\x9a\\x2b\\x4d\\x52\\xaa\\xa3\\x99\\xd5\\xc4\\x8a\\xb8\\xe0\\x5e\\x5f\\x28\\x27\\x65\\x36\\x39\\xda\\xbd\\xad\\x38\\xcd\\xed\\x2d\\xc4\\xce\\xf3\\xcd\\x43\\x66\\x88\\xc7\\x2e\\xcb\\x6c\\xbd\\xd5\\xce\\x79\\xb9\\x9b\\xba\\xc2\\x25\\xa9\\x1f\\xae\\x13\\x13\\x90\\x96\\x5a\\xc2\\x5d\\xfd\\x05\\xb5\\xce\\x67\\xef\\x2f\\xf6\\xbf\\x35\\x6d\\xf4\\x29\\x8d\\x35\\x2a\\xed\\xed\\x01\\xa6\\x9d\\x6d\\xd9\\x03\\x6f\\x20\\x70\\x4f\\xea\\x46\\x27\\x94\\x9f\\xd5\\x80\\x50\\x72\\x07\\x8b\\x81\\xe5\\x3c\\x2a\\x49\\x3a\\xcd\\xcb\\x8d\\x26\\x22\\x21\\x71\\xec\\x29\\x98\\x1e\\xb1\\x43\\x3b\\xc6\\xfe\\xbb\\xdd\\x02\\x30\\xfd\\xe0\\x4d\\xcc\\x8c\\xbe\\x0d\\xcd\\x44\\x1b\\x7e\\xe1\\x37\\xa8\\xc1\\x67\\xcd\\xef\\x8e\\x6d\\x77\\xb0\\x68\\xf6\\xc1\\x12\\x24\\x99\\x53\\x70\\x52\\xbc\\x85\\x11\\xf3\\x43\\x21\\x3d\\x14\\x60\\xd1\\xcc\\xfe\\x5b\\x6d\\x8d\\x95\\xad\\xbe\\xf9\\x4d\\xec\\xb4\\xbc\\x86\\x17\\xa5\\x3a\\x6e\\x4d\\xc5\\x6a\\xb6\\xe5\\x85\\xb2\\xf0\\x6b\\x30\\xcc\\x8c\\x65\\x36\\xe4\\xcc\\x59\\xd6\\x9a\\x03\\xb1\\x6d\\xdf\\xd1\\x84\\xc5\\xc5\\x90\\x16\\xfb\\x5c\\xf2\\x81\\xe1\\xad\\xcd\\x7f\\x90\\xfc\\x58\\x8e\\xff\\x42\\x80\\x7a\\x2f\\x34\\xfe\\xf2\\x64\\x67\\x60\\x97\\xf5\\xd4\\x27\\x60\\x47\\x75\\x56\\x1e\\x44\\xab\\xa8\\xaf\\xb0\\x11\\x55\\x6e\\xa7\\x7d\\x9a\\xdf\\xd2\\x21\\x51\\x91\\x4b\\x4e\\x84\\x74\\x5b\\xd7\\x78\\x50\\xd3\\x99\\x1b\\xd8\\x0e\\x89\\x84\\x74\\x6c\\x0d\\x93\\x68\\x2f\\x5a\\x3b\\xa6\\x3b\\x21\\x21\\x6b\\x07\\xd4\\xe3\\xf0\\x6e\\x68\\xe4\\x05\\xed\\x13\\x54\\x57\\x64\\x09\\x4a\\x67\\x4e\\x68\\xa2\\xde\\x03\\x88\\x6d\\xd7\\xc1\\xae\\x6b\\x29\\xc8\\x29\\x5a\\x6c\\xa3\\xbd\\x2d\\x8c\\xc5\\xa4\\x5b\\x10\\x3e\\xdb\\x1a\\x93\\xbf\\xea\\x80\\x8d\\x00\\x19\\x79\\x03\\xab\\xf2\\x6d\\xc9\\x5d\\x34\\x82\\xe0\\xca\\x70\\x35\\x7d\\xf4\\x3f\\x0d\\x01\\xc5\\x03\\xfe\\x17\\xc9\\x28\\x93\\x6a\\x44\\xce\\x88\\x62\\x7c\\x9a\\x40\\xed\\x99\\x13\\xb7\\x2b\\xdd\\x34\\x1a\\x3c\\x33\\x83\\x1a\\x3a\\x37\\xa7\\x89\\x53\\x7a\\x50\\x4e\\xc0\\xaa\\xbe\\xcd\\x3c\\x96\\x59\\xa5\\x81\\xe3\\x66\\x0d\\xda\\x2f\\xec\\xea\\x47\\x77\\xb0\\x38\\x1a\\x6c\\xf4\\x3c\\x5e\\xdf\\xaa\\xb7\\xe2\\xe8\\x92\\x1f\\x59\\x76\\x61\\x05\\xae\\x0b\\xde\\x02\\x8d\\xf7\\x47\\xf8\\xec\\xa8\\x4f\\x3e\\xac\\x21\\x5f\\xd0\\x56\\x71\\x5f\\x1f\\xb4\\x01\\x48\\x3e\\x0c\\xef\\x8a\\x30\\xe5\\x61\\x4a\\xb3\\xa1\\xbb\\x45\\x5a\\xa4\\x7b\\xdd\\x5e\\xef\\xeb\\xd7\\x42\\x1e\\xba\\x5d\\x56\\xe4\\x38\\xa7\\x58\\x2d\\x48\\xae\\xc0\\x8a\\xac\\x88\\x58\\x08\\x78\\xb9\\x07\\xa5\\x1c\\xd4\\x30\\x71\\xb8\\x47\\x39\\xe5\\x60\\x84\\x07\\x23\\x4e\\x33\\x3e\\xfd\\x36\\x8b\\xa9\\xde\\x2b\\xc4\\xc4\\xb6\\xf6\\x77\\xfb\\xda\\x0e\\x48\\x72\\x1c\\xd1\\x40\\xf2\\x84\\x4d\\x49\\x46\\x25\\x4d\\xd5\\x88\\x5c\\xb9\\x4c\\xf3\\x08\\xd7\\x6c\\x52\\x35\\x95\\xb8\\x7d\\xbe\\x5d\\x64\\x40\\xfe\\xd8\\x7c\\x40\\xbb\\xc2\\x26\\xc8\\x79\\x38\\x6c\\xb2\\xae\\xdb\\x0f\\x17\\x1f\\x5e\\x13\\x3b\\x8a\\x95\\x3c\\xb5\\x20\\x13\\x81\\x3a\\x0b\\x91\\x4b\\xb3\\xd0\\x39\\x70\\xd4\\x35\\x1a\\xc9\\x58\\x70\\xf8\\x30\\x31\\x78\\x83\\x6a\\x98\\x83\\x24\\xf7\\x06\\xa8\\x22\\x16\\x37\\x50\\xa5\\x9a\\x86\\x0a\\xd4\\x47\\xbe\\xdc\\xed\\xb8\\xea\\x94\\x3e\\xdc\\xe4\\x72\\xda\\x00\\xa6\\x48\\x67\\xae\\xa7\\xaa\\xca\\x2e\\x95\\x4a\\x78\\xfb\\xaa\\x09\\x72\\x54\\x34\\x83\\x38\\x4f\\x20\\x26\\x74\\x2c\\xe6\\x50\\x33\\xb4\\x15\\x9f\\x35\\x1c\\x1a\\x35\\x1d\\x0d\\xbf\\xf9\\xce\\xa0\\x6d\\x3f\\x29\\xc3\\xa5\\x8d\\x95\\x48\\x72\\x5d\\x28\\xc4\\x8e\\xe1\\xe1\\x35\\xf9\\x77\\x74\\x76\\xa2\\x24\\x03\\x19\\x01\\xd7\\x74\\x0a\\xcb\\x9a\\x4b\\xfb\\xde\\xab\\x97\\xff\\x76\\xd2\\x74\\x02\\xc8\\x0f\\x99\\xf1\\x9d\\x1e\\xf9\\xa5\\xb9\\x72\\xef\\xe8\\xc3\\xb7\\xbc\\xb4\\xf2\\x30\\x45\\xf6\\xd4\\x62\\x95\\xed\\x6c\\x69\\x21\\x38\\x4a\\x12\\xe5\\x09\\xea\\xa8\\xd1\\x89\\xac\\xb2\\x9c\\xf1\\x82\\x48\\x91\\xa3\\x1b\\x19\\xc9\\xb3\\xa6\\x63\\x55\\xf5\\x6d\\xbf\\xfd\\xf7\\x7f\\x6b\\xfa\\xf9\\x9b\\x07\\x9a\\x66\\x09\\xbc\\xf6\\x85\\x4c\\xac\\xb2\\xd0\\x08\\x24\\x5a\\x90\\x2f\\x5e\\xfe\\xdb\\xc0\\xba\\x19\\xc0\\x7d\\x45\\x79\\x55\\xc2\\x11\\x35\\x40\\x94\\x67\\x84\\xa5\\x36\\x1e\\x04\\x92\\x05\\x76\\xd4\\x94\\x05\\x34\\x74\\xbb\\x8e\\x17\\x95\\xa6\\x52\\xab\\x01\\x41\\x6f\\xb6\\x42\\x94\\xd4\\x42\\xd3\\x64\\x49\\x5f\\x8a\\x9a\\x4a\\xb8\\xb7\\xa0\\x10\\x0b\\x3c\\x4b\\x40\\xb3\\x45\\xc3\\x59\\xbc\\xfa\\xe2\\xe5\\xbf\\xad\\x6a\\xc5\\x3f\\xf0\\x08\\x70\\x1c\\xec\\x1f\\x9d\\x1b\\xc7\\x00\\x9c\\xdc\\xb1\\x24\\x81\\xb8\\x29\\x8f\\xbe\\x6b\\x23\\x27\\xb9\\xd4\\x33\\x90\\x03\\x02\\x5c\\x79\\x53\\x86\\x59\\xfb\\xd2\\xba\\x71\\x2e\\x32\\xe7\\xbc\\xa9\\x2c\\x46\\x08\\xb5\\x06\\x55\\xb4\\x8e\\x54\\xac\\x25\\x6e\\xdb\\x0d\\xb7\\xa9\\x49\\x2a\\x94\\x5e\\xbf\\x1d\\x8d\\x06\\xa3\\x7c\\xf1\\x61\\xd2\\x94\\x3f\\x1f\\xb6\\xd0\\x06\\xaf\\x7e\\xdd\\x42\\x4c\\xad\\xb1\\x54\\x8c\\xeb\\xa1\\x90\\x43\\xdb\\xcd\\x6b\\xa2\\x65\\xde\\x84\\x8b\\x4d\\x6b\\x28\\xe4\\x00\\x29\\x40\\x5e\\x41\\x70\\x2b\\x40\\xf0\\xd1\\xa1\\xf1\\xf6\\xe8\\x36\\x16\\xf7\\xbc\\x2f\\xa2\\x81\\xd4\\xbe\\x15\\xb9\\x78\\x12\\x14\\x5e\\x37\\x2d\\x2d\\x61\\x1e\\xb3\\x0f\\xe6\\xed\\xff\\xbb\\x7a\\xe5\\x9b\\xca\\xe4\\x4b\\x94\\x60\\x33\\x6e\\x77\\xa8\\xb5\\x40\\xdd\\x46\\x56\\x43\\x0f\\x8a\\xc1\\xd2\\x5c\\x1b\\xce\\x60\\xcd\\xca\\x0a\\xac\\x6a\\xf9\\x51\\x6b\\x1d\\x31\\x2f\\xd8\\x49\\xad\\x21\\x71\\x25\\x02\\x6e\\x4c\\xca\\x36\\x90\\x2a\\xbb\\xc6\\xd2\\x79\\x44\\xa3\\xcb\\xa5\\x41\\xc3\\x6a\\x13\\x1e\\x6e\\x38\\x74\\x02\\x54\\xe9\\x75\\x47\\x18\\xb0\\xf6\\xce\\xb6\\x3d\\x92\\x75\\xb9\\xd5\\xe5\\x61\\x23\\x90\\xe1\\x8e\\x17\\x86\\x36\\x0c\\xd2\\x1e\\x03\\x39\\xba\\x06\\xeb\\x06\\x65\\xdd\\xf7\\x6b\\x92\\xd8\\x51\\x61\\x00\\x37\\x87\\xdd\\x52\\x48\\x6b\\xb8\\x6d\\xde\\x86\\xf7\\xa8\\x06\\x6d\\x37\\x46\\x25\\x0a\\xcd\\x99\\x10\\x1d\\x09\\x2a\\x7c\\xaa\\xac\\x83\\xd8\\xfe\\x76\\x6c\\x70\\xa1\\x1a\\xee\\x0a\\xfb\\xc5\\x8c\\x54\\x06\\xd1\\x48\\x02\\x62\\x15\\x1b\\x1c\\x67\\x95\\x45\\xa8\\x43\\x3a\\x4b\\xee\\xe9\\x42\\x1d\\x1d\\x8c\\xbe\\x21\\x05\\x4d\\xb7\\x07\\x5f\\x2f\\xb7\\xf6\\x0c\\xc1\\x8d\\xa6\\x3c\\xa6\\x32\\x76\\x2b\\x7a\\xa1\\x8a\\xd1\\x9b\\x60\\x84\\x77\\xe8\\xdf\\xc4\\x27\\xe2\\x35\\x99\\x69\\x9d\\xa9\\xd7\\xa7\\xa7\\x53\\xa6\\x47\\x77\\xff\\xa1\\x46\\x4c\\x9c\\x46\\x22\\x4d\\x73\\xce\\xf4\\xe2\\x14\\xdd\\x95\\xd8\\x38\\xd7\\x42\\xaa\\xd3\\x18\\xe6\\x90\\x9c\\x2a\\x36\\x1d\\x52\\x19\\xcd\\x98\\x86\\x48\\xe7\\x12\\x4e\\x69\\xc6\\x86\\xa5\\x22\\x40\\x8d\\xd2\\xf8\\x57\\x7e\\x4a\\x8f\\x2b\\xc3\\xd7\\xd0\\x04\\x5a\\x64\\xe4\\x1c\\x86\\x39\\xbf\\xe3\\xe2\\x9e\\x0f\\x51\\x67\\xa9\\x1a\\x21\\x8c\\xfd\\xdc\\x5e\\x7d\\xeb\\x70\\x86\\x4d\\xbc\\x62\\x33\\xd1\\x40\\xd1\\xf9\\xe8\\x27\\x6b\\xb6\\x68\\x48\\x79\\x3c\\xb4\\xbe\\x5e\\x8f\\x7b\\xc0\\x6d\\xec\\xb2\\xc3\\xd2\\x9f\\x74\\xff\\xd9\\xb5\\xd3\\x06\\xd1\\x48\\xb3\\x39\\xb4\\xf2\\x6a\\xf4\\xad\\x9b\\x60\\xf0\\xc1\\xc7\\x39\\xc5\\xb9\\xb4\\xb0\\x54\\x71\\x73\\xf4\\x3e\\x1e\\x29\\x5d\\x20\\x0f\\x8f\\x93\\x25\\xc2\\x32\\x6f\\x5c\\xc4\\xe0\\x6c\\x96\\xf3\\x06\\xbe\\x87\\xbe\\xdd\\x18\\xb4\\x7c\\x6b\\xa4\\x4d\\xe7\\x2a\\x89\\x26\\xe1\\x85\\xd2\\x90\\x5a\\x52\\x60\\x47\\x4b\\x16\\x44\\xcb\\x85\\xf5\\xaf\\x94\\x77\\x84\\x69\\xef\\xb4\\x68\\xc4\\xfb\\x3b\\x7c\\x4f\\x29\\x11\\x31\\x64\\xe9\\xcb\\x63\\x6b\\x27\\xab\\x78\\xb3\\x18\\x25\\x99\\x50\\x0c\\xd7\\xe5\\x18\\x97\\x66\\xfd\\xb5\\xe7\\x79\\x2a\\xfe\\x4b\\xbf\\xff\\x5d\\x13\\x38\\x9a\\x60\\xe2\\xc8\\x86\\xe6\\xfa\\xba\\x7f\\xef\\xa4\\x1a\\xdb\\xeb\\x8e\\xfe\\x85\\xf2\\x5a\\x41\\xc3\\x88\\x46\\x82\\x2b\\x2d\\x29\\xdb\\x9c\\x33\\x61\\x7d\\x6b\\xe9\\x53\\xd1\\xde\\x71\\x81\\x20\\x74\\x9e\\xb5\\xda\\x14\\xb2\\x1a\\x96\\xe0\\x19\\x16\\x04\\x79\\xbf\\xd5\\xd5\\x8d\\xb1\\x29\\x15\\x7c\\x78\\x4d\\x43\\x74\\x6b\\x5b\\xeb\\x3d\\x22\\x9d\\xf6\\xc9\\x7e\\x6d\\x13\\xd7\\xc6\\x17\\x28\\x6f\\xdc\\x14\\xeb\\xba\\x9c\\x72\\x51\\xfc\\xfc\\xe6\\x01\\xa2\\x7c\\xdf\\xbc\\x63\\xab\\xad\\xab\\xdd\\xde\\x36\\xc3\\xed\\x79\\x35\\xb5\\x73\\x7f\\xb6\\xb3\\x37\\x18\\xc2\\x3f\\x70\\x4c\\xa5\\xc0\\xf3\\x72\\xdc\\xa5\\xa2\\x9a\\xa9\\x49\\x53\\x4b\\xb2\\x6f\\xe6\\x54\\x8b\\x73\\x87\\x8a\\x2f\\x58\\x71\\x63\\x0a\\xbf\\x3a\\xe4\\x19\\x6c\\x30\\x33\\xd3\\x88\\x39\\xa3\\x99\\x10\\xaa\\x89\\x9a\\xa8\\xda\\xa8\\x05\\x3a\\x5c\\xc3\\x9c\\x09\\xeb\\xe1\\x84\\xb1\\xf5\\x92\\xa4\\x06\\x6d\\x3a\\x12\\x5f\\x99\\x94\\xb5\\x77\\x96\\x9f\\xb1\\xa6\\xb2\\xba\\x6f\\xa8\\xee\\x2b\\x80\\xc3\\x7b\\xf2\\x98\\xc1\\xd1\\x66\\x67\\xfe\\x98\\x22\\xb3\\xae\\x34\\x51\\x79\\x6a\\xa6\\x72\\x0f\\x6c\\x3a\\xd3\\x6a\\x40\\xd8\\xa8\\xb1\\xbe\\xc8\\x37\\x73\\x8d\\x80\\x46\\xb3\\xca\\x12\\x52\\x00\\x5d\\xab\\xfe\\x5c\\xbd\\x7b\\x55\\xc3\\xee\\xf1\\xd6\\xd4\\x3d\\xbb\\x9b\\xcb\\x63\\x30\\x28\\xf8\\x86\\xe5\\x2b\\xb1\\x16\\x0c\\x06\\x04\\x74\\x34\\x3a\\x69\\xee\\x98\\x61\\x5b\\x99\\xa4\\xcd\\xec\\xe2\\x78\\x41\\x98\\x06\\x43\\x8c\\x51\\xf4\\x97\\x22\\x9f\\xda\\xbd\\x06\\x1f\\x63\\x86\\x7b\\x50\\x84\\xaa\\xa3\\xdf\\x5c\\x1c\\x37\\x57\\x49\\xf8\\x76\\x64\\x0f\\xed\\xc8\\xdc\\x18\\xdc\\xdb\\x3c\\xf5\\xa9\\x85\\xf1\\x04\\xd0\\xaa\\x0f\\x45\\x66\\x05\\x09\\x2a\\x13\\x56\\x4d\\xb6\\x6c\\xef\\xff\\xaf\\x86\\x56\\xfd\\x6a\\x33\\x43\\x1d\\xab\\x93\\x12\\xb4\\x66\\x6c\\x3a\\xf3\\x90\\x45\\x1d\\x7f\\x50\\x87\\xc8\\x76\\x00\\xd6\\xde\\xaf\\xc4\\xb6\\x96\\xde\\x25\\xb6\\xf5\\x83\\x05\\x2b\\x61\\xe6\\xe5\\xf5\\xac\\x5c\\x09\\x0d\\x32\\x2d\\x8e\\x0d\\x6f\\x0d\\x92\\x15\\x67\\x6b\\xf7\\x45\\xc9\\xdd\\x65\\x25\\x2f\\x5b\\xcf\\xe2\\xd8\\xdc\\x72\\xc2\\x8c\\x04\\x69\\xf0\\xd4\\x50\\x64\\x27\\x23\\x72\\x46\\x78\\x5e\\xa0\\xe5\\x6d\\x13\\xe3\\xa2\\x98\\x97\\xeb\\xc8\\x4c\\x56\\x89\\xb2\\xaf\\xb6\\xd8\\xba\\x0b\\x29\\xb5\\xad\\x9d\\x3b\\x67\\xb5\\x0d\\xdd\\x0e\\xc0\\xee\\x92\\x22\\xdb\\x3a\\xb1\\x67\\xd4\\xb2\\x83\\x6e\\x6c\\x81\\xef\\xc3\\xaf\\xa2\\x7d\\x1f\\xcb\\x69\\xbf\\x2d\\x5e\\x29\\xdd\\x82\\x41\\xa6\\x83\\x2a\\x1f\\x5f\\xe0\\x80\\x3a\\xba\\xb1\\x7b\\xd1\\x16\\x2a\\x48\\x3f\\x90\\x41\\x7a\\xda\\x57\\xd2\\xc9\\x43\\x7d\\x7d\\x5b\\xda\\xe5\\x22\\x69\\x45\\x6d\\xb7\\x6b\\xf4\\x72\\xbc\\xc0\\xa7\\x0d\\x9d\\xf7\\x37\\xb7\\xae\\xc8\\xb5\\x6c\\x9d\\xd0\\x6c\\xd9\\xfa\\x42\\xb8\\x65\\x5b\\x86\\xde\\x7e\\xdc\\xdd\\x7b\\x98\\x18\\x0e\\xd7\\x8f\\x13\\xfc\\x86\\x01\\xfa\\xb9\\x3d\\xb6\\x75\\xc7\\xb0\\x65\\x6b\\xee\\x46\\xbf\\xa9\\x9f\\xde\\x8e\\xa3\\x2f\\x14\\x61\\x5b\\x0b\\x47\\xfc\\xf5\\x6d\\xc5\\x63\\xef\\x71\\xfc\\xf2\\xd7\\xb7\\xd6\\xc6\\x9c\\xf5\\xad\\xad\\x0f\\xff\\xfa\\xd6\\x3f\\xa2\\x30\\xed\\xfa\\x09\\xdc\\xfc\\xd7\\xb7\\xbd\\x9c\\xff\\x07\\x75\\xcf\\x7f\\xf2\\xb5\\xb6\\x88\\xe9\\x6d\\x27\\x2a\\x5b\\xb6\\x9e\\x4f\\xbc\\x5d\\xc4\\xc0\\xfa\\xf6\\x38\\xe7\\x7d\\xf6\\x74\\x31\\x05\\xeb\\xdb\\x33\\x47\\x1a\\x34\\x9c\\xd4\\xe6\\x09\\x7d\\xad\\xcd\\x64\\xde\\xea\\x41\\xe5\\xe3\\x9e\\x66\\x53\\x99\\x82\\xcd\\x49\\xe7\\x5d\\xe5\\x9d\\x80\\x3d\\x70\\x19\\x2b\\xbc\\x41\\x12\\xa3\\x63\\x33\\x09\\x98\\xdd\\x10\\xc3\\x46\\x5a\\x29\\x85\\x37\\xb7\\xbd\\xc3\\x2f\\xba\\x84\\x53\\xac\\x6f\\xfd\\xf1\\x6b\\xb6\\xf5\\xc4\\xb5\\xd9\\xd6\\x1b\\xf6\\x40\\x3e\\xfb\\x2b\\x6b\\xcc\\x7b\\x46\\x16\\xdb\\x9a\\x13\\x03\\x8b\\xbd\\xb3\\x05\\x16\\x3b\\xb0\\xd8\\xbb\\x5b\\x60\\xb1\\x57\\x5b\\x60\\xb1\\x03\\x8b\\xdd\\xa9\\x05\\x16\\x7b\\x67\\x0b\\x2c\\xf6\\xce\\x16\\x58\\xec\\xb2\\xfd\\x12\\x58\\xec\\xae\\x61\\xa7\\xeb\\x9b\\xd5\\xf7\\xf7\\x66\\x76\\xf8\\x8b\\x35\\x77\\x2d\\xdb\\x19\\x50\\x38\\xf0\\x6e\\xd6\\x75\\x83\\x83\\xe1\\x42\\x6f\\x1c\\xa9\\xbe\\x45\\x23\\x85\\x8b\\xa0\\x96\\x94\\x4f\\x81\\xbc\\x1a\\xbe\\x7a\\xd9\\xd8\\xa9\\xbf\\xda\\xba\\xf8\\x46\\x57\\x5b\\xd3\\xac\\x47\\xcb\\x6d\\x93\\xb1\\xfb\\xf0\\xfc\\x3f\\x1c\\x1a\\x2b\\x8c\\xf0\\x35\\x49\\x6b\\x83\\x33\\x46\\x91\\xeb\\x3d\\x05\\xdd\\xdc\\x7b\\xde\\xb7\\xaa\\x15\\x93\\xa5\\x50\\x78\\x48\\x59\\x1c\\xe6\\x62\\x3e\\xca\\x08\\x4a\\xc1\\x9d\\x35\\xdd\\xc0\\x50\\x5b\\x18\\x69\\xb5\\xda\\x08\\xa8\\x0d\\xb7\\x1e\\x83\\x59\\x71\\x5b\\xbf\\x13\\x4d\\x94\\x48\\xc1\\x26\\x07\\xf3\\x78\\xd2\\x2c\\x17\\x3c\\x18\\x90\\x63\\x18\\x4d\\x47\\x24\\xce\\xc1\\x25\\x02\\xb0\\x21\\x0a\\x27\\x83\\x8a\\x27\\x5f\\x5b\\xc7\\x13\\x43\\xdd\\x25\\xfe\\xc7\\x6c\\xac\\x73\\x00\\x84\\x39\\x70\\x9d\\xd3\\x24\\x59\\x10\\x98\\xb3\\x48\\x17\\x27\\x80\\x91\\x3c\\x4c\\xab\\x0e\\x7b\\xdd\\x59\\xee\\xea\\x2a\\x6b\\x0d\\x57\\x90\\x4d\\x3b\\x5a\\xdc\\x5d\\x28\\x5a\\x99\\x47\\x7b\\x04\\xbc\\x94\\xf4\\xdd\\xee\\xd0\\x68\\xa3\\xda\\x44\\x9b\\xd1\\xac\\xf7\\x12\\xfe\\x13\\x2f\\xee\\x87\\xeb\\xb6\\x8e\\x1e\\xa4\\x27\\xe2\\xdb\\x99\\xe0\\xf6\\xc9\\x07\\x3b\\xef\\x0a\\x21\\x9d\\xff\\xc7\\xea\\x0e\\xae\\xf1\\xaf\\x58\\x93\\x01\\xa3\\x71\\x20\\x77\\xbd\\xe9\\x19\\xa4\\x6d\\xb2\\x68\\xac\\x6b\\x66\\x6e\\xb7\\x22\\x13\\x89\\x98\\x2e\\xaa\\x80\\xe7\\x8a\\x98\\x97\\xb9\\xb5\\x29\\x51\\xf9\\xd8\\x49\\x72\\xe6\\xee\\xbf\\x5f\\x82\\xd4\\xe0\\x19\\xb0\\xb1\\x05\\xcf\\x80\\x95\\x16\\xd4\\x96\\x41\\x6d\\xd9\\xa0\\x9f\\xa0\\xb6\\x0c\\x6a\\xcb\\xa0\\xb6\\x0c\\x6a\\xcb\\xb6\\x2d\\xa8\\x2d\\x1b\\x4d\\x2a\\xa8\\x2d\\x49\\x50\\x5b\\x6e\\x6c\\xc1\\x33\\x60\\x5d\\x0b\\x2c\\x76\\x60\\xb1\\xf7\\x6b\\x81\\xc5\\x6e\\xd0\\x02\\x8b\\xbd\\xa6\\x05\\x16\\x7b\\x5b\\x0b\\x2c\\xf6\\xf6\\x16\\x58\\xec\\xc0\\x62\\x07\\x16\\xfb\\x97\\xc0\\x62\\xf7\\xef\\x19\\xd0\\x67\\x8f\\x99\\x88\\x7b\\x4f\\x12\\x91\\x89\\x78\\x4b\\x8e\\x08\\x6b\\x34\\x8d\\xc4\\x30\\x11\\x51\\x91\\x11\\xd9\\x7c\\xe2\\x3c\\x0b\\x14\\x4d\\xad\\xcd\\x78\\x40\\x7e\\x12\\x1c\\x6c\\x64\\xb9\\x2d\\x29\\x98\\x02\\x11\\x58\\x19\\x3c\\x13\\xf1\\xb1\\x3a\\x69\\x11\\x1e\\x1b\\x72\\x4c\\xec\\xd3\\x42\\x8e\\x89\\x90\\x63\\x22\\xe4\\x98\\x78\\xda\\x1c\\x13\\x33\\xaa\\x5c\\x35\\x00\\xa4\\xfe\\x9b\\x53\\x4e\\x54\\x30\\xf6\\x2d\\xc8\\x34\\x64\\x9c\\xd8\\xd5\\x56\\x84\\x4e\\x77\\x7d\\xcc\\x09\\x57\\x80\\xdd\\xee\\x78\\xec\\x9c\\xe4\\x20\\xbe\\xaa\\xef\\xb3\\xd3\\x50\\xe1\\xb6\\xd0\\x38\\x86\\x98\\x64\\x20\\x87\\xf6\\xf2\\x08\\x32\\x61\\xae\\x18\\xc7\\xd2\\x6d\\x76\\x3b\\xdc\\x16\\x21\\x1e\\x48\\x1a\\x87\\xfa\\x4e\\x74\\xe8\\xe9\\xf9\\x73\\x39\\xd4\\x97\\xd2\\x9b\\x4f\\x4b\\xd5\\xb5\\xa7\\xc6\\xfe\\x7c\\x74\\x99\\x1d\\xfa\\x51\\x8c\\x0d\\x89\\x76\\xfe\\x2c\\xdf\\x74\\x52\\x8d\\xf5\\xa5\\xc7\\x42\\x3d\\xd3\\x4d\\xa3\\x52\\x97\\x9b\\x5b\\xdf\\xb2\\xbb\\xaf\\x1f\\xf8\\x8f\\x1c\\xe4\\x82\\x88\\x39\\xc8\\x52\\x2b\\xe3\\x29\\xad\\x72\\x9e\\xb7\\x98\\x61\\xdb\\x95\\xc7\\xec\\x2e\\x83\\x5d\\x4e\\x6c\\xee\\x1a\\x9e\\x27\\xc9\\xc0\\xf6\\xbe\\x8c\\xf6\\x3c\\x21\\xb2\\x45\\x6a\\x84\\x79\\xde\\x93\\x9a\\xbe\\x17\\x4d\\x6e\\x9f\\x8a\\xce\\xbe\\x5d\\x8e\\xc8\\x81\\x15\\xd2\\xdc\\xdc\\xfa\\x95\\xc3\\x7b\\x94\\xc2\\x1f\\x49\\x4d\\x76\\x28\\x05\\x3b\\x37\\xb7\\xc7\\x34\\xa4\\x90\\xbe\\x8d\\x29\\xa4\\x67\\x83\\x0a\\xe9\\xd1\\xa8\\x42\\xfa\\x35\\xac\\x90\\xde\\x8d\\x2b\\xa4\\x4f\\x03\\x0b\\x79\\xf2\\x02\\xa4\\x9b\\x5b\\xcf\\xda\\x77\\xd2\\xbb\\xcd\\x85\\x3c\\x1a\\x82\\x21\\x4f\\x5d\\xe8\\x74\\x73\\x7b\\x9a\\x12\\xa8\\x9b\\xdb\\x23\\x40\\x41\\x9f\\x76\\x18\\xf2\\xa8\\x30\\xf0\\x2c\\xa5\\x56\\x37\\xb7\\x83\\xb4\\xce\\x6c\\x9d\\xd8\\xa3\\x97\\x67\\xdd\\xdc\\x7a\\x37\\x76\\x90\\x47\\x30\\x78\\x90\\xbe\\x8d\\x1e\\xa4\\xef\\x2b\\xdb\\xaa\\x40\\xec\\xe6\\xf6\\x18\\x77\\xf5\\x59\\x8b\\xca\\x6e\\x9b\\xd6\\x33\\x96\\x9b\\xdd\\xdc\\x9e\\xbf\\x10\\xed\\xe6\\xd6\\x33\\x57\\xdb\\xb5\\x78\\xed\\xae\\x89\\xf6\\x72\\xc5\\x1e\\x27\\xf2\\x98\\xd4\\xee\\xc5\\x37\\xb0\\xe8\\xd7\\x3b\\xb0\\x87\\x9b\\xfb\\xae\\x36\\x3b\\x2f\\xb6\\x69\\x57\\x51\\xaa\\xe4\\x76\\xd1\\x46\\x65\\x19\\x5d\\xa7\\x5b\\x77\\x45\\x77\\x93\\xa4\\xf3\\x1c\\xc6\\x40\\x34\\xbd\\x03\\x34\\xc9\\x0b\\x2c\\x0e\\xc0\\x62\\xb0\\x55\\x24\\x2c\\xa8\\xe3\\xf8\\x06\\xc4\\x73\\x05\\xb1\\x99\\x48\\x22\\xc4\\x5d\\x9e\\xf9\\xab\\x82\\x71\\x9b\\x7d\\x5c\\x4c\\xc6\\x23\\x91\\xfa\\x00\\x55\\x1b\\xae\\x64\\x6e\\xbc\\xc3\\x05\\x43\\x5b\\xf5\\xc7\\xfe\\x8e\\xd3\\x41\\xe2\\xe6\\x94\\x91\\x3f\\xbe\\xad\\x2a\\xc7\\x7e\\x24\\x54\\x91\\x1f\\x51\\x6c\\xe0\\xe4\\x18\\x3f\\x3c\\xf9\\xb1\\xbb\\xef\\x5e\\x71\\x04\\xd6\\x9e\\x25\\x72\\xc4\\xb0\\x4b\\x75\\x90\\xeb\\xa7\\xb3\\x6d\\x77\\x3b\\x4f\\xc8\\x57\\x2a\\xa8\\x6e\\xdc\\x0b\\x6b\\x87\\x3e\\xa6\\x5c\\xb3\\x93\\x42\\x85\\x3b\\x22\\x08\\x5f\\x28\\x33\\xc5\\x82\\xbf\\xd0\\x76\\xd6\\x1e\\xeb\\xfb\\x0e\\xba\\xbb\\xec\\x15\\x27\\x57\\xba\\x7e\\x58\\xcb\\xf0\\xc8\\x55\\x96\\xb6\\x35\\xb1\\x8a\\x0a\\x4e\\x96\\x37\\xea\\x3c\\xee\\xad\\xb7\\xb9\\x3b\\x51\\x71\\x22\\xe4\\x98\\xc5\\x31\\x60\\xd9\\xbb\\x62\\xa9\\x63\\xa1\\x67\\xcb\\x57\\x0e\\x5d\\xb5\\xaa\\xb0\\xd3\\x7d\\x32\\x67\\x89\\x12\\x83\\xe5\\x71\\x22\\xca\\x7d\\x74\\x39\\x68\\x5b\\x3b\\xaf\\x36\\x2c\\x61\\xca\\x1c\\x8b\\x82\\x1e\\xc4\\x96\\x5b\\x57\\x24\\xd0\\xf0\\xeb\\x49\\x36\\xa3\\x15\\xf3\\x9f\\x23\\x5b\\x8a\\x00\\xa7\\x63\\xb4\\x52\\xd6\\xe7\\x79\\xc9\\x2b\\xba\\x53\\x32\\x01\\xaa\\x73\\x09\\x64\\xda\\xa2\\x6e\\xe4\\x72\\x3b\\x38\\xb7\\xe6\\xc7\\x22\\x5f\\x09\\x53\\xba\\x47\\xfa\\xc5\\xd4\\x81\\x93\\xb0\\xe5\\x09\\x06\\x2a\\xd6\\x3b\\x15\\xe3\\x42\\x07\\x42\\x16\\x08\\xd9\\x12\\x21\\x5b\\xb9\\x78\\x8f\\x47\\xcb\\x56\\x86\\x0a\\xe4\\x2c\\x90\\xb3\\x36\\x8d\\xd3\\x14\\x54\\x46\\x23\\xf8\\x88\\xec\\xd8\\xd6\\xc8\\x60\\xc3\\xc0\\xfc\\xf4\\x55\\xa5\\x14\\x30\\xc8\\xb4\\x57\\xdb\\x83\\xcf\\x9c\\x82\\x30\\x8f\\xfd\\xc6\\xde\\xe1\\x2a\\xe7\\x95\\x3a\\x91\\x95\\xc9\\x58\\x74\\xbe\\xec\\x5b\\xd8\\x79\\x26\\x5e\\x29\\x22\\x38\\x28\\x34\\xf1\\x42\\xe1\\xe1\\x5a\\x19\\x1c\\xc7\\xea\\xbe\\x6c\\xcc\\x88\\x52\\x1a\\x73\\x78\\xbc\\x9c\\x23\\xa5\\x1c\\x11\\xad\\xcd\\x29\\x50\\xae\\xc8\\x91\\x77\\xbd\\x7d\\xa1\\xca\\x37\\xf6\\x2c\\x08\\xbb\\xad\\x15\\xa5\\x79\\x8a\\x19\\x1d\\xff\\xf3\\x5f\\x27\\xb5\\x72\\x3c\\xe5\\x84\\x82\\x2f\\xc1\\xde\\x2d\\xf8\\x12\\x74\\x6a\\xc1\\x97\\x20\\xf8\\x12\\xf4\\xd1\\x57\\xf0\\x25\\x08\\xbe\\x04\\x6b\\x5b\\xf0\\x25\\x08\\xbe\\x04\\xc1\\x97\\x20\\xf8\\x12\\xac\\xb6\\xe0\\x4b\\x10\\x7c\\x09\\x82\\x2f\\xc1\\x6a\\x0b\\xbe\\x04\\x3d\\xb4\\x8f\\xc2\\x97\\xa0\\x14\\xf8\\x0f\\x4d\\x6b\\x55\\x55\\x05\\xb9\\x38\\x53\\x94\\xda\\x34\\xd5\\x2c\\x2a\\x93\\x18\\xf9\\xb7\\xec\\xbf\\x0e\\x4b\\x85\\x55\\x55\\x2f\\x3d\\x8e\\x02\\xab\\xaa\\x24\\x5b\\xd1\\x43\\xf6\\xa4\\xbf\\xda\\xa8\\xad\\x2a\\xf4\\x59\\x2b\\x23\\x3f\\xaa\\x22\\xeb\\xd3\\x55\\x53\\x57\\x62\\xb3\\x0e\\xed\\x36\\xde\\xfa\\x6c\\x00\\x6a\\x26\\xf2\\x24\\x36\\x7c\\x5b\\x91\\x2a\\x20\\x26\\xc7\\xde\\x96\\x75\\x62\\xa0\\x85\\x0b\\x5d\\x7f\\xc8\\x35\\x1b\\x96\\x6f\\x14\\x91\\x76\\x68\\x88\\xf3\\x45\\x0e\\xba\\x9f\\x82\\x17\\x7f\\x4b\\x7b\\x8d\\x4b\\x5c\\x50\\x44\\xa9\\x97\\x00\\x6c\\x88\\x28\\xc8\\xda\\x1a\\x98\\x22\\x31\\x4c\\x18\\xb7\\xe9\\x3c\\x64\\xce\\xb9\\xe1\\x3b\\x05\\x77\\x41\\xe8\\x9d\\xe7\\x67\\xa9\\xb6\\x35\\xae\\x39\\x54\\x61\\xa5\\x75\\xdc\\x0f\\x14\\xd9\\xcb\\xe3\\xaf\\xc4\\x19\\x53\\xc4\\x73\\x94\\xbb\\x8c\\xda\\x82\\x3b\\x33\\xa6\\xf9\\xc5\\xf6\\xd3\\x79\\x6a\\x05\\x16\\xc1\\x13\\x61\\xc5\\xea\\xbb\\x23\\x90\\x37\\x88\\x38\\xaa\\x0b\\x63\\x0a\\xe1\\x83\\x26\\x89\\xb8\\xef\\xce\\x10\\xf4\\x72\\xf5\\x7a\\xae\\xe6\\xd1\\xf1\\xb6\\xdd\\x37\\x2e\\x06\\xb2\\x14\\x3c\\xdb\\x4d\\x68\\x0b\\x75\\x44\\x42\\x1d\\x91\\x50\\x47\\x64\\x5d\\x1d\\x91\\x8a\\xe3\\x4f\\xb5\\xa0\\x48\\xdb\\xdd\\xc6\\x32\\x24\\xcf\\x50\\x50\\x84\\x90\\xbf\\xcc\\x00\\x2f\\xb9\\x04\\xeb\\xad\\x93\\x27\\x9a\\x65\\x65\\xa2\\x2b\\x65\\x4f\\x3e\\xb1\\x0a\\xa1\\x89\\xcb\\x23\\x53\\x47\\x39\\x66\\x8e\\x34\\x9a\\xb5\\x9c\\xc0\\x12\\xc2\\xc2\\x59\\x60\\x3a\\x2d\\x85\\x64\\xc8\\xe6\\x4f\\x41\\x7b\\xa4\\xad\\xb6\\xe1\\x35\\x45\\x36\\x8d\\x0d\\xfb\\xf8\\xb3\\x5d\\x74\\x20\\x11\\x17\\xc8\\xa3\\xd4\\xdd\\xd1\\x14\\x39\\x36\\xac\\x4d\\xb2\\x70\\x4e\\x59\\x35\\x5a\\x51\\xe3\\x89\\x5a\\x0f\\x6b\\xb5\\xd9\\x73\\xf0\\x22\\xcf\\x94\\xcd\\x81\\x97\\x0c\\xd5\\xb1\\x3a\\x39\\xf1\\xb2\\xd7\\x32\\xa3\\xd8\\x7a\\xcc\\x2e\\x0c\\x66\\x7b\\x22\\xd8\\x94\\x31\\x5c\\x62\\xec\\x5a\\x8f\\xbb\\x86\\x21\\xfc\\x43\\x85\\x71\\xfa\\xd3\\x6e\\x96\\xb0\\xf5\\xd0\\x16\\xb5\\xf9\\xe4\\x42\\x15\\xb0\\x2a\\x59\\xc1\\x96\\x7d\\x1f\\x48\\xa6\\x94\\xee\\x49\\x2f\\xfa\\xb0\\x07\\xf6\\x96\\xec\\xa2\\xdf\\xb2\\x3d\\xcf\\x91\\xe4\\xe2\\x19\\x12\\x5c\\xfc\\x92\\xea\\xe8\\x1c\\xa4\\x13\\xca\\xc1\\xe9\\x6d\\x1e\\x23\\x09\\xf8\\x41\\x3b\\x9d\\x84\\x2c\\xe0\\x9d\\xfa\\xf9\\x45\\x65\\x01\\x7f\\x26\\xa7\\x92\\x5f\\x60\\x32\\xf0\\x03\\x70\\x22\\x79\\x4e\\x07\\x92\\x5f\\x5c\\x32\\xf0\\x03\\x72\\x18\\x39\\x48\\x67\\x91\\x43\\x73\\x14\\x09\\xd9\\xb5\\x5b\\xb5\\x1e\\x9d\\x42\\xfa\\xbe\\x87\\x07\\xe8\\x0c\\x72\\x80\\x8e\\x20\\x87\\xea\\x04\\xd2\\x23\\xa7\\xf9\\x38\\xce\\x1f\\x07\\x9b\\xa0\\x9e\\xf4\\x9a\\x3c\\xa2\\xcf\\x5b\\xf9\\xdc\\x49\\x23\\x0e\\x22\\xd4\\xf6\\x90\\x93\\x45\\x1c\\x54\\x7c\\xed\\x61\\xc5\\xd6\\x3e\\x47\\x5c\\xed\\xc1\\x24\\x87\\x78\\xd6\\xc4\\x10\\x07\\x17\\x45\\xdb\\x0f\\x67\\xd7\\x03\\x3f\\xf7\\x18\\x24\\xa8\\xbf\\xa8\\xd9\\x5e\\x13\\x40\\xf4\\x4a\\x86\\x9e\\x3f\\xf1\\xc3\\x27\\x4b\\x89\\x7a\\x4c\\xf8\\x10\\x88\\xd1\\xc6\\x76\\xe8\\xc4\\xe8\\xb1\\x13\\x3c\\x3c\\x77\\x72\\x87\\x40\\x92\\xb6\\x4f\\xe4\\x50\\x49\\x52\\xaf\\x49\\x1c\\x1e\\xd9\\x3e\\xfb\\x94\\xc9\\x1b\\x0e\\x23\\x71\\xc3\\x93\\x25\\x6d\\x38\\x9c\\x84\\x0d\\x4f\\x96\\xac\\x21\\xd8\\xc5\\x83\\x5d\\xbc\\xde\\x82\\x5d\\x3c\\xd8\\xc5\\x9b\\xf4\\x13\\xec\\xe2\\xc1\\x2e\\x1e\\xec\\xe2\\xc1\\x2e\\xde\\xb1\\x05\\xbb\\x78\\xcb\\x49\\x05\\xbb\\xf8\\xfa\\x16\\xec\\xe2\\xed\\xa7\\x16\\xec\\xe2\\x1b\\x5b\\xb0\\x8b\\x77\\x9a\\xe0\\x81\\xda\\xc5\\xfb\\x49\\x84\\xd0\\xe7\\x8d\\x3c\\xa4\\x04\\x08\\x87\\x90\\xfc\\xe0\\xa9\\x12\\x1f\\x1c\\x5c\\xd2\\x83\\x4f\\x4b\\x85\\xdb\\x53\\x92\\x83\\x3e\\x6f\\xda\\x61\\x27\\x37\\x38\\xe4\\xc4\\x06\\x07\\x9a\\xd4\\xe0\\x71\\x12\\x1a\\x3c\\x66\\x32\\x83\\x0e\\x57\\x2b\\x13\\xf1\\x19\\xd7\\xcc\\x5b\\x8e\\x9a\\x5f\\xaa\\xda\\x55\\xba\\xc0\\x3f\\xc6\\x60\\x2f\\x44\\x0d\\xba\\xab\\x11\\xe2\\x32\\x4f\\x40\\xb9\\x00\\x69\\x3a\\x17\\x2c\\x26\\x59\\xae\\x5d\\xd1\\x7e\\x77\\x99\\x3c\\x94\\xd2\\xd4\\xc6\\x88\\x0f\\xc8\\x4f\\x82\\xc3\\x80\\x80\\x8e\\x46\\x06\\x12\\x31\\xfa\\x5a\\xe8\\x19\\x48\\xf3\\xfa\\xb1\\x3a\\x39\\x69\\xbe\\x81\\x9d\\x78\\x9e\\x6e\\xea\\xa6\\xa2\\x98\\xfc\\xe1\\xe7\\x14\\x40\\x03\\xad\\x0b\\xdc\\x97\\xd6\\x2e\\x6c\\x67\\x8f\\x96\\x74\\xf7\\xc0\\xde\\x15\\x2d\\x5c\\xbc\\x37\\xde\\x51\\x1b\\x70\\xdd\\x96\\xea\\x60\\x64\\x7f\\x0d\\x80\\xa0\\xa2\\x7a\\xdf\\x10\\xdd\\x3f\\x20\\xe3\\x5c\\x13\\xa6\\x31\\x24\\x3e\\x9a\\x09\\xa1\\xda\\xa2\\x02\\x17\\x9e\\x8b\\x0b\\x99\\x33\\x61\\x55\\xbc\\x82\\x03\\xc6\\xdb\\x0b\\x59\\x20\\xac\\xca\\xa4\\x2c\\x7b\\x5e\\x7e\\xc6\\xda\\x0a\\x30\\xa9\\x50\\xba\\x84\\x10\\xaf\\x30\\x34\\x83\\x17\\x04\\x62\\x2a\\xc1\\xcc\\x48\\x13\\x95\\xa7\\x66\\x2a\\x36\\xef\\x87\\xb2\\xc1\\xef\\x2d\\x87\\x9d\\x18\\xb6\\x85\\x46\\xb3\\xca\\x12\\x52\\x00\\x6d\\xcd\\x45\\x3e\\xbe\\xb7\\x72\\x89\\xab\\x72\\xc8\\xb1\\x8f\\xf6\\x6c\\x39\\xb6\\xe9\\x0c\\x94\\x1e\\x6c\\xcc\\xb5\\xb1\\x19\\x16\\x2c\\x4e\\x38\\x69\\xab\\x28\\x89\\x44\\x9a\\xe5\\x1a\\x0c\\x6f\\x9c\\xa7\\x06\\x9a\\x98\\x46\\xc7\\x0e\\x44\\x46\\x52\\xe4\\x53\\xbb\\xe1\\x3e\\xbd\\x81\\xdd\\x88\\x32\\x77\\x06\\x8f\\x51\\xde\\x69\\x4d\\xa5\\x8f\\xec\\xc9\\x1d\\x79\\x86\\xd8\\x4c\\x82\\x4d\\x8a\\xd4\\x18\\x64\\x46\\x55\\xd5\\x23\\xa5\\x24\\x82\\x3b\\xf2\\xb8\\xfc\\x57\\x07\\x32\\x68\\x06\\x3e\\x56\\x15\\x76\\x64\\xc6\\xa6\\x33\\x0f\\x6c\\x46\\xe2\\x44\\x39\\xbd\\x06\\xa4\\x1f\\x7b\\x4e\\x05\\x73\\x73\\xdd\\x1d\\x42\\xde\\xa2\\x84\\x78\\xbb\\xe3\\x31\\xf9\\x0b\\x3e\\x85\\x78\\x39\\xd2\\x18\\xe1\\xc0\\x0a\\xe2\\x34\\x8e\\x0d\\xd7\\x00\\x72\\x68\\x6f\\x90\\x20\\x13\\xe6\\xc4\\x8e\\xa5\\x2b\\xed\\x76\\xb8\\x2d\\x6a\\x3c\\x8c\\xb8\\xf8\\x25\\x88\\xeb\\xd0\\x93\\xdd\\xf9\\x96\\x1d\\xf4\\x61\\xf7\\x59\\x5a\\x4a\\x6f\\xa2\\xc5\\xb5\\xdb\\xe6\\x11\\x39\\xb3\\x1c\\x91\\xc7\\x5f\\x46\\x1c\\x1e\\xac\\xa4\\x69\\x5a\\xbd\\xd5\\x76\\x67\\x0e\\xc0\\x42\\xdf\\x8f\\xf1\\xb0\\x8f\\x64\\x0a\\xa4\\x47\\x5b\\x5f\\x6f\\x49\\x15\\xc8\\xd3\\x54\\x5e\\x79\\x82\\xe4\\x0a\\xe4\\x79\\x12\\x2c\\x90\\x50\\xf5\\xe3\\xb0\\x1c\\x4b\\x48\\xa8\\xfa\\x71\\x60\\x8e\\x26\\x24\\x54\\xfd\\x08\\x55\\x3f\\xda\\xb7\\x43\\x70\\x44\\x21\\xa1\\xea\\xc7\\x01\\x38\\xa6\\x90\\x50\\xf5\\x63\\x9f\\x16\\xaa\\x7e\\x84\\xaa\\x1f\\xab\\x2d\\x54\\xfd\\x08\\x55\\x3f\\x42\\xd5\\x8f\\xd5\\x76\\xa8\\x8e\\x2d\\x24\\x54\\xfd\\xe8\\xb9\\xea\\xc7\\x81\\x97\\x5f\\x0f\\xb5\\xd7\\xcb\\x76\\xc8\\x49\\x21\\xc8\\xa1\\xc5\\xe2\\x92\\x83\\x8b\\xc7\\x25\\x1f\\x49\\xe1\\xf5\\xa7\\xaa\\xba\\x1e\\x4a\\xae\\xd7\\xda\\xc1\\xc5\\x7e\\x7d\\x1c\\x25\\xd7\\x7b\\x4d\\x20\\x41\\x1e\\x83\\x84\\x3d\\x7f\\x22\\x09\\xf2\\xa9\\x53\\xb1\\x1e\\x13\\x4a\\x90\\x40\\xc8\\xf6\\x69\\x1f\\x03\\x21\\x7b\\xec\\x04\\x13\\xe4\\x00\\x92\\x4c\\x90\\x40\\xce\\x1a\\x4d\\xe8\\xd0\\xc9\\x59\\xaf\\xc9\\x27\\xc8\\xd3\\xd8\\xb1\\x9f\\x32\\x09\\x05\\x39\\x98\\x44\\x14\\xe4\\x29\\x93\\x51\\x90\\x83\\x4a\\x48\\x41\\x9e\\x32\\x29\\x05\\x09\\xbe\\x04\\xc1\\x97\\x60\\xef\\x16\\x7c\\x09\\x82\\x2f\\x41\\x1f\\x7d\\x05\\x5f\\x82\\xe0\\x4b\\xb0\\xb6\\x05\\x5f\\x82\\xe0\\x4b\\x10\\x7c\\x09\\x82\\x2f\\xc1\\x6a\\x0b\\xbe\\x04\\xc1\\x97\\x20\\xf8\\x12\\xac\\xb6\\xe0\\x4b\\xd0\\x43\\xfb\\x28\\x7c\\x09\\xfa\\x49\\x9c\\x41\\x1e\\xe1\\xd6\\x1e\\x52\\x02\\x0d\\x72\\x20\\x49\\x34\\xc8\\x13\\x26\\xd2\\x20\\x87\\x98\\x4c\\x83\\x7c\\xd2\\x6a\\xea\\x9e\\x92\\x6b\\x90\\x47\\xb8\\x8d\\x87\\x9d\\x64\\x83\\x1c\\x78\\xa2\\x0d\\x72\\xb8\\xc9\\x36\\xc8\\xa3\\x25\\xdc\\x20\\x8f\\x9c\\x74\\x83\\xf4\\x75\\xf5\\x6c\\x8c\\xe7\\xa1\\xa4\\xb3\\xb1\\xb3\\x59\\x09\\x4d\\xad\\x55\\x85\\xdf\\x1a\\x79\\xde\\x4d\\x68\\x73\\x97\\x46\\x52\\x3e\\x05\\xf2\\x6a\\xf8\\xea\\xe5\\xcb\\xee\\xc1\\xaf\\x8c\\x6b\\x98\\x42\\x17\\xc5\\xdc\\x44\\xc8\\x94\\x6a\\xec\\xe9\\x8b\\xdf\\xb6\\xe8\\x67\\x53\\x56\\x83\\xc3\\xcb\\xf6\\xe1\\x64\\xf3\\x7a\\xb6\\x85\\x1a\\x37\\xbd\\x21\\xf5\\x06\\x72\\xd9\\xe6\\x6a\\xa5\\xa0\\x49\\x6b\\x1d\\x75\\x25\\xbf\\x84\\x66\\x29\\x0c\\x3c\\xa2\\xb6\\x2e\\x03\\xde\\x3e\\xee\\x92\\x8e\\xc4\\x44\\x70\\xc7\\x02\\x19\\xdc\\xd4\\x16\\x50\\xda\\x2f\\x39\\x02\\xaa\\x30\\xce\\x7f\\x0c\\x66\\xd9\\x2d\\xc7\\xa7\\xda\\x66\\xb3\\xc9\\x04\\xe3\\xda\\x2b\\x1c\\xcc\\x9a\\xc1\\x03\\x84\\x4b\\x95\\x13\\xe7\\x60\\x35\\x79\\xa5\\x0b\\x50\\x9e\\xc5\\x54\\xc3\\x49\\x17\\xd1\\x4b\\x2d\\x94\\x86\\x14\\x33\\xa6\\x18\\xce\\x89\\xa2\\x6f\\x0c\\xd1\\x72\\x81\\xfe\\x11\\x73\\xe0\\x3a\\xa7\\x49\\xb2\\x20\\x30\\x67\\xce\\xbd\\xc5\\x0c\\x8f\\xce\\x3d\\x4c\\xab\\x4e\\x3b\\xff\\x97\\x19\\xe0\\x75\\x97\\x60\\xfd\\x76\\xf2\\x44\\xb3\\x2c\\x29\\x93\\x6d\\xd8\\xe3\\x4f\\xac\\x6a\\x68\\xe2\\x72\\xcb\\xd4\\x91\\x8f\\x99\\x23\\x8d\\x66\\x2d\\x27\\xb0\\x84\\xba\\x70\\x16\\x06\\x5b\\x48\\x85\\x04\\xc9\\xa6\\x53\\x41\\xcb\\xa4\\x61\\xbd\\x55\\xa1\\x33\\xb2\\xa9\\x6d\\xd8\\xc7\\x9f\\xf7\\xa2\\x03\\xb1\\xb8\\x40\\x6e\\xa5\\xee\\x98\\xa6\\xc8\\xb1\\x61\\x72\\x92\\x85\\x73\\xcf\\xaa\\x51\\x8d\\x1a\\x77\\xd4\\x7a\\x58\\xab\\xd7\\x9e\\x83\\x17\\x7e\\xa6\\x6c\\x0e\\xbc\\x64\\xad\\x8e\\xd5\\xc9\\x89\\x97\\xc2\\x96\\x59\\xc6\\xd6\\x63\\x76\\x61\\x35\\xdb\\x93\\xc3\\xa6\\x2c\\xe2\\x12\\x8b\\xd7\\x7a\\xdc\\x35\\xac\\xe1\\x1f\\x2a\\x2c\\xd4\\x9f\\x76\\x33\\x87\\xad\\x87\\xb6\\xa8\\xcd\\xe7\\x1a\\xaa\\x80\\x55\\xc9\\x14\\xb6\\xec\\xfb\\x40\\x72\\xa6\\x74\\x4f\\x7f\\xd1\\x87\\x65\\xb0\\xb7\\xb4\\x17\\x8f\\x5c\\xab\\xe6\\x09\\xd2\\x5d\\x3c\\x43\\xaa\\x8b\\x50\\x33\\x25\\xd4\\x4c\\xa9\\xb7\\x50\\x33\\x25\\xd4\\x4c\\x69\\xd2\\x4f\\xa8\\x99\\x12\\x6a\\xa6\\x84\\x9a\\x29\\xa1\\x66\\x4a\\xc7\\x76\\x40\\xae\\x23\\x07\\xe9\\x36\\x72\\x68\\x2e\\x23\\xa1\\x66\\x4a\\xab\\x16\\x6a\\xa6\\x34\\x9b\\xd2\\xc1\\xb9\\x84\\x1c\\xaa\\x3b\\x48\\xa8\\x99\\xd2\\xa9\\x8e\\xfb\\x61\\x16\\x71\\x0f\\x15\\xdc\\x0f\\x3b\\x6d\\xc4\\x41\\x45\\xda\\x1e\\x56\\x94\\xed\\xa1\\x97\\x6f\\x7f\\x8a\\xda\\xed\\xa1\\x70\\x3b\\xb6\\x4f\\xab\\xea\\xcf\\xa3\\xc5\\xcf\\xf6\\x9a\\x0a\\xa2\\x57\\x32\\xf4\\xfc\\x29\\x20\\x3e\\x59\\x4a\\xd4\\x63\\xea\\x87\\x40\\x8c\\x36\\xb6\\x43\\x27\\x46\\x8f\\x9d\\xea\\xe1\\xb9\\xd3\\x3c\\x04\\x92\\xb4\\x7d\\x22\\x87\\x4a\\x92\\x7a\\x4d\\xe7\\xf0\\xc8\\xf6\\xd9\\xa7\\x4c\\xe3\\x70\\x18\\x29\\x1c\\x9e\\x2c\\x7d\\xc3\\xe1\\xa4\\x6e\\x78\\xb2\\xb4\\x0d\\xc1\\x2e\\x1e\\xec\\xe2\\xf5\\x16\\xec\\xe2\\xc1\\x2e\\xde\\xa4\\x9f\\x60\\x17\\x0f\\x76\\xf1\\x60\\x17\\x0f\\x76\\xf1\\x8e\\x2d\\xd8\\xc5\\x5b\\x4e\\x2a\\xd8\\xc5\\xd7\\xb7\\x60\\x17\\x6f\\x3f\\xb5\\x60\\x17\\xdf\\xd8\\x82\\x5d\\xbc\\xd3\\x04\\x0f\\xd4\\x2e\\xde\\x4f\\x4a\\x84\\x3e\\x6f\\xe4\\x21\\xa5\\x42\\x38\\x84\\x34\\x08\\x4f\\x95\\x02\\xe1\\xe0\\xd2\\x1f\\x7c\\x5a\\x2a\\xdc\\x9e\\xd2\\x1d\\xf4\\x79\\xd3\\x0e\\x3b\\xcd\\xc1\\x21\\xa7\\x38\\x38\\xd0\\xf4\\x06\\x8f\\x93\\xda\\xe0\\x31\\xd3\\x1a\\xb4\\xbc\\x5a\\x34\\xd7\\x22\\x15\\x39\\xd7\\x37\\x20\\xe7\\x2c\\x82\\xb3\\x28\\x32\\x7f\\xdd\\x8a\\x3b\\x68\\x18\\xcf\\x5e\\xbb\\x4f\\x67\\x5b\\xba\\x25\\x8c\\xc7\\x2c\\x42\\x7d\\xd9\\xfd\\x0c\\xf4\\xcc\\x05\\x8c\\xe1\\x7b\\x84\\xda\\x17\\x89\\xc6\\x37\\xcb\\xeb\\x84\\xf3\\x34\\x74\\x0b\\x63\\x9a\\xb1\\xeb\\xa6\\xfb\\x65\\x77\\x68\\x2c\\x44\\x02\\xb4\\x89\\xc5\\xd6\\xf1\\x61\\x20\\x1b\\x22\\xbf\\x6e\\x08\\xe6\\xad\\x23\\xcf\\xe5\\xe8\\x64\\x0c\\x89\\xe0\\x53\\x17\\x3d\\xed\\x50\\x44\\x53\\x90\\x39\\x2f\\xbb\\x73\\x16\\xcd\\x28\\x97\\x12\\xb8\\x4e\\x16\\xb8\\xcd\\x58\\x0a\\x1f\\x55\\x26\\xa9\\x98\\x37\\x87\\xc8\\x5b\\xc4\\x1d\\x5e\\xae\\xa4\\x9a\\x24\\x40\\xcd\\x3a\\x38\\x94\\x0b\\x31\\xd8\\x87\\x92\\xab\\x16\\x73\\x2f\\x4c\\xb0\\x36\\x7c\\xbe\\xd5\\xf9\\x37\\xa7\\x82\\xad\\xe8\\x5e\\xfd\\x36\\x78\\x59\\x07\\x39\\x9f\\x08\\x15\\x4f\\x95\\xfd\\x40\\x6c\\xb6\\x10\\x39\\xb9\\xa7\\x56\\x3c\\x91\\x39\\x47\\xfc\\x87\\x1b\\xd5\\xe2\\x90\\x3b\\x30\\xf2\\xed\\x15\\xc4\\x43\\x24\\x22\\x0d\\x3f\\xeb\\xa2\\xb0\\xa5\\x72\\xda\\x8a\\x1d\\xe9\\x83\\xf0\\x9f\\xc9\\x69\\x6e\\xa5\\x2f\\x77\\x15\\x81\\x6b\\xb9\\xc0\\x4c\\x10\\xed\\x90\\xf8\\xed\\xac\\x76\\x43\\x52\\x3a\\x85\\x17\\x8a\\x9c\\xbf\\xbb\\x30\\x24\\x02\\x1d\\x75\\xd8\\xc4\\xf2\\xc1\\x8e\\x64\\x64\\x52\\xcc\\x59\\xdc\\x96\\x66\\x7c\\x47\\x25\\xa3\\xe3\\xc4\\x48\\x92\\x13\\x90\\xc0\\x0d\\x77\\xfa\\xeb\\xe3\\xef\\xce\\xae\\xff\\xf6\\xfe\\xec\\xdd\\x9b\\x13\\x94\\x29\\xe1\\x21\\xa3\\xdc\\xa0\\x83\\x5c\\x95\\x09\\x64\\xdc\\x0c\\x5f\\x28\\x02\\x7c\\xce\\xa4\\xe0\\x66\\x17\\x50\\x97\\x45\\xc9\\xdc\\x75\\xda\\x6a\\x46\\xa5\\x7f\\x85\\x04\\x25\\x92\\x39\\xc4\\x36\\x8b\\x44\\x31\\xc1\\xd2\\xcb\\x25\\xcb\\xb5\\xd7\\xea\\x79\\x17\\x95\\x9c\\x47\\x33\\xca\\xa7\\x10\\x8f\\xc8\\x85\\xc8\\xcd\\xc2\\x7e\\xfd\\x6b\\x5c\\x84\\x84\\x38\\x8f\\xa0\\x9d\\xdc\\x60\\xd5\\xc2\\xf6\\xe6\\xfe\\x7a\\xe0\\x19\\x0c\\x43\\xaa\\xd1\\x45\\x85\\x80\\x8a\\x68\\xe6\\xb7\\xa6\\xba\\x7b\\x6a\\xc1\\x35\\x7d\\x78\\x6d\\xb3\\x50\\x1c\\xfd\\xba\\xf2\\xe8\\xa8\\xbd\\x7f\\x57\\x26\\x85\\x59\\x8a\\x65\\xdc\\xec\\xea\\x13\\xa6\\x41\\xd2\\x84\\x1c\\x55\\x47\\x18\\x91\\x37\\x66\\x5e\\x10\\x57\\xcf\\xd6\\xa6\\x61\\x81\\x39\\x48\\xd4\\xf7\\xb9\\x93\\x1d\\x10\\x09\\x53\\x2a\\xe3\\x04\\x54\\x3b\\x45\\x8b\\x98\\x14\\x24\\xdc\\xaa\\x2f\\x1c\\x54\\x41\\xa1\\xc7\\xe4\\x42\\x8f\\xba\\x22\\x6e\\xdf\\xde\\x09\\x4c\\xf3\\x31\\x11\\xaf\\xc9\\x4c\\xeb\\x4c\\xbd\\x3e\\x3d\\x2d\\x05\\xf9\\x11\\x13\\xa7\\xb1\\x88\\xd4\\xa9\\xa6\\xea\\x4e\\x9d\\x32\\x6e\\x90\\xdf\\x30\\xa6\\x9a\\x0e\\x2b\\x58\\xf7\\xd4\\x32\\xb2\\xc3\\x48\\xa4\\x29\\xe5\\xf1\\x90\\xba\\x7b\\x3c\\x2c\\x20\\xfb\\xf4\\x57\\x8e\\xd5\\x1b\\xd2\\xe2\\x2d\\xc6\\x87\\x74\\xa8\\x66\\xd0\\xea\\xe4\\xba\\x09\\x5f\\x1d\\x84\\xae\\x4e\\xc2\\x96\\x5b\\xfa\\x73\\xe1\\xd7\\x37\\x05\\x3a\\xb5\\x3b\\x37\\x22\\xef\\x85\\x76\\x89\\x75\\x9c\\x9f\\x20\\x12\\x47\\x3c\\x94\\x3e\\x31\\xee\\x9b\\xf7\\xb7\\xd7\\xff\\x73\\xf5\\xe1\\xf2\\xfd\\x6d\\x40\\xbc\\x01\\xf1\\x62\\x0b\\x88\\x37\\x20\\xde\\x16\\x03\\xb7\\x44\\xbc\\xc0\\xe7\\xcf\\x85\\x74\\xbd\\xc8\\x59\\x41\\x30\\x05\\x64\\x39\\x6f\\xf5\\xc2\\xd7\\xb8\\x38\\xb6\\x76\\x10\\xd5\\x0b\\x60\\x3e\\xdb\\x01\\xd7\\x36\\xfb\\x0d\\x9f\\x7f\\x47\\xeb\\x3e\\x06\\x7c\\xed\\x16\\x12\\xf7\\x82\\x95\\x7f\\xcf\\xbb\\x6d\\x60\\x67\\x5b\\x4d\\x57\\x4f\\xa0\\x56\\xe2\\x9e\\x6d\\xdd\\xbd\\x74\\xcc\\xd0\\xed\\x75\\xbf\\xb5\\xe3\\x7b\\x4f\\xd3\\x42\\xf3\\xb8\\xee\\xd4\\x46\\xe4\\x9d\\xd7\\x66\\x90\\xf3\\xbf\\x5d\\x5e\\xbc\\x79\\x7f\\x7b\\xf9\\xd5\\xe5\\x9b\\xeb\\xf6\\xba\\xba\\x1e\\x94\\xe0\\xa8\\x2f\\xed\\x69\\x03\\x3a\\xa9\\xbe\\x9b\\xb0\\x33\\x1d\\x86\\x29\\x19\\xa1\\x4c\\xc2\\x9c\\x89\\x5c\\x25\\x8b\\x42\\x27\\xbd\\x1e\\x5d\\x2d\\xe3\\x29\\x42\\x79\\x97\\x19\\x50\\xbe\\x28\\x74\\x94\\x6b\\x07\\x5c\\x62\\xc5\\xd6\\xb1\\x55\\x5d\\xb4\\xbb\\xcf\\xcb\\x90\\xb9\\x49\\xf4\\xc1\\x96\\x75\\x18\\x7f\\x0d\\x43\\xb7\\x3f\\x73\\xd6\\x61\\xdc\\x56\\x6c\\xdd\\x26\\x16\\xad\\xc3\\x3c\\xea\\xcc\\x5d\\x87\\x8e\\x2e\\x6c\\x0c\\x0f\\xd2\\xf4\\xa3\\x0e\\x5b\\xd3\\x17\\x26\\xfb\\x4a\\x8a\\xb4\\x27\\x6c\\x76\\x83\\xf9\\xe6\\x8a\\x98\\xaa\\x75\\x57\\xf5\\x85\\xf3\\x0a\\xae\\xb1\\xc7\\x4e\\xd0\\x2b\\xa2\\x9a\\xcc\\xef\\x1d\\x23\\x9b\\x7a\\x71\\xa7\\xe8\\xc7\\xa3\\x35\\x12\\x7c\\xc2\\xa6\\xef\\x68\\xf6\\x0d\\x2c\\xae\\x61\\xd2\\xcd\\x88\\x5b\\xdf\\x6f\\x34\\x94\\x39\\xbf\\x4a\\x34\\xc9\\x19\\xce\\xc6\\x0e\\xd6\\xcd\\x58\\xd6\\x9b\\x37\\x4a\\x5f\\x3e\\xcf\\xdd\\xfd\\x9d\\xfb\\x73\\x4f\\xee\\xc5\\x35\\xb9\\x76\\x90\\x2e\\x32\\xb4\\x0c\\x8d\\xec\\xcb\\x73\\xbd\\x17\\x07\\xd4\\x6e\\x0c\\x9f\\x6f\\xfd\\xbb\\x9d\\x56\\xb9\\x47\\x47\\x1e\\x7a\\xf1\\xde\\xdd\\x4f\\xe2\\x8e\\x04\\x8f\\x20\\xd3\\xea\\x54\\xcc\\x0d\\x6b\\x02\\xf7\\xa7\\xf7\\x42\\xde\\x19\\x11\\xfa\\x9e\\xe9\\xd9\\xd0\\xde\\x1d\\x75\\x8a\\xc6\\xfd\\xd3\\x5f\\xe1\\x7f\\x7a\\x98\\xdb\\xed\\x87\\x8b\\x0f\\xaf\\xc9\\x59\\x1c\\x13\\x81\\xd4\\x2d\\x57\\x30\\xc9\\x13\\xeb\\x9f\\xa3\\x46\\x84\\x66\\xec\\x3b\\x90\\x8a\\x09\\x3e\\x20\\x77\\x8c\\xc7\\x03\\x92\\xb3\\xf8\\xcb\\x43\\x02\\x26\\x91\\x59\\xd7\\xb4\\x9e\\x01\\xea\\x06\\xbd\\x29\\x16\\x35\\xaa\\x5f\\xe0\\x42\\x43\\xb5\\x99\\x56\\x78\\xc5\\xbc\\x79\\xd4\\x31\\xb0\\x3d\\x6d\\x4d\\x73\\xc3\\xf6\\x6a\\x7b\\xac\\x82\\x41\\x08\\x1b\\xfd\\x12\\x9e\\xce\\xd7\\xb7\\xa4\\x5c\\xd6\\xc7\\xd3\\xdd\\xe2\\x4c\\xc4\\xaf\\x89\\xca\\xb3\\x4c\\x48\\xad\\x48\\x0a\\x9a\\xc6\\x54\\xd3\\x91\\xb9\\x3c\\x83\\xfa\\x9f\\xe8\\x2f\\x33\\x20\\x3f\\x16\\x3f\\xda\\xb0\\xe9\\xef\\x5f\\xfc\\xe1\\x9b\\x37\\xff\\xf3\\xa7\\x17\\x3f\\xfc\\x58\\x7d\\x86\\x9c\\x86\\x8d\\x38\\xa8\\xbc\\xd0\\x71\\x09\\x2a\\x83\\x68\\xc4\\x45\\x0c\\xef\\x71\\x76\\xf8\\xa7\\xaa\\x39\\x5c\\xb8\\x07\\x9a\\xea\\x5c\\x8d\\x66\\x42\\xe9\\xcb\\xab\\xe2\\xcf\\x4c\\xc4\\xcb\\x7f\\x75\\x8c\\x7b\\x38\\x40\\x92\\x8d\\x67\\x7b\\x45\\x75\\xfb\\xdc\\xd6\\xa4\\x57\\xc2\\x5d\\x62\\xc7\\x9e\\xb1\\x8f\\xeb\\xb5\\x48\\xc2\\x1d\\xcd\\x20\\xa5\\xf8\\xcf\\xaf\\xfc\\x16\\x18\\xbe\\xf6\\x5e\\x32\\xad\\xd1\\x07\\xc7\\xa5\\xc6\\x17\\x93\\x81\\x8f\\xe9\\xb7\\xf2\\xc0\\xfc\\x55\\x0f\\x35\\xc3\\x7b\\xc4\\xd6\\xc5\\x09\\xf6\\xbc\\x61\\xb8\\x23\\x6e\\xb7\\x2c\\x06\\x28\\xb3\\x42\\xac\\xf8\\xc7\\x9d\\x5d\\x5d\\x92\\xb9\\xdd\\xe1\\x03\\xda\\x9c\\xc7\\x42\\xd7\\x3e\\x6d\\xf7\\x57\\x07\\x8d\\xb6\\xfd\\x2c\\xfd\\x21\\x16\\xaa\\x9e\\xd7\\xd6\\x63\\xbe\\x48\\x3e\\x4e\\x12\\x96\\x32\\x17\\x66\\x65\\x30\\x0b\\x28\\xdd\\x95\\x0f\\x3a\\xb6\\x5d\\x8e\\xa2\\x2c\\x1f\\xb8\\xee\\x47\\x29\\xa4\\x42\\x2e\\x8a\\x3f\\x21\\x9b\\x41\\x0a\\x92\\x26\\x43\\xa5\\x85\\xa4\\x53\\x18\\x14\\x83\\xdb\\xcf\\x8a\\xbf\\xec\\x87\\xb5\\xe9\\xad\\x7e\\x6d\\x75\\x69\\xa5\\xb3\\x96\\x23\\x51\\x5d\\xbd\\xfe\\x0f\\x10\\x65\\xfb\\x73\\x3b\\x10\\x8c\\x5d\\x80\\xd5\\xfb\\xfe\\x65\\x90\\x17\\x85\\x15\\xc0\\x4a\\x38\\xc5\\x2e\\xa2\\x02\\x63\\x2e\\x92\\x3c\\x05\\x35\\x28\\x18\\x56\\xab\\x65\\xe3\\x73\\x32\\xa7\\x52\\xbd\\x38\\x1c\\x3c\\x44\\x48\\xcc\\xe6\\x4c\\xf5\\x11\\x0d\\xba\\x86\\xa3\\x66\\x2e\\xb0\\x5a\\xe4\\x3a\\xcb\\xb5\\xab\\xe9\\x54\\xa8\\xec\\x1f\\x32\\xa1\\x50\\x37\\x57\\x54\\x1a\\xa8\\x51\\xb3\\x57\\x47\\x9d\\xa7\\x94\\x51\\xad\\x41\\xf2\\xd7\\xe4\\x7f\\x8f\\xff\\xfa\\x9b\\x9f\\x87\\x27\\x5f\\x1e\\x1f\\x7f\\xff\\x72\\xf8\\x9f\\x3f\\xfc\\xe6\\xf8\\xaf\\x23\\xfc\\xc7\\xe7\\x27\\x5f\\x9e\\xfc\\xec\\xff\\xf8\\xcd\\xc9\\xc9\\xf1\\xf1\\xf7\\xdf\\xbc\\xfb\\xfa\\xf6\\xea\\xcd\\x0f\\xec\\xe4\\xe7\\xef\\x79\\x9e\\xde\\xd9\\xbf\\x7e\\x3e\\xfe\\x1e\\xde\\xfc\\xb0\\x67\\x27\\x27\\x27\\x5f\\xfe\\xba\\xf3\\xd4\\x29\\x5f\\x7c\\xe8\\x88\\xbd\\x6d\\x1b\\xf6\\x56\\x92\\x6b\\xb9\\xc7\\x9e\\xe2\\x53\\x6b\\xa4\\x90\\x71\\x3d\\x14\\x72\\x68\\xbb\\x7e\\x4d\\xb4\\xcc\\xbb\\x06\\x6d\\x79\\xf0\\xea\\xfb\\xfe\\x5f\\x7b\\xac\\x59\\x52\\xb3\\x82\\x0b\\x39\\xa0\\x0b\\xfe\\x58\\x8c\\x86\\x82\\x48\\x82\\x7e\\x0a\\xa5\\xa4\\x1d\\xc9\\x33\\x76\\x4b\\xc1\\x35\\x9f\\x1a\\x05\\xfd\\x25\\xe8\\x29\\x8b\\x62\\x43\\x78\\xae\\x25\\xeb\\x3e\\x91\\x22\\x1d\\x91\\x8a\\xd1\\x76\\x8e\\x21\\xf8\\xee\\xbd\\x3b\\xe8\\x98\\xaa\\x8c\\x04\\xbd\\x66\\x97\\x16\\xf4\\x9a\\xcb\\xed\\xe3\\xd4\\x6b\\xde\\xd8\\xeb\\xf4\\x0b\\x54\\x6a\\x02\\x9f\\xb7\\x35\\x57\\xf6\\xe9\\xa3\\xe5\\x45\\x5b\\x2d\\x48\\x26\\xb2\\x3c\\xa1\\x7a\\x83\\x5f\\x42\\x4f\\x0e\\x5b\\x45\\xe2\\x50\\xef\\x75\\x51\\xba\\xe0\\x5a\\xb6\\x25\\x5d\\xef\\x25\\x43\\xce\\x92\\x84\\x30\\x6e\\x91\\xb0\\xe9\\xa0\\xd5\\xe8\\xde\\xb9\\x41\\x82\\x95\\x79\\x09\\xb5\\x5e\\x56\\x73\\xb3\\xd4\\x7b\\x57\\x8d\\xb2\\xea\\xcd\\xab\\x88\\xd2\\x54\\x6a\\xc6\\xa7\\x23\\x5b\\xad\\xd2\\xb2\\x02\\xce\\x82\\xce\\x78\\x51\\xb3\\xb2\\xd5\\x74\\x0a\\x51\\xa3\\x88\\xd9\\x5f\\xa9\\xbb\\x6b\\x03\\x19\\x95\\xf6\\xdb\\x83\\x2b\\xd0\\xf4\\x0e\\x3d\\x58\\x22\\x88\\x81\\x47\\x2d\\x7d\\x21\\xbe\\xb3\\x39\\x02\\xfc\\x39\\x8c\\x17\\x66\\x27\\xde\\xf0\\xb9\\x1d\\x97\\x92\\x38\\xb7\\x4e\\x97\\x96\\x4c\\xf6\\x37\\xee\\xa7\\xe5\\xb2\\x67\\xee\\xb0\\xf3\\x15\\xa8\\x78\\xee\\x21\\x47\\x51\\x28\\x95\\x8a\\x9c\\x40\\x85\\x15\\xa7\\x1d\\xf4\\x76\\xe6\\x10\\xbb\\xf3\\x63\\x85\\x03\\x40\\x27\\x46\\x7b\\x85\\x11\\x2b\\xcd\\x5b\\x75\\x06\\xec\\x53\\xf0\\x99\\xe8\\xce\\x9a\\xf5\\xcb\\x96\\x3d\\x06\\x4b\\x76\\xa8\\xec\\xd8\\xd3\\xb3\\x62\\x3d\\xb1\\x61\\xfd\\xb0\\x60\\x0d\\xcc\\xca\\x7d\\xb2\\x5d\\xfd\\xb0\\x5c\\x8f\\xa1\\x2b\\xc8\\x24\\x4c\\xd8\\x43\\x4f\\x88\\xeb\\x8c\\x97\\x0a\\x55\\x16\\x03\\xd7\\x6c\\xc2\\xcc\\xbe\\x0a\\x33\\x4c\\x06\\x3c\\xf6\\xc5\\xa9\\x89\\xab\\x7f\\x51\\xdb\\xf1\\x83\\xf4\\x07\\xb6\\xd2\\x6d\\xbf\\xb8\\xfd\\x66\\x9d\\x64\\x1d\\x10\\x3b\\x09\\x88\\xbd\\x43\\x0b\\x88\\x7d\\x2f\\xb9\\xfa\\x53\\xc7\\xea\\x18\\x6d\\xf9\\x5c\\x22\\xf4\\x79\\x3d\\xe8\\x13\\xf1\\xc1\\x63\\xc6\\xc5\\x15\\xb7\\xac\\x4c\\xe5\\x71\\x8a\\x23\\xb7\\xbb\\x4c\\xb7\\x45\\x32\\x2c\\x23\\xe6\\x16\\x94\\x4c\\x0b\\xeb\\x8a\\x4f\\x66\\x6c\\x6a\\xa0\\x29\\x81\\x39\\x24\\x8e\\xef\\x27\\x29\\xe5\\x74\\x6a\\xf3\\xdd\\x69\\x51\\x94\\x70\\x10\\x12\\xd3\\xc1\\x4b\\xd6\\x32\\x87\\xcf\\x52\\xf4\\x2c\\xca\\xd5\\x06\\x81\\x24\\x82\\xc6\\xf8\\x50\\x8a\\x24\\x01\\xa9\\x48\\xc2\\xee\\x80\\x5c\\x40\\x96\\x88\\x85\\x4b\\x59\\xc7\\x63\\x72\\xa3\\xa9\\x36\\x97\\xff\\x06\\x74\\x2b\\xb7\\xa3\\x4e\\x17\\x1b\\x27\\x7c\\x95\\x27\\xc9\\x95\\x48\\x58\\xd4\\x4a\\x47\\xdd\\x07\\x28\\x5e\\x22\\x00\\x66\\x79\\x92\\x90\\x0c\\x27\\xd2\\x0e\\x0e\\x3f\\x70\\x24\\x20\\x67\\xc9\\x3d\\x5d\\xa8\\x01\\x79\\x0f\\x73\\x90\\x03\\x72\\x39\\x79\\x2f\\xf4\\x95\\x15\\x6d\\xdb\\xf5\\x5b\\x8d\\x13\\xb0\\x9d\\x13\\x36\\x21\\xaf\\x31\\xd7\\xb5\\x26\\x9a\\x4e\\x51\\xd1\\xe2\\x9d\\x64\\x06\\x06\\xa0\\xaa\\x83\\x5a\\x1c\\x7f\\xcf\\xd4\\x73\\x6a\\x1c\\xba\\xdf\\xd2\\x5f\\xe1\\xe8\\x86\\x2a\\xb6\\xbe\\xb5\\x9d\\x60\\x35\\x61\\x13\\x88\\x16\\x51\\xf2\\x6c\\x08\\xf3\\x2c\\x42\\xbf\\xc5\\x32\\x33\\x60\\x05\\x9d\\xa8\\x85\\xd2\\x90\\xfa\\x44\\x4d\\xa8\\x68\\x62\\x9c\\x48\\x50\\x99\\xe0\\x0a\\x8d\\x99\\x25\\x96\\x28\\x16\\x62\\x15\\x77\\x2d\\x9d\\x0d\\x7b\\xd4\\x43\\xb5\\x66\\x47\\xbb\\x32\\xa2\\x99\\x50\\xfa\\x46\\x53\\xa9\\xdb\\xb2\\x13\\x7d\\x71\\xa0\\x57\\x7e\\x22\\xe6\\x26\\x47\\x34\\x49\\x20\\x26\\x2c\\x4d\\x21\\x66\\x54\\x43\\xb2\\x20\\x74\\xa2\\x31\\x3d\\x57\\x4d\\xb5\\x1a\\x49\\xc0\\x7d\\xf7\\x19\\x8c\\x67\\x94\\xc7\\x09\\x48\\x32\\xa1\\x2c\\x51\\xed\\x7d\\x5a\\x57\\x54\\xb8\\x1a\\x64\\xca\\x38\\xea\\x54\\xad\\x6f\\x14\\xea\\x74\\xcd\\x5f\\x51\\x24\\x64\\xec\\x12\\x61\\x31\\xad\\xfc\\xa3\\x4e\\x48\\xd4\\xb4\\x0f\\xc8\\x88\\x55\\xc0\\x7b\\xd9\\xb5\\x8c\\x8c\\x13\\x11\\xdd\\x29\\x92\\x73\\xcd\\x12\\xbb\\x78\\x21\\xee\\x48\\x24\\xd2\\x2c\\x41\\x74\\xd2\\x7a\\xe8\\xf6\\x58\\xaa\\xf8\\xe7\\xb0\\xb8\\x60\\x43\\x33\\x2b\\x75\\xfa\\xab\\xf2\\x11\\xfe\\xd0\\x72\\x72\\x3d\\xc8\\x6e\\x7d\\x48\\x6e\\xf0\\x00\\x51\\x6f\\x09\\x1f\\xdf\\x3c\\x40\\x54\\xc9\\x8a\\x6a\\x4e\\x92\\x22\\x9a\\xc3\\x84\\x4e\\xf4\\xae\\x87\\x92\\x49\\x07\\x53\\x11\\xa5\\x43\\x2e\\x97\\x6a\\xeb\\xdb\\xca\\x7c\\x6e\\xa7\\xe5\\x8b\\x21\\xb8\\x59\\x92\\x84\\x71\\xb0\\x75\\xbf\\x30\\xd9\\x0b\\x61\\x58\\x67\\xad\\x7e\\x0d\\xad\\xe5\\xc5\\x09\\xab\\x24\\x66\\x12\\xd3\\x5a\\x2e\\x7c\\xd8\\x5f\\xe7\\xa9\\xf9\\xb9\\x60\\xe6\\x47\\x21\\x34\\x39\\x7e\\x71\\xfa\\xe2\\x64\\xc5\\x94\\xf6\\xc2\\x30\\xe2\\x09\\x58\\x1a\\x38\\x72\\x19\\x65\\x8a\\x45\\x29\\x96\\x66\\xc9\\x02\\xd7\\xf1\\x22\\x1e\\x10\\x66\\x70\\x6c\\xe7\\x99\\x19\\xd2\\x27\\x73\\xee\\x77\\xc5\\x65\\xc0\\x19\\x10\\x25\\x88\\x96\\xd4\\x27\\x5d\\xb6\\xbf\\x9a\\x97\\xb4\\xcc\\x1d\\xf5\\x3e\\x7e\\xf1\\xf3\\x8b\\x01\\x01\\x1d\\x9d\\x90\\x7b\\xac\\x1d\\x67\\xb6\\x6f\\x44\\x6e\\x85\\x11\\xc2\\xbb\\x7b\\x9a\\xf9\\x89\\x2c\\x44\\x4e\\x38\\xd8\\xec\\xbe\\xf0\\x90\\x25\\x2c\\x62\\x3a\\x59\\x20\\x6d\\x21\\x22\\xd7\\x36\\x5f\\x1a\\xd5\\x5d\\x32\\xf7\\x54\\xdb\\x9b\\x07\\xa6\\x5d\\x08\\x83\\x41\\xd6\\x2f\\x11\\x9a\\x2c\\x7d\\x22\\xd4\\x48\\x1e\\x73\\x38\\x9d\\x01\\x4d\\xf4\\xcc\\x3a\\xd8\\x72\\xc1\\x87\\x3f\\x81\\x14\\x98\\xdd\\x87\\xbb\\x27\\x9f\\x5c\\x01\\x9e\\x5e\\x94\\x1e\\x86\\x0c\\x7d\\x0d\\xad\\x59\\x14\\xb2\\x8c\\x32\\xfe\\x7c\\x7b\\x7b\\xf5\\x35\\xe8\\x25\\xac\\x6b\\x46\\xf1\\x6e\\xcf\\xa8\\x83\\x05\\x39\\x11\\x32\\x3d\\x00\\xf4\\xdb\\x8f\\x3f\\xd6\\x90\\x64\\x42\\x1e\\x02\\x15\\x98\\x09\\xd5\\xe9\\x2c\\xc9\\x23\\x90\\x80\\x3f\\x0b\\xa5\\x51\\xff\\xe2\\x04\\x05\\x8e\\x25\\x39\\x45\\xdd\\x87\\xd7\\x39\\xec\\x91\\xcb\\xab\\x11\\xf9\\x1f\\x91\\x9b\\x0d\\x19\\xd3\\x71\\xb2\\x28\\xd2\\x65\\x2a\\xe8\\x5e\\x18\\xe9\\xc8\\x4c\\xe5\\xc8\\x60\\x78\\x03\\x90\\x7f\\x06\\x1a\\x83\\x54\\x88\\x40\\x81\\xf6\\x94\\x58\\xbf\\x07\\x1f\\x9f\\xca\\xdc\\x7a\\x3d\\xca\\xf3\\x5c\\x69\\x91\\x92\\x99\\x5b\\x76\\x3d\\xd5\\x8f\\xbb\\x9c\\x23\\xbc\\xc0\\x3e\\xdf\\x83\\x84\\xcc\\x22\\x59\\xf7\\xcd\\x27\\x87\\x42\\x57\\x50\\x97\\xdd\\x77\\xf7\\xfb\\x18\\x33\\xe9\\x47\\xd5\\x6d\\x33\\xbb\\x56\\x64\\x12\\xe0\\x76\\xb3\\x0c\\xa8\\xf6\\xe0\\x9b\\x76\\xc0\\x25\\xc0\\x5a\\x27\\x01\\x5a\\xee\\x08\\xdd\\x68\\x3a\\xf7\\xd4\\x6f\\x01\\xb0\\x7e\\xbc\\x33\\xc9\\xa3\\x15\\x3c\\x32\\x0c\\xa7\\x03\\x3e\\xab\\x10\\x6e\\xaf\\xca\\x5e\\xd7\\x39\\x2b\\x4b\\x00\\x47\\x94\\x0b\\xce\\x22\\x9a\\xb0\\x9f\\x20\\x26\\x79\\x26\\xb8\\x0b\\xc7\\x40\\xce\\x33\\xa2\\x0a\\x86\\xe8\\x71\\xc6\\xb5\\xab\\x22\\x51\\xa6\\xa3\\x31\\xd8\\x41\\x0b\\x81\\xec\\x98\\xf6\\x85\\x7e\\xed\\xac\\x0f\\xb7\\xce\\xd5\\x23\\x9c\\xfa\\xca\\x61\\xf5\\x03\\xf1\\xa4\\xcf\\x1d\\xc8\\x7a\\x08\\xb3\\x5c\\x0d\\xb2\\xd4\\x82\\xd0\\x28\\xc2\\x9c\\x38\\x96\\xa2\\x20\\x6e\\x54\\x20\\xe7\\xdd\\x41\\xa0\\xbf\\xa5\\x8b\\xf6\\xda\\x38\\xdf\\xfa\\xbe\\xe5\\xd6\\x32\\x2c\\x09\\xcf\\xd3\\x31\\xc8\\x32\\x42\\x5d\\xea\\xd5\\x3d\\xed\\xe8\\xdf\\x59\\x1b\\xd6\\x0e\\xe7\\x8d\\x90\\x9e\\x0d\\xa0\\x7c\\x0a\\xe4\\x95\\x19\\xf9\\xf7\\xff\\xfe\\xef\\x5f\\xfc\\x7b\\x0f\\xe3\\x98\\xe5\\x15\\x7e\\xa3\\x9c\\x5c\\x9e\\xbd\\x3f\\xfb\\xdb\\xcd\\x77\\xe7\\x98\\xb2\\xa9\\x6b\\xf7\\x3d\\x85\\x3e\\xf5\\x1d\\xf8\\xd4\\x6b\\xd8\\xd3\\xa3\\x06\\x3d\\x61\\x04\\x79\\x67\\x44\\xd8\\xf7\\x95\\xb8\\xc1\\x59\\x19\\x20\\xcc\\x95\\x4d\\xf3\\xe4\\xc4\\x86\\x4a\\x59\\x04\\x23\\xe9\\x74\\x87\\xce\\xaa\\xf1\\xcb\\x20\\xac\\x83\\xc0\\x54\\x2a\\x01\\xc8\\x7a\\x93\\xc8\\x6f\\x4c\\x6f\\xcb\\xfe\\xaf\\x71\\x2e\\x6d\\x81\\x82\\xc2\\xdc\\x53\\x6a\\xbf\\x9d\\x99\\x07\\x67\\x41\\xc6\\x30\\x11\\x12\\xc8\\x18\\x70\\xeb\\x0b\\x5d\\xfd\\x27\\x24\\xb9\\x2b\\x88\\x04\\x8f\\xbb\\xf0\\xef\\x7d\\xf1\\xa3\\x6e\\x26\\xbd\\xde\\xc6\\x1b\\xdb\\xa7\\xd7\\xbf\\x96\\x44\\xc6\\x0d\\x86\\x62\\xa0\\x39\\xe9\\x7e\\x20\\xbf\\x1f\\x0c\\x6a\\xa3\\x7f\\xb1\\xb7\\xdf\\xff\\xae\\xbd\\xa9\\x29\\xca\\x6e\\x44\\x74\\xd7\\xa3\\x72\\xab\\x23\\x6a\\xbb\\x30\\x77\\x30\\xb2\\x56\\xb5\\xdb\\xf3\\x2b\\x3b\\x39\\x73\\x32\\xef\\x3f\\xdc\\x96\\xa1\\xfe\\x18\\xf6\\x40\\xde\\x7a\\x2b\\xcf\\x9f\\x9d\\xdd\\x8d\\xf2\\x98\\xdc\\x41\\xd6\\x4d\\x34\\xf4\\x19\\xf3\\xc6\\x34\\xba\\xbb\\xa7\\x32\\x46\\x9b\\x16\\xd5\\x6c\\xcc\\x12\\x66\\x8b\\x83\\x82\\x04\\xcc\\x41\\xc0\\x85\\x8d\\xa9\\xb3\\x58\\x42\\x4c\\x2a\\xe5\\xd9\\x3a\\x26\\xd9\\xac\\xd8\\xba\\xd1\\xae\\xe6\\xc4\\x88\\x09\\x65\\x09\\x5a\\x95\\x73\\xae\\x59\\x0a\\x2e\\xe0\\x23\\xca\\x0a\\xc3\\x63\\xd5\\x0b\\xe1\\x13\\x42\\x3f\\x9f\\xaa\\xe2\\xf0\\xc5\\x07\\xef\\x4c\\xd7\\x58\\x01\\xd8\\x35\\x26\\xfa\\xd3\\x16\\x17\\x1c\\x06\\xb7\\xc9\\x24\\x82\\xb8\\xd0\\xa4\\x05\\x71\\xa1\\xa5\\xb8\\x90\\x49\\xb8\\xd1\\xa2\\x35\\x4f\\xda\\x9b\\x23\\x8b\\x9d\\xc6\\x06\\x37\\x16\\xc7\\xaa\\xd2\\x8d\\xfe\\x25\\x71\\x0e\\xb6\\x2e\\x70\\xeb\\x09\\x9c\\x5d\\x5d\\x16\\x66\\x2c\\x51\\xf3\\x21\\xb1\\x51\\x8a\\x2a\\x8f\\x66\\xde\\x22\\xc9\\x41\\xa9\\x53\\xf4\\x58\\xc9\\x33\\xab\\x23\\x46\\x1a\\x97\\x4b\\x68\\xef\\x3d\\x93\\x49\\x80\\x14\\xf7\\x71\\x50\\xe6\\x92\\x30\\xcb\\x05\\x6e\\x7f\\x04\\x1d\\x59\\x13\\x75\\x85\\x6a\\x62\\xfd\\x37\\xb7\\x5d\\xdd\\x8a\\x26\\x96\\x1b\\x1b\\x49\\xaa\\x66\\x80\\x69\\x8a\\xe1\\x81\\x69\\x65\\x07\\xbd\\xc2\\x8c\\x0b\\x7e\\xc7\\x0d\\xe3\\x30\\x95\\x34\\x02\\x92\\x81\\x64\\xc2\\x30\\x1b\\x39\\xd7\\xb1\\xb8\\xe7\\x64\\x0c\\x53\\xc6\\x95\\x3f\\xb1\\x2e\\x53\\xf2\\x20\\x81\\x1e\\x3a\\x4c\\x15\\xd5\\x63\\x46\\xe4\\xba\\x96\\xa5\\xd9\\xe5\\x96\\x89\\x44\\x89\\x33\\xdd\\x16\\x75\\x2b\\xf7\\x5c\\x6e\\x09\\x72\\x31\\x08\\x06\\x39\\x96\\x2f\\x2c\\x00\\xcf\\x47\\xd1\\xea\\xcd\\x3b\\xd4\\x1e\\x20\\xec\\xce\\x1e\\xe7\\x1c\\x17\\x1a\\x43\\x42\\x17\\x36\\x5e\\x74\\xc2\\x38\\x2a\\x72\\xa5\\x3a\\x19\\x75\\x77\\x79\\x6a\\x3d\\x41\\x21\\x2b\\x7d\\x6e\\x84\\x0c\\xac\\x44\\x4f\\xa3\\x59\\x17\\xce\\x2e\\xf8\\x56\\xed\\x6a\\xc1\\xb7\\xaa\\x65\\x0b\\xbe\\x55\\x4d\\x5b\\xf0\\xad\\x6a\\xda\\x82\\x6f\\xd5\\x21\\x39\\x06\\x04\\xdf\\xaa\\xa0\\x22\\x59\\x6e\\xc1\\xb7\\x6a\\x5b\\x0b\\xbe\\x55\\xc1\\xb7\\xaa\\xd6\\x82\\x6f\\xd5\\x1e\\x2d\\xf8\\x56\\xed\\xd9\\x82\\x6f\\x55\\xf0\\xad\\x0a\\xbe\\x55\\xc1\\xb7\\xaa\\x59\\x0b\\xbe\\x55\\xed\\x5b\\x30\\x96\\x04\\xdf\\xaa\\x4e\\x2d\\xf8\\x56\\x05\\xdf\\xaa\\xe0\\x5b\\x15\\x7c\\xab\\x36\\xb6\\xe0\\x5b\\x15\\x7c\\xab\\xd6\\xb6\\xa0\\x38\\x5c\\x69\\xc1\\xb7\\x6a\\x4d\\x0b\\xbe\\x55\\xcd\\xc6\\x09\\xe2\\x42\\xb7\\xce\\x7a\\x17\\x17\\xbc\\x9f\\xd0\\x95\\x14\\xe3\\x67\\xcb\\xfc\\x74\\x85\\x3e\\x18\\x2c\\x72\\x4e\\x4a\\x62\\x52\\xcb\\xe6\\x64\\x27\\xd8\\x32\\x8b\\x53\\xdd\\x39\\xc6\\x96\\xc9\\x77\\xe9\\x7d\\x98\\xbb\\x5c\\x85\\x63\\xd4\\x73\\x66\\x8a\\x6a\\xec\\x3d\\xe2\\x33\\xe0\\xa9\\xd3\\x4c\\xd8\\xff\\x2b\\x7d\\x47\\x2a\\x4e\\x23\\xad\\xd5\\xd7\\xcf\\x9c\\xba\\xaa\\x8b\\xa7\\xc8\\xd3\\x78\\x89\\x1c\\x88\\x4b\\x4d\\x0f\\x9e\\x21\\x7d\\x12\\xb1\\x03\\xf5\\x08\\x39\\x4c\\x6f\\x90\\x43\\xf4\\x04\\x79\\x0e\\x2f\\x90\\x67\\xf7\\x00\\xe9\\xc7\\x74\\xd9\\x83\\xd9\\xb2\\x33\\xab\\xe0\\x1c\\x7c\\x6f\\x67\\x12\\xd4\\x4c\\x24\\xad\\xf1\\x42\\x5f\\x38\\xe1\\x1d\\xe3\\x2c\\xcd\\x53\\x73\\xc5\\x94\\xb9\\xfa\\x6c\\x5e\\x38\\x21\\xab\\x42\\x60\\xb5\\x24\\xd8\\x1a\\x5f\\xcd\\x8b\\x2c\\x06\\x2c\\x4e\\x49\\x59\\x62\\x20\\x00\\x93\\x03\\xce\\xe8\\xdc\\xa0\\x05\\x95\\x47\\x11\\x40\\xdc\\x45\\x48\\xac\\x6a\\x05\\xbf\\x18\\x15\\x33\\xb4\\x05\\x56\\x98\\x22\\xaf\\xba\\x51\\x84\\x6e\\x7c\\x63\\x45\\x39\\xf2\\xc5\\x6f\\x5b\\xf5\\x31\\x95\\x59\\x3f\\x94\\xf3\\xeb\\xeb\\xab\\xf3\\x0a\\xe5\\xa4\\xdc\\x13\\x4e\\xc6\\xe7\\x22\\xc1\\xd3\\xa0\\xf6\\x25\\x23\\x9f\\x3c\\x23\\x19\\xed\\x2e\\xac\\x77\\x12\\xd4\\xfb\\xa0\\xe2\\x5d\\x65\\xd1\\xba\\xc5\\xce\\x88\\x8b\\x75\\x83\\xd3\\x14\\xcf\\xd2\\xd6\\x6c\\x1f\\x3d\\x81\\xb8\\xd7\\x97\\x08\\xd5\\xfd\\x3a\\x10\\x54\\xbd\\xe2\\xc2\\x0f\\x85\\x47\\xba\\xb1\\xd3\\x29\\xb4\\xb6\\x15\\x49\\xdf\\xcd\\x14\\xbd\\xe8\\x12\\x1a\\x15\\x67\\x83\\xe7\\xf7\\x67\\x24\\x74\\xe7\\x33\\x88\\xee\\xae\\xad\\x43\\x4f\\xa7\\x69\\x1c\\x2b\\x80\\x42\\xd4\\x98\\x32\\x3d\\xcb\\xc7\\xa3\\x48\\xa4\\xa7\\x06\\x81\\xd8\\xff\\x1b\\x27\\x62\\x7c\\x9a\\x52\\xa5\\x41\\x1a\\xe9\\xc3\\xd1\\xe0\\x61\\x64\\x66\\xc0\\xf8\\x74\\x94\\xc6\\x27\\xa3\\xcf\\x3e\\xeb\\x34\\x89\\x4b\\xa7\\x7b\\x74\\x51\\x22\\x95\\x2c\\xcf\\x68\\xc8\\x70\\x29\\xc4\\xc7\\x60\\xd0\\xbf\\x40\\x35\\x61\\xa5\\x22\\x95\\xd9\\x95\\xee\\x50\\xda\\x81\\xda\\x76\\xf4\\xaf\\x7c\\x7a\\xdf\\xca\\x80\\x6d\\x49\\x0f\\xea\\xd0\\x3e\\x91\\xc1\\x61\\xf8\\x4f\\x3e\\x9a\\xef\\x64\\x6f\\x6e\\xcc\\x3d\\xf8\\x4c\\x1e\\x90\\xbf\\xe4\\xc1\\x08\\x1c\\x87\\xe2\\x23\\x79\\x80\\xe5\\x8d\\x7b\\xf0\\x8b\\xec\\xc3\\x27\\xb2\\x3f\\x7f\\xc8\\x43\\xad\\x02\\xfc\\x68\\x3e\\x90\\x1f\\x85\\xff\\x63\\x8f\\xd6\\x81\\x9e\\xfc\\x1e\\x9f\\xc2\\xe7\\xb1\\x97\\x55\\x77\\xf5\\x75\\x7c\\x3a\\x3f\\xc7\\x7e\\x96\\xdb\\xa7\\x90\\xd8\\xf1\\xe6\\x3e\\x83\\x5f\\xe3\\x53\\x18\\x29\\x1f\\xcd\\x40\\xd9\\x83\\x71\\xb2\\x4f\\xc3\\x64\\x6f\\x46\\xc9\\x47\\xf3\\x5f\\xec\\xee\\xbb\\xd8\\xab\\xc8\\xfe\\x24\\x3e\\x8b\\x7d\\xfa\\x2b\\x76\\x3e\\x5f\\xc6\\x99\\x66\\x34\\xb9\\x80\\x84\\x2e\\x6e\\xba\\xf9\\xae\\xf5\\x75\\x12\\xef\\x57\\xfc\\xdb\\xac\\x6e\\xb8\\xee\\xe1\\x38\\xa3\\xae\\x2c\\x37\\xc4\\xde\\xc1\\xd1\\x1b\\x91\\x1d\\xa7\\x8a\\x3e\\x50\\x76\\x7d\\x9d\\xbc\\x1d\\x0f\\xcc\\x64\\x4b\\x0e\\x46\\x07\\x6d\\x93\\x2a\\x1c\\x08\\xd4\\xfc\\x59\\xdc\\x13\\x31\\xd1\\xc0\\xc9\\x31\\xe3\\x1e\\x72\\x4e\\x2a\\xca\\x94\\xd2\\x06\\xd1\\xd9\\xa8\\x60\\x7a\\x7d\\xf5\\xd2\\x0f\\xf2\\xe9\\x19\\x17\\xd0\\xfc\\xa2\\xd4\\x41\\x9b\\x97\\xdc\\x1c\\x77\\xdb\\x97\\xdc\\x8b\\x93\\x3c\\xa9\\xdb\\x98\\xac\\xdd\\xa9\\x1f\\x03\\xd3\\xab\\xb2\\x90\\xef\\x2b\\x9c\\x4f\\x81\\x8a\\x28\\x8f\\x89\\x4b\\xce\\xf3\\xe9\\xc1\\x49\\x67\\xef\\xdc\\xba\\x0c\\x52\\xb8\\xd3\\xee\\x32\\x47\\xdd\\x9e\\x5f\\x05\\x6b\\xd4\\x61\\xe9\\x47\\x9f\\xc9\\x55\\xf4\\xd3\\x93\\xb8\\x9e\\xde\\x35\\x34\\x48\\x5c\\xbf\\x14\\x89\\xab\\x92\\x17\\xeb\\x6b\\x49\\x23\\xb8\\x3a\\x24\\x06\\xce\\x23\\x90\\x32\\xae\\xa9\\xe4\\xe3\\x0a\\x74\\xc1\\x01\\x6c\\xbc\\x4b\\x99\\xf5\\x0c\\x13\\x7c\\x4d\\xf2\\x24\\x59\\x58\\x75\\x5f\\x2d\\x05\\x5e\\x7b\\xd0\\xba\\x9d\\xc1\\x4a\\xee\\xb0\\x5a\\xd4\\x55\\x65\\x76\\xa5\\x7c\\x92\\x49\\xe1\\xb8\\x12\\x99\\x73\\x6e\\xa8\\x95\\xbb\\x4e\\x66\\xf2\\x46\\x1e\\x51\\xc0\\xdb\\x6b\\xbe\\x69\\x2d\\xb3\\x99\\x62\\x53\\xb3\\x5d\\x86\\xc3\\xc0\\xa4\\x67\\x65\\xc4\\x45\\x6d\\x22\\x66\\xd4\\x89\\x90\\x11\\x1b\\x27\\x0b\\x32\\xa3\\x89\\x11\\x98\\xee\\x99\\x9e\\x11\\x4a\\xee\\x58\\x92\\xb8\\x6e\\xda\\x6f\\xd4\\x0d\\x68\\x6b\\xdc\\xb5\\x5c\\x4d\\x22\\xf8\\x14\\x37\\x83\\xda\\x89\\xc0\\x43\\x06\\x91\\x19\\x33\\x4a\\x80\\xf2\\x3c\\xb3\\xf3\\x34\\x3c\\xd2\\x42\\xe4\\xd2\\xcf\\xb3\\xfd\\xf0\\xde\\xb4\\x5c\\xf0\\x54\\x9c\\x25\\x03\\xbf\\xe5\\xf5\\x1c\\x78\\xab\\x30\\x5f\\x6a\\x7f\\x15\\xc4\\x2e\\x7d\\xdd\\x3d\\x53\\x30\\xc0\\x3e\\x5b\\xcf\\xc9\\xce\\xc5\\x97\\xc3\\xb6\\x70\\x63\\x7f\\xcb\\xa4\\x98\\xb3\\xd8\\xda\\xb5\\x3d\\x58\\x18\\x6e\\xa7\\xfd\\xfa\\xbf\\xc3\\x7e\\x3d\\x6a\\xe5\\x82\\x0f\\x39\\x4c\\x29\\xb2\\xc8\\x0e\\xa1\\x59\\x0f\\x47\\x3b\\xbe\\xf5\\xa7\\xe3\\x31\\x8b\\xa8\\x06\\x23\\x40\\x8b\\xac\\x96\\xdb\\x72\\xce\\x68\\xeb\\x99\\x98\\xf5\\x54\\x20\\x8a\\x1c\\x73\\x41\\x04\\x06\\x44\\xe5\\x9c\\xe9\\x05\\x1a\\xdf\\x66\\xb9\\x26\\xb1\\xb8\\xe7\\x27\\x5d\\x2e\\xa6\\x75\\x24\\xa0\\x64\\x0c\\x9a\\x96\\xe1\\x4c\\x9e\\x25\\x53\\x04\\x38\\x1d\\x27\\xe6\\xee\\xa1\\xbb\\xfb\\xed\\x5a\\x00\\x20\\x13\\xa0\\x3a\\x97\\x40\\xa6\\x54\\x77\\xc0\\x12\\x6b\\x38\\x7a\\x7b\\x9e\\xdb\\xc1\\x8e\\x29\\x67\\x5a\\x9b\\x90\\x9c\\x2b\\xe8\\xc8\\xc8\\xf6\\x26\\x06\\xb4\\x0c\\xd4\\x33\\x37\\x5a\\xe4\\xfa\\x40\\xe8\\xc8\\x26\\xf5\\xd1\\xfd\\x8c\\x45\\xb3\\xaa\\xa0\\xc8\\x52\\x50\\x44\\xe4\\x1d\\xb4\\x79\\x35\\x11\\xd0\\x0d\\xd7\\xa7\\x94\\x17\\x74\\x4f\\x6b\\x5b\\x5b\\x0b\\x67\\x1f\\x10\\xf6\\xbe\\xc2\\x95\\x57\\xc2\\xad\\xbd\\x43\\x93\\x0d\\xfc\\xbc\\x78\\x7f\\xf3\\xb7\\xb7\\x67\\xff\\xfd\\xe6\\x6d\\xbb\\x83\\x7f\\x43\\xa3\\x59\\x35\\xb9\\x30\\x27\\x14\\x09\\x05\\x22\\xf9\\x19\\x9d\\x03\\xa1\\x24\\xe7\\xec\\x1f\\xb9\\xf3\\x2a\\x3b\\x2e\\xc6\\x6b\\x89\\x56\\x7b\\xac\\x82\\xde\\x92\\xf1\\x35\\x54\\xa2\\x15\\xe6\\xe8\\xe3\\x4c\\xdf\\x32\\x85\\x99\\x6a\\x71\\x12\\xce\\x11\\x5e\\x28\\x20\\x13\\x29\\xd2\\x25\\x41\\x8b\\xbc\\x2f\\xdc\\xd7\\x16\\x56\\x17\\x81\\xa2\\xd9\\x0c\\x64\\x3b\\x8e\\xfc\\xe2\\xc3\\x9b\\x1b\\x0c\\x1d\\xce\\xa4\\xcd\\xec\\x8c\\xce\\xf6\\xd8\\x27\\x8e\\x6e\\x63\\xf6\\xed\\x7c\\xe2\\x11\\x39\\xe3\\x0b\\xfb\\xd0\\x22\\xb3\\x96\\x2c\\x4a\\xc2\\x94\\x06\\x64\\x4e\\x9d\\x20\\xe9\\x1d\\xf0\\x8e\\x5e\\x8e\\xf0\\x7f\\x47\\x84\\xc6\\xb1\\x34\\x92\\x66\\x11\\xb3\\x10\\x2d\\x87\\x58\\xb5\\x1a\\xd9\\xca\\xaf\\x6c\\x9c\\x54\\x36\\x97\\x83\\xc6\\xb0\\x86\\x56\\x1d\\xbe\\x13\\xb1\\x3b\\x09\\x64\\x02\\xd1\\xd5\\xc6\\x72\\xb7\\x4a\\x4b\\xaa\\x61\\xca\\x22\\x92\\x82\\x9c\\x02\\xc9\\xa8\\x8e\\x66\\x24\\xa5\\x0b\\x12\\x09\\x29\\xf3\\xcc\\x66\\x4c\\x88\\xa9\\xa6\\xed\\x46\\xfe\\x4a\\x48\\x92\\x7a\\xec\\x6c\\xb0\\x99\\x61\\xc9\\x6f\\xd6\\xfb\\x5a\\x96\\x28\\xbb\\xfa\\x4f\\xa6\\x54\\x0e\\xea\\xf4\\xd5\\xcb\\xff\\xf8\\xed\\xbf\\xb7\\x14\\xaf\\x7b\\xbc\\xb8\\x6d\\xbd\\x94\\x3a\\x78\\x27\\xd5\\x3d\\xb5\\x3c\\x80\\xa1\\x5f\\x73\\x25\\xd5\\x05\\xf5\\x10\\x62\\x21\\x1f\\xb1\\xa1\\x62\\x7c\\x9a\\x74\\x56\\x80\\x74\\x56\\x03\\x76\\x55\\x02\\x0e\\xcb\\x15\\x5c\\xb5\\xd5\\x05\\x76\\xd7\\x04\\xd6\\xe6\\xd0\\x5e\\x95\\xd2\\x9f\\x16\\xac\\xe4\\xe0\\xbc\\xde\\xcb\\x21\\x64\\xc1\\x2b\\x82\\xdd\\xe5\\x95\\xc7\\x52\\x5d\\xf4\\x47\\x28\\x4d\\x14\\x8a\\x29\\x9b\\x2f\\xc1\\x0e\\x6b\\x7d\\x1e\\x06\\xe4\\x25\\xf9\\x03\\x79\\x20\\x7f\\x40\\x2d\\xd8\\xef\\xdb\\x0f\\xd5\\x8f\\x8e\\xa9\\x0f\\x4f\\xf9\\x99\\x50\\xfa\\xf2\\xaa\\xa7\\x83\\xfe\\x8b\\xa1\\x57\\xa6\\x47\\x73\\x1e\\x5a\\x90\\x31\\x73\\xea\\x08\\x78\\xd0\\x20\\x8d\\x18\\xe8\\xce\\xb0\\xeb\\xce\\x75\\xd2\\xa8\\x99\\x09\\x7e\\x2c\\xd0\\xdd\\xd5\\xc1\\xe0\\x72\\x52\\xf7\\xaf\\x7f\\x22\\xf8\\xc6\\x81\\xff\\x2c\\x94\\x7e\\xef\\xb0\\x75\\x35\\xd7\\x47\\x75\\x1e\\x29\\x12\\xe2\\x1a\\xba\\xef\\x32\\xea\\x3b\\x03\\x7b\\x65\\x92\\x7d\\x12\\x0b\\x0c\\x31\\xb0\\x31\\x8d\\x33\\xd6\\x01\\x39\\x1c\\xce\\x8d\\xed\\xe6\\xd2\\xd9\\x1f\\xe8\\x6e\\x03\\xad\\x25\\x9d\\x3e\\x6a\\x64\\x9c\\x90\\x52\\xa9\\x4b\\x91\\x89\\x78\\x84\\xf2\\x4d\\x87\\x59\\x98\\xdd\\x88\\x2b\\xcc\\xc0\\x16\\xd1\\x68\\x64\\xe5\\xb5\\xc2\\x42\\x8c\\x17\\xce\\x60\\xac\\x88\\xf2\\xb6\\x3c\\xac\\x6d\\x12\\x26\\x20\\xa5\\x8d\\x9b\\x1d\\x2f\\x7c\\x44\\x4f\\x67\\x68\\xeb\\x84\\xe5\\x32\\x29\\xb4\\x88\\x44\\x72\\x08\\xa0\\x72\\xe5\\xe6\\x82\\x7b\\x8f\\xb6\\xda\\xc2\\x42\\xfe\\xed\\xc5\\xd5\\x80\\xdc\\x9e\\x5f\\x0d\\x88\\x90\\xe4\\xe6\\xbc\\x9b\\x03\\x54\\x55\\x05\\x73\\x74\\x7b\\x7e\\x75\\xf4\\xac\\x27\\x40\\xbc\\x28\\x85\\xd6\\xec\\x16\\x9d\\xd4\\xcc\\x3e\\x46\\x4e\\x1b\\xa6\\x34\\x1b\\xde\\xc1\\xa2\\x25\\x77\\xd7\\x07\\x87\\x39\\x2c\\x00\\xab\\x97\\x05\\xd9\\x6d\\x4e\\x69\\xd6\\xb8\\x37\\x09\\x34\\x66\\x07\\x9d\\xc6\\xc4\\x07\\xf6\\x15\\x33\\xed\\x2f\\x9f\\x49\\x2a\\xe6\\x10\\x5b\\xa9\\xd9\\x8f\\x02\\x3c\\xce\\x04\\x33\\x32\\x52\\x48\\x72\\xb2\\xad\\x85\\x24\\x27\\x3b\\x5a\\x48\\x72\\xb2\\xae\\x85\\x24\\x27\\x0d\\x5a\\x48\\x72\\x62\\x5b\\x48\\x72\\x52\\x9f\\x48\\x48\\x72\\x12\\x92\\x9c\\x84\\x24\\x27\\x7b\\xb7\\x4f\\xc0\\xad\\x34\\x24\\x39\\x59\\xdf\\x42\\x92\\x93\\x90\\xe4\\x24\\x24\\x39\\x09\\x49\\x4e\\xca\\x76\\x70\\x4e\\xfc\\x21\\xc9\\xc9\\xb6\\x16\\x92\\x9c\\xac\\x6d\\x07\\x23\\x70\\x84\\x24\\x27\\x1b\\x5a\\x48\\x72\\xb2\\xa1\\x85\\x24\\x27\\x21\\xc9\\x49\\x48\\x72\\xd2\\xb0\\x7d\\x7a\\x21\\x77\\x21\\xc9\\x49\\xa3\\x16\\x42\\xee\\x1a\\xb6\\x90\\xe4\\x24\\x24\\x39\\x59\\x6e\\x21\\xc9\\xc9\\xce\\x76\\x18\\x3a\\xe8\\x90\\xe4\\x24\\x24\\x39\\xd9\\xda\\x42\\x92\\x93\\x90\\xe4\\x64\\x6b\\x0b\\x49\\x4e\\x3e\\x15\\xfd\\x68\\x48\\x72\\x12\\x92\\x9c\\x6c\\x1b\\x23\\x48\\x5c\\xcd\\x5a\\x48\\x72\\x12\\x92\\x9c\\xac\\xb4\\x90\\xe4\\x64\\xb5\\x85\\x24\\x27\\x21\\xc9\\x49\\x48\\x72\\x12\\x92\\x9c\\x14\\x2d\\x24\\x39\\xf9\\xd4\\x75\\x4f\\x12\\x14\\xfb\\x09\\xae\\x44\\xc2\\xa2\\x45\\xe7\\x50\\x97\\x6b\\x50\\x22\\x97\\x91\\xa1\\xd8\\xd8\\x2d\\xc9\\xb0\\xdf\\x42\\xab\\xd0\\x89\\xc9\\x3e\\xb0\\xfc\\x01\\xd7\\x95\\x8d\\xab\\xe6\\x11\\x90\\x6e\\x0f\\x1e\\x63\\x0b\\x0e\\x22\\x97\\x80\\x5f\\xe0\\xfb\\xf6\\xc6\\xfe\\xa1\\x2f\\x9c\\x6c\\xb7\\xaf\\x9d\\xc2\\xb4\\xb3\\xd4\\x5e\\x5d\\xc8\\x21\\xc4\\x32\\x56\\x73\\xfe\\x14\\x50\\xa4\\x45\\x81\\x6c\\xd9\\x46\\xe0\\xa2\\x59\\x96\\xb0\\x2e\\x51\\xa1\\x84\\xdc\\xe4\\xc8\\x5d\\x80\\xb3\\x56\\xab\\xd7\\x24\\xca\\xf2\\x01\\x49\\x21\\x15\\xb2\\x43\\xa0\\x40\\x0f\\x12\\x5c\\x0d\\x54\\x0e\\xe1\\x9c\\xae\\xed\\x84\\xfc\\xe6\\x6b\\x81\\xfb\\xbf\\xb0\\xf2\\x42\\x99\\xa2\\xa9\\x38\\x2b\\xe6\\xd1\\x61\\x27\\xb7\\xb0\\xcb\\xc9\\xb2\\xbb\\x27\\xd3\\x35\\x2d\\xd0\\x7b\\xa1\\xaf\\xdd\\xe5\\x7e\\xb6\\xf3\\xda\\x14\\x86\\x49\\xb5\\x48\\x59\\xd4\\x86\\x38\\x59\\x7a\\xf2\\x5c\\x41\\x98\\xe7\\x22\\xcd\\x72\\x0d\\x35\\xc2\\x66\\xb7\\xd8\\x0a\\x1d\\x4c\\x75\\x45\\xe8\\xcf\\x13\\x0a\\x19\\x09\\x3e\\x61\\x53\\x27\\x7d\\x9f\\xa6\\x94\\xd3\\x29\\x0c\\x8b\\xdd\\x1e\\x96\\x79\\x0e\\x4e\\x5b\\x13\\xea\\x67\\x8b\\x83\\x8c\\x12\\xca\\xda\\xfb\\xf8\\xf5\\x85\\x26\\xce\\x71\\x16\\x98\\x03\\xab\\xf4\\x59\\xc7\\x58\\xad\\x62\\x9b\\x07\\x85\\x63\\x36\\xb3\\x78\\x63\\xe4\\x1f\\xd9\\x8f\\x07\\x1d\\xa4\\x47\\xaa\\x51\\x57\\x81\\x82\\xd1\\x1a\\x48\\x6d\\xef\\x81\\x5e\\x48\\x8c\\x9c\\xd0\\x24\\x9b\\x6d\\x97\\x19\\xbb\\xc4\\x20\\x5e\\x2c\\x38\\x4d\\x59\\xe4\\x6f\\xde\\x59\\x92\\x88\\xc8\\xea\\x6a\\xea\\xd2\\x66\\xc7\\xa5\\xd8\\xe9\\x9b\\x35\\xa5\\x69\\xae\\xe9\\x38\\x81\\x11\\xb9\\xb4\\x89\\x1b\\x04\\x4f\\x16\\xe6\\x62\\x2a\\xd0\\xde\\x7f\\xc1\\xdd\\x8a\\x6e\\x22\\x66\\x17\\x1f\\xd6\\x8e\\xfe\\xab\\x6b\\xb9\\x75\\x84\\x36\\x9b\\x69\\x02\\xb8\\xc1\\x71\\x82\\x03\\x01\\xae\\xe5\\xc2\\x00\\xe6\\x95\\x88\\x6f\\x0c\\x6c\\xd6\\xde\\xee\\x9c\\x80\\xa2\\xa3\\xdb\\x6a\\x1f\\x2e\\xab\\x1d\\xdd\\x55\\xfb\\x71\\x32\\xed\\xee\\x60\\xda\\xaf\\x73\\x69\\x69\\x5b\\xb0\\xf9\\x73\\xaa\\xd1\\x36\\x35\\xb0\\xc8\\x44\\x3c\\x5a\\x83\\xb3\\x88\\x98\\x74\\x9c\\x81\\x19\\xf1\\x4a\\xc4\\x86\\x9b\\x92\\x60\\x11\\x57\\x71\\x47\\xad\\x66\\xf1\\xd2\\x4c\\xee\\x0e\\x55\\x81\\x54\\x97\\x6c\\x16\\x9d\\x53\\x96\\x98\\x0b\\xdc\\x71\\x02\\xab\\xb9\\x08\\xbb\\x99\\x6b\\x7a\\x60\\x81\\xfb\\x4e\\xd7\\x41\\xba\\x82\\x7f\\x9f\\xe9\\x36\\x08\\xa6\\x8a\\x4c\\x59\\xbb\\xc4\\x9c\\xa4\\xc7\\x2b\\xf0\\x16\\x67\\x51\\x71\\xe4\\x37\\xb0\\x98\\xd2\\x07\\xd4\\x40\\xd1\\x54\\xe4\\x5c\\xdb\\x3c\\x1c\\x96\\x29\\x2c\\x08\\xb9\\x0d\\x77\\x78\\x42\\xb7\\xa8\\x47\\x65\\xdf\\x48\\x3f\\x48\\x9a\\xc6\\x3e\\x1a\\xff\\xaa\\x8f\\x68\\x4f\\xaa\\x35\\x48\\xfe\\x9a\\xfc\\xef\\xf1\\x5f\\x7f\\xf3\\xf3\\xf0\\xe4\\xcb\\xe3\\xe3\\xef\\x5f\\x0e\\xff\\xf3\\x87\\xdf\\x1c\\xff\\x75\\x84\\xff\\xf8\\xfc\\xe4\\xcb\\x93\\x9f\\xfd\\x1f\\xbf\\x39\\x39\\x39\\x3e\\xfe\\xfe\\x9b\\x77\\x5f\\xdf\\x5e\\xbd\\xf9\\x81\\x9d\\xfc\\xfc\\x3d\\xcf\\xd3\\x3b\\xfb\\xd7\\xcf\\xc7\\xdf\\xc3\\x9b\\x1f\\xf6\\xec\\xe4\\xe4\\xe4\\xcb\\x5f\\xb7\\x37\\x30\\x75\\xb5\\xa6\\xf6\\x67\\x4b\\xed\\xc9\\x92\\xfa\\x28\\x76\\x54\\x17\\x38\\xf4\\xec\\x97\\xdf\\xc5\\x87\\xae\\x5c\\x7f\\xa7\\x80\\xde\\x76\\xfd\\x65\\x67\\xb1\\xfb\\x72\\x52\\x8e\\xcf\\x14\\x11\\x29\\xd3\\x1a\\x62\\xe4\\x3a\\x69\\x35\\xdd\\xc7\\x92\\xc8\\xef\\x10\\x16\\xa6\\xe5\\xa1\\xda\\x7c\\x59\\x49\\x3b\\x51\\x6a\\x0a\\x5a\\x4f\\x4b\\x78\\x1b\\x1e\\x2a\\x39\\x38\\x61\\x69\\x96\\x40\\x0a\\x5c\\x23\\xe2\\x19\\x7a\\xf1\\x05\\x35\\x46\\xa3\\x72\\x05\\x91\\x95\\x69\\xe1\\x21\\x02\\x88\\xdd\\x24\\x03\\x6e\\xac\\xb4\\x80\\x1b\\x03\\x6e\\xdc\\xd5\\x3a\\xab\\x3d\\xfb\\x40\\x8c\\xd7\\xd5\\x49\\x38\\x75\\x85\\xf2\\x0a\\x6a\\x54\\x82\\x16\\x71\\xe6\\x62\\x82\\xb6\\xf0\\x39\\x8b\\x73\\x9a\\x54\\x33\\x65\\xfa\\xe4\\x89\\xed\\x30\\x40\\x45\\x48\\x4f\\xe9\\x62\\x45\\x26\\x67\\x9c\\x55\\xd3\\x72\\x0e\\x0a\\x0f\\x0e\\x7c\\xd1\\xf1\\x65\\xa5\\xf5\\xf0\\xe8\\x2c\\xb9\\xa7\\x0b\\xd5\\x32\\x7b\\xdf\\x57\\x42\\xa2\\x53\\xc0\\xd2\\xa0\\x44\\x48\\xef\\x2b\\x52\\x15\\x56\\xea\\xda\\xda\\x76\\xd6\\x9e\\x75\\x1b\\x5d\\x0f\\xe8\\x77\\xe2\\xd2\\x0b\\x55\\xbc\\xe8\\x6d\\x02\\x6e\\x23\\x4a\\x2f\\x7f\\x03\\xe7\\xed\\x16\\x7e\\x03\\x5a\\x3b\\x7d\\xce\\x12\\x48\\xd0\\x72\\x4f\\x0b\\x13\\x57\\x7d\\x7b\\xac\\x5b\\x08\\xe6\\xcc\\x34\\x0f\\x27\\xc2\\x9c\\x09\\x66\\x9b\\x9f\\x4c\\x20\\x6a\\xe9\\x2b\\x68\\x13\\x20\\xac\\x19\\xc7\\xba\\x2b\\x6b\\xc6\\x73\\x9a\\x24\\x0b\\xbf\\x27\\x10\\x13\\xc1\\x5b\\x0d\\x04\\x0f\\x4c\\x93\\x9c\\x6b\\x96\\x18\\x60\\x22\\x12\\xa6\\x79\\x42\\xab\\xaa\\x20\\xb7\\x32\\xef\\x41\\x15\\x8f\\xc8\\x07\\x6e\\x84\\xd1\\xf2\\xe5\\x76\\x4a\\xcc\\xa5\\x01\\x0c\\xd3\\x91\\x80\\x86\\x78\\x80\\x5d\\x2f\\x43\\x20\\xfa\\x20\\xd5\\x30\\x46\\x71\\x2c\\xad\\x86\\xf7\\x7b\\x59\\xf8\\x98\\x8c\\xec\\x45\\x2c\\x0c\\xe0\\x24\\x66\\x93\\x89\\x19\\x19\\x33\\x05\\x72\\x21\\x53\\xba\\x3a\\x2b\\xca\\xe3\\x56\\xa3\\x1b\\x0e\\x08\\xa3\\x0f\\xaa\\xd9\\x4f\\xb1\\xe2\\xc5\\x91\\x11\\xcd\\x23\\x2a\\x8f\\xaa\\xb5\\x12\\xce\\x12\\x3d\\x13\\xf9\\x74\\x56\\x42\\x45\\xb7\\x2d\\x27\\x4a\\xa3\\xe7\\x8d\\xd9\\x4c\\xe5\\x7d\\xce\\x96\\x80\\x4d\\x19\\x5e\\x87\\x47\\x60\\x59\\x32\\x01\\xf6\\xba\\xdf\\xd3\\x96\\x63\\xaf\\x58\\x87\\xad\\xbb\\xaf\\x3d\\x73\\x1f\\x92\\x83\\xee\\x5d\\x10\\x57\\xe2\\xa7\\x38\\x3c\\xe8\\x1e\\x16\\x3c\\x22\\x97\\x36\\x6d\\xc1\\xa0\\xde\\x6b\\x6d\\x4b\\xec\\x66\\x54\\xdc\\x9b\\xbc\\xa3\\x5e\\x4b\\xdf\\xae\\xa5\\x01\\x58\\x11\\x81\\x84\\xf9\\x5a\\x6d\\xe7\\x94\\x2f\\xbc\\xc3\\x3f\\xba\\x1f\\xd9\\x40\\xa5\\x22\\x06\\x21\\x69\\xa7\\x45\\x2d\\xee\\xd2\\x93\\x97\\x1f\\x51\\x10\\xe5\\x92\\xe9\\xc5\\xb9\\xe0\\x1a\\x1e\\x5a\\xe1\\xbe\\x3e\\xa8\\xfa\\x4d\\x7d\\x1a\\x35\\xba\\xee\\xa7\\x48\\x44\\x66\\xf3\\xe6\\x2d\\x55\\xa0\\x99\\x89\\x3c\\x89\\x31\\x55\\x68\\xce\\x11\\xed\\xb4\\xa3\\x28\\x97\\x13\\x43\\xc2\\x2d\\xbc\\x21\\xc5\\x44\\xd3\\xc8\\xf2\\xc4\\xbc\\xd7\\x9f\\x75\\x7e\\xfc\\x47\\xce\\xe6\\x34\\x01\\xae\\x2b\\x5f\\x5c\\xa1\\x1f\\x58\\xf5\\xa3\\xc7\\xb4\\x9f\\x69\\xaa\\xee\\x4a\\x09\\x03\\x86\\x99\\x88\\x4b\\x81\\xe2\\xd4\\x6f\\x1d\\xfe\\x04\\x0f\\xfa\\x23\\xb4\\x9d\\x21\\xc3\\x74\\x25\\xd9\\x9c\\x25\\x30\\x85\\x37\\x2a\\xa2\\x09\\xca\\x51\\xcf\\x2d\\x9c\\x9f\\x6d\\x98\\x17\\x42\\xa6\\x14\\x89\\x32\\x0c\\x98\\x11\\x56\\x0d\\xab\\x69\\xbd\\x60\\xd1\\x84\\x33\\xa5\\x8c\\x63\\xf9\\x94\\x0e\\x6a\\x7e\\x37\\xa8\\xb2\\x6e\\xb8\\x46\\xde\\xce\\xa8\\x34\\x50\\xe8\\xdd\\x6d\\x2d\\x69\\x1c\\x0b\\x91\\xb8\\x14\\x9c\\xc9\\xa2\\x9c\\x17\\x6b\\xaf\\x0f\\x47\\x5c\\x2c\\xfe\\xc6\\xe1\\xfe\\x6f\\x66\\x16\\x8a\\x4c\\x12\\x3a\\x2d\\x49\\x33\\xe8\\x95\\xd8\\x85\\xee\\x1e\\xc0\\x1b\\x37\\x1a\\xf3\\x4b\\xe6\\x86\\xb1\\x31\\x5c\\x45\\xe9\\x1b\\x5d\\xc5\\xe0\\xed\\x05\\xba\\x57\\x27\\x88\\x4f\\xa8\\x22\\xc5\\xd8\\xed\\x58\\x07\\xd3\\x7e\\x7b\\x82\\x74\\xe2\\xfc\\xec\\xea\\x6f\\x37\\xff\\x73\\xf3\\xb7\\xb3\\x8b\\x77\\x97\\xef\\xdb\\x7b\\x40\\x0a\\x0d\\x56\\xbb\\x52\\xe1\\xee\\xa3\\xc2\\x68\\x6f\\x4e\\xa1\\xf0\\xfb\\x18\\x09\\x35\\x42\\x63\\x09\\xe6\\xd0\\xe0\\xb1\\xb8\\xef\\x68\\x29\\x34\\x30\\x05\\xb4\\x1d\\xe7\\x1a\\xd1\\x8c\\x8e\\x59\\xc2\\xba\\xe8\\x16\\xfa\\xba\\xbe\\x98\\x15\\xb6\\x32\\x1f\\xe4\\xe7\\xe2\\xf8\\x34\\x96\\x22\\xb3\\xdb\\xe7\\x3d\\xfc\\xbb\\xdb\\x58\\xeb\\x9e\\xa4\\xd5\\x94\\x68\\x78\\x63\\x26\\xf5\\x89\\x4c\\x25\\xe5\\xba\\x94\\xa4\\x4a\\x68\\x96\\x86\\xe9\\xef\\x92\\x53\\xe5\\x59\\x01\\xe7\\xd9\\x73\\x2c\\xd3\\xb8\\xbf\\xfc\\xca\\x67\\x71\\x0c\\x71\\xed\\xd8\\x3a\\xf4\\x7c\\x98\\x69\\xa4\\xce\\xfd\\xe2\\x2a\\xae\\xa4\\xe4\\xea\\xc3\\xcd\\xe5\\xff\\x7f\\xe9\\xde\\x2c\\xb2\\x6e\\xe6\\xcd\\x7e\\x8a\\x0f\\x48\\x91\\xf5\\x76\\xba\\xd7\\x2e\\xe5\\x7c\\x38\\xdf\\x83\\x38\\xdf\\x82\\xdf\\x79\\xf6\\x40\\xf5\\xeb\\x9c\\xd7\\xab\\x53\\x96\\x53\\x23\\xa9\\x88\\x3b\\xa0\\xe6\\xab\\x22\\x9e\\xab\\xde\\x6b\\x55\\x75\\x21\\x81\\x98\\x57\\xb8\\x66\\xa8\\x48\\xaa\\x08\\x1f\\x5a\\xd8\\x7c\\xe8\\xbd\\xd4\\x51\\xaa\\xd2\\xaa\\x09\\x4d\\xd4\\xc7\\x4a\\x70\\xba\\x70\\x2a\\x86\\x69\\x7d\\x27\\x72\\xde\\x4f\\xe4\\x7b\\x07\\x88\\x2b\\x26\\x42\\x62\\xe0\\x42\\x3b\\x89\\xd8\\x2c\\x10\\xcb\\x68\\x49\\x11\\x11\\x6b\\x05\\xac\\x24\\xb5\\xa9\\x71\\x0d\\x1d\\x98\\x96\\xdb\\x0a\\xa3\\xc2\\x94\\x87\\x8b\\xab\\x62\\x46\\xd6\\x09\\x3c\\x57\\xb0\\x2c\\x91\\x3b\\x46\\xa5\\xb4\\x0b\\x4e\\x44\\x7b\\x73\\x88\\x04\\x1a\\xa3\\xe6\\x3c\\xa3\\x7a\\x66\\x13\\x2e\\xa4\\x54\\xdd\\x41\\x6c\\x7f\\xe8\\x18\\x68\\x56\\x38\\x08\\xa2\\xd2\\xda\\x2f\\xed\\xd6\\xec\\xaf\\xf7\\xe9\\x43\\x11\\xc7\\xa6\\x9d\\x40\\x2f\\xc2\\x2e\\x46\\xd5\\x67\\xbd\\x10\\x1d\\x50\\xb0\\x39\\x84\\x0f\\x3c\\x59\\x5c\\x0b\\xa1\\xbf\\x2a\\x6a\\x2b\\x3c\\xf7\\xe5\\xf8\\x8b\\x13\\xb0\\xeb\\xae\\xa4\\x28\\x69\\x51\\x9c\\xf2\\x10\\x01\\x07\\x51\\x63\\xa5\\x22\\x44\\x57\\xcc\\x68\\x0e\\xe4\\x97\\x8a\\x18\\x65\\xce\\xcf\\xd4\\xd7\\x52\\xe4\\xad\\xb9\\xad\\x3e\\x05\\xb8\\xaf\\x2f\\x2f\\x90\\xf6\\xe5\\x2e\\x16\\x99\\x6b\\xb9\\xc0\\xba\\x40\\xab\\x75\\xaa\\x3b\\xab\\x21\\xbe\\x75\\x51\\xdf\\x55\\xcc\\xd6\\x39\\xc0\\x93\\x90\\x77\\x74\\x41\\x68\\xa2\\x84\\x3f\\x76\\xe7\\xde\\xba\\xa4\\x40\\xf4\\xda\\x49\\xf3\\x78\\x2c\\xf4\\x6c\\x45\\x2d\\xd9\\xd6\\xae\\x61\\xda\\xea\\x78\\x83\\x4a\\x48\\x73\\x19\\x3d\\xc2\\xf8\\xca\\xb0\\x1a\\x9d\\x1e\\x33\\x09\\x11\\xc4\\xc0\\xa3\\x8f\\xf5\\x46\\x3c\\x77\\x84\\x2d\\xde\\xaa\\xf7\\x82\\x1b\\xf4\\xfa\\xdc\\xf7\\xea\\xb2\\x88\\x1e\\x77\\xa7\\x51\\xbd\\x45\\xe8\\x86\\xeb\\xd4\\x62\\x14\\x0d\\xcf\\x88\\x5c\\x73\\xd5\\xc5\\x23\\xf5\\x72\\x82\\x7a\\x3c\\x0b\\x74\\xdf\\xe4\\x63\\x48\\xcc\\x61\\xb3\\x24\\xb1\\x35\\x3b\\xa9\\xb6\\xca\\x76\\x96\\xd2\\x29\\x10\\xaa\\x8b\\x4b\\xa8\\x05\\x01\\xae\\x72\\xe9\\xe0\\xa6\\xa5\\xc9\\xc9\\xb4\\xc2\\x5a\\xe6\\x96\\xf6\\xed\\xe5\\x05\\x79\\x49\\x8e\\xcd\\xda\\x4e\\x90\\xe3\\x98\\x50\\x96\\x60\\x80\\x3b\\x9a\\xb3\\x97\\x94\\x8c\\x13\\x6f\\x70\\xeb\\xb4\\x05\\x88\\x47\\x88\\x90\\x96\\xb4\\x0c\\x08\\x17\\x44\\xe5\\xd1\\xcc\\xef\\x01\\x13\\xbc\\xd0\\xb3\\xba\\x8c\\x67\\x9d\\xbc\\x3b\\x03\\xda\\xe9\\x8f\\x1e\\x7e\\xab\\x40\\x3e\\xf7\\xb5\\x35\\xe4\\xf0\\xdb\\x27\\x24\\x87\\x55\\x29\\xd1\\x5c\\xff\\xfa\\x81\\xd9\\xbb\\x9a\\x82\\xa6\\x31\\xd5\\xd4\\x91\\x49\\xff\\x42\\x80\\xda\\x40\\x2c\\x3b\\x10\\x4b\\x05\\x6f\\x19\\xcf\\x1f\\x6c\\x3e\\xa1\\x83\\xb0\\x23\\xdc\\xbc\\xc1\\x19\\x91\\xc8\\x1f\\x34\\x02\\xa8\\x8d\\x80\\x8e\\xbd\\xca\\xbf\\x87\\xd0\\x8d\\xcb\\xff\\x8f\\xbd\\xb7\\xef\\x6d\\x23\\x47\\xf2\\xc7\\xff\\xbf\\x57\\x41\\x64\\x07\\x67\\xfb\\x56\\xb2\\x93\\x7d\\xc2\\xee\\xe0\\xf0\\x1b\\xf8\\x1c\\x4f\\x62\\x6c\\xe2\\x08\\xb1\\x27\\xfb\\x1d\\xcc\\xce\\xcd\\x51\\xdd\\x94\\xc4\\x73\\x37\\xd9\\xd7\\x64\\xcb\\xd6\\x62\\x5e\\xfc\\x0f\\xac\\x22\\xd9\\x6c\\x49\\x4e\\xe2\\x26\\x63\\x29\\x9e\\xe6\\x02\\xb3\\xb1\\x25\\x93\\xc5\\xa7\\x62\\x3d\\x7e\\xaa\\x73\\x8d\\x46\\xf7\\x68\\xdd\\xf0\\x4a\\x50\\xcc\\x4d\\x63\\x46\\x11\\xa2\\x22\\x97\\xe5\\x06\\x91\\x33\\x59\\x13\\x16\\x53\\x8e\\x38\\x88\\xd5\\x18\\x2e\\xa6\\x6d\\xbf\\x6d\\x0f\\x4b\\xc1\\x96\\x2c\\xa2\\x04\\xf3\\xda\\xa5\\x7c\\x63\\x7a\\x33\\x8b\\xe3\\x4e\\x2e\\x74\\x4f\\x0a\\x3a\\x65\\x85\\x4d\\x27\\x45\\x8c\\x81\\x84\\x37\\x2c\\x91\\x37\\xa2\\x96\\x45\\x3a\\xd0\\xeb\\xf7\\xb2\\x60\\x08\\x88\\xe4\\x16\\xc2\\x74\\xff\\x55\\xac\\x03\\x74\\x92\\x6a\\x1d\\xc0\\x28\\xd7\\x59\\x07\\x30\\x83\\x7e\\x0d\\xeb\\xd0\\x44\\x08\\x88\\x64\\x7d\\x1d\\x8c\\xb4\\xd9\\x5d\\x07\\x90\\xbf\\xf6\\x7d\\x1d\\x14\\xcb\\x32\\x59\\x56\\x93\\x5a\\xce\\x78\\xff\\xdb\\x91\\xf2\\xd9\\xb6\\x14\\xb5\\x61\\x65\\x68\\x42\\xdf\\xcc\\x4d\\xc7\\x67\\xab\\xfb\\x65\\x1a\\x15\\xc0\\x63\\x51\\xe2\\xa8\\xc6\\x77\\xd0\\x41\\xc5\\xfd\\x7b\\xf0\\x9c\\x03\\xb7\\x5b\\x7f\\xe3\\xed\\xe8\\xbd\\x47\\xee\\x44\\xaf\\x99\\x11\\x6d\\x87\\xbf\\xc5\\x17\\x2f\\x05\\xc4\\x6f\\x84\\x73\\x34\\xc9\\x83\\x2b\\x33\\x5a\\x2c\\xa4\\xd2\\x91\\xb7\\x8a\\x24\\x4e\\xda\\x5e\\xa7\\x2b\\x80\\x24\\x84\\x60\\x38\\xf8\\x5d\\x80\\x34\\x41\\xc1\\x3c\\xef\\xdc\\x97\\x42\\xe6\\x2c\\x88\\xea\\x84\\x0c\\xeb\\x28\\x72\\xae\\x11\\x14\\x0e\\xc6\\x70\\x48\\x8a\\x46\\xda\\x73\\x41\\x93\\x79\\x67\\x64\\x2d\\xb1\\x0e\\x73\\xd4\\x90\\x0e\\x2e\\x9c\\xc2\\xba\\x32\\x01\\x21\\xd2\\x15\\xd5\\x8b\\x11\\xa9\\x59\\x81\\xf8\\x8d\\x96\\x3d\\xdf\\xa0\\xc5\\xeb\\x00\\x38\\x8e\\x23\\xc8\\xb1\\x1b\\x47\\xb6\\x43\\x9a\\x48\\x43\\x15\\xc8\\xe0\\x33\\x7c\\x3f\\xb9\\x22\\xcf\\xde\\xb8\\xfd\\x7a\\x66\\x81\\xce\\x2f\\xdf\\x5d\\x87\\x29\\x2d\\x54\\xac\\x30\\xf1\\x2e\\x22\\x61\\x03\\xdb\\xfe\\x89\\x15\\x91\\x47\\x1d\\xd7\\xd0\\x1f\\x6f\\xf4\\x89\\xde\\x70\\x91\\x5b\\x84\\xc2\\xce\\x2e\\x3a\\x03\\x9e\\x55\\x0d\\xe3\\x36\\xf3\\x03\\x2d\\x78\\x1e\\xbe\\x47\\xdf\\x46\\x56\\xf1\\xf4\\xa7\\x80\\x8c\\x77\\x72\\x4d\\xdf\\xa3\\x02\\xeb\\xbc\\x6c\\xe3\\x8f\\x7b\\x95\\x3d\\x81\\x29\\x49\\xf8\\x41\\xc0\\x1d\\x34\\xf3\\x1d\\x13\\x21\\xb7\\x8c\\x91\\x60\\xeb\\xa2\\xef\\x80\\x7d\\x3b\\xf7\\xc8\\x02\\xf2\\x0f\\xa4\\xc8\\xa9\\xd9\\x99\\xe1\\x1c\\x9a\\x8b\\xb9\\x0a\\xad\\x20\\xb4\\x28\\x92\\xc4\\x25\\x6c\\x33\\x83\\xb8\\x6b\\x00\\xb9\\x3f\\x36\\x01\\x6d\\x5d\\xcd\\xef\\x80\\x01\\xc7\\x8c\\xfe\\x09\\x13\\xc6\\xd7\\x6d\\x8a\\x28\\x8c\\x4a\\xf1\\x95\\x1b\\x22\\xe6\\xa5\\xa2\\x67\\xb5\\x59\\x41\\xcd\\x69\\x71\\x55\\xb1\\xde\\xb5\\xd4\\x49\\xe2\\xe7\\xe2\\xd5\\xdb\\xab\\xd3\\x2e\\x65\\x20\\x0c\\x5b\\x60\\x19\\x06\\x9f\\x13\\x9a\\x97\\x5c\\x29\\xf0\\xf8\\xb0\\xe9\\x42\\xca\\x9b\\xa8\\x21\\x0f\\xb7\\x54\\x87\\x0e\\x12\\x83\\x15\\x9f\\xab\\x13\\xcb\\x51\\xc6\\x66\\xe1\\x8e\\x08\\x17\\x85\\x4f\\xbe\\x01\\x73\\xa1\\xd0\\xca\\xba\\x10\\xa2\\x27\\x4f\\x32\\x3f\\x7b\\x38\\x7a\\x00\\xf9\\xe2\\x83\\x9d\\x37\\x97\\x07\\xd0\\x7f\\xe0\\xf0\\xee\\x5c\\xec\\xd8\\x3c\\x55\\x71\\x30\\x9d\\xeb\\x95\\xfa\\xb7\\xcf\\x7d\\x4b\\x7d\\xf1\\xad\\xeb\\x88\\xda\\xeb\\xce\\x17\\xc9\\x4a\\xfd\\x19\\x53\\xe9\\xaa\\xfc\\x26\\x28\\xce\\x6c\\x49\\x22\\x39\\xc3\\xbc\\x58\\x06\\x10\\x15\\xf4\\xde\\x34\\x32\\xf0\\x6f\\x1f\\x40\\xa9\\x13\\xfb\\xa7\\x07\\xa9\\xc0\\x97\\x4e\\x8b\\xc2\\x6c\\x24\\xb5\\x39\\xd2\\x41\\x84\\x27\\xe8\\x26\\x3e\\x2d\\x19\\xea\\x93\\x62\\x46\\xb2\\xd1\\x16\\xc2\\x59\\xc4\\x57\\xef\\x3c\\xe4\\xda\\x25\\x84\\xbb\\x8c\\x74\\x2d\\x71\\x6c\\x4a\\x4a\\x7e\\x67\\x28\\x0c\\x47\\xec\\xa6\\xd0\\x82\\xe7\\x7f\\xfb\\xc7\\x11\\xc8\\xef\\x04\\xa2\\x0f\\x3c\\x12\\xc5\\xc8\\xec\\x50\\x38\\x88\\xcb\\xf7\\xd1\\xe6\\xd9\\x32\\x1f\\x5c\\x32\\x6d\\x34\\x35\\x5c\\xb7\\xd0\\xfd\\x60\\x34\\xab\\xba\\x49\\x70\\x19\\x62\\x5c\\xc3\\x24\\x74\\x0f\\x27\\xe5\\x14\\x91\\xf7\\x01\\x5c\\xc5\\x96\\x26\\x23\\x83\\x38\\xe1\\xed\\xb1\\x5c\\xc7\\x64\\x4b\\x42\\xcc\\xa3\\xb9\\x90\\xc9\\xe7\\xbb\\x91\\xbf\\xa0\\xb3\\x8a\\xec\\x8b\\xc3\\x2a\\x36\\x7b\\x38\\xc8\\x84\\xde\\x59\\xea\\x70\\x98\\x8d\\xcd\\x37\\xa3\\x97\\x26\\x32\\xdf\\x48\\xd2\\x76\\x75\\x31\\xfb\\x23\\x20\\x9b\\xc3\\xd1\\xaa\\x20\\x42\\x5a\\xfb\\x48\\x50\\x9a\\x92\\xdd\\xb1\\xac\\xd1\\x2c\\xb7\\x58\\x0d\\xd6\\xa6\\x8c\\x79\\xde\\x5d\\x6a\\x7a\\x53\\x00\\x7d\\xb6\\x05\\x71\\xd4\\xa8\\x85\\x2a\\xb4\\xba\\x8e\\x47\\x9b\\x18\\x91\\xff\\x05\\x2e\\x69\\xa1\\x99\\xda\\x6a\\x9a\\x13\\xff\\xe7\\x7d\\x97\\x02\\x02\\xa9\\x33\\x2a\\x7c\\x45\\x79\\x2d\\x9d\\x89\\xdb\\x62\\x32\\xd8\\xd4\\xd4\\x29\\x23\\x15\\xad\\x69\\x69\\xde\\x60\\x45\\xec\\xf6\\x4c\\xd9\\x9c\\x63\\xa2\\x5d\\xf0\\x28\\x7a\\x50\\x87\\x7e\\x20\\x25\\xa0\\xd8\\x70\\x4d\\x4a\\x3e\\x5f\\xe0\\x6d\\x21\\x14\\x2a\\xd7\\x10\\x17\\x38\\x56\\x48\\x9a\\x13\\x60\\x2c\\xb2\\x26\\xb7\\xb4\\x2e\\x8d\\x2c\\x40\\xb3\\x05\\x44\\xa1\\x51\\x41\\xf2\\xc6\\xdc\\x07\\x02\\x10\\x04\\xab\\xb1\\xd2\\x54\\x1b\\x1d\\x93\\xd5\\x11\\x46\\x38\\xb7\\x4c\\x3b\\xc0\\x56\\xfe\\xd2\\x75\\x23\\x76\\x9c\\x22\\x6e\\x6e\\x5a\\x12\\x2b\\xc8\\xf9\\x1d\\xcb\\x82\\xea\\x84\\xe6\\x78\\xda\\xf2\\x84\\xe6\\x99\\xa2\\x37\\x91\\x81\\x66\\x3b\\xd7\\x8b\\x33\\x59\\x96\\x54\\xa4\\x4b\\x83\\x8c\\x14\\x44\\xce\\x90\\x1c\\xa7\\xe2\\x58\\xea\\x88\\x51\\x3e\\x21\\xb8\\x13\\x19\\xa8\\x43\\x3f\\xed\\x48\\x21\\xc8\\xe9\\xcc\\xb9\\x36\\xd7\\x14\\x73\\xdc\\x65\\xed\\x6b\\x5a\\x44\\x91\\xe5\\xe8\\x00\\x94\\x7c\\x29\\x35\\x39\\x3c\\x38\\x39\\x38\\x72\\xa8\\x2b\\x9e\\x84\\x03\\x15\\x26\\x15\\x60\\x42\\x71\\x3b\\x21\\xc5\\xcb\\xaa\\x58\\xc1\\x1c\\x0e\\x10\\x18\\x3f\\xa2\\xe0\\x94\\x69\\x2e\\x3c\\xd5\\x63\\xc1\\xaa\\x05\\x2b\\x8a\\x11\\x51\\x46\\xd6\\xa5\\x0e\\xbc\\x0d\\x7f\\x6b\\xbe\\xa4\\xeb\\x26\\x43\\x9b\\xd8\\xe1\\xc1\\xaf\\x07\\x23\\xc2\\x74\\x76\\x44\\x6e\\xa5\\x38\\xd0\\xe8\\xde\\x20\\xd7\\xa0\\x30\\x46\\xd1\\xe4\\x89\\x58\\xc9\\x06\\x6a\\xb7\\xe1\\xb6\\x79\\xbc\\xbf\\x8c\\x1a\\x5d\\xa7\\x41\\x81\\xdc\\xbc\\xc7\\xf0\\xf5\\x38\\xe1\\xed\\xfc\\x8e\\x6b\\x23\\x77\\xe8\\x06\\x6c\\x12\\xcf\\x51\\x2d\\x60\\x86\\x97\\x9a\\xd7\\xcd\\x3c\\x6b\\x27\\x0b\\x46\\x0b\\xbd\\x58\\x79\\x55\\x05\\xcb\\x62\\x29\\xd2\\x08\\xfb\\x49\\xbc\\xc0\\xb4\\x07\\xe9\\x9c\\xd1\\xfa\\xba\\x2d\\xa2\\xb7\\xd7\\x75\\x80\\x2d\\x8d\\x9f\\x2c\\x03\\x8c\\x02\\x4c\\xb7\\x04\\x30\\xc8\\x58\\x2c\\x4f\\x55\\x05\\xf8\\x8f\\x4f\\xaf\\xc2\\xef\\xbc\\xae\\xd2\\xbc\\x9c\\xaf\\xde\\x4f\\xce\\x3e\\x59\\xd7\\x17\\xbe\\x34\\x14\\xf6\\x8d\\x06\\xd7\\x4c\\x59\\xcf\\x76\\x22\\x6b\\x4d\\x84\\xaf\\xa9\\x66\\x6e\\xd8\\x1c\\xf6\\x92\\xd5\\x4b\\x9e\\xb1\\xe3\\x47\\x28\\x1f\\x9b\\x0a\\x36\\x33\\xfe\\x3a\\x10\\x88\\x53\\x82\\x89\\xef\\x8b\\x8c\\x74\\x85\\xe4\\x6c\\x33\\x03\\x5b\\x4a\\x41\\xdd\\x2a\\x68\\xe6\\xf7\\x06\\xf6\\xef\\x35\\x3c\\x74\\x67\\x0b\\x96\\xdd\\x58\\x10\\xdc\\x38\\x7b\\xa1\\x62\\x8c\\x6c\\x71\\x24\\x18\\x06\\x82\\xff\\x99\\x16\\x72\\x7a\\x52\\x52\\xa5\\x59\\x6d\\xb4\\x0f\\xfb\\x06\\x8f\\x33\\x43\\x01\\x17\\xf3\\xe3\\x32\\x3f\\x8a\\xa9\\x8c\\x41\\x02\\x8d\\x77\\x03\\xc9\\xb2\\x83\\xa9\\x72\\x0f\\x2a\\xa5\\x59\\x95\\x9d\\x5a\\xc7\\xcd\\xea\\xbd\\x4a\\x54\\x4b\\xfd\\xf5\\xf5\\xf5\\xe4\\x55\\xa7\\x92\\x3a\\xe4\\xfd\\x6b\\x5d\\x39\\xf0\\x6a\\x38\\x15\\x98\\x27\\x34\\x70\\xdb\\xbd\\x29\\xa3\\x9e\\xc0\\x93\\xf1\\x90\\xd2\\xeb\\xe4\\x47\\xd9\\x80\\xc0\\x44\\xa7\\xc5\\x8a\\xdc\\x52\\xc4\\x09\\x50\\x2c\\x8e\\x17\\x3c\\x33\\x64\\x3c\\x33\\xdc\\xc6\\x1c\\xb8\\xd7\\x8c\\xe6\\x88\\xa9\\x0b\\xc6\\x92\\xdd\\x3b\\xa0\\x5a\\x9a\\x92\\x6d\\xdb\\x59\\xa3\\xb4\\x2c\\xc9\\xc2\\x4e\\x15\\xd7\\xd0\\x3f\\x85\\x78\\xe1\\x8e\\xe1\\x52\\xa2\\x37\\x45\\x91\\x9a\\x55\\xa8\\x92\\xd8\\xbf\\x79\\x12\\x0a\\xc7\\x06\\x0b\\xc2\\x75\\x0e\\xe0\\xe9\\x29\\xc9\\xc2\\xa5\\xb2\\x62\\x3a\\xd6\\xc2\\x15\\xb8\\x40\\x51\\xc5\\x49\\xb1\\x25\\xa9\\xd7\\x43\\x12\\xd5\\xec\\x21\\xf1\\x75\\x7b\\x5c\\x27\\xf1\\x6e\\xbd\\x34\\x15\\x80\\x48\\x92\\x2a\\x40\\x24\\x79\\x25\\x20\\x62\\x9d\\x57\\xf6\\x70\\x61\\x48\\x8b\\x21\\x34\\xce\\xa2\\xe0\\x3a\\xe6\\x6d\\xbd\\xf0\\x8c\\x0a\\x29\\x78\\x86\\x0e\\x02\\xac\\x3b\\x2f\\x1b\\x5d\\x35\\x1a\\xec\\x2d\\x19\\x55\\x6c\\xbc\\xa4\\x35\\x37\\x0c\\x15\\x8b\\xa8\\xf9\\xd8\\x22\\x61\\x6e\\xbb\\x96\\x12\\x8c\\x11\\xde\\x8d\\x8b\\x14\\xc7\\x93\\x99\\x84\\x43\\x62\\x83\\xc3\\x96\\x78\\x87\\x37\\x36\\x27\\xfe\\x44\\x93\\x54\\xb3\\xae\\xa8\\x5e\\xa4\\xd3\\x9a\\xa8\\x5e\\x40\\x48\\x1b\\x38\\x71\\x5c\\x44\\x24\\xf0\\x37\\x23\\x95\\xef\\x41\\xca\\x49\\x52\\x25\\x31\\xf2\\xe6\\x62\\x15\\xd9\\x7a\\x4d\\xcd\\x34\\x14\\x6e\\xae\\x61\\xa2\\x20\\x8b\\x2f\\xaf\\xb5\\x86\\x85\\xc9\\xa6\\x8c\\x50\\x41\\x2e\\x4e\\x2f\\x4f\\x7f\\xb9\\xfa\\x70\\xf6\\xcb\\xe5\\xe9\\xdb\\xf3\\x98\\xae\\xa3\\x4b\\x51\\xa4\\x2c\\x46\\x91\\xac\\x1c\\xc5\\x17\\x2a\\xd6\\x63\\x9a\\xca\\x16\\x6c\\x7f\\xe2\\x2b\\xae\\x80\\x9a\\x10\\x91\\xcb\\x8a\\xea\\x01\\x4c\\x7a\\x1c\\x44\\x1b\\x59\\xb3\\x4c\\x1a\\xc6\\xb3\\x53\\x8e\\x63\\xdd\\xe9\\x2f\\x59\\x41\\x57\\x57\\x58\\x96\\x7f\\xd7\\xc6\\xe4\\x4b\\xcf\\x6c\\xb0\\x70\\xbf\\xf2\\xe8\\xf0\\x6c\\x0d\\x2b\\xca\\xd5\\x63\\xb0\\x98\\xf6\\xce\\x31\\x1e\\xfa\\xf2\\x71\\x7e\\xbd\\xdd\\xb5\\x64\\xff\\x5c\\xb6\\x64\\x6f\\x6c\\xd0\\x15\\xab\\x39\\x84\\xc2\\xec\\xc3\\xa9\\x79\\x2d\\x6f\\x6d\\xa1\\x87\\x43\\x2e\\xdc\\xc9\\x39\\x0a\\x8c\\x29\\xad\\x0f\\x22\\x1e\\x47\\x4c\\x4b\\xf2\\xe2\\xb9\\x1b\\xe4\\xe9\\x39\\x17\\x6c\\x88\\xcb\\x5e\\xbb\\x97\\x2c\\x8d\\x9f\\xf6\\x2f\\xb5\\xf1\\x3a\\x5d\\x1f\\x53\\x4c\\xe0\\x0c\\x59\\x63\\xe3\\x2f\\x8e\\x7d\\x86\\xd6\\x0b\\xa0\\xc7\\xb3\\x22\\x2a\\x72\\x17\\x6b\\xf5\\xf4\\xce\\x89\\xce\\xaa\\x2b\\x99\\xdd\\x24\\x32\\x8d\\x5e\\x9f\\x4d\\xb0\\xb7\\x4f\\xba\\xa3\\xae\\xcf\\x26\\x83\\x37\\x6a\\xbf\\xec\\xa3\\x07\\x98\\xd3\\x44\\x8b\\x6f\\x1f\\x6c\\xeb\\x3c\\x18\\x34\\xae\\xb6\\x39\\xe1\\xa7\\xee\\x38\\x8c\\x06\\x8d\\xeb\\xbe\\x36\\x68\\x5c\\x0f\\x68\\xae\\xb2\\x18\\x97\\xe2\\x55\\x4d\\x33\\x36\\xd9\\x27\\x01\\xce\\x31\\x10\\x92\\xdb\\x7a\\x9b\\xa4\\x95\\xe3\\x3c\\xbb\\x10\\x8c\\xe5\\xc8\\x3f\\x5c\\x91\\x34\\x32\\x37\\x33\\xc1\\xd8\\x60\\x30\\xf7\\xb5\\x51\\xb5\\x4d\\x1d\\x21\\xea\\x5d\\x2f\\x6c\\xd7\\x56\\xcc\\x75\\x7e\\xdc\\x6d\\xd4\\xb5\\xfa\\x49\\xe5\\xd1\\xc0\\x5d\\x11\\x0a\\x7b\\x9d\\x0c\\xf1\\x46\\x1f\\x51\\x4c\\xf4\\xb7\\x7c\\xd3\\x70\\x07\\x89\\xe2\\x73\\xb3\\x5c\\xae\\x36\\x1f\\x42\\x48\\xb9\\x52\\x2a\\x2d\\x21\\x66\\xd4\\x99\\xac\\x33\\x3e\\x2d\\x56\\x64\\x41\\x0b\\xa3\\x30\\x41\\x89\\x37\\x4a\\x6e\\xa0\\x34\\x19\\x74\\xd3\\x7f\\xa1\\xae\\x98\\x4d\\x54\\x44\\xa9\\xa6\\x90\\x62\\x0e\\x8b\\x41\\x6d\\x42\\xc2\\x5d\\xc5\\x32\\x33\\x66\\x56\\x30\\x2a\\x9a\\x0a\\xe9\\x34\\x32\\xd2\\x4a\\x36\\x09\\x72\\x12\\x9c\\x6b\\xd9\\xcb\\x54\\x82\\x5b\\xf0\\x8d\\x0a\\x02\\x92\\x3f\\x7a\\xe6\\xbb\\x99\\xa5\\xe4\\x9d\\x2b\\x51\\x3b\\xea\\x5f\\x8a\\x8c\\x38\\x0b\\xad\\x87\\xec\\x50\\x41\\x72\\x80\\x07\\x10\\xb1\\x69\\x73\\xe6\\x58\\x40\\x1e\\x67\\xef\\xb1\\x3e\\x40\\xbf\\x8e\\xb5\\x0a\\x29\\xc6\\x82\\xcd\\x11\\xa6\\xc0\\x32\\x34\\x8c\\x70\\xc4\\xf1\\x31\\x9e\\xce\\x87\\xda\\x2b\\x2d\\xab\\x4e\\x1d\\xb6\\x25\\xa7\\xbd\\x29\\x01\\x48\\x84\\xf6\\x44\\x91\\x43\\x21\\x89\\xac\\xcc\\xd3\\xd5\\x08\\xae\\x57\\xe0\\x7c\\x73\\x25\\x00\\x23\\x92\\x8d\\xae\\x6d\\x20\\x01\\x25\\x53\\xa6\\xa9\\x35\\x57\\x9b\\x4b\\xe0\\x11\\xc1\\x01\\xec\\xdb\\xdc\\x3d\\x88\\x90\\xbf\\xde\\x7a\\x00\\x3c\\x48\\xf8\\x9c\\xea\\x08\\x2e\\xb1\\x45\\xa2\\xc7\\xfd\\xfc\\xf8\\xb1\\xe3\\xca\\xba\\xd6\\x22\\x51\\x88\\xf7\\x03\\xd7\\xcf\\xdc\\x68\\xd9\\xe8\\x3d\\x79\\x47\\xee\\x33\\x1f\\x21\\xc0\\x43\\xa0\\x28\\xf2\\x92\\x29\\x22\\x9b\\x44\\x05\\x17\\x5e\\xd8\\xe1\\x52\\x6a\\x79\\x83\\xed\\x69\\x6b\\x53\\x3a\\xe7\\xbd\\xaa\\xc8\\xa5\\x38\\x62\\xf7\\x40\\xd7\\xdb\\x24\\xd4\\x00\\xbd\\x71\\xda\\xcc\\x66\\xac\\x86\\x97\\x0e\\x08\\xde\\x08\\x43\\xf7\\x65\\xa1\\xdc\\x1b\\xd6\\xcf\\x80\\x6b\\x43\\xaa\\x98\\x1e\\x01\\x72\\xbe\\x45\\x52\\xb8\\x67\\x48\\x0b\\x31\\x09\\x65\\xd7\\x6a\\xa6\\x00\\x09\\x5d\\x90\\xf3\\x77\\xdf\\xf7\\x3b\\xa2\\x29\\x70\\xf5\\xe3\\xf2\\x35\\x61\\x9e\\xef\\x44\\xbf\\xb0\\xbf\\xb4\\xe7\\x61\\x1b\\xe4\\x89\\x3d\\x16\\x59\\x21\\x95\\xcd\\x0d\\x86\\x7d\\xc9\\x16\\x54\\x08\\xe6\\x0c\\x52\\x5c\\x83\\x35\\x7b\\xca\\x98\\x20\\xb2\\x62\\x18\\xf6\\xd6\\x8b\\x18\\x4a\\x14\\x17\\xf3\\x82\\x11\\xaa\\x35\\xcd\\x16\\xc7\\x86\\x3a\\xe1\\xce\\x42\\x9b\\x84\\x6b\\x7f\\xa3\\x74\\xcd\\x68\\x89\\x67\\xa2\\x66\\x25\\xe5\\x38\\x3c\\xa1\\x59\\x2d\\x95\\x22\\x65\\x53\\x68\\x5e\\xf9\\xce\\xfa\\x59\\x12\\x19\\xc0\\x21\\x28\\xcc\\xc9\\x74\\x7b\\x05\\x69\\x16\\x6d\\xb6\\xef\\xa8\\xa5\\xd0\\x4e\\x5f\\x8a\\xf5\\x72\\xb1\\x23\\xf3\\x29\\x2b\\x2b\\xbd\\xf2\\x59\\x79\\xfd\\x74\\xa0\\x19\\xaf\\x95\\x26\\x59\\xc1\\x99\\xd0\\x76\\x66\\x08\\xb8\\x07\\x34\\xf8\\x9a\\xdf\\xc2\\xae\\x88\\xb2\\x4b\\x22\\x72\\x50\\xbe\\x2b\\xad\\x30\\xf9\\xcc\\x13\\xe1\\xba\\xca\\xb9\\xb2\\xb6\\x0e\\xd5\\x2f\\xf5\\x8d\\xba\\xba\\x2c\\x78\\x70\\xdc\\x8a\\xc0\\xd1\\x71\\x02\\x0e\\x52\\x64\\x7f\\x15\\x90\\x10\\x56\\xbe\\xf5\\x89\\x83\\x71\\x7c\\x05\\x8a\\xa7\\xb8\\x7b\\x3d\\xea\\x24\\xdc\\xb7\\xba\\x05\\xa4\\x86\\x6c\\x70\\x1d\\x38\\x50\\x82\\x2d\\xcd\\x3d\\x60\\x19\\x33\\xa2\\x28\\x4d\\xc8\\x64\\x1e\\x9d\\xc7\\x04\\xb2\\xdc\\x5b\\xa6\\x14\\x9d\\xb3\\x49\\xcf\\x90\\x84\\x14\\x0c\\xa7\\x35\\xb4\\x41\\x2c\\x43\\x7b\\x6c\\xa0\\xfa\\x6d\\x81\\x30\\x68\\xfe\\x37\\x61\\xd2\\x53\\xa8\\x3c\\x96\\x38\\x91\\x5e\\x14\\x38\\xa5\\xe9\\xb6\\xe6\\x5a\\x33\\x38\\xa5\\x50\\xca\\x08\\x62\\xc5\\xd6\\xa1\\x2b\\xbb\\xc9\\x56\\xbd\\xc6\\xb3\\x8b\\x1e\\x8e\\x67\\xc4\\x0f\\x91\\x63\\xda\\xd2\\x94\\x91\\x69\\xcd\\xd9\\x8c\\xcc\\x38\\xe4\\x51\\x41\\x86\\xd1\\x08\\x31\\xf8\\x29\\x9a\\x90\\x95\\x62\\x35\\x4c\\xdb\\x9a\\x05\\xdc\\xf4\\xfb\\xd1\\xf3\\x0f\\x3b\\x7f\\x5d\\x37\\x22\\xa3\\x41\\xc5\\x47\\x00\\xd6\\xe2\\x33\\x32\\x87\\xac\\x26\\xab\\x04\\xff\\xe9\\xf9\\xdf\\xfe\\x42\\xa6\\x2b\\x23\\xaf\\x81\\x22\\xa6\\xa5\\xa6\\x85\\x23\\x80\\x14\\x4c\\xcc\\xcd\\x2e\\x02\\xcb\\xed\\xc7\\x37\\x3a\\xe0\\x4c\\x7e\\x73\\x0a\\x5e\\x72\\x8d\\x0b\\xf4\\xe2\\x0f\\x37\\xd3\\xa8\\xab\\x07\\xfc\\xf1\\x24\\x67\\xcb\\x93\\xe0\\x08\\x8d\\x0b\\x39\\xef\\xd7\\xeb\\x59\\x8a\\x54\\xda\\x28\\x3b\\xdb\\x96\\x1b\\x0d\\x85\\xee\\x77\\x75\\xa7\\x5d\\xe9\\x0e\\xb2\\x90\\xb7\\x68\\xcc\\xd9\\xbc\\xaa\\x01\\xce\\x49\\x25\\xab\\xa6\\x80\\x85\\x23\\xdf\\x7b\\x74\\xba\\x46\\xb1\\x75\\xdc\\x9f\\x58\\x23\\x61\\xc0\\xed\\xc0\\x91\\x6a\\x87\\x5d\\x2f\\xe3\\x8d\\x29\\x7d\\x8e\\x4c\\x69\\x51\\x17\\xac\\xdf\\xcd\\x57\\xe1\\xe8\\x6d\\x8d\\xfb\\x9e\\x16\\xc5\\x94\\x66\\x37\\xd7\\xf2\\x8d\\x9c\\xab\\x77\\xe2\\xbc\\xae\\x65\\xdd\\x9d\\x73\\x41\\xcd\\x9b\\xbe\\x68\\xc4\\x0d\\x14\\x65\\x6d\\xa1\\x58\\xe5\\xdc\\x86\\xff\\xb9\\xe4\\xf9\\x60\\x76\\xbd\\x88\\x71\\xb3\\x44\\x70\\x4c\\x27\\x92\\x38\\x1b\\x5c\\x3b\\x32\\xbb\\xe3\\xad\\xa1\\x4d\\x10\\x66\\x68\\xee\\x9b\\x7d\\xce\\x3a\\xf3\\x50\\xe1\\xd5\\xfe\\xc3\\xf3\\x3f\\xfd\\x15\\x99\\x0b\\x91\\x35\\xf9\\xeb\\x73\\x48\\xc1\\x55\\x23\\x7c\\x00\\xe0\\x05\\x36\\xa2\\x56\\x49\\x8b\\xa2\\xaf\\x97\\x20\\x64\\x01\\xe6\\xb0\\x7d\\xb5\\x57\\x5e\\xef\\xec\\x76\\x7f\\xb6\\xca\\x78\\x7d\\xfd\\x23\\xe8\\x8b\\x5c\\x2b\\x56\\xcc\\x46\\x08\\x75\\xe2\\xcd\\x5a\\x07\\x20\\x5d\\x1d\\xd8\\x27\\xaf\\x3f\\x4c\\xce\\xee\\x95\\xb6\\xa5\\x2c\\x9a\\x92\\xbd\\x64\\x4b\\x9e\\xf5\\x73\\x60\\x76\\x76\\xa5\\xd3\\x9b\\x33\\xd3\\x17\\x5c\\x01\\x02\\xce\\xb4\\x90\\xd9\\x0d\\xc9\\xed\\x87\\x41\\x54\\xfb\\x7a\\x91\\xe6\\xfe\\xab\\xd0\\x37\\xbe\\x3f\\x22\\xae\\xff\\xde\\xf9\\x77\\x22\\xfa\\x4b\\x5a\\x55\\x1e\\x9e\\xa3\\xa6\\xb7\\x9d\\xc5\\x00\\xd6\\x04\\xd0\\xa0\\x91\\x6e\\xc4\\x68\\x67\\x7a\\xac\\x2b\\x7d\\x6c\\x67\\x64\\x9e\\xa9\\xde\\x5d\\xf4\\x4e\\x03\\x88\\xf7\\xc4\\xb7\\xd4\\xf7\\xf7\\x63\\x76\\x0e\\x44\\xdb\\xa1\\xbb\\x0d\\x15\\xfc\\x1b\\xf1\\x07\\x36\\x60\\xa1\\x3c\\xde\\x8e\\x3f\\x18\\x28\\x41\\x9a\\xe3\\x03\\xaf\\x4c\\x7f\\xf3\\x65\\x02\\x67\\x68\\x5c\\x3a\\x43\\x67\\x5d\\x84\\x77\\x42\\x97\\x54\\x5b\\xfd\\xc8\\x79\\xd9\\x29\\xa9\\x58\\xad\\xb8\\x32\\xa2\\xd3\\x07\\xb8\\x50\\x67\\x05\\xe5\\x65\\xe0\\xbe\\xdb\\xcd\\x22\\xe0\\xe5\\x86\\xda\\xa6\\xf1\\x9c\\xb2\\xe7\\xfb\\x35\\x91\\xb9\\xa5\\x03\\x38\\x28\\x96\\xad\\xfd\\x22\\x9a\\x5e\\x42\\x31\\x61\\xd7\\x5c\\xf9\\x43\\xbb\\x71\\x5d\\xa6\\x6c\\x7e\\xe3\\xb9\\x32\\x7e\\xeb\\x29\\xf1\\x62\\x98\\xdf\\xd7\\xca\\x8a\\x3d\\xf1\\x89\\x38\\x4e\\x54\\x30\\x10\\x30\\x70\\x7b\\x32\\xba\\x1c\\xbb\\x63\\xf3\\xc1\\x9b\\x19\\x68\\x87\\xd6\\x16\\x73\\x8c\\xa8\\xf1\\x11\\x04\\x98\\xab\\x68\\x07\\x25\\x07\\xdf\\x1e\\xec\\xf4\\x19\\xc0\\x9d\\xa9\\x65\\x45\\xe7\\xa0\\xbc\\xed\\xc3\\x06\\xad\\xd3\\x14\\x62\\x94\\x1a\\x45\\x1e\\x3e\\xc7\\x00\\x8c\\xca\\x7e\\x8b\\xe5\\x2d\\xd0\\xf5\\x42\\x46\\xed\\x0e\\x06\\xd7\\xb9\\x13\\x61\\x15\\x50\\xc4\\xb2\\xbb\\xa5\\x2b\\x42\\x6b\\xd9\\x88\\xa8\\xa4\\x5e\\xf0\\x1d\\x78\\xdf\\xd2\\xdb\\xb5\\xc9\\x5e\\x4a\\xc1\\x9c\\x1f\\x3b\\x66\\x94\\xeb\\x16\\xe3\\x9a\\x2b\\x74\\xe9\\x73\\x41\\x5e\\x1c\\xbf\\x78\\xfe\\x54\\xc4\\x0e\\x98\\xe1\\x9a\\xd8\\x71\\xe9\\xc5\\x0e\\x7c\\x01\\x76\\x3a\\x57\\x57\\x23\\x7c\\x1f\\xee\\xd4\\x5b\\x6b\\x48\\x6e\\x8b\\x80\\x73\\x57\\x64\\x16\\x7e\\x75\\x5b\\x73\\x6d\\x8f\\xf9\\x2d\\x57\\x8c\\x1c\\x82\\x0a\\x4b\\x64\\x1d\\x82\\x8c\\x46\\x41\\xd9\\x86\\x06\\x8f\\xc8\\x62\\xe1\\x29\\xa0\\x68\\x55\\x33\\xdd\\xd7\\x07\\xc9\\xbe\\x3c\\xc0\\xd0\\xb6\\x7b\\x1c\\xee\\x7d\\x9b\\x12\\xed\\xcf\\xb3\\x67\\xe4\\x10\\xc7\\x38\\x40\\xc4\\xb7\\x88\\x9d\\x4f\\x70\\x91\\xec\\x5e\\x9d\\xdf\\x55\\x11\\x45\\xc3\\xd2\\xed\\xd7\\xf9\\x5d\\x45\\xc1\\x49\\x52\\xed\\xc5\\xc6\\xfd\\x17\\x5b\\xd0\\x25\\x03\\x80\\x3d\\x5e\\xd0\\xba\\x80\\x88\\xb0\\x2b\\x5c\\x32\\x32\\x6d\\x34\\x61\\x62\\xc9\\x6b\\x29\\x4a\\x26\\x34\\x81\\x24\\xed\\x69\\xc1\\x48\\xcd\\x00\\x86\\x34\\x63\\x8a\\x7c\\x73\\xf8\\xe1\\xf4\\x3d\\x44\\x0c\\x1f\\x59\\x9c\\x56\\x3b\\xbf\\x46\\x41\\x82\\xde\\xda\\x1c\\x82\\xee\\xf6\\xf1\\xbc\\x11\\x37\\x77\\x73\\x5c\\xe0\\x01\\x77\\x6b\\x61\\xe6\\x56\\x36\\xba\\xa1\\x05\\xe0\\x10\\x66\\x45\\xa3\\xf8\\x72\\x57\\x4f\\x84\\x45\\x6a\\x7c\\xc9\\x7b\\x1d\\xe9\\x14\\x87\\xf9\\x2c\\xd8\\xd3\\x0d\\xdc\\xc8\\xde\\x08\\xbc\\x5b\\x70\\x88\\x36\\xc2\\x37\\x0e\\x94\\xc7\\x26\\x0a\\x03\\x45\\xad\\x79\\xbd\\x9f\\xff\\x00\\x80\\x6d\\x31\\x43\\xc9\\x95\\x8c\\xda\\x90\\xef\\x01\\x41\\x7b\\xe7\\x1a\\xf4\\x83\\x0f\\x4c\\x2e\\xd4\\x19\\xcc\\xea\\x61\\x27\\x25\\xee\\x8c\\x5c\\x75\\x80\\x94\\x5e\\x5e\\x5e\\x85\\x48\\xc5\\x68\\xd8\\x91\\x0f\\x5e\\x84\\x49\\xdb\\x45\\x0b\\xe7\\x0d\\xa5\\x3e\\xbc\\x71\\x8c\\xd5\\xf3\\xb6\\x44\\xf0\\x9c\\x09\\x56\\x83\\x74\\xff\\xf2\\xf2\\xea\\x81\\x63\\xb9\\x83\\x80\\x2a\\xc4\\x94\\x2a\\x8c\\x7f\\x79\\x79\\x79\\x85\\x3e\\xc9\\x87\\xd1\\xde\\xdb\\x02\\xd0\\x5f\\x79\\x06\\x1c\\x0d\\xc0\\x4e\\xe8\\xa1\\x77\\xc7\\x33\\x88\\x53\\x6f\\xeb\\x37\\x9b\\x0f\\xf6\\x3c\\xa4\\x86\\x5c\\x4c\\x08\\xcd\\xf3\\x1a\\x42\\x55\\xfa\\x5c\\x83\\x0e\\xb0\\x08\\xad\\x2a\\x1f\\x71\\x00\\xe8\\xd7\\x54\\xb1\\x70\\xea\\xc1\\x19\\x80\\x77\\xb5\\xe7\\xfe\\x61\\x7b\\xd9\\x54\\x05\\xc7\\xd0\\x82\\x70\\x88\\x16\\x1b\\xbc\\x94\\xcb\\x3e\\x57\\x3b\\xc6\\x34\\xd6\\xdb\\x30\\x16\\xf1\\xfc\\xc8\\xbe\\x85\\xb2\\x52\\x1f\\xab\\x9a\\x29\\x59\\x2c\\xdb\\x3a\\x9e\\xd1\\xc7\\xc9\\xf2\\x0f\\xf0\\x0f\\xfb\\xe3\\xe4\\x6a\\x61\\x7d\\xa1\\xa3\\xc4\\x84\\xae\\x39\\xdb\\x3c\\x46\\xe4\\xbd\\x99\\x5d\\x03\\xfc\\xc7\\x93\\xc0\\x97\\x0c\\xe2\\x47\\xdf\\xf5\\x2e\\x5c\\x0a\\xc3\\x04\\x75\\x4b\\x31\\x04\\x12\\xab\\xdc\\x32\\x5a\\xbb\\x67\\x0f\\x66\\x1e\\x31\\xc5\\x9d\\x9c\\xe9\\x35\\x24\\xce\\xfc\\xe5\\xe5\\x15\\x3e\\x7d\\xb8\\x5c\\x16\\xbe\\x50\\x6d\\x3d\\x3b\\xbd\\x5f\\x25\\xb2\\x7b\\xc0\\xf6\\x18\\xb3\\x48\\xb7\\x36\\xb6\\x35\\x34\\xc7\\x65\\x3e\\x44\\x68\\x6b\\x51\\x28\\x4a\\x11\\xa3\\x2b\\x46\\xeb\\x6c\\xd1\\x67\\xfd\\x53\\xf3\\x34\\xa4\\x84\\xe4\\x12\\xa3\\x4a\\x67\\xb2\\x06\\x93\\xe4\\x18\\x9e\\xd0\\x42\\xca\\x9b\\xa6\\xfa\\x32\\xaf\\xa6\\x1d\\xd8\\x68\\xa5\\x5f\\x8c\\xd7\\x75\\xc6\\xf8\\x4d\\xbd\\x9b\\xb9\\x50\\x7d\\x82\\xd9\\x22\\xa5\\x70\\xa6\\x51\\xf6\\x86\\x91\\x5b\\x48\\x86\\x87\\x33\\xb9\\x8e\\xba\\x7d\\x56\\x34\\x4a\\xb3\\xfa\\x7b\\x5e\\x2b\\xfd\\xec\\xa1\\x3d\\x61\\x99\\x55\\xb8\\xe7\\x68\\x84\\x3f\\x08\\xbb\\xfb\\x07\\xd7\\x0b\\x5b\\x8a\\xea\\x60\\xd4\\xfd\\xc8\\xfc\\x6c\\xc9\\x38\\x20\\xb2\\x26\\x07\\x97\\x52\\xb0\\x07\\xbb\\x3f\\xd6\\x54\\x11\\xff\\xa0\\xfa\\xa7\\xe2\\x5e\\x59\\xc0\\x2e\\xa2\\x62\\x05\\x66\\x4e\\xc2\\x07\\xbd\\x2f\\xc6\\xb5\\xad\\x0e\\x66\\xe8\\x71\\x2f\\x90\\x62\\x9a\\x50\\x28\\xab\\x02\\x7d\\x2f\\xda\\x92\\x5c\\x58\\x11\\x00\\x4b\\x99\\x49\\xab\\xfc\\xac\\x82\\xad\\x7d\\xe0\\xe0\\x41\\x49\\x01\\x2d\\xef\\xdf\\x80\\x3e\\x3a\\xce\\x83\\x2f\\x06\\xa4\\x05\\x32\\x0b\\xcb\\xfc\\x86\\x8b\\x9b\\x07\\xde\\xca\\xb8\\x1b\\x72\\xbe\\x31\\x7a\\xa7\\xf8\\x30\\x46\\x88\\x71\\x81\\x99\\x51\\x46\\x84\\xa0\\x53\\xd9\\x68\\x07\\x15\\xad\\x02\\x53\\x1c\\x17\\xff\\x8b\\xe7\\x02\\x5c\\xf0\\x90\\xe5\\xfa\\xd0\\x5d\\xd9\\x62\\x68\\x53\\x23\\x74\\x4f\\x38\\x4b\\x9a\\x5a\\x09\\x4d\\xa1\\x9a\\xdc\\x4b\\x99\\xdd\\xb0\\x9a\\x14\\x86\\xe6\\x87\\x1e\\xbe\\x36\\x58\\xbd\\x53\\x37\\xec\\xc1\\xb1\\x6b\\x7d\\x2d\\xe9\\xac\\x5a\\xb0\\x92\\xd5\\xb4\\xf0\\x46\\xa4\\x47\\xdd\\xf4\\x37\\xf6\\xb9\\xf5\\x64\\x84\\x91\\xda\\x58\\x13\\xc4\\x96\\x82\\x92\\xf9\\x31\\x39\\xdf\\xf6\\xad\\x92\\xae\\x5c\\x69\\x43\\x2e\\x20\\x94\\xf4\\x8e\\x2b\\xfd\\x70\\xb9\\xa3\\x92\\x79\\x08\\x86\\xd4\\x28\\x56\\x8f\\x3d\\x38\\x96\\x05\\x59\\x51\\x3e\\x68\\x3e\\x67\\xd3\\x66\\x3e\\xe7\\x62\\x7e\\x8c\\xef\\x39\\xc8\\x0d\\x41\\x0d\\x5a\\x6f\\x14\\xb9\\x5d\\xb0\\x87\\x7a\\x36\\xb2\\x9a\\x51\\x8d\\x40\\x2e\\x95\\xcc\\x31\\xe3\\x86\\x87\\xbd\\x97\\x32\\xc7\\xce\\xa7\\x2b\\xb4\\x62\\xb9\\x33\\xe9\\xb3\\xa5\\xc9\\x85\\x20\\xb2\\xb6\\x38\\xb5\\x34\\xcf\\xc9\\x83\\xdd\\x2b\\x5b\\x76\\x04\\xfa\\x6a\\xd7\\x17\\x89\\x73\\x11\\xc6\\x98\\x4c\\xee\\xff\\x2a\\xd8\\x20\\xd5\\x4c\\x8d\\x84\\xdf\\xd4\\x0f\\xad\\xe6\\xd6\\x57\\xa8\\xe8\\x25\\x50\\xc4\\x0a\\x8f\\xa7\\xa2\\x3d\\x9e\\x67\\x61\\xba\\x11\\x25\\x9a\\x95\\x95\\xac\\x69\\xbd\\x5a\\x8f\\x29\\x33\\x2f\\x89\\x39\\xbe\\x66\\x83\\xd6\\xd6\\x76\\x22\\x73\\x23\\x24\\x3c\\x98\\x8c\\x2d\\xc7\\x76\\xc9\\x8d\\x3a\\xb3\\xed\\xe4\\x6e\\xbd\\x4f\\xf0\\xb4\\x09\\x49\\xdc\\x9e\\x91\\x1e\\x54\\xa8\\x6c\\xc1\\xf2\\x06\\x52\\xcc\\xe7\\x0d\\xad\\xa9\\xd0\\xcc\\xf0\\x4f\\xeb\\x84\\x5f\\xd9\\x04\\x28\\x3c\\xcc\\x3e\\x1d\\xcb\\x63\\x33\\xac\\x20\\x38\\x1c\\xca\\x97\\x99\\xdf\\x40\\xe5\\xb4\\x3e\\x35\\x86\\xac\\x34\\x6b\\x3a\\x0a\\x72\\xbe\\xae\\x17\\x8c\\xdc\\x34\\x53\\x56\\x30\\x0d\\x8b\\xcf\\x96\\x3c\\xd3\\x6e\\x90\\x19\\x6c\\xc2\\x96\\xa3\\x9f\\xd1\\x06\\xf3\\xb9\\x1e\\x1e\\x79\\x33\\x91\\xb6\\x78\\x50\\xc6\\xcc\\x9b\\xa4\\x55\\xbb\\xb4\\x36\\xb4\\x19\\x0a\\xaf\\x3d\\xbc\\x80\\xc0\\xb5\\xbb\\xda\\xdb\\x28\\x6e\\x6f\\xe6\\x27\\xee\\x24\\x68\\xdb\\xbd\\xb9\\x26\\x4c\\xef\\x23\\x9c\\xd9\\x6f\\xf2\\x96\\xad\\x78\\xe0\\x50\\x11\\x9a\\x7d\\xff\\xa8\\xad\\x5e\\xd1\\x56\\x31\\x46\\x04\\x5a\\xcf\\x77\\x16\\xc7\\x78\\x5a\\xcf\\x9b\\x12\\x52\\x63\\xac\\x36\\xda\\x16\\x4b\\xed\\x9f\\x9a\\x01\\xbe\\x9a\\x03\\x45\\xce\\xde\\xbe\\x0c\\x61\\x1d\\xc2\\x72\\x17\\x0e\\xf4\\xa3\\xdf\\x20\\x1f\\xd2\\x7a\\x42\\xc9\\xc5\\x8c\\x50\\x2f\\xf5\\xf5\\xa2\\xa8\\x7d\\xa9\\xad\\x69\\xcb\\xfa\\xcf\\x3c\\x81\\xce\\xb4\\xc7\\x45\\x65\\x44\\x58\\x10\\xd4\\x03\\xa0\\xed\\x6c\\x41\\xc5\\xdc\\xf0\\xaa\\x97\\xb2\\x31\\x13\\xfb\\xe6\\x1b\\x98\\x44\\xcd\\xf2\\x26\\x63\\xfd\\xe2\\x6c\\xcd\\xf3\\xe2\\x72\\x9f\\xbf\\xb1\\xfe\\x39\\x87\\xe8\\x6f\\x94\\x51\\xa6\\x32\\x5a\\xb9\\xa5\\x09\\x57\\x0f\\xc5\\xdc\\x6f\\x09\\x3f\\x66\\xc7\\xe4\\xd9\\x37\\xc1\\x47\\xcf\\x80\\xe2\\xbe\\x81\\x88\\x66\\x2a\\x36\\xd5\\x1a\\x66\\x5f\\x70\\x0d\\xfc\\xe3\\x59\\x38\\xc2\\x31\\x39\\x37\\x74\\x41\\xb8\\x8b\\xdf\\xdb\\x20\\x7b\\x76\\xda\\xee\\xec\\x88\\xd4\\x6c\\x4e\\xeb\\xbc\\x60\\x3d\\xd3\\x04\\xe5\\xcc\\x6b\\x19\\x08\\x47\\x63\\x4f\\x15\\x30\\x46\\xc8\\x1e\\x12\\x52\\x1f\\xa7\\xf1\\x1f\\x7e\\x2e\\x6e\\x85\\xa6\\xea\\x46\\x9d\\xa0\\x3e\\x33\\xce\\xa9\\xa6\\x63\\x5a\\xa1\\x05\\x87\\x4b\\x71\\x82\\x36\\xd4\\xb1\\x2d\\xcd\\x37\\xa6\\xf6\\xf6\\x8e\\xfd\\xc9\\x3e\\xf9\\x9d\\x05\\x59\\x1a\\x53\\xff\\x2d\\x2e\\xc6\\x74\\x0c\\xc5\\xea\\x7a\\x5b\\x5c\\x76\\x10\\x39\\x1c\\x65\\xcd\\x8c\\xa8\\x0d\\x99\\x82\\xab\\x9e\\xb7\\x15\\xa7\\x61\\xe5\\x8e\\xc9\\xa5\\xd4\\x6d\\x0d\\x5d\\x1f\\xda\\x1c\\x51\\x41\\x30\\xe4\\xb3\\xe7\\x97\\xd7\\xef\\x7f\\x9c\\xbc\\xbb\\xb8\\xbc\\x1e\\xd8\\xed\\xc0\\x6e\\xa1\\x0d\\xec\\x76\\x60\\xb7\\x3d\\x06\\xee\\xc9\\x6e\\x99\\x58\\xee\\x8a\\xd5\\x7a\\x73\\xd2\\x36\\xfb\\xdd\\x5a\\x71\\xa3\\xc8\\x4c\\x92\\x27\\x94\\x89\\x73\\x2e\\x96\\x1f\\xa8\\x51\\xcc\\xaa\\x9a\\x29\\x10\\xff\\x8d\\x3e\\xb8\\x2d\\xd6\\xd0\\x7e\\x01\\x0c\\x6d\\x6d\\xd8\\xd9\\x57\\x9b\\x8a\\xb3\\xc3\\x44\\x9a\\x84\\xe1\\xf3\\x97\\x01\\x0e\\xee\\xb6\\x5d\\x6b\\xa1\\xb7\\x29\\x39\\xfb\\xe5\\xe2\\xe5\\xf9\\xe5\\xf5\\xc5\\xf7\\x17\\xe7\\xef\\x77\\x1a\\x09\\x1c\\x59\\xa3\\x27\\x5d\\x0c\\xf0\\x43\\xc4\\x99\\x88\\x61\\x5a\\x41\\xa8\\xaa\\xd9\\x92\\xcb\\x46\\x15\\x2b\\x5f\\xc3\\x71\\x3b\\xbb\\xda\\xcc\\x6a\\x12\\x31\\x14\\x50\\xb1\\xf2\\x75\\x35\\xb7\\x0e\\xb8\\x26\\x8a\\x6d\\x13\\xab\\x22\\x86\\xdf\\xb1\\x40\\x66\\x89\\x48\\x21\\x96\\x45\\x8c\\xbf\\x45\\xa0\\xfb\\x7c\\xe1\\x2c\\x62\\xdc\\x5e\\x62\\xdd\\x7d\\x22\\x5a\\x04\\x1d\\x5d\\xe1\\x2e\\xa2\\xa3\\x6e\\xcc\\xf9\\xee\\x39\\xd9\\xf7\\xb5\\x2c\\x13\\x71\\xb3\\x2b\\xb4\\xca\\xba\\x08\\x81\\x6d\\x57\\xf5\\xc0\\xa2\\xf9\\x76\\xc4\\x63\\xab\\xe8\\xb5\\x30\\xbf\\x46\\xc9\\x2c\\x2b\\x1d\\x51\\x11\\x3e\\x49\\x35\\xc2\\x34\\x85\\xfb\\x30\\x08\\xf8\\x2d\\xad\\xfe\\xce\\x56\\xef\\x59\\x24\\xa0\\x79\\x77\\xbd\\x21\\x8a\\x40\\x11\\x4a\\x6e\\xd8\\x0a\\x43\\xcf\\xce\\xdc\\x60\\x71\\x98\\xee\\x7b\\x58\\xcc\\xf1\\x86\\xc5\\x14\\xda\\x4c\\x59\\x85\\xf1\\x86\\x45\\xa4\\xd3\\xb9\\xb6\\x51\\xa2\\xcf\\x6c\\x21\\x88\\xf9\\x66\\x4f\\xf7\\xaa\\x28\\xe1\\xbe\\x56\\x9d\\x0c\\xa5\\x47\\xfb\\x3c\\x24\\x58\\xb8\\x07\\x03\\xf3\\xca\\xa5\\x11\\x4d\\xd8\\xed\\x89\\x4d\\x60\\x19\\xdf\\x72\\xbd\\x18\\xe3\\xdd\\x51\\x27\\x10\\xe3\\x7d\\xf2\\x3b\\xf8\\xbf\\x04\\xb4\\x5d\\xbf\\x7b\\xf9\\xee\\x5b\\x72\\x9a\\xe7\\x36\\x1d\\xb8\\x51\\x6c\\xd6\\x14\\x98\\x64\\xab\\x8e\\x09\\xad\\xf8\\x07\\x56\\x2b\\x2e\\xc5\\x88\\xdc\\x70\\x91\\x8f\\x48\\xc3\\xf3\\xef\\xf6\\xe9\\x30\\x49\\x17\\x35\\x92\\xf6\\x40\\x5d\\xd9\\x68\\xa6\\xf0\\xd5\\xf7\\xbc\\x90\\x20\\xee\\x12\\x5c\\x31\\x87\\xa6\\x6e\\x05\\xd8\\x44\\x4b\\x13\\x97\\x07\\x8a\\xad\\x53\\x16\\xa2\\xa4\\xd5\\xd8\\xaa\\xd8\\x5a\\x96\\x3c\\x8b\\xe8\\x19\\xce\\x46\\xda\\x87\\x27\\xfa\\xfa\\xb6\\x2f\\x17\\xa6\\x87\\xfb\\x5a\\x28\\xf9\\xb7\\x44\\x35\\x00\\x2c\\xaf\\x48\\xc9\\x34\\xcd\\xa9\\xa6\\xc7\\xe6\\xf2\\x8c\\xba\\x3f\\xaa\\x8a\\x66\\x6c\\x44\\xfe\\xc7\\xff\\xb2\\xa0\\x53\\x56\\xa8\\x9f\\x0e\\xfe\\xf3\\xef\\xe7\\x3f\\xfe\\x7f\\x07\\x3f\\xff\\x4f\\xf8\\x19\\x48\\x1a\\x60\\x09\\x0b\\xbf\\x10\\x39\\x05\\x08\\x56\\x11\\x32\\x67\\x97\\x40\\x1d\\xfc\\x68\\x95\\x94\\xd3\\x2c\\x93\\x8d\\xd0\\xf6\\x03\\x80\\xd0\\x3b\\x5e\\x48\\xa5\\x2f\\x26\\xfe\\xc7\\x4a\\xe6\\xeb\\x3f\\x45\\x95\\xa3\\xde\\xcb\\x27\\x1b\\xf6\\x36\\x02\\x2f\\x04\\x5b\\xba\\x87\\xbb\\xe5\\x8e\\x89\\xb9\\x8f\\xed\\xd5\\x1d\\x63\\xa8\\x7c\\x49\\xe1\\x9f\\xdf\\xbb\\x25\\x30\\x72\\xad\\x07\\x39\\x15\\x80\\x55\\x68\\xd4\\x94\\x6e\\xe5\\xa4\\x67\\xcb\\x17\\x51\\xca\\x12\\xb6\\x84\\xdc\\xda\\xef\\x60\\xe2\\x05\\x83\\x15\\xb1\\xab\\x85\\x1c\\xc0\\x8b\\x3e\\x4e\\xc1\\x6e\\xe3\\xd0\\x4e\\x27\\x17\\x64\\x89\\x2b\\xbc\\x47\\x8b\\xf3\\xa5\\xd8\\xb5\\x0b\\x6e\\xf9\\x7e\\xaf\\xd9\\x76\\x18\\x82\\xd3\\x31\\xf5\\x7c\\x4b\\x00\\xd9\\xc1\\x7d\\x6e\\x11\\x2d\\x95\\xaf\\xe2\\xc1\\x94\\x8e\\x95\\x83\\x0e\\xb1\\xcb\\xe3\\xac\\x6a\\x46\\xb6\\xfb\\xe3\\x92\\x95\\xb2\\x5e\\xf9\\x1f\\x7d\\xe0\\xd0\\x58\\x69\\x59\\xd3\\x39\\x40\\x4c\\xe0\\xe0\\xf8\\x67\\xfe\\x27\\xfc\\xc3\\x0e\\x79\\x9b\\x7f\\x8d\\xb6\\xb4\\xac\\xa9\\x8d\\x88\\x59\\xac\\xdc\\x13\\x15\\x97\\x33\\xbf\\x97\\x2c\\xdb\\xed\\xdb\\x9e\\x70\\x6c\\x7f\\xac\\x2e\\xd3\\xeb\\x20\\x07\\x6d\\xac\\x23\\x68\\x38\\x7e\\x15\\xc1\\x80\\x61\\x41\\xd1\\x46\\x5e\\x60\\x45\\x2b\\x9b\\x58\\x92\\x25\\xad\\x55\\x4c\\x5d\\x3b\\x6c\\x09\\x99\\x74\\xce\\x97\\x5c\\xc9\\x08\\x58\\x0a\\xdf\\xd1\\xa6\\x44\\xed\\x92\\xaf\\x2d\\x42\\x2d\\x86\\xb0\\x7b\\x93\\xfd\\x5d\\x05\\x68\\xf5\\xfe\\xb2\\xaf\\xbd\\x66\\x2f\\x9e\\x45\\x93\\x54\\x51\\xad\\x59\\x2d\\xbe\\x25\\xff\\x7d\\xf8\\xcf\\xdf\\xff\\x3a\\x3e\\xfa\\xee\\xf0\\xf0\\xa7\\xe7\\xe3\\xbf\\xfd\\xfc\\xfb\\xc3\\x7f\\x1e\\xc3\\x3f\\xfe\\xe3\\xe8\\xbb\\xa3\\x5f\\xdd\\x0f\\xbf\\x3f\\x3a\\x3a\\x3c\\xfc\\xe9\\xef\\x6f\\x5f\\x5d\\x4f\\xce\\x7f\\xe6\\x47\\xbf\\xfe\\x24\\x9a\\xf2\\x06\\x7f\\xfa\\xf5\\xf0\\x27\\x76\\xfe\\xf3\\x67\\x76\\x72\\x74\\xf4\\xdd\\x37\\xd1\\xa4\\x27\\x28\\x5f\\x87\\x2d\\x65\\x11\\xbb\\x6e\\x8f\\x49\\x8e\\xdf\\x17\\x2c\\x21\\x8e\\xcd\\x1d\\xaf\\xd4\\xf7\\xdf\\xe5\\x29\\x7e\\xdb\\xbe\\x66\\x5e\\x0a\\xd9\\xa3\\x0b\\xfe\\xa5\\x04\\x0d\\xc5\\xb2\\x9a\\xe9\\xc7\\x30\\x4a\\xe2\\x48\\x01\\xde\\xe6\\x81\\x22\\x5e\\x89\\x7b\\x6a\\x2f\\xe8\\x6f\\xc1\\x4e\\xe9\\xf4\\x1c\\xdc\\xd7\\x56\\x74\\x9f\\xd5\\xb2\\xb4\\xd8\\x84\\xe8\\xb4\\x5d\\x42\\x9e\\x9e\\xfd\\xde\\x0d\\x8b\\x30\\xe8\\xbb\\x36\\xd8\\x35\\x7b\\xb7\\xc1\\xae\\xb9\\xde\\xbe\\x4e\\xbb\\xe6\\x15\\x5e\\xa7\\xdf\\xa0\\x51\\x93\\x89\\x65\\x5f\\x77\\x65\\xca\\x18\\x2d\\xa7\\xda\\x86\\x75\\x33\\x3e\\x2f\\x10\\xa2\\x7f\\x8c\\xec\\x0d\\x5b\\x29\\x1f\\x75\\xd1\\x06\\xde\\xa2\\xd8\\x52\\x6e\\x8f\\x92\\x21\\xa7\\x45\\x41\\xb8\\x40\\x26\\x6c\\x3a\\xe8\\x35\\x7a\\x9b\\x61\\x8f\\x3a\\xaf\\x2d\\xbc\\xc3\\x96\\x66\\xaa\\xbe\\x28\\x6d\\xa7\\x4e\\x15\\xa4\\xc9\\x40\\x9e\\xd6\\x3f\\x30\\x0d\\xea\\x06\\x33\\xa3\\x94\\x86\\x25\\x71\\xd5\\xc7\\x7a\\x91\\xe3\\x55\\x8d\\xb6\\xf2\\x2a\\x55\\x4a\\x66\\x98\\x35\\xe6\\x13\\xad\\xa1\\x6c\\x88\\x5d\\x1e\\x98\\x81\\xa6\\x37\\x10\\xc1\\x92\\xb1\\x9c\\x89\\x87\\xe6\\xf3\\xb9\\xf6\\x01\\x33\\xce\\xdd\\x3e\\x4c\\x57\\x50\\xfd\\x4a\\x2c\\x5d\\xd5\\xdd\\xdc\\xa1\\x14\\xc0\\x8c\\xd3\\x8d\\xfb\\xb4\\x42\\xf6\\xcc\\x1d\\xb6\\xb1\\x02\\x41\\xe4\\x1e\\x48\\x14\\x6d\\x5e\\x17\\x04\\x3c\\xca\\x59\\xeb\\xc5\\xe9\\x77\\x7a\\xa3\\x25\\xc4\\x78\\x79\\xcc\\x07\\x00\\x44\\x09\\xda\\x1b\\x82\\x58\\xeb\\xde\\xea\\x0a\\x60\\x4f\\x21\\x66\\x22\\x5e\\x34\\x4b\\x2b\\x96\\x7d\\x09\\x91\\x6c\\x5f\\xc5\\xb1\\xc7\\x17\\xc5\\x12\\x89\\x61\\x69\\x44\\xb0\\x07\\xb8\\x95\\x53\\x8a\\x5d\\x69\\x44\\xae\\x2f\\x61\\x2b\\xa8\\x6a\\x36\\xe3\\x77\\x89\\x18\\xd7\\xa9\\x68\\x0d\\xaa\\x3c\\x67\\x42\\xf3\\x19\\xc7\\xf4\\xfc\\xaa\\x66\\x15\\x13\\x98\\x6f\\x4c\\xb3\\x05\\x3c\\xa0\\x56\\x7c\\x6a\\x83\\x9a\\xf6\\x31\\x1e\\x18\\xb5\\xdb\\xb4\\xbc\\xfd\\x6a\\x9b\\x66\\x3d\\x30\\x76\\x32\\x30\\xf6\\x88\\x36\\x30\\xf6\\xcf\\xd2\\xab\\x9f\\x3a\\x57\\x87\\x6c\\xcb\\x9d\\x03\\x3e\\x23\\x19\\xc0\\x0f\\xbe\\x64\\x5e\\x9c\\xbf\\x65\\x2d\\xb8\\xc3\\x09\\x8c\\xdc\\xe7\\x32\\x45\\x1d\\x67\\x18\\x75\\xd2\\x14\\xc5\\x8e\\xcb\\x91\\xc2\\xb2\\x57\\x4d\\x51\\x58\\xd4\\xaf\\x7e\\xab\\xff\\x4e\\x00\\xdb\\x3c\\x85\\x72\\xf3\\x23\\x72\\xc9\\x96\\xac\\x1e\\x91\\x8b\\xd9\\xa5\\xd4\\x13\\x54\\xe8\\xe2\\x4b\\x52\\x62\\xe7\\x84\\xcf\\xc8\\xb7\\x05\\xd5\\x4c\\x69\\xa2\\xb1\\x6e\\x75\\x80\\xed\\x2d\\xeb\\xce\\xa0\\x6d\\xf5\\x88\\x1d\\xea\\xd9\\xf1\\x67\\xf3\\x77\\x0e\\x1a\\x69\\xbc\\x9b\\xb3\\x5a\\xf0\\x19\\xcb\\x56\\x59\\x11\\xcf\\x26\\xde\\xb8\\x9e\\x5c\\x5c\\x3f\\xa4\\xac\\x58\\x1f\\xfb\\x36\\xe8\\xac\\xaf\\x10\\x38\\xb5\\x92\\x4a\\x5f\\x69\\x5a\\xeb\\x24\\xe8\\xa9\\x11\\x22\\xcd\\xc4\\x11\\x02\\xc5\\xe5\\x69\\x51\\xb0\\x9c\\xf0\\xb2\\x64\\x39\\xa7\\x9a\\x15\\x2b\\x42\\x67\\x9a\\xd5\\x9d\\x72\\xef\\xe6\\x7b\\x50\\xd0\\xda\\x55\\x94\\x67\\x64\\x41\\x45\\x5e\\xb0\\x1a\\xea\\xfa\\xf6\\x2c\\x77\\x4f\\x6c\\xd2\\x54\\x67\\x1c\\x57\\x9d\\xd7\\x17\\xbc\\x77\\xd8\\x49\\x34\\xcb\\x64\\x9d\\x43\\xea\\x92\\x74\\x18\\x43\\x30\\x89\\x18\\xfe\\x64\\xda\\x3b\\x78\\xd9\\x4b\\x2a\\xe8\\x9c\\x81\\x5d\\x76\\xa3\\x3c\\x22\\x14\\xcd\\x54\\x41\\xb5\\xfd\\x85\\x94\\x37\\x24\\x93\\x65\\x55\\xc0\\x4d\\xed\\x3d\\x74\\x7f\\x06\\xe0\\xff\\x39\\xf6\\x97\\x70\\x6c\\xa8\\x52\\x27\\xbf\\x6b\\x3f\\x82\\x5f\\xf4\\x24\\x2e\\x81\\x32\\x90\\x42\\x15\\x60\\x77\\x2c\\x8b\\x91\\xe7\\xba\\x36\\xc5\\x3b\\x96\\xf9\\x57\\x01\\x2d\\x89\\x88\\x7a\\x07\\x68\\x40\\xf4\\x26\\x2a\\xf3\\x2d\\x91\\x8f\\x39\\x95\\x5f\\x37\\x02\\x12\\x24\\x6c\\xa9\\xdd\\x96\\x67\\x48\\x96\\xab\\x4a\\x6a\\xa9\\x84\\x9a\\xd5\\x08\\x21\\x06\\x98\\x21\\xae\\x50\\x69\\xe7\\x1a\\xa2\\x29\\x7f\\xa3\\xfc\\x87\\xcb\\x23\\x8b\\x26\\xcd\\xd1\\x62\\x68\\xab\\xa5\\xd4\\xe4\\xf0\\xe0\\xe4\\xe0\\x68\\xc3\\x37\\xd3\\xad\\x71\\x09\\x6a\\x78\\xd6\\x4e\\x4a\\xf1\\xb2\\x82\\x92\\x2d\\x2c\\x3b\\xc8\\x47\\x84\\xeb\\x3e\\xb0\\x6e\\xeb\\xcd\\x3c\\x88\\x88\\xfe\\x08\\xab\\x62\\x81\\x54\\x46\\x44\\x49\\xa2\\x6b\\x9a\\x73\\x6b\\x28\\x81\\xdf\\x9a\\x2f\\xe9\\xba\\xb1\\x60\\x8e\\x87\\x07\\xbf\\x1e\\x8c\\x08\\xd3\\xd9\\x11\\xb9\\x95\\xe2\\x40\\xc3\\xf2\\x1d\\x93\\x6b\\x69\\xb4\\xba\\xf8\\xd0\\x25\\x47\\xc8\\x4a\\x36\\x44\\x30\\x66\\x51\\xe0\\x3c\\xde\\xab\\x79\\x5b\\x88\\x6c\\x34\\x82\\x6d\\x51\\x1d\\x03\\x00\\x13\\xb6\\xf3\\x3b\\xae\\x5d\\xcd\\x79\\x39\\x23\\xcf\\xe1\\x34\\xe1\\xfb\\x44\\xa8\\x22\\x05\\x5f\\xb2\\x93\\x05\\xa3\\x85\\x5e\\x60\\xc4\\xa6\\x90\\x62\\xfc\\x2f\\x56\\x4b\\x80\\x8b\\x11\\xf6\\x93\\x58\\x32\\xe2\\xdc\\x24\\x61\\x8b\\x70\\x99\\x6c\\x12\\x14\\xa9\\x45\\x9b\\x67\\xe8\\x15\\xeb\\x2d\\xa2\\x90\\x75\\x96\\xf1\\xfa\\xfa\\x7a\\xf2\\x8a\\xe9\\x35\\xae\\x6b\\x46\\x71\\x71\\xb4\\x01\\x24\\xe9\\x1e\\xb0\\xdf\\x34\\x01\\x3e\\x63\\x52\\xc9\\x7a\\x1f\\x5e\\x81\\x85\\x54\\x51\\x7b\\x49\\xbe\\xc0\\x13\\xf0\\x5a\\x2a\\x8d\\x45\\x5a\\xb0\\x7e\\xa5\\x60\\x99\\x39\\x04\\xdd\\xa0\\x50\\x87\\xf5\\x7a\\x31\\x39\\x26\\x3f\\xca\\xc6\\x2c\\xc8\\x94\\x4e\\x8b\\x15\\xb9\\xa5\\xc2\\x1a\\x3c\\xe3\\x22\\xb9\\x4c\\x7b\\x66\\x48\\x79\\x66\\x38\\xbc\\x39\\x90\\xaf\\x19\\xcd\\x59\\xad\\x80\\x81\\x32\\x1a\\x19\\xb3\\x9d\\x30\\x68\\x24\\xa0\\x2d\\xe9\\x56\\x9e\\x35\\x4a\\xcb\\x92\\x2c\\xec\\xb4\\xbb\\xd8\\x31\\xf6\\x72\\x1e\\xc3\\x05\\x76\\x00\\x02\\x35\\xab\\x90\\xc9\\xda\\xbf\\x79\\x72\\x2c\\x74\\x83\\x75\\xe1\\xba\\x77\\xaa\\x37\\x67\\xe1\\xb2\\x99\\x55\\xf3\\xa9\\xe9\\x02\\x17\\xcb\\x1c\\xd5\\x04\\xc1\\x4e\\xc9\\x62\\x16\\x49\\xc2\\xb8\\x45\\x12\\x87\\x2a\\xb3\\xde\\x11\\xc4\\x65\\x44\\xf7\\x94\\x2e\\x14\\x92\\x24\\x0b\\xf7\\x23\\x5f\\x24\\xe4\\x8f\\xd8\\x28\\x1f\\x7b\\xf8\\x30\\x25\\xaa\\xbf\\x6d\\x74\\x5b\\xe7\\x41\\xe5\\x8e\\x8c\\x0a\\x29\\x78\\x46\\x0b\\xfe\\x2f\\x96\\x93\\xa6\\x92\\xc2\\xc6\\xf7\\x83\\xe4\\x99\\x51\\xc5\\xc6\\x10\\xc2\\x24\\x90\\x9d\\xab\\x00\\xdf\\xc4\\x70\\x07\\x2d\\x25\\x88\\x63\\x10\\xb0\\x61\\xd8\\x3d\\x52\\x9d\\x86\\xd4\\xa4\\x81\\xe9\\xd1\\x60\\x3d\\x61\\xdb\\x70\\xd2\\x75\\x36\\x2b\\xcd\\x89\\x27\\x29\\x57\\xa0\\x4a\\x90\\xb7\\xb7\\x99\\xb5\\xa7\\x25\\xa1\\x59\\x06\\x20\\x2b\\xf8\\xa2\\x00\\x6f\\xc4\\x32\\x66\\x7b\\xf3\\xb4\\x1a\\x29\\x6d\\xdf\\xc4\\x23\\x74\\x35\\xd6\\x44\\x34\\xe5\\x94\\xd5\\x6d\\xca\\x73\\xad\\x37\\xd7\\x34\\x32\\x60\\xb0\\x33\\x2c\\x0e\\xe7\\xbc\\x5a\\x4e\\x0c\\xa0\\x62\\xce\\xc8\\x0b\\x33\\xf2\\x5f\\xfe\\xfc\\xe7\\x3f\\xfe\\x39\\xc1\\x38\\x66\\x7a\\x3e\\x10\\x51\\x90\\x8b\\xd3\\xcb\\xd3\\x5f\\xae\\x3e\\x9c\\x01\\x06\\x50\\x6c\\xf7\\x89\\x72\\x69\\x52\\x67\\xd2\\x24\\xcd\\xa3\\xf9\\xa2\\x59\\x34\\x90\\x92\\x1c\\xcd\\x08\\x53\\x5f\\x89\\x2b\\xa0\\xca\\x1c\\xc2\\x46\\x21\\x6e\\x90\\x55\\x1b\\xac\\x35\\xd8\\x95\\xd2\\x8f\\x3f\\x9d\\xa1\\x5f\\xc9\\x30\\xac\\xbd\\xe0\\x54\\xaa\\x60\\xac\\x4a\\xa6\\x91\\x5f\\x99\\xde\\xd6\\x03\\x2a\\x73\\x57\\x7c\\x14\\xcc\\x34\\x5d\\xeb\\xb7\\x2d\\x3b\\x03\\x54\\x90\\x29\\x9b\\xc9\\x9a\\x91\\x29\\x83\\xa5\\xf7\\xb6\\xfa\\x27\\xa4\\xb9\\x2b\\x96\\x49\\x91\\xc7\\xc8\\xef\\xa9\\xe4\\x51\\x4b\\x49\\xd2\\xdb\\x78\\x85\\x7d\\x3a\\xfb\\x6b\\xfb\\xc8\\xd8\\xc1\\x40\\x0d\\x34\\x3b\\x9d\\xe6\\xe4\\xa7\\xe1\\xa0\\x98\\x4e\\x0a\\xbd\\xfd\\xe5\\x4f\\xfd\\x5d\\x4d\\x59\\x75\\x25\\xb3\\x9b\\x84\\xc6\\xad\\x48\\xd6\\xf6\\xd2\\xdc\\xc1\\x0c\\xbd\\x6a\\xd7\\x67\\x13\\x24\\xce\\xec\\xcc\\xe5\\xbb\\xeb\\x36\\x77\\x1c\\xe2\\xe8\\x5b\\x07\\xe9\\x6b\\xeb\\x77\\xa3\\x22\\x27\\x37\\xac\\x8a\\x53\\x0d\\x1d\\x04\\xdb\\x94\\x66\\x37\\xb7\\xb4\\xce\\xc1\\xa7\\x45\\x35\\x9f\\xf2\\x82\\xeb\\x15\\x18\\xb7\\x6b\\x06\\x49\\xed\\x42\\x62\\x92\\x16\\x72\\x09\\x69\\xe1\\xb6\\x51\\xa6\\x8d\\x43\\x6d\\x0c\\xdc\\xc8\\xe0\\x57\\xb3\\x6a\\xc4\\x8c\\xf2\\xc2\\x48\\x21\\xb6\\x0e\\xb7\\xcd\\x20\\xc8\\x2a\\xef\\x78\\x0c\\x1d\\xfc\\x4f\\x88\\xfd\\x3c\\x55\\xc3\\xe1\\x41\\x5b\\x07\\xec\\xa1\\x06\\xc0\\xd8\\x24\\xdb\\xa7\\xad\\x2e\\x58\\x0e\\x8e\\xe8\\x04\\x83\\xba\\xf0\\x90\\x36\\xa8\\x0b\\x3d\\xd5\\x85\\xaa\\x66\\x57\\x5a\\xf6\\x96\\x49\\x93\\x05\\xb2\\x20\\x19\\xf7\\x84\\xb1\\x58\\x51\\x95\\xde\\x1b\\x5f\\x92\\x37\\x0c\\x8b\\x92\\xf5\\x26\\xe0\\x74\\x72\\xe1\\xdd\\x58\\xb2\\x13\\x43\\x82\\x69\\x6f\\xae\\x22\\x59\\xc1\\x97\\x4c\\x30\\xa5\\x4e\\x20\\x62\\xa5\\xa9\\xd0\\x46\\x0c\\x6f\\x5c\\x53\\xb3\\xfe\\xd1\\x33\\x55\\xcd\\x58\\x09\\xeb\\x38\\x6a\\xc1\\x09\\xcc\\x74\\x99\\xc0\\x5f\\x32\\x9d\\xa1\\x8b\\x3a\\x78\\x35\\x85\\xd4\\x7e\\xb9\\x66\\x51\\x9e\\xf3\\xa0\\x78\\x58\\x4d\\xd5\\x82\\x01\\xee\\x2d\\xbb\\xe3\\x5a\\xe1\\xa0\\x13\\x48\\xe1\\x77\\x2b\\x6e\\x04\\x87\\x79\\x4d\\x33\\x46\\x2a\\x56\\x73\\x69\\x84\\x8d\\x46\\xe8\\x5c\\xde\\x0a\\x32\\x65\\x73\\x2e\\x94\\xdb\\xb1\\x18\\x92\\xdc\\x91\\x80\\x08\\x1d\\xae\\x7c\\x11\\x92\\x63\\xf2\\xbe\\x03\\xfb\\x6b\\xc1\\x4a\\x32\\xd9\\xf2\\x4c\\xbb\\x44\\xa3\\x44\\x4b\\x02\\x52\\x0c\\x1c\\x83\\x86\\x16\\xc5\\xaa\\x3d\\x78\\x2e\\x2d\\x53\\xdf\\xbf\\x42\\xfd\\x0f\\x04\\xae\\xec\\x61\\x23\\x60\\xa2\\x39\\x2b\\xe8\\x0a\\x13\\x10\\x67\\x5c\\x80\\x21\\xb7\\x56\\x47\\xc7\\xf1\\x21\\x4f\\xbd\\x09\\x94\\x75\\xd0\\xe7\\xbd\\x27\\x83\\x2b\\x52\\x33\\x9a\\x2d\\x62\\x24\\xbb\\x21\\xb6\\xea\\x53\\x6d\\x88\\xad\\xea\\xd9\\x86\\xd8\\xaa\\x87\\xb6\\x21\\xb6\\xea\\xa1\\x6d\\x88\\xad\\xda\\xa7\\xc0\\x80\\x21\\xb6\\x6a\\x30\\x91\\xac\\xb7\\x21\\xb6\\xea\\x63\\x6d\\x88\\xad\\x1a\\x62\\xab\\x3a\\x6d\\x88\\xad\\xfa\\x8c\\x36\\xc4\\x56\\x7d\\x66\\x1b\\x62\\xab\\x86\\xd8\\xaa\\x21\\xb6\\x6a\\x88\\xad\\x7a\\x58\\x1b\\x62\\xab\\xfa\\xb7\\xc1\\x59\\x32\\xc4\\x56\\x45\\xb5\\x21\\xb6\\x6a\\x88\\xad\\x1a\\x62\\xab\\x86\\xd8\\xaa\\x7b\\xdb\\x10\\x5b\\x35\\xc4\\x56\\x6d\\x6d\\x83\\xe1\\x70\\xa3\\x0d\\xb1\\x55\\x5b\\xda\\x10\\x5b\\xf5\\xb0\\x71\\x06\\x75\\x21\\xae\\xb3\\xe4\\xea\\x82\\x8b\\x13\\x9a\\xd4\\x72\\x1a\\x0f\\xaa\\x04\\xbd\\x28\\xfb\\xc4\\x3c\\x49\\x48\\xa5\\x98\\x08\\x86\\xc7\\x89\\x5e\\xd8\\x93\\x50\\x8f\\x04\\x11\\x0b\\x29\\x99\\xeb\\x9e\\x46\\x2a\\xec\\x67\\x94\\xc2\\x3e\\x46\\x28\\xec\\x22\\x3a\\x61\\xe7\\x91\\x09\\x69\\x5c\\x6a\\x09\\xdc\\x69\\xd1\\x4f\\x98\\x0d\\x3c\\xbd\\x5e\\xd4\\x4c\\x2d\\x64\\xd1\\x9b\\x2f\\xa4\\xe2\\x09\\x6f\\xb9\\xe0\\x65\\x53\\x9a\\x2b\\xa6\\xcc\\xd5\\xe7\\x4b\\x1f\\x1c\\xab\\xbc\\x22\\x85\\x31\\xb3\\xe8\\x14\\x34\\x5f\\xe4\\x39\\x83\\x2a\\x7c\\x94\\x17\\xe6\\x04\\x00\\x68\\xdd\\x82\\x2e\\x0d\\x5b\\x50\\x4d\\x96\\x31\\x96\\xc7\\x28\\x2f\\xa1\\xb5\\xea\\x8f\\xc7\\x9e\\x42\\xac\\x24\\xc1\\x15\\x79\\x11\\xf7\\x22\\xc4\\xc9\\x33\\x81\\xd2\\xfe\\xc7\\x3f\\xf4\\xea\\x63\\x5e\\x57\\x69\\x5e\\xce\\x57\\xef\\x27\\x67\\xc1\\xcb\\x49\\x85\\x7b\\x38\\xb9\\x58\\xca\\x02\\x76\\x83\\xe2\\x97\\x8c\\xdc\\xbc\\xc3\\x67\\x34\\x5e\\x89\\x8c\\x52\\x20\\x53\\xbc\\xe2\\xb1\\x3a\\x52\\x57\\x3a\\x34\\x6a\\x4c\\xd7\\x11\\x32\\x87\\xbd\\xc4\\xe2\\xd4\\xc7\\x8f\\xa0\\x86\\xa4\\x12\\xed\\xe3\\xaf\\x03\\x01\\x93\\x20\\x4c\\x7c\\x5f\\x64\\xa4\\x2b\\x24\\xc7\\x5b\\x13\\x03\\x0d\\xd4\\x52\\x0a\\xd1\\x5d\\x05\\xcd\\xfc\\xde\\xc0\\xfe\\xbd\\x86\\x87\\xee\\x6c\\xc1\\xb2\\x9b\\xf7\\x18\\x68\\x12\\x45\\xc6\\xa1\\x62\\xcc\\x07\\x50\\xcf\\xb9\\x5e\\x34\\xd3\\xe3\\x4c\\x96\\x27\\x86\\x81\\xe0\\x7f\\xa6\\x85\\x9c\\x9e\\x94\\x54\\x69\\x56\\x9f\\xe4\\x32\\xb3\\x6f\\xf0\\x38\\x33\\x14\\x70\\x31\\x3f\\x2e\\xf3\\xa3\\xe3\\x7f\\xfb\\xb7\\x28\\x22\\x2e\\xac\\x4d\\xcc\\x66\\x2f\\x04\\xc0\\xbe\\x60\\x60\\x47\\x56\\x4d\\xa6\\xcc\\xb0\\x7f\\x09\\xe6\\xab\\xa0\\xf4\\x8e\\x59\\x95\\xf8\\x53\\x1a\\xf1\\xda\\x46\\xc6\\xfd\\x3d\\x7e\\xcc\\xdf\\xc0\\x6d\\x49\\x02\\x33\\x5d\\x4a\\x66\\xb0\\x1f\\x71\\x7d\\x5f\\x2c\\xa6\\x2f\\x59\\x78\\x6d\\x82\\x58\\xbe\\x3d\\x8a\\xe3\\xdb\\x1b\\x85\\x63\\x5f\\x62\\xf7\\xf6\\xb0\\x8e\\x6b\\x82\\x78\\xbd\\x14\\xb1\\x7a\\xe9\\xe2\\xf4\\xf6\\xb5\\xdc\\xe9\\x17\\x8b\\xcd\\xfb\\x2a\\xe2\\xf2\\x12\\x5a\\xad\\x13\\xc5\\xe3\\x3d\\x46\\x2c\\x5e\\x92\\x59\\xc7\\xc6\\xe0\\x3d\\x5e\\xfc\\x5d\\x9a\\xe9\\xa6\\x54\\x12\\x23\\x6f\\xee\\x0e\\xe2\\xed\\x1e\\xc3\\x79\\xf6\\xc5\\x1c\\x67\\x09\\x9c\\x66\\x29\\x1d\\x66\\xc9\\x9c\\x65\\x5f\\x2c\\xae\\x2e\\x3e\\xa6\\x2e\\xa9\\xca\\xfe\\x28\\xb1\\x74\\x29\\xe3\\xe8\\xa2\\xf7\\x97\\x0b\\xae\\x39\\x2d\\x5e\\xb2\\x82\\xae\\xae\\xe2\\x62\\xaa\\x52\\xed\\xc4\\xe5\\x46\\xdc\\x15\\xda\\x86\\xbb\\x91\\x77\\x0b\\x6a\\xeb\\x0f\\xb3\\xdc\\x05\\xde\\x39\\xef\\xab\\x95\\x54\\xc1\\x71\\x8a\\xf3\\x8b\\x8a\\xc2\\x7b\\x60\\x22\\xfa\\xad\\xac\\x6f\\x0a\\x49\\x73\\x75\\x52\\x49\\xfc\\x4f\\x9b\\x86\\x1e\\xe4\\x9f\\x47\\x49\\xd3\\xfb\\x61\\x83\\xc6\\x64\\xff\\x3d\\x39\\x35\\xaf\\xe5\\x2d\\x91\\x33\\xcd\\x04\\x39\\xe4\\xc2\\x9d\\x9c\\xa3\\xc0\\x98\\xd2\\xfa\\x20\\xa2\\x9d\\x0a\\xa6\\xd7\\x17\\xcf\\xdd\\x20\\x4f\\xcf\\xb9\\x00\\xee\\x17\\xa5\\xf6\\xda\\xbd\\x64\\x69\\xfc\\xb4\\x7f\\xc9\\x7e\\x71\\xd6\\x14\\x5d\\x1f\\x13\\xfa\\x9d\\xd2\\x38\\x98\\x5e\\xb4\\x15\\x4b\\x5f\\x00\\x3d\\x9e\\x15\\x51\\x91\\x13\\x0b\\x1a\\xf3\\xf4\\xce\\x49\\x74\\xd4\\x68\\x57\\x07\\xf1\\x61\\x9e\\x9f\\x72\\x47\\x5d\\x9f\\x4d\\x06\\x6f\\xd4\\x7e\\xd9\\x47\\x77\\x14\\xc2\\xf8\\xf4\\x34\\xae\\xc7\\x0f\\x59\\x1c\\x34\\xae\\xdf\\x8a\\xc6\\x15\\xe0\\x35\\xbd\\xaa\\x69\\xc6\\x26\\xfb\\x24\\xc0\\x39\\x06\\xd2\\xe6\\xdb\\xb4\\x72\\x9c\\x67\\x17\\x82\\x31\\xcc\\xc3\\x68\\xd1\\xb8\\x00\\x78\\x6a\\xd6\\x14\\xc5\\x0a\\xcd\\x7d\\x1d\\x68\\xb6\\xfe\\x47\\xeb\\x7a\\xc1\\x36\\x30\\xad\\x3a\\xd9\\x40\\x01\\x75\\xad\\x7e\\x52\\xd5\\xd2\\x4a\\x25\\x75\\x23\\x84\\x79\\xad\\xec\\x75\\x32\\xc4\\x1b\\x7d\\x44\\x31\\xd1\\xdf\\xf2\\x4d\\x3b\\x88\\x5b\\x8a\\xcf\\xcd\\x72\\x19\\x09\\x03\\xc0\\xb8\\xda\\x4c\\x80\\x0e\\x21\\x66\\xd4\\x99\\xac\\x33\\x3e\\x2d\\x56\\x64\\x41\\x0b\\xa3\\x30\\xdd\\x72\\xbd\\x20\\x94\\xdc\\xf0\\xa2\\xb0\\xdd\\xf4\\x5f\\xa8\\x2b\\xa6\\xd1\\xb9\\x8b\\x52\\x4d\\x21\\xc5\\x1c\\x16\\x83\\x22\\x21\\xec\\xae\\x62\\x99\\x19\\x33\\x2b\\x18\\x15\\x4d\\x85\\x74\\x1a\\x19\\x69\\x25\\x9b\\xda\\xd1\\xd9\\x7f\\x78\\xe7\\x5a\\xf6\\x32\\x95\\xe0\\xc5\\xc8\\x2d\\x79\\x17\\x9b\\x6d\\xf3\\xcc\\xb7\\xd6\\x5f\\xc5\\x72\\x0b\\xab\\x76\\xcb\\x15\\x1b\\x41\\x9f\\xbd\\x69\\x42\\x5a\\xe4\\x92\\xd5\\x35\\xcf\\xad\\x8b\\x17\\x7f\\x57\\xd5\\x72\\xc9\\x73\\xf4\\x6b\\xbb\\x63\\x61\\xa4\\x9d\\xfe\\xf3\\xff\\x00\\xfd\\x3a\\xd6\\x2a\\xa4\\x18\\x0b\\x36\\xa7\\x20\\x22\\x5b\\x86\\x86\\x11\\x8e\\x38\\x3e\\xc6\\xd3\\x89\\x9c\\x67\\x54\\x33\\xa3\\x40\\xcb\\xaa\\x83\\xb9\\xb8\\xe4\\xb4\\x37\\x25\\x66\\x3e\\xc1\\x89\\x22\\x87\\x42\\x12\\x09\\x89\\x3a\\x8d\\xe0\\x7a\\x05\\xce\\xb7\\x45\\xa3\\x49\\x2e\\x6f\\xc5\\x51\\xcc\\xc5\\xc4\\x40\\x02\\x4a\\xa6\\x4c\\xd3\\x36\\xcd\\xc6\\x89\\x64\\x8a\\x30\\x41\\xa7\\x85\\xb9\\x7b\\x10\\x40\\x7d\\xbd\\xf5\\x00\\x90\\x19\\xa3\\xba\\xa9\\x19\\x99\\x53\\x1d\\xc1\\x25\\xb6\\x48\\xf4\\xb8\\x9f\\x1f\\x3f\\x76\\x5c\\x59\\xd7\\xda\\x8c\\x34\\x42\\xb1\\x48\\x41\\x36\\x99\\x1a\\xd0\\x33\\x81\\xcc\\xdc\\x68\\xd9\\xe8\\x3d\\x79\\x47\\xee\\x33\\x1f\\xdd\\x2e\\x78\\xb6\\x08\\x15\\x45\\x5e\\x32\\x45\\x64\\x13\\x61\\xcd\\xeb\\xa8\\x80\\x76\\xb8\\x94\\x5a\\xde\\x60\\x7b\\xda\\xda\\xfa\\x7a\\x38\\x53\\x9c\\xb0\\xcb\\x40\\x2a\\xdf\\x92\\x84\\xd1\\x86\\x36\\x61\\x6a\\xe2\\xcb\\xcb\\xab\\x5f\\xde\\x9c\\xfe\\xd7\\xf9\\x9b\\x7e\\x47\\x00\\x78\\x9d\\x08\\x65\\xe7\\x46\\xf0\\xff\\x6b\\x18\\xa1\\xa5\\x34\\x9a\\x70\\x11\\xe6\\x7f\\x8c\\xc0\\xd8\\x19\\xfc\\x02\\xb8\\x62\\xda\\x4c\\x91\\x9e\\x72\\xad\\x79\\x04\\x7a\\x31\\x86\\x8d\\x88\\xc7\\xc7\\x48\\x87\\xe9\\x1b\\xb0\\x11\\x11\\xa8\\xd1\\x0d\\x5a\\x71\\x73\\x80\\x10\\xcf\\x20\\x1b\\x9d\\x12\\xc1\\xb4\\xb9\\xe3\\xa8\\x10\\x72\\x41\\x28\\x51\\x5c\\xcc\\x8b\\x68\\x5d\\x30\\xda\\x22\\x12\\x6b\\x0f\\x19\\xb7\\x33\\x98\\xf4\\x35\\x8b\\xc4\\x1b\\x45\\x3a\\x34\\xf4\\xd7\\x2a\\xd3\\x19\\x04\\xda\\xc7\\xcc\\x99\\x00\\xd8\\x5d\\x25\\x15\\x73\\x26\\x00\\x94\\x71\\x2f\\x26\\x84\\xe6\\x79\\x1d\\x25\\x47\\x5b\\x66\\xe3\\x75\\x74\\x4c\\x69\\xc6\\x61\\xd1\\xfd\\x3b\\x22\\xcf\\xc9\\x7f\\x92\\x3b\\xf2\\x9f\\x60\\x10\\xf8\\x4b\\xff\\xa1\\xd2\\xa8\\xdb\\x29\\x82\\x86\\x17\\x52\\xe9\\x8b\\x49\\xa2\\x8d\\xfe\\xc7\\x82\\x6a\\xe8\\xd1\\xec\\x87\\x96\\x64\\xca\\xad\\x66\\xc6\\xee\\x34\\xab\\x8d\\x44\\x6c\\xf7\\x30\\x76\\xe5\\xa2\\x8c\\x0b\\x86\\xc0\\xaf\\xe5\\x74\\xc7\\xfa\\x5a\\x2f\\x66\\xdd\\x50\\xe3\\x47\\x3a\\xdf\\x30\\xf0\\x6b\\xa9\\xf4\\xa5\\xe5\\xd6\\x61\\x3a\\x7e\\x48\\x47\\x49\\x75\\xb6\\xe8\\xb2\\xfb\\x98\\x51\\xdf\\x9a\\xb3\\x17\\x3c\\xff\\xb9\\x84\\x87\\x12\\xd3\\xbb\\x16\\x3c\\x82\\x39\\xec\\xcf\\x8d\\x8d\\x8b\\x6e\\x4b\\x77\\x74\\x3f\\x76\\xb4\\xd6\\xcc\\x9b\\x20\\x86\\x59\\xb9\\x2d\\x80\\x8e\\xaf\\x64\\x7e\\x4c\\xce\\x69\\xb6\\x88\\xa0\\xc2\\xac\\x46\\x1e\\x08\\x03\\x95\\xcc\\x91\\x8c\\x05\\x5d\\x9a\\x33\\x6e\\x47\\x85\\x48\\x3b\\x14\\x5d\\xbd\\xb3\\x0c\\x2e\\x9c\\xe1\\x58\\x19\\x15\\x64\\x1a\\x13\\xea\\x55\\xb3\\x19\\xab\\x6b\\x4c\\x21\\x9c\\xae\\x5c\\x72\\x43\\xf4\\x69\\x8b\\xe2\\x72\\x55\\x2d\\xb5\\xcc\\x64\\xb1\\x0f\\x47\\x65\\x62\\x69\\x81\\xb5\\x07\\xb7\\x95\\x77\\x16\\xfe\\xf0\\x72\\x32\\x22\\xd7\\x67\\x93\\x11\\x91\\x35\\xb9\\x3a\\x8b\\x8b\\x05\\x09\\xb5\\xd1\\x67\\xd7\\x67\\x93\\x67\\x3b\\xdd\\x01\\xe2\\xdc\\x3d\\xe0\\xd8\\xeb\\xd1\\x49\\xc7\\x02\\x5e\\x70\\xa5\\xc7\\x25\\xad\\xc6\\x37\\x6c\\xd5\\x53\\xba\\x4b\\x21\\x61\\x8e\\xfd\\xc1\\x4a\\x32\\x21\\x5c\\xe6\\x92\\x56\\x0f\\xee\\xad\\x66\\x34\\xe7\\x03\\xd2\\xc0\\xe7\\xb7\\x01\\x69\\xe0\\x33\\xdb\\x80\\x34\\xf0\\x39\\x6d\\x40\\x1a\\xf8\\xdc\\x36\\x20\\x0d\\xf4\\x6e\\x03\\xd2\\xc0\\x66\\x1b\\x90\\x06\\x1e\\xd6\\x06\\xa4\\x81\\x87\\xb7\\x27\\x10\\xdb\\x35\\x20\\x0d\\x6c\\x6f\\x03\\xd2\\xc0\\x80\\x34\\x30\\x20\\x0d\\x0c\\x48\\x03\\x6d\\xdb\\xbb\\x48\\xda\\x01\\x69\\xe0\\x63\\x6d\\x40\\x1a\\xd8\\xda\\xf6\\x46\\xe1\\x18\\x90\\x06\\xee\\x69\\x03\\xd2\\xc0\\x3d\\x6d\\x40\\x1a\\x18\\x90\\x06\\x06\\xa4\\x81\\x07\\xb6\\xa7\\x97\\xf7\\x32\\x20\\x0d\\x3c\\xa8\\x0d\\x79\\x2f\\x0f\\x6c\\x03\\xd2\\xc0\\x80\\x34\\xb0\\xde\\x06\\xa4\\x81\\x4f\\xb6\\xfd\\xb0\\x41\\x0f\\x48\\x03\\x03\\xd2\\xc0\\x47\\xdb\\x80\\x34\\x30\\x20\\x0d\\x7c\\xb4\\x0d\\x48\\x03\\x4f\\xc5\\x3e\\x3a\\x20\\x0d\\x0c\\x48\\x03\\x1f\\x1b\\x63\\xd0\\xb8\\x1e\\xd6\\x06\\xa4\\x81\\x01\\x69\\x60\\xa3\\x0d\\x48\\x03\\x9b\\x6d\\x40\\x1a\\x18\\x90\\x06\\x06\\xa4\\x81\\x01\\x69\\xc0\\xb7\\x01\\x69\\xe0\\xa9\\xdb\\x9e\\x6a\\xa6\\xf8\\xbf\\xd8\\x44\\x16\\x3c\\x5b\\x45\\x27\\x59\\xbc\\x67\\x4a\\x36\\x75\\x66\\x5e\\x6c\\xe8\\x96\\x54\\xd0\\xaf\\xb7\\x2a\\x44\\x09\\xd9\\x7b\\x96\\xb9\\xfe\\x3e\\x58\\xb8\\x30\\x83\\xbd\\xb6\\x6b\\xf0\\x25\\x96\\x60\\x2f\\xb2\\xd8\\xdd\\x04\\x2f\\xfb\\x3b\\xfb\\xa1\\x13\\x4d\\x6b\\x8d\\xcb\\xd7\\xcf\\x60\\x1a\\xad\\xb5\\x87\\x13\\xd9\\x87\\x2c\\xba\\x10\\x78\\xc3\\x9f\\x22\\x2d\\x3d\\xb3\\xe5\\xf7\\x1e\\x2e\\x5a\\x55\\x05\\x8f\\xc9\\x47\\x24\\xe4\\xca\\x17\\x1c\\x07\\x56\\xab\\xbe\\x25\\x59\\xd5\\x8c\\x48\\xc9\\x4a\\x59\\x47\\x24\\x0a\\x24\\xd0\\xe0\\x3a\\x47\\x65\\x1f\\xf6\\xe9\\x3d\\x12\\xe4\\x16\\x5f\\x4b\\x58\\xff\\x15\\xea\\x0b\\x2d\\x3a\\x8a\\xdf\\x2b\\xee\\xd8\\x61\\x54\\x58\\xd8\\xc5\\x6c\\x3d\\xdc\\x93\\xeb\\x8e\\x15\\xe8\\x52\\xea\\xf7\\xf6\\x72\\xef\\x6c\\xbf\\xee\\x4b\\x00\\xa4\\x5a\\x96\\x3c\\xeb\\xf3\\x38\\xe1\\x7b\\xb2\\x2b\\x2c\\x9c\\xf6\\x41\\xfb\\xec\\xc4\\x41\\x72\\xbe\\xe5\\xb7\\xe0\\x03\\x55\\x95\\xe9\\xc4\\xcf\\xa9\\x17\\x41\\xb4\\xa8\\x19\\xcd\\x57\\x40\\x46\\x06\\xa1\\x75\\xad\\xfd\\xef\\x2b\\xcc\\x59\\xcc\\x0a\\xca\\xfb\\xc7\\xe3\\xa5\\xba\\xd2\\x67\\x40\\x05\\x31\\xe7\\xb5\\x8d\\x2f\\x87\\xbc\\x2a\\xbf\\x59\\x23\\x1f\\x44\\xcd\\xf1\\x8e\\x1f\\xbb\\x8f\\xf0\\x8f\\x47\\x11\\x9a\\x1e\\xd5\\x70\\xba\\x40\\x89\\x01\\x55\\x96\\xab\\x50\\x4c\\xe8\\x1f\\x2d\\xee\\xb5\\x3b\\x41\\x68\\x51\\x2d\\x3e\\xae\\xdf\\xc5\\xe4\\x0b\\xbe\\x5c\\x09\\x5a\\xf2\\xcc\\xdd\\x96\\x53\\x3c\\x9c\\x5c\\x8a\\x35\\xcd\\x30\\x72\\x2a\\x48\\xbe\\x99\\x53\\x59\\x36\\x9a\\x4e\\x0b\\x76\\x4c\\x2e\\x30\\xbd\\x5f\\x8a\\x62\\x65\\x74\\x76\\xc5\\xb4\\x8b\\x35\\x88\\xc8\\xe4\\x25\\x49\\xe2\\x4d\\x23\\x63\\x4d\\xb7\\x4a\\xd6\\x70\\xda\\x10\\x8f\\x80\\x09\\xc3\\x97\\xa4\\x60\\x84\\x09\\x5d\\xaf\\xcc\\xc1\\x9c\\xc8\\xfc\\xca\\x9c\\xcd\\xce\\xb7\\xa3\\x61\\x0a\\x22\\x43\\x4c\\x53\\x84\\x97\\x46\\x86\\x96\\xa6\\x09\\x08\\x8d\\x0f\\x06\\x4d\\x1b\\x08\\xda\\xfa\\x01\\x10\\x65\\x25\\xcc\\x8c\\xe9\\x1c\\x0b\\xf3\\x36\\x6c\\xe1\\x59\\x44\\xce\\x22\\x29\\x30\\x23\\x4e\\x64\\x6e\\x24\\x9f\\x9a\\x21\\xe3\\xf2\\x77\\x14\\xad\\x80\\x17\\x86\\xb8\\x1b\\x30\\xdb\\x51\\xdd\\x8a\\x44\\x74\\x49\\x79\\x61\\x2e\\x70\\x24\\x01\\x3e\\x0d\\x38\\x91\\xfb\\x26\\x81\\xb8\\x9a\\x1a\\xd4\\x81\\xc4\\x1e\\xff\\x94\\xa0\\x0c\\xa6\\x15\\xbc\\xe4\\xfd\\xa0\\xee\\x48\\xc2\\x2b\\xf0\\x06\\xa8\\x08\\x82\\xee\\xcd\\x59\\x2c\\xe9\\x1d\\x58\\x8b\\x68\\x29\\x1b\\xa1\\xcd\\x3d\\xc8\\x64\\x59\\x35\\x3a\\x90\\xba\\x9c\\x00\\xf7\\x68\\x66\\xa4\\x4c\\x8a\\x19\\x9f\\x5b\\x47\\xc7\\x49\\x49\\x05\\x9d\\xb3\\xb1\\x27\\x67\\xdc\\x3e\\x54\\x27\\xbb\\x73\\xc0\\xd3\\xdc\\x65\\xce\\x4f\\x52\\x64\\x66\\x52\\xad\\x59\\x2d\\xbe\\x25\\xff\\x7d\\xf8\\xcf\\xdf\\xff\\x3a\\x3e\\xfa\\xee\\xf0\\xf0\\xa7\\xe7\\xe3\\xbf\\xfd\\xfc\\xfb\\xc3\\x7f\\x1e\\xc3\\x3f\\xfe\\xe3\\xe8\\xbb\\xa3\\x5f\\xdd\\x0f\\xbf\\x3f\\x3a\\x3a\\x3c\\xfc\\xe9\\xef\\x6f\\x5f\\x5d\\x4f\\xce\\x7f\\xe6\\x47\\xbf\\xfe\\x24\\x9a\\xf2\\x06\\x7f\\xfa\\xf5\\xf0\\x27\\x76\\xfe\\xf3\\x67\\x76\\x72\\x74\\xf4\\xdd\\x37\\xfd\\x9d\\x41\\xb1\\x9e\\xcf\\x74\\x7e\\xcf\\x44\\x5e\\xcf\\x2f\\xe2\\xf3\\xb4\\x49\\x3e\\x3b\\xbf\\xfc\\x36\\x97\\x73\\xe3\\xfa\\x5b\\x63\\xf1\\xc7\\xae\\x7f\\x1d\\xad\\x22\\x5f\\xcc\\xda\\xf1\\xb9\\x22\\xb2\\xe4\\x5a\\x5b\\x85\\x90\\x86\\xd0\\x1c\\x6b\\xea\\xb9\\x65\\x58\\x7c\\x86\\x4f\\x21\\x57\\x21\\x44\\x44\\xab\\xd5\\xf7\\x26\\x4b\\x3a\\x7f\\x1b\\x18\\x24\\x04\\xe1\\x65\\x55\\xb0\\x92\\x09\\x0d\\x8c\\x67\\xec\\xd4\\x17\\xb0\\xee\\x1c\\xb7\\x33\\xc8\\xa8\\x30\\x6a\\x2d\\xbb\\xcb\\x18\\xcb\\x2d\\x91\\x03\\x6f\\x0c\\xda\\xc0\\x1b\\x07\\xde\\xf8\\xa9\\x16\\x6d\\xa2\\x4c\\x64\\xab\\x0a\\xcd\\x92\\x1b\\x0e\\x07\\xc3\\x17\\xf0\\x8a\\x39\\x0b\\x33\\x7c\\xdd\\x27\\x8a\\xcb\\x19\\x61\\x7d\\xb1\\xfa\\xda\\x41\\x2c\\xfc\\x1f\\xed\\x6b\\x90\\x72\\x20\\xad\\x74\\xb5\\xa1\\xd3\\xaf\\x61\\x3f\\x63\\x5e\\xaf\\xe5\\x5f\\xca\\x05\\x4e\\xa0\\xfe\\x21\\x45\\xaf\\xa1\\xf7\\x02\\x49\\x5a\\xb1\\xac\\xa9\\xb9\\x5e\\x9d\\x49\\xa1\\xd9\\x5d\\xaf\\x60\\xba\\x14\\xc7\\xa9\\x8d\\x41\\xbc\\xea\\x12\\x64\\x2d\\x61\\x36\\xaf\\xcf\\x7e\\x46\\x64\\x85\\x30\\x4b\\xf7\\xa2\\x86\\x2f\\x64\\x53\\xe4\\x66\\x3b\\xeb\\x46\\xc0\\x29\\xe9\\x77\\x3a\\x2e\\x66\\x66\\xaf\\x31\\x28\\x05\\xf6\\x1a\\xec\\x74\\xeb\\x24\\xba\\x70\\x11\\x24\\xe7\\xff\\x1a\\xbe\\xa4\\x05\\x13\\x3a\\xf8\\x8b\\x09\\x04\\x10\\x84\\x7f\\xf4\\x15\\x9a\\x4f\\x41\\x97\\x99\\xd4\\x7c\\xc9\\x0b\\x36\\x67\\xe7\\x2a\\xa3\\x05\\x3c\\xa5\\xbb\\x96\\xcf\\x4e\\xef\\xa1\\x0b\\xce\\x43\\x2d\\x0b\\x45\\x6e\\x17\\xcc\\xc8\\x2b\\x86\\x4f\\x60\\xd0\\x12\\x58\\xf1\\xe6\\x94\\x0b\\x52\\xca\\x3a\\xc6\\xd2\\x63\\x07\\x55\\x18\\x35\\x65\\x44\\xae\\x8a\\xd6\\x66\\xef\\x5d\\x74\\x14\\x32\\x98\\xa9\\x94\\x85\\x45\\x4c\\x2b\\x56\\x2d\\x5d\\xbc\\xbf\\x49\\x04\\xcc\\x2f\\xf2\\x17\\xc1\\x6e\\x7f\\x31\\x54\\x28\\x32\\x2b\\xe8\\xdc\\x07\\x45\\x19\\x06\\xb5\\x1e\\x6a\\x1a\\x1f\\xb0\\x75\\xef\\x42\\x03\\x1c\\x58\\xc3\\x08\\x2d\\x6e\\xe9\\x4a\\xb5\\xa1\\x6c\\xed\\xd8\\x3c\\x42\\x8a\\x79\\x71\\x04\\xb7\\x98\\x2a\\xe2\\xc7\\xce\\x7b\\x77\\xf6\\x87\\x23\\xc8\\x3f\\x3a\\x3b\\x9d\\xfc\\x72\\xf5\\xe3\\xd5\\x2f\\xa7\\x2f\\xdf\\x5e\\x5c\\xf6\\x0f\\x58\\x91\\x9a\\xa1\\x80\\x1d\\xbc\\x06\\xf6\\x8d\\xb0\\xbb\\xe0\\xdd\\x74\\xc7\\x52\\x1d\\x83\\xbd\\x0c\\x52\\x9e\\x45\\x2e\\x6f\\x23\\x8d\\xc5\\xe6\\x4c\\x31\\xda\\xef\\xe9\\xc9\\x68\\x45\\xa7\\xbc\\xe0\\x31\\xe2\\x65\\xaa\\xeb\\x0b\\x20\\x7e\\x01\\x3d\\xa0\\x51\\xe4\\xf9\\x49\\x5e\\xcb\\x0a\\x97\\xcf\\x05\\x64\\xc6\\x9b\\xd9\\xbb\\x81\\x3f\\x21\\x82\\x0d\\xdc\\x98\\x59\\x97\\x90\\x79\\x4d\\x85\\x6e\\x23\\xfe\\xda\\xd3\\x5c\\x37\\x42\\xf3\\x98\\x14\\xf8\\x9d\\x1e\\x9c\\x9d\\x43\\x62\\xd2\\x3c\\x1d\\x1c\\xe6\\x69\\x9e\\xb3\\xbc\\xb3\\x6d\\x11\\x3d\\xef\\x27\\xea\\xc7\\x99\\x9b\\x5c\\x10\\xf9\\x43\\x26\\xef\\xae\\x2e\\xfe\\xdf\\xda\\xbd\\x59\\x55\\x71\\x16\\xee\\x34\\x28\\xc5\\xb5\\xac\\x92\\xed\\xee\\x7b\\x56\\xca\\xe5\\xb0\\xbf\\xfb\\xb2\\xbf\\x5e\\xde\\xd9\\x79\\x5e\\xe1\\xfb\\x46\\x84\\xd2\\x85\\x08\\x48\\x23\\xa5\\xcc\\x23\\x58\\xf3\\xc4\\x87\\xdf\\x77\\x7b\\x0d\\xcb\\x00\\xd5\\x8c\\x98\\xaf\\x08\\xcd\\x69\\x51\\xac\\x42\\x91\\x5f\\x4b\\x84\\xaf\\x4d\\x52\\x70\\x21\\x7c\\xab\\x66\\xb4\\x50\\x5f\\xeb\\x83\\x13\\x23\\xa9\\x18\\xa1\\xf5\\xad\\x6c\\x44\\x9a\\x44\\xc5\\x88\\x13\\xe7\\x09\\x21\\x39\\x13\\x52\\x5b\\x8d\\xd4\\x4c\\x10\\xea\\x6d\\xd4\\x32\\x23\\x68\\x08\\x0e\\x30\\x08\\x3a\\x52\\x43\\x84\\xd0\\x72\\x1d\\x08\\x2a\\x5c\\xb9\\x73\\x31\\xf1\\x14\\x61\\xcc\\x5e\\xa3\\x98\\xda\\x2e\\xa8\\xb4\\xa6\\xe1\\x99\\xec\\x6f\\x11\\xab\\x19\\xcd\\xc1\\x4a\\x52\\x51\\xbd\\xc0\\xfc\\xd8\\x92\\xaa\\x1b\\x96\\xe3\\x2f\\x22\\xf3\\x02\\x7c\\x8c\\x08\\xb8\\x79\\xdd\\xd4\\xae\\xcd\\xfa\\xba\\xb0\\x0e\\x50\\x71\\x30\\x4b\\x18\\x02\\x49\\x62\\xec\\xea\\x3b\\xbd\\x10\\x11\\x2c\\xd8\\x6c\\xc2\\x3b\\x51\\xac\\xde\\x4b\\xa9\\xbf\\xf7\\x50\\xd8\\xbb\\xbe\\x1c\\xff\\xb0\\x0a\\x76\\x37\\x9a\\x08\\x34\\x2d\\x0a\\x24\\x8f\\xe1\\xe0\\x00\\x6b\\x0c\\x00\\xbc\\x63\\x39\\xa3\\xd9\\x90\\xdf\\x2a\\x63\\xac\\x1b\\x71\\xaa\\x5e\\xd5\\xb2\\xe9\\x2d\\x6d\\xa5\\x54\\xe0\\x5e\\x5d\\xbc\\x84\\xb7\\xaf\\xb1\\xa9\\x63\\x42\\xd7\\xab\\x4a\\x72\\xf4\\x8b\\x25\\x36\\x43\\xfc\\x60\\x93\\xf4\\x42\\xce\\x16\\x9d\\x8f\\x43\\xc8\\x5b\\xba\\x22\\xb4\\x50\\xd2\\x6d\\xbb\\x8d\\x70\\x5a\\x33\\xdb\\x39\\x9b\\xa0\\xf9\\x78\\x2a\\xf5\\x62\\xc3\\x18\\x48\\x45\\x7f\\xe3\\xc4\\xe6\\x78\\xa3\\x20\\x03\\xad\\x0d\\xf6\\xe5\\x62\\x63\\x58\\x0d\\x71\\x2f\\x55\\xcd\\x32\\x96\\x33\\x91\\x7d\\xad\\x37\\x62\\xd7\\x09\\x51\\x70\\xab\\x2e\\xa5\\x30\\xec\\x75\\xd7\\xf7\\xea\\xc2\\x27\\xfb\\xd9\\xdd\\x08\\x6f\\x11\\x44\\x62\\x59\\xb3\\x18\\x85\\xe4\\x41\\x60\\xae\\x8d\\x8a\\x09\\x4a\\xba\\x98\\x81\\x1d\\x0f\\x0f\\xdd\\xdf\\x9b\\x29\\x2b\\xcc\\x66\\xf3\\xa2\\xc0\\xe2\\x5e\\x54\\xa3\\x89\\x9b\\x97\\x74\\xce\\x08\\xd5\\xfe\\x12\\x6a\\x49\\x98\\x50\\x4d\\x6d\\xcf\\x0d\\xef\\x1f\\xbe\\x97\\x4b\\xa6\\x7c\\xd9\\x05\\xaa\\xc8\\x0f\\x17\\x2f\\xc9\\x73\\x72\\x68\\xe6\\x76\\x04\\x12\\xc7\\x8c\\xf2\\x02\\xf2\\x11\\xc1\\x9d\\xb4\\x66\\x64\\x9c\\x81\\x1b\\x5c\\xc6\\xe4\\x26\\x5c\\x58\\x3e\\x42\\x64\\x8d\\x4f\\xcb\\x88\\x08\\x49\\x54\\x93\\x2d\\xdc\\x1a\\x70\\x29\\xbc\\x9d\\xd5\\x02\\xd4\\x44\\x05\\xf8\\x0c\\x6c\\x27\\xdd\\x7b\\xf8\\x83\\x62\\xf5\\xae\\xaf\\xad\\x79\\x0e\\x7f\\x78\\xc4\\xe7\\x30\\xd4\\x12\\xcd\\xf5\\xef\\x6e\\x18\\xde\\xd5\\x92\\x69\\x9a\\x53\\x4d\\xed\\x33\\xe9\\xbe\\x30\\x9c\\xda\\xe1\\xb1\\x8c\\x78\\x2c\\x15\\x7b\\xc3\\x45\\x73\\x87\\xbe\\xdb\\xbd\\xf0\\x23\\x5c\\x9d\\x03\\x45\\x70\\xbd\\x60\\xa3\\xe1\\x80\\x62\\xc2\\x9a\\x4f\\x5e\\x49\\x10\\xbd\\x7b\\xd1\\xb9\\x46\\xa3\\x7b\\xb4\\x6e\\x78\\x25\\x5c\\xee\\x8c\\x51\\x84\\xa8\\xc8\\x65\\xb9\\x41\\x24\\x24\\xf7\\xc4\\xd4\\x2d\\x6c\\x27\\x34\\x5c\\x4c\\xd7\\x7e\\xdb\\x1e\\x96\\x82\\x2d\\x59\\x44\\xad\\xc6\\xb5\\x4b\\xf9\\xc6\\xf4\\x66\\x16\\xc7\\x9d\\x5c\\xe8\\x9e\\x14\\x74\\xca\\x0a\\x9b\\x51\\x84\\x29\\xa1\\x09\\x6f\\x58\\x22\\x6f\\x44\\x2d\\x8b\\x74\\x18\\xa5\\xef\\x65\\xc1\\x10\\xbf\\xc2\\x2d\\x84\\xe9\\xfe\\xab\\x58\\x07\\xe8\\x24\\xd5\\x3a\\x80\\x51\\xae\\xb3\\x0e\\x60\\x06\\xfd\\x1a\\xd6\\xa1\\x89\\x10\\x10\\xc9\\xfa\\x3a\\x18\\x69\\xb3\\xbb\\x0e\\x20\\x7f\\xed\\xfb\\x3a\\x28\\x96\\x65\\xb2\\xac\\x26\\xb5\\x9c\\xf1\\xfe\\xb7\\x23\\xe5\\xb3\\x6d\\x29\\x6a\\xc3\\xba\\xd0\\x84\\xbe\\x99\\x9e\\x88\\xcf\\x56\\xf7\\xcb\\x34\\x2a\\x80\\xc7\\x82\\xfa\\x50\\x8d\\xef\\xa0\\x43\\xf6\\xf9\\xf7\\xe0\\x39\\x07\\x6e\\xb7\\xfe\\xc6\\xdb\\xd1\\xfb\\x07\\x50\\x87\\x31\\x63\\x66\\x44\\xdb\\xe1\\x6f\\xf1\\xc5\\x4b\\x81\\xc8\\x18\\xe1\\x1c\\x4d\\xf2\\xe0\\xca\\x8c\\x16\\x50\\x0a\\x3e\\xee\\x56\\x91\\xc4\\x79\\x7b\\xeb\\x74\\x05\\x08\\x52\\x10\\x0c\\x07\\xbf\\x0b\\x92\\x8d\\x29\\x98\\xe7\\x9d\\xfb\\x52\\xc8\\x9c\\x05\\xb1\\x94\\x90\\x64\\x17\\x45\\xce\\x35\\x62\\xf8\\xc0\\x18\\x0e\\xf8\\xca\\x48\\x7b\\x36\\x32\\x9f\\xe5\\x9d\\x91\\xb5\\xc4\\xb2\\x99\\x51\\x43\\xbe\\xf5\\x05\\xea\\xcd\\xba\\x32\\x91\\x73\\x31\\x07\\x87\\xd5\\x88\\xd4\\xac\\x40\\xb8\\x2d\\xcb\\x9e\\x6f\\xd0\\xe2\\x75\\x00\\x1c\\xc7\\x11\\xe4\\xd8\\x8d\\x23\\xdb\\x25\\x1b\\xa7\\xa1\\x0a\\x64\\xf0\\x19\\xbe\\x9f\\x5c\\x91\\x67\\x6f\\xdc\\x7e\\x3d\\xb3\\xb8\\xb4\\x97\\xef\\xae\\xc3\\xa8\\x64\\x2a\\x56\\x98\\x7b\\x01\\x7f\\xb2\\xf3\\xe7\\x34\\xa9\\x58\\x11\\x79\\xd4\\x71\\x0d\\xfd\\xf1\\x46\\x9f\\xe8\\x0d\\x17\\xb9\\x05\\x94\\xea\\xec\\xa2\\x33\\xe0\\x59\\xd5\\x30\\x6e\\x33\\x3f\\xd0\\x82\\xe7\\xe1\\x7b\\xf4\\x6d\\x64\\xd1\\x35\\x7f\\x0a\\xc8\\x78\\x27\\xd7\\xf4\\x3d\\x2a\\xb0\\xce\\xcb\\x36\\xfe\\xb8\\x57\\xd9\\x13\\x98\\x92\\x84\\x1f\\x04\\xdc\\x41\\x33\\xdf\\x31\\x11\\x72\\xcb\\x18\\x09\\xb6\\x2e\\xfa\\x0e\\xd8\\xb7\\x73\\x8f\\x2c\\x20\\xff\\x40\\x8a\\x9c\\x9a\\x9d\\x19\\xce\\xa1\\xb9\\x98\\xab\\xd0\\x0a\\x42\\x8b\\xd8\\x9c\\x03\\x6c\\xdb\\xcc\\x20\\xee\\x1a\\xcc\\x6a\\x59\\xba\\x94\\xed\\x75\\x35\\xbf\\x83\\xdd\\x18\\x33\\xfa\\x27\\x4c\\x18\\x5f\\xb7\\x29\\xa2\\x30\\x2a\\xc5\\x57\\x6e\\x88\\x98\\x97\\x8a\\x9e\\xd5\\x66\\x05\\x35\\xa7\\xc5\\x55\\xd5\\xbf\\x68\\x3c\\x49\\xfc\\x5c\\xbc\\x7a\\x7b\\x75\\xda\\xa5\\x0c\\x84\\x61\\x8b\\x2d\\xc0\\xe0\\x73\\x42\\xf3\\x92\\x2b\\x05\\x1e\\x1f\\x36\\x5d\\x48\\x79\\x13\\x35\\xe4\\xe1\\x96\\x62\\x9e\\x41\\x6e\\x98\\xe2\\x73\\x75\\x62\\x39\\xca\\xd8\\x2c\\xdc\\x11\\xe1\\xa2\\xf0\\xc9\\x2f\\x60\\x2e\\x14\\x5a\\x59\\x17\\x42\\xf4\\xe4\\x49\\xe6\\x67\\x0f\\x47\\x0f\\xb2\\xfe\\x7d\\xb0\\xf3\\xe6\\xf2\\x00\\x00\\x04\\x1c\\xde\\x9d\\x8b\\x1d\\x9b\\xa7\\x2a\\x0e\\x55\\x6d\\xbd\\xb0\\xf2\\xf6\\xb9\\x6f\\x29\\x07\\xbb\\x75\\x1d\\x51\\x7b\\xdd\\xf9\\x22\\x59\\xa9\\x3f\\x63\\x2a\\x5d\\x51\\xc6\\x04\\xb5\\x34\\x2d\\x49\\x24\\x67\\x08\\xb4\\xca\\x20\\x4b\\x99\\xde\\x9b\\xbc\\x05\\xfe\\xed\\x03\\x40\\xa6\\xb7\\x7f\\x7a\\x90\\x0a\\x7f\\xe3\\xb4\\x28\\xcc\\x46\\x52\\xf3\\x4c\\x1c\\xa8\\x30\\xc2\\x13\\x74\\x93\\x05\\x5d\\xb2\\xb6\\x9c\\x1c\\x9b\\xcd\\x58\\x06\\xda\\x42\\x38\\x8b\\xf8\\x62\\x6b\\x87\\x5c\\xbb\\xe2\\xba\\x0e\\xed\\x4b\\x4b\\x1c\\x9b\\x92\\x92\\xdf\\x19\\x0a\\xc3\\x11\\xc3\\x38\\x54\\x5b\\x6a\\x7f\\xfb\\xc7\\x11\\x40\\xbd\\x04\\xa2\\x0f\\x7c\\x32\\xf2\\xc8\\xec\\x50\\x38\\x88\\xcb\\xf7\\xd1\\xe6\\xd9\\x32\\x1f\\x5c\\x32\\x6d\\x34\\x35\\x5c\\xb7\\xd0\\xfd\\x60\\x34\\xab\\xba\\x49\\x70\\x19\\x62\\x5c\\xc3\\x24\\x74\\x0f\\x27\\xe5\\x14\\x91\\xf7\\x01\\x5c\\xc5\\x96\\x26\\x23\\x83\\x38\\xe1\\xed\\xb1\\x5c\\xc7\\x64\\x4b\\x42\\xcc\\xa3\\xb9\\x90\\xc9\\xe7\\xbb\\x91\\xbf\\xa0\\xb3\\x8a\\xec\\x8b\\xc3\\x2a\\x36\\x8f\\x17\\x2b\\xd5\\x00\\x6e\\x76\\x74\\x12\\xef\\xa4\\xad\\xc2\\xf5\\x59\\x28\\x84\\x3d\\xc6\\xdb\\x71\\x2e\\x2b\\xbb\\xeb\\x2f\\x89\\x76\\x96\\xea\\xfc\\x8e\\x65\\x6b\\x25\\xc1\\x6d\\xd9\\x1b\\x73\\x9f\\xe8\\x4d\\x64\\x44\\xcc\\xce\\x05\\xf8\\x4c\\x96\\x25\\x15\\xe9\\xf2\\xb5\\x22\\x39\\xe6\\x19\\x92\\xe3\\x64\\x31\\x4b\\x9d\\x51\\x95\\x30\\x0a\\xed\\x8e\\x65\\x8d\\x66\\x0e\\xa9\\xab\\xc3\\x2e\\xf1\\x4e\\x9b\\x67\\x8a\\x8b\\xb9\\x4d\\xc6\\x95\\xb5\\x87\\x2e\\x88\\x22\\xcb\\xd1\\x01\\xe8\\xab\\x52\\x6a\\x72\\x78\\x70\\x72\\x70\\xe4\\x2a\\x48\\x78\\x12\\x0e\\x54\\x18\\xfd\\x8c\\x99\\x8f\\xed\\x84\\x14\\x2f\\xab\\x62\\x05\\x73\\x38\\x40\\xc0\\xd5\\x88\\x42\\x06\\xa6\\xb9\\x38\\x3a\\x8f\\x5b\\xa6\\x16\\xac\\x28\\xa0\\x9c\\xae\\xae\\xa9\\x03\\x1a\\xc1\\xdf\\x42\\x2d\\xf1\\xba\\xc9\\x50\\x79\\x3f\\x3c\\xf8\\xf5\\x60\\x44\\x98\\xce\\x8e\\xc8\\xad\\x14\\x07\\x1a\\xed\\xb0\\xe4\\x1a\\x24\\xdb\\x28\\x9a\\x3c\\x11\\x2b\\xd9\\x40\\x4d\\x10\\xdc\\x36\\x8f\\x4d\\x93\\x51\\x23\\x94\\x35\\x28\\x39\\x18\\x9d\\x19\\xbe\\x1e\\xf7\\xca\\x9c\\xdf\\x71\\x6d\\x18\\xa4\\x6e\\x40\\x79\\x7a\\x8e\\xf2\\x0b\\xd6\\x0a\\xa7\\x0a\\x2a\\x7e\\x9d\\x2c\\x18\\x2d\\xf4\\x62\\xe5\\x65\\x2a\\x2c\\xb7\\xa0\\x48\\x23\\xec\\x27\\x4f\\xa2\\x9a\\x78\\xb4\\x62\\x61\\x8b\\xb3\\xec\\x75\\x7d\\x39\\x4b\\xe3\\x27\\xcb\\xcb\\x61\\x19\\xb9\\x6e\\x69\\x39\\x28\\x39\\xc7\\xf2\\x54\\xd5\\xe5\\xfe\\xf8\\xf4\\x2a\\xc7\\xcd\\xeb\\x2a\\xcd\\xcb\\xf9\\xea\\xfd\\xe4\\xec\\x93\\xf5\\xe2\\xe0\\x4b\\x43\\xc1\\xb8\\x68\\x20\\xa8\\x94\\x75\\xd2\\x26\\xb2\\xd6\\x6b\\x75\\xa5\\xe7\\xb0\\x97\\xac\\x5e\\xf2\\x8c\\x1d\\x3f\\x42\\x59\\xb2\\x54\\x10\\x4f\\xf1\\xd7\\x81\\x40\\x40\\x05\\x4c\\x7c\\x5f\\x64\\xa4\\x2b\\x24\\x67\\x9b\\xbd\\xca\\x52\\x0a\\xb5\\x55\\x0b\\x9a\\xf9\\xbd\\x81\\xfd\\x7b\\x0d\\x0f\\xdd\\xd9\\x82\\x65\\x37\\x16\\xb0\\x2d\\xce\\xb0\\xa1\\x18\\x23\\x5b\\x2c\\x9e\\x86\\x81\\xe0\\x7f\\xa6\\x85\\x9c\\x9e\\x94\\x54\\x69\\x56\\x9f\\xe4\\x32\\xb3\\x6f\\xf0\\x38\\x33\\x14\\x70\\x31\\x3f\\x2e\\xf3\\xa3\\x18\\x14\\x67\\x12\\xd4\\x98\\xb2\\x16\\x96\\x35\\x5f\\x85\\x73\\x60\\x79\\x54\\x2a\\xae\\xbc\\x97\\x6d\\xba\\x82\\x55\\xd9\\xa9\\x19\\xcf\\xac\\xde\\xab\\x44\\x35\\x3a\\x5f\\x5f\\x5f\\x4f\\x5e\\x75\\x2a\\x74\\x42\\x82\\xb2\\xd6\\x95\\x03\\x5a\\x0c\\x2a\\xee\\x0e\\xdc\\x76\\x6f\\xca\\x73\\x26\\x30\\xb9\\x3e\\xa4\\xa4\\x27\\xc0\\x9c\\x19\\x81\\x89\\x4e\\x8b\\x15\\xb9\\xa5\\x98\\xd0\\xac\\x58\\x1c\\x2f\\x78\\x66\\xc8\\x78\\x66\\xb8\\x8d\\x39\\x70\\xaf\\x19\\xcd\\x59\\xad\\x40\\xe5\\x60\\x74\\xf7\\xee\\x84\\x80\\xa6\\x64\\xdb\\x76\\xd6\\x28\\x2d\\x4b\\xb2\\xb0\\x53\\xc5\\x35\\xf4\\x4f\\x21\\x5e\\xb8\\x63\\xb8\\x94\\x68\\x5e\\x51\\xa4\\x66\\x15\\xaa\\x24\\xf6\\x6f\\x9e\\x84\\xc2\\xb1\\xc1\\x82\\x70\\x9d\\x03\\x28\\x55\\x4a\\xb2\\x70\\xa9\\xac\\x98\\x8e\\x35\\xd6\\x04\\x2e\\x50\\x54\\xd1\\x2b\\x6c\\x49\\xb0\\xe5\\x49\\x22\\x7c\\x79\\x12\\x8f\\x31\\xef\\x3a\\x89\\xf7\\x3f\\xa4\\x41\\xab\\x27\\x49\\x10\\xeb\\x49\\x72\\xd4\\x7a\\x62\\xad\\xec\\xf6\\x70\\xa1\\xef\\xdd\\x10\\x1a\\x67\\x51\\x70\\x1d\\xf3\\xb6\\x0e\\x65\\x46\\x85\\x14\\x3c\\xa3\\x05\\xff\\x17\\xcb\\xb1\\x9e\\xa9\\x6c\\x74\\xd5\\x68\\xb0\\xb7\\x64\\x54\\xb1\\xf1\\x92\\xd6\\xdc\\x30\\x54\\x2c\\xf8\\xe1\\x83\\x20\\x84\\xb9\\xed\\x5a\\x4a\\x30\\x46\\x78\\x7f\\x13\\x52\\x1c\\x4f\\x66\\xa2\\xaa\\xb6\\xc4\\x15\\xc7\\x4c\\xbc\\xc3\\x1b\\x9b\\x13\\x7f\\xa2\\x49\\xb2\\xea\\xd2\\x54\\x2f\\xd2\\x69\\x4d\\x54\\x2f\\x36\\x0b\\x41\\x03\\x7f\\x33\\x52\\xf9\\x1e\\xc4\\xc6\\xef\\x55\\x31\\x6d\\x50\\x5a\\xea\\x35\\x35\\x73\\x28\\xa6\\x7d\\x5f\\x1b\\x8a\\x69\\x3f\\xb0\\xa9\\x6c\\xc1\\xf6\\xc7\\x11\\x7c\\x05\\xd4\\x84\\xd0\\x41\\x56\\x54\\x87\\x5a\\x49\\x32\\x01\\x96\\x14\\x59\\xb3\\x4c\\x1a\\xc6\\xb3\\x53\\x8e\\xc3\\x05\\xd7\\x9c\\x16\\x2f\\x59\\x41\\x57\\x7b\\x5e\\x7f\\xb6\\xeb\\x75\\x5f\\x50\\x85\\xde\\x56\\x96\\x93\\x29\\x9b\\xc9\\x9a\\x81\\x07\\x41\\x18\\x8e\\x54\\xb5\\x8e\\x53\\x9c\\x9f\\x7e\\xc4\\xda\\x1f\\xbf\\x8d\\x12\\xb2\\xa6\\x55\\xfb\\x54\\xfd\\xfe\\xb5\\xbc\\x25\\x72\\xa6\\x99\\x20\\x87\\x6d\\x61\\xf9\\xa3\\xc0\\x98\\xd2\\xfa\\x20\\xe2\\x01\\x8f\\xb4\\x24\\x2f\\x9e\\xbb\\x41\\x9e\\x9e\\x73\\x01\\xdc\\x2f\\x4a\\xed\\xb5\\x7b\\xc9\\xd2\\xf8\\x69\\xff\\x92\\xfd\\xe2\\xac\\x29\\xba\\x3e\\x26\\xf4\\x3b\\x25\\xaa\\x5d\\x7d\\xec\\x53\\x49\\x5e\\x00\\x3d\\x9e\\x15\\x51\\x91\\xbb\\xa0\\x90\\xa7\\x77\\x4e\\x74\\x56\\x5d\\xc9\\xec\\x26\\x91\\x69\\xf4\\xfa\\x6c\\x82\\xbd\\x7d\\xd2\\x1d\\x75\\x7d\\x36\\x19\\xbc\\x51\\xfb\\x65\\x1f\\x3d\\x68\\x4b\\x07\\x3c\\xd4\\xd6\\x79\\x30\\x68\\x5c\\x6d\\x73\\xc2\\x4f\\xdd\\x71\\x18\\x0d\\x1a\\xd7\\x7d\\x6d\\xd0\\xb8\\x1e\\xd0\\x30\\xd4\\x1b\\xf2\\x26\\x5f\\xd5\\x34\\x63\\x93\\x7d\\x12\\xe0\\x1c\\x03\\x21\\xb9\\xad\\x0d\\x45\\x5a\\x39\\xce\\xb3\\x0b\\xc1\\x58\\x8e\\xfc\\xc3\\x4e\\x85\\x91\\xb9\\x99\\xc9\\xac\\x29\\x8a\\x15\\x9a\\xfb\\x50\\x0c\\xb0\\xd1\\x27\\x71\\x60\\xaf\\xd0\\xb5\\x15\\x73\\x9d\\x1f\\x77\\x1b\\x75\\xad\\x7e\\x52\\x79\\xd8\\x62\\x87\\x96\\x6f\\xaf\\x93\\x21\\xde\\xe8\\x23\\x8a\\x89\\xfe\\x96\\x6f\\x1a\\xee\\x20\\x51\\x7c\\x6e\\x96\\xcb\\x48\\x18\\x80\\x81\\x0b\\x58\\x37\\xae\\xe6\\x43\\x4b\\x88\\x19\\x75\\x26\\xeb\\x8c\\x4f\\x8b\\x15\\x59\\xd0\\xc2\\x28\\x4c\\xb7\\x5c\\x2f\\x08\\x25\\x37\\xbc\\x28\\x6c\\x37\\xfd\\x17\\xea\\xca\\x55\\xe1\\x41\\xa9\\xa6\\x90\\x62\\x0e\\x8b\\x41\\x6d\\xe4\\xf4\\x5d\\xc5\\x32\\x33\\x66\\x56\\x30\\x2a\\x9a\\x0a\\xe9\\x34\\x32\\xd2\\x4a\\x36\\x09\\x82\\xa7\\x9d\\x6b\\xd9\\xcb\\x54\\x82\\x5b\\x94\\x80\\x0a\\xd2\\x09\\x3e\\x7a\\xe6\\xbb\\x29\\x70\\xe4\\x9d\\x2b\\xa7\\x36\\x82\\x3e\\x7b\\xd3\\x84\\xb4\\x38\\x6c\\x01\\x15\\x44\\x31\\x7b\\xa4\\x03\\x9b\\xdf\\x63\\x8e\\x05\\x24\\x9c\\xf5\\x1e\\xeb\\x03\\xf4\\xeb\\x58\\xab\\x90\\x62\\x2c\\xd8\\x1c\\xf3\\xa9\\x2d\\x43\\xc3\\x08\\x47\\x1c\\x1f\\xe3\\xe9\\x7c\\x76\\xae\\xd2\\xb2\\x22\\xbc\\x2c\\x59\\x6e\\x74\\xe4\\x62\\x45\\x96\\x9c\\xf6\\xa6\\x04\\x72\\xb7\\xdb\\x13\\x45\\x0e\\x85\\x24\\xb2\\x32\\x4f\\x57\\x23\\xb8\\x86\\x9a\\xf9\\x6a\\xd1\\x68\\x92\\xcb\\x5b\\x11\\x91\\x15\\xe1\\x0b\\x5c\\x93\\x29\\xd3\\x1f\\x2f\\x6f\\x0d\\x01\\xd4\\xd7\\x5b\\x0f\\xc0\\x5a\\x91\\xea\\xbe\\xc4\\x6c\\x91\\xe8\\x71\\x3f\\x3f\\x7e\\xec\\x6c\\xa9\\xdc\\x68\\xb8\\xd4\\xfd\\x00\\x20\\x33\\x37\\x5a\\x36\\x7a\\x4f\\xde\\x91\\xfb\\xcc\\x47\\x98\\x89\\x1e\\x28\\x8a\\x1c\\xea\\xbd\\x37\\x89\\x90\\xe1\\x5f\\xd8\\xe1\\x52\\x6a\\x79\\x83\\xed\\x69\\x6b\\x53\\x3a\\xe7\\xbd\\xca\\x5d\\xa5\\x38\\x62\\xf7\\x60\\x6c\\xdb\\x6c\\xb9\\x00\\x66\\x6e\\xda\\xcc\\x66\\xac\\x86\\x97\\x0e\\x08\\xde\\x08\\x43\\xf7\\xf5\\x6b\\xdc\\x1b\\xd6\\xcf\\x80\\x6b\\x43\\xaa\\x98\\x1e\\x01\\xc4\\xb7\\x4d\\xf9\\xbe\\x67\\x48\\x8b\\x85\\x07\\xf5\\xa1\\x6a\\xa6\\x00\\xb2\\x59\\x90\\xf3\\x77\\xdf\\xf7\\x3b\\xa2\\x29\\x00\\xc0\\xe3\\x12\\xcb\\x60\\x9e\\xef\\x44\\xbf\\xb0\\xbf\\xb4\\xe7\\x61\\x1b\\x36\\x83\\x3d\\x16\\x59\\x21\\x95\\x4d\\x62\\x84\\x7d\\xc9\\x16\\x54\\x08\\xe6\\x0c\\x52\\x5c\\x83\\x35\\x7b\\xca\\x98\\x20\\xb2\\x62\\x18\\xf6\\xd6\\x8b\\x18\\x4a\\x14\\x17\\xf3\\x82\\x11\\xaa\\x35\\xcd\\x16\\xc7\\x86\\x3a\\xe1\\xce\\x42\\x9b\\x2d\\x68\\x7f\\xa3\\x74\\xcd\\x68\\x89\\x67\\xa2\\x66\\x25\\xe5\\x38\\x3c\\xa1\\x59\\x2d\\x95\\x22\\x65\\x53\\x68\\x5e\\xf9\\xce\\xfa\\x59\\x12\\x19\\xe4\\x6d\\x2b\\x4c\\x1e\\x73\\x7b\\x05\\x69\\x16\\x6d\\x5a\\xe2\\xa8\\xa5\\xd0\\x4e\\x5f\\x86\\x65\\x45\\xc0\\x7c\\x36\\x82\\xe2\\xb9\\x65\\xa5\\x57\\xc4\\x2c\\x6d\\xd1\\x3b\\x57\\x64\\xc6\\x6b\\xa5\\x49\\x56\\x70\\x26\\xb4\\x9d\\x19\\x22\\x83\\x01\\x0d\\x23\\x27\\x4e\\x0b\\xbb\\x22\\xca\\x2e\\x89\\xc8\\x41\\xf9\\xae\\xb4\\x22\\x90\\x7e\\xe7\\x89\\x70\\x5d\\xe5\\x5c\\x59\\x5b\\x87\\xea\\x57\\xcf\\x97\\xba\\x02\\x12\\x78\\x70\\xdc\\x8a\\xc0\\xd1\\x71\\x02\\x0e\\x52\\x64\\x7f\\x15\\x90\\x10\\x14\\x78\\x73\\x35\\x3e\\xa1\\x10\\x7f\\x04\\x5f\\x81\\x2a\\x0f\\xee\\x5e\\x8f\\x3a\\x99\\xc1\\xad\\x6e\\x61\\x0b\\xfc\\xaf\\x71\\x1d\\x38\\x50\\x82\\x2d\\xcd\\x3d\\x60\\x19\\x33\\xa2\\x28\\x4d\\xc8\\x64\\x1e\\x9d\\xc7\\x68\\x5a\\xcf\\x99\\x3e\\x73\\xf3\\xef\\x9b\\xba\\x9a\\x82\\xdb\\x84\\x95\\x30\\x43\\x03\\x51\\xbb\\x39\\xb0\\x0f\\x13\\x99\\x03\\x94\\x42\\x0b\\x77\\xb1\\xad\\x3c\\x27\\xce\\xab\\xa7\\xee\\x75\\x7d\\x4f\\xcd\\x4f\\xa7\\x51\\x61\\xc6\\x93\\x27\\x54\\x55\\x34\\x63\\x8a\\x1c\\x5e\\x4c\\xce\\x46\\x64\\x72\\xf1\\xd2\\xa6\\x35\\xc9\\xd9\\x3a\\xb6\\x5c\\xdf\\x65\\x69\\x0b\\xc2\\x5a\\x0d\\x78\\x1b\\x71\\xbe\\x36\\x4b\\x40\\x52\\x00\\x32\\x65\\xe9\\x9d\\x78\\xa5\\xac\\x5f\\xd4\\xf3\\xf5\\xd6\\xa7\\x00\\x54\\x34\\x5f\\xa0\\x9b\\xa8\\x06\\x54\\x23\\xeb\\xbd\\x30\\x67\\x1b\\x15\\x12\\x7b\\x6b\\x59\\x0b\\xef\\x63\\xb1\\xd8\\x7b\\x7a\\x72\\x70\\x14\\x3f\\x5f\\xbb\\xe9\\xe0\\xd0\\x76\\x2b\\x65\\x05\\x01\\x90\\x98\\xb5\\xfd\\xc8\\x23\\xa4\\x40\\xf2\\x95\\x8d\\xc6\\x7e\\xf4\\xb2\\xb8\\x81\\x16\\xf5\\x96\\x29\\x45\\xe7\\x6c\\xd2\\x33\\x18\\x28\\x6d\\x75\\x5c\\x88\\x22\\x6a\\x19\\x36\\x94\\xa5\\x2d\\x10\\x29\\xcd\\xff\\x26\\x4c\\x37\\x0c\\xcd\\x36\\x25\\x4e\\xa4\\x17\\x05\\xee\\x72\\xdd\\xd6\\x5c\\x6b\\x06\\xef\\x03\\x54\\x3b\\x82\\xb3\\xbb\\x8e\\x6e\\xd9\\x4d\\x73\\xec\\x35\\x9e\\x5d\\xf4\\x70\\x3c\\x23\\xf8\\x8b\\x1c\\x13\\x06\\xa7\\x8c\\x4c\\x6b\\xce\\x66\\x64\\xc6\\x21\\x83\\x11\\x72\\xfb\\x46\\x08\\xd3\\x4f\\xd1\\x79\\xa3\\x14\\xab\\x61\\xda\\xd6\\x20\\xe7\\xa6\\xdf\\x8f\\x9e\\x7f\\xd8\\xf9\\xeb\\xba\\x11\\x19\\x0d\\x8a\\x42\\x02\\xf6\\x16\\x9f\\x91\\x39\\xe4\\x13\\x5a\\xf3\\xd3\\x9f\\x9e\\xff\\xed\\x2f\\x64\\xba\\x32\\x9a\\x12\\xdc\\x49\\x2d\\x35\\x2d\\x1c\\x01\\xa4\\x60\\x62\\x6e\\x76\\x11\\x84\\x9d\\x7e\\x2f\\x76\\x07\\xbf\\xc9\\x6f\\x4e\\xc1\\x4b\\xae\\x71\\x81\\x5e\\xfc\\xe1\\x66\\x1a\\xf5\\xe8\\x81\\x64\\x72\\x92\\xb3\\xe5\\x49\\x70\\x84\\xc6\\x85\\x9c\\xf7\\xeb\\xf5\\xcc\\xc3\\x1d\\x35\\x55\\xde\\x37\\x2a\\x22\\xf5\\x8d\\xde\\x69\\x01\\x75\\x57\\xdd\\x83\\x2c\\xe4\\x2d\\x9a\\x51\\x37\\xaf\\x6a\\x00\\x85\\x52\\xc9\\xaa\\x29\\x60\\xe1\\xc8\\xf7\\x1e\\xc0\\xae\\x51\\x6c\\x1d\\x1a\\x28\\xd6\\x3c\\x1f\\x70\\x3b\\x08\\x61\\xb0\\xc3\\xae\\xbd\\xf5\\x36\\x99\\xd6\\x91\\x29\\x2d\\x30\\x83\\xf5\\x78\\xfb\\x42\\x1d\\xbd\\xed\\xe0\\xdf\\xd3\\xa2\\x98\\xd2\\xec\\xe6\\x5a\\xbe\\x91\\x73\\xf5\\x4e\\x9c\\xd7\\xb5\\xac\\xbb\\x73\\x2e\\xa8\\x91\\xa6\\x17\\x8d\\xb8\\x81\\xba\\xad\\x2d\\x5a\\xab\\x9c\\xdb\\xc0\\x5b\\x00\\x56\\xec\\x2e\\x6c\\x2f\\x62\\xdc\\x2c\\x11\\x3f\\xd3\\x29\\x03\\xce\\xfa\\xdd\\x8e\\xcc\\xee\\x78\\x6b\\xe2\\x16\\x84\\x19\\x9a\\xfb\\x8b\\x38\\xe1\\x3c\\x54\\x78\\xb5\\xff\\xf0\\xfc\\x4f\\x7f\\x45\\xe6\\x42\\x64\\x4d\\xfe\\xfa\\x1c\\x92\\xdf\\xd5\\x08\\x1f\\x00\\x90\\x7d\\x8d\\x92\\x53\\xd2\\xa2\\xe8\\x2b\\xd4\\x84\\x2c\\xc0\\x1c\\xb6\\xaf\\xf6\\xca\\xeb\\x9d\\xdd\\xee\\xcf\\x36\\xd6\\x5c\\x5f\\xff\\x08\\x92\\x18\\xd7\\x8a\\x15\\xb3\\x11\\xa2\\xa1\\x78\\x83\\xf2\\x01\\xe8\\x35\\x07\\xf6\\xc9\\xeb\\x8f\\xa4\\xb3\\x7b\\x73\\xc9\\x52\\x16\\x4d\\xc9\\x5e\\xb2\\x25\\xcf\\xfa\\x85\\x0e\\x74\\x76\\xa5\\xd3\\x9b\\x73\\x90\\x15\\x5c\\x81\\x2c\\x39\\x2d\\x64\\x76\\x43\\x72\\xfb\\x61\\x90\\x4f\\xb2\\x5e\\xc7\\xb9\\xff\\x2a\\xf4\\xcd\\xac\\x89\\xc8\\xa8\\xb9\\x77\\xfe\\x9d\\x5c\\x9a\\x92\\x56\\x95\\x91\\xa3\\x01\\xd6\\xaa\\xa6\\xb7\\x9d\\xc5\\x00\\xd6\\x04\\xe8\\xa1\\x91\\x5a\\x4f\\x74\\x18\\x4b\\x6c\\x10\\xcb\\xd8\\xce\\xc8\\x3c\\x53\\xbd\\xbb\\xe8\\x9d\\x80\\x13\\x1f\\x03\\xd3\\x52\\xdf\\x3f\\x82\\xa0\\x73\\x20\\xda\\x0e\\xdd\\x6d\\xa8\\xe0\\xdf\\x88\\xfc\\xb1\\xa1\\xab\\xfb\\x82\\x62\\xfe\\x60\\xa0\\x04\\x69\\x8e\\x0f\\xbc\\x32\\xfd\\x1d\\x07\\x09\\xc2\\x10\\xe2\\x12\\x89\\x3a\\xeb\\x22\\x7c\\xf8\\x47\\x49\\xb5\\xd5\\x8f\\x9c\\xf9\\x82\\x92\\x8a\\xd5\\x8a\\x2b\\x23\\x3a\\x7d\\x80\\x0b\\x75\\x56\\x50\\x5e\\x06\\x8e\\xf3\\xdd\\x2c\\x02\\x5e\\x6e\\x28\\x7f\\x1a\\xcf\\x29\\x7b\\xbe\\x5f\\x13\\x99\\x5b\\x3a\\x80\\x83\\x62\\x65\\xdb\\x4f\\x69\\x7a\\xe4\\xaa\\x99\\xc2\\xb1\\x83\\xaf\\x7f\\x59\\xfc\\xa8\\xa4\\xf2\\xc5\\xae\\xd9\\xf9\\x87\\x76\\xc7\\xbb\\xdc\\xdc\\xfc\\xc6\\xb3\\x73\\xfc\\xd6\\x53\\x62\\xe2\\x30\\xbf\\xaf\\x95\\x87\\x7b\\xe2\\x13\\xb1\\xaa\\xa8\\xf8\\x3d\\xe0\\xfc\\xf6\\x64\\x74\\x59\\x7d\\xc7\\x58\\x84\\x57\\x3a\\x50\\x2b\\xad\\x11\\xe7\\x18\\x11\\xe9\\x23\\x08\\x30\\x57\\xd1\\x0e\\x4a\\x0e\\xbe\\x3d\\xd8\\xe9\\xfb\\x81\\x3b\\x53\\xcb\\x8a\\xce\\x41\\xeb\\xdb\\x87\\x0d\\x5a\\xa7\\x29\\xc4\\x3f\\x5d\\xc8\\xdb\\x90\\x65\\x56\\xf6\\x5b\\x86\\x63\\x3a\\x10\\xed\\x85\\x8c\\xda\\x1d\\x8c\\x87\\x75\\x27\\xc2\\x6a\\xae\\x58\\x47\\xe0\\x96\\xae\\x08\\xad\\x65\\x23\\xa2\\xf2\\xf0\\xc1\\xdd\\xe7\\xdd\\xc1\\x6f\\xd7\\x26\\x7b\\x29\\x05\\x73\\xa1\\x27\\x31\\xa3\\x5c\\x77\\xac\\xc3\\x10\\x85\\xc3\\x05\\x79\\x71\\xfc\\xe2\\xf9\\x53\\x91\\x57\\x60\\x86\\x6b\\xf2\\xca\\xa5\\x97\\x57\\xf0\\x05\\xd8\\xe9\\x5c\\x5d\\xfd\\xf1\\x7d\\xb8\\x53\\x6f\\xad\\x05\\xba\\x2d\\x30\\xce\\x5d\\x01\\x5b\\xf8\\xd5\\x6d\\xcd\\xb5\\x3d\\xe6\\xb7\\x5c\\x31\\x72\\x08\\xba\\x2f\\x91\\x75\\x08\\x60\\x1a\\x05\\x93\\x1b\\x5a\\x4a\\x22\\x0b\\x91\\xa7\\x80\\xb9\\x55\\xcd\\x74\\x5f\\x1f\\x24\\xfb\\xf2\\x00\\x43\\xdb\\xee\\xaa\\xb8\\xf7\\x6d\\x4a\\xb4\\x3f\\xcf\\x9e\\x91\\x43\\x1c\\xe3\\x00\\x41\\x1a\\x23\\x76\\x3e\\xc1\\x45\\xb2\\x7b\\x75\\x7e\\x57\\x45\\x14\\x24\\x4b\\xb7\\x5f\\xe7\\x77\\x15\\x05\\xef\\x4a\\xb5\\x17\\x1b\\xf7\\x5f\\x6c\\x41\\x97\\x0c\\x30\\x31\\x79\\x41\\xeb\\x02\\x82\\x38\\xaf\\x70\\xc9\\xc8\\xb4\\xd1\\x84\\x89\\x25\\xaf\\xa5\\x00\\x8f\\x26\\xe0\\x2a\\x4c\\x0b\\x46\\x6a\\x36\\x63\\x35\\x13\\x19\\x53\\xe4\\x9b\\xc3\\x0f\\xa7\\xef\\x21\\xc8\\xff\\x08\\x1e\\x55\\xe6\\xe6\\xd7\\x28\\xeb\\x82\\xec\\xcc\\x21\\xe8\\x6e\\x1f\\xcf\\x1b\\x71\\x73\\x37\\xc7\\x05\\x1e\\x70\\xb7\\x16\\x66\\x6e\\x65\\xa3\\x1b\\x5a\\x00\\x74\\x68\\x56\\x34\\x8a\\x2f\\x77\\xf5\\x44\\x58\\x70\\xd5\\x97\\xbc\\xd7\\x91\\x4e\\x71\\x98\\xcf\\x82\\x3d\\xdd\\x80\\x7a\\x8d\\x73\\xf1\\x7f\\xa2\\xda\\xeb\\x81\\xf2\\x70\\x62\\x61\\x6c\\xb7\\xb5\\xcb\\xf7\\x73\\x3c\\xf0\\xf9\\x42\\xdb\\xa4\\xc2\\xb5\\x48\\x81\\x20\\xf0\\xa6\\xec\\xed\\xd4\\xdc\\xa5\\x85\\xde\\x08\\xb4\\xa7\\x05\\xa7\\xea\\xa1\\x0a\\x58\\xdc\\x29\\x79\\xdd\\x0e\\x0b\\xa1\\xdc\\xc2\\xd6\\xab\\xa1\\x85\\x37\\x1f\\x1b\\xca\\xd0\\x85\\x75\\x31\\xb1\\x81\\x46\\x6e\\x43\\xb9\\xf8\\x5f\\x4c\\x29\\xf0\\x96\\x10\\x0c\\xf5\\x87\\x3f\\x79\\x20\\x25\\xe8\\x4d\\x9a\\xb5\\xe7\\xea\\xd8\\x07\\x98\\x83\\x28\\x03\\xd5\\xe6\\xc1\\x64\\x22\\xa4\\x18\\x2f\\x02\\x90\\xfd\\x4a\\xe6\\x0f\\x34\\x99\\xf4\\xb5\\x72\\xf4\\xb2\\x6f\\xc4\\x5e\\x63\\xbf\\x45\\x64\\x21\\x0b\\x9b\\x81\\xe3\\xcc\\xda\\x53\\xa6\\x6f\\x19\\x13\\xe4\\x62\\x02\\x1b\\x64\\x56\\x05\\xc1\\x74\\xb6\\x6f\\x13\\x86\\x02\\x00\\x84\\xbe\\xbd\\x38\\x0f\\xa6\\x26\\xd8\\x60\\xd8\\xb2\\x87\\x5e\\x91\\x08\\x2b\\x4b\\x8c\\x89\\xc2\\xaf\\x4c\\x34\\x23\\x7e\\xed\\xd7\\xd8\\xa5\\x3b\\xd3\\xa9\\x5c\\x32\\xd8\\x82\\x3c\\xaf\\x7b\\xa6\\xd0\\xec\\xcc\\xee\\x16\\xf5\\xbe\\xf1\\x2a\\x7a\\x39\\xdb\\x65\\x73\\x56\\x79\\xa8\\xf3\\x06\\xdc\\x00\\x0e\\xea\\x23\\xf3\\xe0\\x8b\\xc9\\xd9\\x63\\xf2\\xdf\\x1f\\xac\\xf7\\xde\\x0c\\x7d\\xa0\\x08\\xaf\\xb2\\x36\\x42\\xec\\xa1\\x33\\x6f\\xa3\\xa2\\x02\\x74\\x84\\x1e\\x5a\\x58\\x5f\\xcd\\x2b\\xe0\\xc9\\x8f\\xfd\\x84\\x11\\x81\\xe3\\x1a\\x9e\\x68\\xc1\\x04\\xad\\x7d\\x1d\\x1c\\xce\\x95\\xcc\\x8f\\xd7\\x97\\xda\\xfe\\x45\\xff\\xe5\\x76\\xf9\\x6e\\xf8\\x60\\xda\\x48\\xea\\x91\\xcf\\x12\\x5e\\xe3\\xc1\\xe0\\x70\\x75\\xc9\\x61\\xbd\\xab\\x85\\xec\\x6e\\x63\\x27\\x17\\x2f\\x77\\x78\\x2f\\x2a\\x9e\\x7f\\xdd\\xf7\\xe2\\x07\\xf5\\x60\\x30\\xcd\\xa4\\x0b\\x08\\x55\\x6c\\xd2\\xae\\x60\\x9f\\xe8\\x0b\\x5b\\xb8\\xc6\\xfe\\x35\\x24\\xd7\\x4b\\x4d\\xaa\\x9a\\x29\\x26\\xfc\\xdd\\xc9\\xb7\\x85\\x2e\\xc3\\xab\\xd0\\x9d\\xc5\\xc8\\xfc\\x3c\\x6b\\x8a\\x87\\x0a\\x9a\\xb2\\x0e\\xb2\\x73\\x7d\\x2a\\x33\\xf5\\x89\\x88\\x20\\x6e\\xd2\\x25\\xe5\\x05\\x28\\xd1\\x01\\xdc\\xd4\\x06\\x01\\x36\\xc0\\xf2\\x81\\x14\\x14\\x92\\xe6\\x88\\x9f\\x71\\xc3\\x6a\\xc1\\x0a\\x52\\xca\\xbc\\x29\\xd0\\x93\\x45\\xce\\x4e\\x27\\xbf\\x5c\\xfd\\x78\\xf5\\xcb\\xdb\\x77\\x2f\\x7f\\x78\\xf3\\xe0\\x8c\\x7c\\x4c\\x33\\x61\\xed\\x11\\x1f\\x11\\x4a\\x04\\xbb\\x05\\xca\\x05\\x48\\xd3\\x99\\xad\\xf4\\xe0\\xd1\\x5a\\x0c\\x73\\xbc\\xb2\\xf1\\xc6\\x68\\x11\\x44\\xd3\\xf4\\xac\\x29\\xcc\\x97\\x1e\\x48\\x41\\xc9\\x35\\x9f\\x53\\xe8\\xac\\x55\\xca\\xa6\\x35\\xa3\\x37\\xb2\\xd1\\x64\\xd9\\x14\\x82\\xd5\\x74\\xca\\x0b\\x6e\\x04\\x39\\xc2\\x96\\x4c\\xa0\\x3f\\xd4\\xfc\\x81\\x21\\x32\\xac\\xf6\\xc4\\x1f\\x3a\\x78\\x58\\x0c\\xcc\\x56\\x1e\\x31\\x8b\\x6a\\x46\\xa6\\x99\\x35\\x0a\\x58\\xd4\\x19\\xf8\\xb0\\xaa\\xf9\\x92\\x17\\x6c\\xce\\x3c\\x94\\x43\\x1f\\x54\\xb1\\xae\\x19\\x9e\\x16\\xd5\\x82\\x8e\\xa1\\x48\\x3a\\xb1\\x95\\x4c\\xe0\\x44\\x2d\\xa4\\x90\\x35\\x46\\xdd\\x20\\xc0\\xa1\\x7d\\x21\\x20\\x49\\x16\\x2f\\xab\\xab\\x7d\\x85\\x01\\xf1\\x57\\x2e\\x30\\xdd\\xc6\\xa3\\x3f\\x1a\\xb3\\x7a\\xb8\\xfd\\x3e\\x8e\\x57\\x5d\\x75\\x21\\xb8\\x2d\\x05\\x4e\\x1e\\x9c\\x3c\\x38\\xee\\x60\\xbb\\x85\\xa2\\xd5\\x5c\\xa0\\x77\\xc7\\x63\\xec\\x65\\xa1\\x04\\x9d\\xf6\\x63\\x87\\x77\\x0e\\x49\\xa3\\x7d\\xd6\\xfc\\xc1\\x62\\x27\\x58\\x2c\\x26\\x4d\\x51\\x5c\\xb1\\xac\\x66\\x0f\\x8d\\x71\\x88\\x5b\\xfa\\x8b\\xb5\\xb1\\xef\\x33\\x02\\x04\\x96\\x44\\x80\\x6e\\xb6\\x5f\\x16\\x2d\\x3e\\x6b\\x90\\xd8\\xd0\\xa2\\xf6\\x55\\x4d\\x01\\xf9\\xdf\\x50\\xa6\\x1b\\xb7\\x13\\x66\\xab\\x82\\x00\\x34\\xae\\x5c\\x96\\x4c\\x9f\\xd7\\xa4\\xb3\\xc7\\x8a\\x79\\xd2\\xdc\\xf6\\x56\\x54\\x29\\x8c\\x13\\xe5\\x22\\xe7\\x4b\\x9e\\x37\\xb4\\x00\\xb2\\xc0\\x54\\x64\\x73\\x40\\xa8\\x2d\\xd1\\x8b\\x1c\\xb1\\xec\\x59\\xb1\\xf2\\x81\\x29\\xc2\\x2d\\xaf\\x3a\\xc1\\x35\\xf9\\x1d\\x4e\\x66\\xc5\\xc5\\x7c\\x0c\\xbf\\x31\\x64\\xda\\xf9\\x8c\\xa5\\x18\\xd3\\xf1\\x43\\x43\\x70\\xbe\\x2a\\x3b\\x07\\x14\\xf9\\x7e\\x07\\x86\\x81\\xf7\\xee\\xb4\\x39\\x86\\xae\\x08\\x13\\xb2\\x99\\x2f\\x60\\x79\\xeb\\x92\\xba\\x82\\x62\\x05\\xd3\\x50\\x38\\xc9\\x86\\x8f\\xf6\\x31\\x68\\xf8\\x93\\x9d\\x5b\\xab\\x44\\x58\\x2c\\xab\\x7b\\xb2\\xbf\\x12\\x5b\\x47\\x5f\\xf7\\x6b\\x0a\\x7b\\xf3\\x65\\xc0\\xb8\\xed\\xca\\xf6\\x74\\x20\\x3c\\xf0\\x36\\xc9\\x25\\xab\\x97\\x9c\\xdd\\x9e\\x58\\x35\\x70\\x6c\\xde\\xfd\\x31\\xae\\xbd\\x3a\\x81\\x2d\\x3c\\xf9\\x1d\\xfc\\x5f\\x2f\\x6a\\xae\\xdf\\xbd\\x7c\\xf7\\x2d\\x39\\xcd\\x73\\x1b\\x25\\xe0\\xc4\\x23\\xf3\\xe8\\xab\\x63\\x42\\x2b\\xfe\\x81\\xd5\\x0a\\x6a\\x83\\xde\\x70\\x91\\x8f\\x48\\xc3\\xf3\\xef\\x1e\\xcf\\x72\\x41\\xd6\\x81\\x8a\\x4a\\x5a\\x8d\\xed\\xed\\xd7\\xb2\\xe4\\xd9\\x43\\x9e\\x23\\xc1\\xdb\\x14\\xcb\\x47\\x7d\\x8c\\xde\\xd8\\xc7\\xc6\\x42\\xa1\\xf2\\x7f\\xe1\\x3d\\x0f\\x84\\xba\\x29\\x2b\\xa4\\x98\\x07\\x20\\xb0\\x46\\x78\\x7d\\xe8\\xab\\x21\\xb8\\xee\\x08\\x8a\\xe0\\x0d\\x83\\x3a\\x79\\xe0\\x4e\\x90\\x75\\x0e\\xa9\\xb5\\x5c\\xd6\\x9d\\x38\\x11\\x33\\x3a\\x94\\xc4\\x0a\\x92\\x7a\\xa9\\x78\\xa8\\xb9\\x8e\\x77\\x46\\x87\\xac\\x10\\xd5\\x2a\\x3e\\x18\\x1c\\xef\\x00\\x13\\x5d\\xdd\\x5b\\x57\\x98\\x0b\\x85\\xc9\\x05\\x15\\x39\\xfc\\x98\\x65\\xb2\\xce\\x1f\\x7e\\x4e\\xcc\\x53\\xa8\\x7d\\x76\\x32\\x26\\xfd\\x60\\x5a\\x16\\xc8\\x45\\xe6\\x11\\xa4\\x62\\x9d\\x4e\\xd0\\xd4\\xea\\xb2\\x93\\xc3\\x69\\xad\\x19\\x0f\\x1c\\xbe\\x11\\xfc\\xff\\x1a\\x46\\x68\\x29\\x8d\\x5c\\x10\\x55\\x78\\x7f\\x7d\\x27\\x4b\\xba\\x02\\xc1\\x0f\\x16\\xed\\x8d\\x83\\xdb\\xb0\\xb8\\x85\\x6a\\x44\\xde\\x33\\xa3\\x77\\xb5\\xb8\\xb4\\x23\\xf2\\xa6\\x0b\\x54\\x3b\\x32\\xf3\\xbc\\x42\\x90\\x48\\xfb\\xab\\x87\\xeb\\x02\\x90\\xc6\\x29\\x9b\\x3a\\x63\\xef\\x31\\x20\\xb0\\x74\\x55\\xca\\x37\\x97\\xd5\\x9c\\x3d\\x4d\\x6f\\x98\\x40\\x0f\\x8a\\xd9\\x52\\x88\\x79\\x6c\\x6a\\x38\\x69\\xd9\\x82\\xe5\\x4d\\xf1\\xf0\\x2d\\x9e\\xae\\xc8\\xcc\\x88\\x3b\\xd6\\xb1\\xbb\\xe0\\xf3\\x05\\x53\\xda\\x59\\xc6\\x4e\\x20\\x79\\x06\\xa3\\x4f\\x69\\xb6\\xf0\\xe4\\x02\\xf3\\x09\\xf2\\xee\\x5b\\xcf\\x70\\x49\\xef\\x1e\\x9e\\x4a\\x05\\xaf\\x00\\xd5\\x0e\\x83\\x09\\x95\\x4d\\xd5\\x94\\xee\\x79\\x58\\x3f\\x4f\\xea\\x98\\xbc\\x31\\x84\\xe1\\x8d\\xa4\\x55\\x55\\x70\\x27\\xb8\\x75\\xb6\\xf9\\xc1\\x17\\x0e\\xc0\\x18\\xc0\\x6d\\x4e\\x66\\x54\\x2d\\xb8\\x14\\xb1\\x07\\x2d\\x43\\x47\\x61\\xd6\\xd4\\xe6\\x7d\\x2b\\x56\\x80\\xa5\\x97\\xe7\\x46\\x84\\xa8\\x49\\xcd\\x4a\\xb9\\x7c\\xb8\\x69\\x2f\\xda\\xf9\\x18\\x87\\x50\\x63\\x16\\x79\\x1c\\x88\\xa4\\x5f\\x89\\x9c\\x79\\xea\\x71\\x36\\xcc\\x79\\xc9\\xd6\\x1e\\x0c\\x3c\\x80\\x46\\x40\\x74\\x85\\x7b\\xea\\x46\\xb4\\x01\\xc3\\x3d\\x1e\\x8f\\x08\\x91\\xae\\x7f\\x78\\x70\\xaf\\xb0\\xde\\x18\\x09\\x92\\xd6\\xf3\\x9d\\x45\\xda\\x9f\\xd6\\xf3\\x06\\x39\\xa6\\x7d\\xe2\\xdb\\x8a\\xdf\\xfd\\x93\\x07\\xd7\\xc2\\x03\\x0e\\x14\\x39\\x7b\\xfb\\x32\\x04\\xff\\x0a\\x8b\\xa2\\x39\\x68\\xb8\\x7e\\xc3\\x7d\\x48\\x1b\\x7c\\x03\\x52\\x86\\x8f\\xe8\\xe9\\x45\\x51\\xe6\\x39\\x8b\\xe1\\xf4\\xc5\\xd2\\x19\\x44\\x3c\\x81\\x4e\\x8f\\xe7\\xa2\\x6a\\xb4\\x15\\x3e\\x83\\x72\\x2c\\xd9\\x82\\x8a\\xb9\\x11\\x78\\x5e\\xca\\xc6\\x4c\\xec\\x9b\\x6f\\x60\\x12\\x35\\xcb\\x9b\\x8c\\xf5\\xcb\\x09\\x41\\x83\\x0b\\xde\\xdc\\x6f\\x6c\\x48\\x88\\xab\\xfb\\x04\\xef\\x92\\xca\\x68\\xe5\\x96\\x26\\x5c\\x3d\\xb5\\x12\\x9a\\xde\\x7d\\x4b\\xf8\\x31\\x3b\\x26\\xcf\\xbe\\x09\\x3e\\x7a\\x06\\x14\\xf7\\xa2\\xa6\\xaa\\xa5\\x99\\x8a\\x05\\xe4\\x81\\xd9\\x17\\x5c\\x43\\x52\\xc6\\xb3\\x70\\x84\\x63\\x72\\x6e\\xe8\\x82\\x08\\x4b\\xbf\\xb7\\x01\\xc6\\xca\\xb4\\xdd\\xd9\\x11\\xa9\\xd9\\x9c\\xd6\\x79\\xc1\\x7a\\xa6\\xb4\\xcb\\x19\\xb9\\x0d\\x00\\x8d\\x7c\\x48\\x17\\xbb\\xe3\\x4a\\x2b\\x6b\\x39\\x3f\\x4e\\x13\\xb2\\xf2\\xb9\\x6f\\x87\\xa6\\xea\\xc6\\xbc\\x14\\x86\\xf9\\x8d\\x73\\xaa\\xe9\\x38\\xe0\\xba\\x27\\x68\\x38\\x1b\\xdb\\x02\\xce\\x63\\x6a\\xef\\x71\\xfb\\xa8\\x9c\\xfc\\xce\\x42\\x71\\x8e\\xa9\\xff\\x16\\x17\\x63\\x3a\\x86\\x92\\xc6\\xbf\\x19\\xa7\\x79\\x44\\x05\\xf1\\x14\\xfc\\xf5\\xdc\\xb3\\x53\\x5c\\xb9\\x63\\x72\\x29\\x75\\xab\\x00\\xf9\\xc7\\x31\\xa2\\xce\\xf4\\x76\\x8e\\x7b\\x7e\\x79\\xfd\\xfe\\xc7\\xc9\\xbb\\x8b\\xcb\\xeb\\x81\\xf1\\x0e\\x8c\\x17\\xda\\xc0\\x78\\x07\\xc6\\xdb\\x63\\xe0\\x9e\\x8c\\x97\\x89\\xe5\\xae\\x98\\xae\\xb3\\x6c\\x6d\\x8b\\xd2\\x5e\\x2f\\x86\\x19\\x99\\xc6\\xf8\\x84\\xd2\\x40\\xcf\\xc5\\xf2\\x03\\x35\\x0a\\xb5\\x0d\\x10\\xb0\\xd1\\x8b\\x5b\\x02\\xdd\\xed\\x17\\x50\\xd9\\x3f\\xfb\\xea\\xf3\\x40\\x77\\x98\\xc5\\x99\\x30\\x77\\x2b\\xf4\\x05\\x6c\\xdb\\xb5\\xb6\\x54\\x0b\\x25\\x67\\xbf\\x5c\\xbc\\x3c\\xbf\\xbc\\xbe\\xf8\\xfe\\xe2\\xfc\\xfd\\x4e\\xd3\\x50\\x22\\x6b\\x3a\\xa6\\x4b\\x40\\x79\\x88\\x38\\x13\\x31\\x4c\\x2b\\x08\\x55\\x35\\x5b\\x72\\xd9\\xa8\\x62\\xe5\\x6b\\x7e\\x6f\\x67\\x57\\x9b\\x29\\xb5\\x22\\x86\\x02\\x2a\\x56\\xbe\\x0e\\xfb\\xd6\\x01\\xd7\\x44\\xb1\\x6d\\x62\\x55\\xc4\\xf0\\x3b\\x16\\xc8\\x2c\\x11\\x29\\xc4\\xb2\\x88\\xf1\\xb7\\x08\\x74\\x9f\\x2f\\x9c\\x45\\x8c\\xdb\\x4b\\xac\\xbb\\x4f\\x44\\x8b\\xa0\\xa3\\x2b\\xdc\\x45\\x74\\xd4\\x4d\\x78\\xda\\x3d\\x27\\xfb\\xbe\\x96\\x65\\x22\\x6e\\x76\\x85\\x4e\\x02\\x17\\x36\\xb6\\xed\\xaa\\x1e\\xd8\\xea\\x0f\\x1d\\xf1\\xd8\\x2a\\x7a\\x6d\\x59\\x08\\xa3\\x6e\\x96\\x95\\xee\\x99\\x7e\\x44\\x52\\x55\\xaf\\x4e\\x53\\xe8\\x19\\x53\\x91\\xde\\xd2\\xea\\xef\\x6c\\xf5\\x9e\\x45\\x16\\xc0\\xe9\\xae\\x37\\x2b\\x58\\x66\\x64\\x1e\\x72\\xc3\\x56\\x98\\xef\\x7c\\xe6\\x06\\x8b\\xab\\x01\\xb4\\x87\\xc5\\xbf\\x6f\\x58\\x4c\\x61\\xf6\\x94\\x55\\xbb\\x6f\\x58\\x44\\x2e\\xb7\\x6b\\x1b\\x25\\x9d\\xcd\\x16\\x82\\x98\\x6f\\xf6\\x74\\xaf\\x8a\\x58\\xef\\x6b\\x95\\xf2\\x74\\x91\\x24\\xdd\\xb6\\x5f\\x71\\x25\\xdd\\xf6\\x58\\x51\\x26\\xdd\\x96\\xf0\\x30\\xb9\\xb8\\xc1\\xc4\\x07\\x0a\\x03\\x44\\x57\\x9d\\x57\\xdf\\xf3\\x42\\x82\\x68\\x81\\x70\\xc5\\x5c\\x82\\x85\\x15\\x60\\x13\\x2d\\x4d\\x1c\\x08\\x01\\xb6\\x54\\xd1\\x39\\xeb\\x0d\\xce\\x46\\xda\\x87\\x27\\xfa\\xfa\\xb6\\x2f\\x17\\x06\\x45\\xfb\\xda\\x79\\xf9\\xb7\\x0e\\x07\\x5b\\x91\\x92\\x69\\x9a\\x53\\x4d\\x8f\\xcd\\xe5\\x19\\x75\\x7f\\xb4\\xd1\\xf5\\xff\\xe3\\x7f\\x59\\xd0\\x29\\x2b\\xd4\\x4f\\x07\\xff\\xf9\\xf7\\xf3\\x1f\\xff\\xbf\\x83\\x9f\\xff\\x27\\xfc\\x0c\\x24\\x0d\\x8c\\xe0\\x0c\\xbe\\x10\\x39\\x05\\x40\\x1d\\x17\\x32\\x67\\x97\\x40\\x1d\\xfc\\x68\\x95\\x94\\x53\\x0c\\xd2\\xb0\\x1f\\x00\\xf0\\xeb\\x31\\x66\\x8e\\xf9\\x1f\\x2b\\x99\\xaf\\xff\\x14\\x51\\x58\\x8b\\xec\\xe7\\x93\\x0d\\x7b\\x1b\\x01\\x56\\x85\\x2d\\xdd\\xc3\\xdd\\x72\\xc7\\xc4\\xdc\\xc7\\xf6\\xea\\x8e\\x31\\x54\\x4a\\xa7\\xf0\\xcf\\xef\\xdd\\x12\\x18\\xb9\\xd6\\x43\\x73\\x0b\\x40\\xd8\\x35\\x6a\\x4a\\xb7\\xd2\\xe6\\xb3\\xe5\\x8b\\x28\\x65\\x09\\x5b\\x42\\x6e\\xed\\x77\\x30\\xf1\\x82\\xc1\\x8a\\xd8\\xd5\\x42\\x0e\\xe0\\x45\\x1f\\x1f\\x32\\xee\\xe2\\xb6\\xc9\\xe9\\xe4\\x82\\x2c\\x71\\x85\\xf7\\x68\\x71\\xbe\\x14\\xbb\\x76\\xb1\\x56\\xdf\\xef\\x35\\xdb\\xf6\\x11\\x61\\xeb\\x40\\x99\\xdf\\x62\\x2a\\x8b\\xfb\\xdc\\xe2\\x30\\x2b\\x5f\\xf5\\x8d\\x3d\\x3c\\xef\\x7f\\xbd\\x1d\\x62\\x97\\xc7\\x59\\xd5\\x8c\\x6c\\xf7\\xc7\\x25\\x2b\\x65\\xbd\\xf2\\x3f\\x7a\\xcc\\xc4\\xb1\\xd2\\xb2\\xa6\\x73\\xc0\\x37\\xc2\\xc1\\xf1\\xcf\\xfc\\x4f\\xf8\\x87\\x1d\\xf2\\x36\\xff\\x1a\\x6d\\x69\\x6d\\x30\\x97\\x7d\\xa2\\xe2\\x00\\x5b\\xf6\\x92\\x65\\xbb\\x7d\\xdb\\x13\\x8e\\x9d\\xc5\\x16\\x72\\xe9\\xb6\\x6e\\x19\\x64\\xef\\x05\\x40\\x0d\\xc7\\xaf\\x22\\x18\\x30\\x2c\\x94\\xe7\\xa8\\x4d\\x74\\x01\\x2b\\x9b\\x58\\x92\\x25\\xad\\x55\\x4c\\x1d\\x64\\x6c\\x09\\x99\\x74\\xce\\x97\\x5c\\xc9\\x08\\x4c\\x24\\xdf\\xd1\\xa6\\x44\\xed\\x52\\xae\\x2c\\xae\\x3a\\xa6\\x56\\x78\\x93\\xfd\\x5d\\x05\\xd5\\x8d\\xfc\\x65\\x5f\\x7b\\xcd\\x5e\\x3c\\x8b\\x26\\xa9\\xa2\\x5a\\xb3\\x5a\\x7c\\x4b\\xfe\\xfb\\xf0\\x9f\\xbf\\xff\\x75\\x7c\\xf4\\xdd\\xe1\\xe1\\x4f\\xcf\\xc7\\x7f\\xfb\\xf9\\xf7\\x87\\xff\\x3c\\x86\\x7f\\xfc\\xc7\\xd1\\x77\\x47\\xbf\\xba\\x1f\\x7e\\x7f\\x74\\x74\\x78\\xf8\\xd3\\xdf\\xdf\\xbe\\xba\\x9e\\x9c\\xff\\xcc\\x8f\\x7e\\xfd\\x49\\x34\\xe5\\x0d\\xfe\\xf4\\xeb\\xe1\\x4f\\xec\\xfc\\xe7\\xcf\\xec\\xe4\\xe8\\xe8\\xbb\\x6f\\xa2\\x49\\x4f\\x50\\xee\\x18\\x5b\\xca\\xa2\\xc7\\xdd\\x1e\\x93\\x1c\\xbf\\x2f\\x54\\x00\\xb9\\x6d\\xee\\x78\\xa5\\xbe\\xff\\xef\\x1d\\xd7\\x0c\\xe2\\x9b\\x9d\\x14\\xb2\\x47\\x17\\xfc\\x4b\\x09\\x1a\\x98\\x37\\xf6\\x18\\x46\\x49\\x1c\\x29\\x40\\x89\\x3e\\x50\\x6d\\xca\\xd4\\x53\\x7b\\x41\\x7f\\x0b\\x76\\x4a\\xa7\\xe7\\xe0\\xbe\\xb6\\xa2\\xfb\\xac\\x96\\xa5\\x05\\xc6\\x45\\xa7\\x2d\\x42\\x32\\xd9\\xef\\xdd\\xb0\\x08\\x83\\xbe\\x6b\\x83\\x5d\\xb3\\x77\\x1b\\xec\\x9a\\xeb\\xed\\xeb\\xb4\\x6b\\x62\\x22\\xf6\\x6f\\xd1\\xa8\\xc9\\xc4\\xb2\\xaf\\xbb\\x32\\x65\\x8c\\x96\\x53\\x6d\\xc3\\x6a\\x4f\\x9f\\x17\\x08\\xd1\\x3f\\x5a\\xf6\\x86\\xad\\x94\\x8f\\xba\\x68\\x43\\x70\\x51\\x6c\\x29\\xb7\\x47\\xc9\\x90\\xd3\\xa2\\x20\\x5c\\x20\\x13\\x36\\x1d\\xf4\\x1a\\xdd\\x43\\xad\\x30\\xd4\\x79\\x1d\\x46\\xdc\\xd2\\x4c\\xd5\\xc3\\xa4\\x74\\xea\\x9a\\x42\\xde\\x20\\x17\\x73\\x5b\\xd4\\x16\\x45\\x01\\xeb\\x41\\xe7\\xc2\\x57\\xab\\xed\\x45\\x8e\\x57\\x35\\xda\\x4a\\xfd\\x54\\x29\\x99\\x71\\xea\\x4b\\x49\\xf9\\x62\\x57\\x76\\x79\\x60\\x06\\x9a\\xde\\x40\\x04\\x4b\\xc6\\x72\\x26\\x1e\\x9e\\xa9\\x8d\\x0d\\x2a\\xf8\\xb7\\xfb\\x30\\x5d\\x41\\xb5\\x54\\xb1\\xb4\\x25\\xac\\x48\\xde\\x60\\xd0\\x25\\x3e\\x93\\xe9\\xc6\\x7d\\x5a\\x21\\x7b\\xe6\\x0e\\xdb\\x58\\x81\\x20\\x72\\x0f\\x24\\x0a\\x6f\\x54\\xa2\\x10\\xf0\\x28\\x67\\xad\\x17\\xa7\\xdf\\xe9\\x8d\\x96\\x10\\xe3\\xe5\\x31\\x1f\\x00\\x10\\x25\\x68\\x6f\\x08\\x62\\xad\\x7b\\xab\\x2b\\x80\\x3d\\x85\\x98\\x89\\x78\\xd1\\x2c\\xad\\x58\\xf6\\x25\\x44\\xb2\\x7d\\x15\\xc7\\x1e\\x5f\\x14\\x4b\\x24\\x86\\xa5\\x11\\xc1\\x1e\\xe0\\x56\\x4e\\x29\\x76\\xa5\\x11\\xb9\\xbe\\x84\\xad\\xa0\\xaa\\xd9\\x8c\\xdf\\x25\\x62\\x5c\\xa7\\x01\\x72\\x10\\xcf\\x99\\xd0\\x7c\\xc6\\x19\\xa0\\x28\\x54\\x35\\xab\\x98\\x00\\x47\\x10\\xe4\\x9c\\x9b\\x07\\xd4\\x8a\\x4f\\x6d\\x50\\xd3\\x3e\\xc6\\x03\\xa3\\x76\\x9b\\x96\\xb7\\x5f\\x6d\\xd3\\xac\\x07\\xc6\\x4e\\x06\\xc6\\x1e\\xd1\\x06\\xc6\\xfe\\x59\\x7a\\xf5\\x53\\xe7\\xea\\x90\\x6d\\xb9\\xf3\\x6a\\x03\\x48\\x06\\xf0\\x83\\x47\\x41\\x7f\\xda\\xc0\\x52\\xeb\\xa9\\x89\\x87\\x38\\x8e\\xfe\\x25\\xd3\\x12\\x43\\xf1\\x11\\x47\\xa5\\x26\\x08\\xed\\x88\\x72\\x3f\\x29\\xa9\\xa0\\x73\\x80\\x78\\x31\\xdf\\x73\\x15\\x0f\\x64\\x4d\\xcc\\xc5\\xaf\\x79\\xde\\x33\\x73\\xb4\\xbb\\x90\\xa0\\x57\\x3b\\xc0\\x0e\\xf8\\xb0\\x96\\x45\\xc1\\x6a\\x45\\x0a\\x7e\\xc3\\xc8\\x4b\\x56\\x15\\x72\\x55\\xda\\x0c\\xa9\\x9c\\x5c\\x69\\xaa\\xcd\\xe5\\xbf\\x62\\x3a\\x02\\x8c\\xbc\\x2f\\x26\\xb8\\x43\\x14\\xdc\\x71\\x39\\x71\\x38\\x80\\x55\\x53\\x14\\xa4\\x42\\x88\\xa3\\x5e\\xdd\\xbc\\x13\\xf0\\x80\\x9c\\x16\\xb7\\x74\\xa5\\x46\\xe4\\x92\\x2d\\x59\\x3d\\x22\\x17\\xb3\\x4b\\xa9\\x27\\xa8\\xda\\xc6\\x97\\x94\\xc6\\xce\\x09\\x9f\\x91\\x6f\\x0b\\xaa\\x99\\xd2\\x44\\xd3\\x39\\x18\\x5a\\x5a\\x70\\x43\\x59\\x77\\x06\\x6d\\x8b\\x38\\xed\\xd0\\xe2\\x90\\x00\\xf1\\x10\\x46\\xf7\\x78\\x87\\x7d\\x6e\\x6d\\xd4\\x59\\x2d\\x1c\\x46\\xd4\\xce\\xc0\\x4e\\x10\\x9a\\xaa\\xad\\x3f\\x1b\\xb0\\x13\\xc4\\x23\\x75\\x65\\x84\\xc0\\xd0\\xc4\\x05\\xa9\\x99\\xaa\\xa4\\x50\\xac\\x5b\\xc2\\xce\\x4f\\x04\\x0d\\x77\\xbb\\xaf\\x20\\xda\\x5b\\x1c\\x8d\\x15\\x44\\x2b\\xa9\\x34\\x20\\x78\\xf5\\x2f\\x45\\x9c\\x46\\x02\\x9d\\x38\\x42\\x00\\xd4\\x8d\\x16\\x05\\xcb\\x09\\x2f\\x4b\\x96\\x73\\xaa\\x59\\xb1\\x22\\x74\\xa6\\x59\\x1d\\x56\\x2d\\x0d\\xb0\\x99\\x8f\\x11\\x5c\\x9e\\x59\\xac\\x37\\x07\\x13\\xd7\\x5f\\x45\\x58\\x37\\xe1\\x62\\xa9\\x45\\xb0\\xa9\\x62\\x6c\\x94\\x05\\xb5\\x6b\\x41\\xe5\\xd6\\x60\\xe2\\xa2\\x98\\xa8\\x69\\xef\\x40\\x10\\x0b\\x8e\\xf7\\x46\\x0d\\x66\\xa8\\xcc\\xad\\x48\\x23\\x34\\x2f\\x2c\\x10\\xb0\\xbc\\x21\\x99\\x2c\\xab\\x02\\xd8\\x49\\xef\\xa1\\xfb\\x73\\x29\\xff\\xcf\\xb1\\xbf\\x60\\x63\\x43\\x95\\x3a\\xf9\\x5d\\xfb\\x11\\xfc\\xa2\\x27\\x71\\x09\\x74\\xb7\\x14\\x9a\\x1b\\xbb\\x63\\x59\\x8c\\xf8\\xdd\\x35\\x01\\xdf\\xb1\\xcc\\x3f\\x5d\\x68\\xf8\\x45\\x04\\x3e\\x00\\x74\\xa2\\x37\\x51\\x89\\x8a\\x89\\x42\\x02\\x52\\xb9\\xe1\\x23\\xb0\\x5c\\xc2\\x96\\xda\\xcb\\x7c\\x86\\x64\\xb9\\xd2\\xe7\\x96\\x4a\\x52\\x70\\x01\\xef\\x86\\x05\\x7b\\x09\\x81\\x6e\\xfd\\x71\\x46\\xcf\\xcb\\x46\\xa9\\x30\\x97\\xf6\\x17\\x4d\\x9a\\xa3\\xc5\\xd0\\x06\\x10\\xec\\x87\\x07\\x27\\x07\\x47\\x1b\\xae\\xb4\\xb5\\x42\\xda\\xd7\\xc1\\x2c\\x38\\x54\\xc1\\xab\\xa0\\xbc\\x1b\\xcb\\x0e\\xf2\\x11\\xe1\\x86\\xc7\\x46\\x53\\x66\\x9e\\x3e\\x2c\\x38\\x00\\xab\\x62\\x11\\x70\\x46\\x44\\x49\\xa2\\x6b\\x9a\\x73\\xab\\x0d\\xc0\\x6f\\xcd\\x97\\x74\\xdd\\xd8\\xd7\\xfb\\xf0\\xe0\\xd7\\x83\\x11\\x61\\x3a\\x3b\\x22\\xb7\\x52\\x1c\\x68\\x58\\xbe\\x63\\x72\\x0d\\x28\\xd2\\xf1\\x91\\x66\\x8e\\x90\\x95\\x6c\\xa0\\x56\\x01\\x6e\\x61\\x55\\xf0\\x8c\\xeb\\x62\\x05\\x6f\\x0b\\x91\\x0d\\x56\\x55\\x30\\x72\\x44\\x04\\x72\\x4f\\xd8\\xce\\xef\\xb8\\xb6\\x29\\x0c\\x86\\x59\\x3f\\x87\\xd3\\x64\\x6b\\x07\\x50\\xa3\\x79\\x2c\\xd9\\xc9\\x82\\xd1\\x42\\x2f\\x30\\xc0\\x56\\x48\\x31\\xfe\\x17\\xab\\x25\\xa0\\xfb\\x08\\xfb\\x49\\x2c\\x19\\x71\\x5e\\xad\\xb0\\x45\\x78\\xb8\\x36\\x09\\x8a\\x34\\x7a\\x98\\x67\\xe8\\x15\\xeb\\x2d\\xa2\\x90\\x8d\\x9a\\x54\\xd7\\xd7\\x93\\x57\\x4c\\xaf\\x71\\x5d\\x33\\x8a\\x0b\\x7b\\x06\\x1b\\x2c\\xab\\x67\\xb2\\x2e\\xf7\\x80\\xfd\\xa6\\x89\\xc7\\x1a\\x43\\x9d\\x9d\\x3d\\x78\\x05\\x16\\x52\\x45\\xed\\x25\\xf9\\x02\\x4f\\x00\\x56\\x45\\xa2\\xa5\\x53\\x14\\x04\\xcb\\xcc\\x21\\xe8\\xc6\\xf0\\x3a\\xd8\\xe1\\x8b\\xc9\\x31\\xf9\\x51\\x36\\x00\\x79\\x4b\\xa7\\xc5\\xca\\xc3\\x65\\x2a\\x16\\x17\\x78\\x67\\xda\\x33\\x43\\xca\\x33\\xc3\\xe1\\xcd\\x81\\x7c\\xcd\\x68\\xce\\x6a\\x05\\x0c\\x94\\xd1\\xc8\\x10\\xfb\\x84\\x31\\x3e\\x01\\x6d\\x49\\xb7\\xf2\\xac\\x51\\x5a\\x96\\x64\\x61\\xa7\\xdd\\x85\\xfa\\xb1\\x97\\xf3\\x18\\x2e\\xb0\\xc3\\x7b\\xa8\\x59\\x85\\x4c\\xd6\\xfe\\xcd\\x93\\x63\\xa1\\x1b\\xac\\x0b\\xd7\\xdd\\xfe\\x7e\\xca\\x94\\xd1\\x8a\\xc2\\x65\\x33\\xab\\xe6\\x91\\x04\\x04\\x2e\\x16\\xa2\\x33\\x27\\x62\\xe7\\x09\\x42\\x4c\\x49\\xc2\\x30\\x53\\x12\\x07\\x02\\xb4\\xde\\x11\\x84\\xd1\\x44\\xf7\\x94\\x2e\\x72\\x95\\x24\\x8b\\xce\\x24\\x5f\\x24\\x42\\x93\\xd8\\xa0\\x2c\\x7b\\xf8\\xd0\\x20\\xdc\\xdf\\x94\\xbd\\xad\\x73\\xde\\x16\\x28\\xc9\\xa8\\x90\\x82\\x67\\xb4\\xe0\\xff\\x62\\x39\\x69\\x2a\\x29\\x6c\\x3a\\x06\\x48\\x9e\\x19\\x55\\x6c\\x0c\\x11\\x67\\x02\\xd9\\xb9\\x0a\\xe0\\x68\\x0c\\x77\\xd0\\x52\\x82\\x38\\xe6\\xab\\x55\\x20\\xd5\\x69\\x48\\x4d\\x9a\\x47\\x10\\x8d\\xad\\x14\\xb6\\x0d\\x9f\\x6a\\x67\\xb3\\xd2\\x9c\\x78\\x92\\x72\\x05\\xaa\\x04\\x69\\x96\\x9b\\x49\\x96\\x88\\x19\\x0f\\x98\\x38\\xf8\\xa2\\x00\\x6f\\xc4\\xf2\\x52\\x7b\\xf3\\xb4\\x1a\\x29\\x6d\\xdf\\xc4\\x23\\xf4\\x0c\\xd7\\x44\\x34\\xe5\\x94\\xd5\\x6d\\x86\\x7a\\xad\\x37\\xd7\\x34\\x32\\xbe\\xb3\\x33\\x2c\\x0e\\xe7\\x9c\\x90\\x4e\\x0c\\xa0\\x62\\xce\\xc8\\x0b\\x33\\xf2\\x5f\\xfe\\xfc\\xe7\\x3f\\xfe\\x39\\xc1\\x38\\x66\\x7a\\x3e\\x6e\\x54\\x90\\x8b\\xd3\\xcb\\xd3\\x5f\\xae\\x3e\\x9c\\x01\\x64\\x53\\x6c\\xf7\\x89\\x52\\x9f\\x52\\x27\\x3e\\x25\\x4d\\x7b\\xfa\\xa2\\x49\\x4f\\x90\\x41\\x1e\\xcd\\x08\\x53\\x5f\\x89\\x2b\\xa0\\x2a\\xac\\xde\\x65\\xd5\\x86\\xa0\\xdc\\x4a\\x9f\\xea\\x78\\x9b\\x2d\\x74\\x7e\\x19\\x86\\xb5\\x17\\x9c\\x4a\\x15\\x8c\\xf5\\x2a\\x67\\xec\\x5a\\x37\\x02\\xc1\\xf4\\xb6\\x1e\\xff\\x9a\\x37\\xb5\\xad\\x5c\\xe5\\xdc\\x3d\\xad\\xf5\\xdb\\xba\\x79\\x80\\x0a\\x32\\x65\\x33\\x59\\x33\\x5b\\x6f\\xa6\\xb5\\xd5\\x3f\\x21\\xcd\\x5d\\xb1\\x4c\\x8a\\x3c\\x46\\x7e\\x4f\\x25\\x8f\\x5a\\x4a\\x92\\xde\\xc6\\x2b\\xec\\xd3\\xd9\\x5f\\xdb\\x47\\xc6\\x0e\\x06\\x6a\\xa0\\xd9\\xe9\\x34\\x27\\x3f\\x0d\\x07\\xc5\\xec\\x5f\\xe8\\xed\\x2f\\x7f\\xea\\xef\\x6a\\xca\\xaa\\x2b\\x99\\xdd\\x24\\x34\\x6e\\x45\\xb2\\xb6\\x97\\xe6\\x0e\\x66\\xe8\\x55\\xbb\\x3e\\x9b\\x20\\x71\\x66\\x67\\x2e\\xdf\\x5d\\xb7\\xa9\\xfe\\x90\\xf6\\xd0\\xd6\\x0c\\x7a\\x6d\\xfd\\x6e\\x54\\xe4\\xe4\\x86\\x55\\x71\\xaa\\xa1\\x43\\xcc\\x9b\\xd2\\xec\\xe6\\x96\\xd6\\x39\\xf8\\xb4\\xa8\\xe6\\x50\\x04\\x15\\x4b\\x2f\\xd5\\x0c\\x30\\x08\\x84\\xc4\\x9c\\x3a\\xe4\\x12\\xd2\\xa2\\xa3\\xa3\\x4c\\x1b\\x07\\xb2\\x19\\xf8\\xba\\xc1\\xaf\\x66\\xd5\\x88\\x19\\xe5\\x05\\x78\\x95\\x1b\\xa1\\x79\\xc9\\x6c\\xc2\\x47\\x56\\x79\\xc7\\x63\\x18\\x85\\xf0\\x84\\xd8\\xcf\\x53\\x35\\x1c\\x1e\\xb4\\x95\\x9a\\x1f\\x6a\\x00\\x8c\\xcd\\x89\\x7e\\xda\\xea\\x82\\xe5\\xe0\\x08\\x26\\x31\\xa8\\x0b\\x0f\\x69\\x83\\xba\\xd0\\x53\\x5d\\xa8\\x6a\\x76\\xa5\\x65\\x6f\\x99\\x34\\x59\\x20\\x0b\\x92\\x71\\x4f\\x18\\x8b\\x15\\x55\\xe9\\xbd\\xf1\\x25\\x79\\x03\\x1c\\x28\\x22\\x40\\xf6\\x74\\x72\\xe1\\xdd\\x58\\xb2\\x13\\x43\\x82\\x59\\x8a\\xb6\\x08\\x3b\\x78\\x24\\x05\\x53\\xea\\x44\\x85\\x15\\xfc\\xe0\\x8d\\x6b\\x6a\\xd6\\x3f\\x7a\\xa6\\xaa\\x19\\x2b\\x61\\x1d\\x47\\x2d\\x96\\x84\\x99\\x2e\\x13\\xf8\\x4b\\xa6\\x33\\x74\\x51\\x07\\xaf\\x26\\xd4\\x87\\xb3\\xcb\\x35\\x8b\\xf2\\x9c\\xb7\\x0b\\x9b\\xd5\\x54\\x2d\\x18\\xc0\\x14\\xb3\\x3b\\xae\\x15\\x0e\\x3a\\x01\\xc4\\x05\\xb7\\xe2\\x46\\x70\\x98\\xd7\\x34\\x63\\xa4\\x62\\x35\\x97\\x46\\xd8\\x68\\x84\\xce\\xe5\\xad\\x20\\x53\\x36\\xe7\\x42\\xb9\\x1d\\x8b\\x21\\xc9\\x1d\\x09\\x88\\xd0\\xe1\\xca\\x57\\x8f\\x39\\x26\\xef\\x3b\\x28\\xcd\\x16\\x5b\\x26\\x93\\x2d\\xcf\\xb4\\x4b\\x34\\x4a\\xb4\\x24\\x20\\xc5\\xc0\\x31\\xc0\\xe2\\xee\\xfe\\xe0\\xb9\\x2c\\x5a\\x7d\\xff\\x0a\\xf5\\x3f\\x10\\xb8\\xb2\\x87\\x8d\\x80\\x89\\xe6\\xac\\xa0\\x2b\\xcc\\x17\\x9d\\x71\\x01\\x86\\xdc\\x5a\\x1d\\x1d\\xc7\\x87\\x3c\\xf5\\x26\\x50\\xd6\\x41\\x9f\\xf7\\x9e\\x0c\\xae\\x48\\xcd\\x68\\xb6\\x88\\x91\\xec\\x86\\xd8\\xaa\\x4f\\xb5\\x21\\xb6\\xaa\\x67\\x1b\\x62\\xab\\x1e\\xda\\x86\\xd8\\xaa\\x87\\xb6\\x21\\xb6\\x6a\\x9f\\x02\\x03\\x86\\xd8\\xaa\\xc1\\x44\\xb2\\xde\\x86\\xd8\\xaa\\x8f\\xb5\\x21\\xb6\\x6a\\x88\\xad\\xea\\xb4\\x21\\xb6\\xea\\x33\\xda\\x10\\x5b\\xf5\\x99\\x6d\\x88\\xad\\x1a\\x62\\xab\\x86\\xd8\\xaa\\x21\\xb6\\xea\\x61\\x6d\\x88\\xad\\xea\\xdf\\x06\\x67\\xc9\\x10\\x5b\\x15\\xd5\\x86\\xd8\\xaa\\x21\\xb6\\x6a\\x88\\xad\\x1a\\x62\\xab\\xee\\x6d\\x43\\x6c\\xd5\\x10\\x5b\\xb5\\xb5\\x0d\\x86\\xc3\\x8d\\x36\\xc4\\x56\\x6d\\x69\\x43\\x6c\\xd5\\xc3\\xc6\\x19\\xd4\\x85\\xb8\\xce\\x92\\xab\\x0b\\x2e\\x4e\\x68\\x52\\xcb\\xe9\\xce\\x90\\x9f\\x26\\x10\\x83\\xc1\\x33\\x1b\\xa4\\x24\\x67\\x1d\\x34\\x27\\x24\\xb0\\x27\\x8a\\x53\\x37\\x38\\x06\\xcb\\xe4\\x5b\\x78\\x1f\\x6e\\x2f\\x97\\x0f\\x8c\\xda\\x25\\x52\\xd4\\x83\\xa3\\x47\\x1c\\x02\\x9e\\x3a\\xa9\\x24\\xfe\\xa7\\x8d\\x1d\\x09\\x82\\x46\\x7a\\x9b\\xaf\\x77\\x0c\\x5d\\x15\\x13\\x29\\xf2\\x38\\x51\\x22\\x7b\\x12\\x52\\x93\\x20\\x32\\x24\\xe5\\x23\\xb6\\xa7\\x11\\x21\\xfb\\x19\\x0d\\xb2\\x8f\\x91\\x20\\xbb\\x88\\x02\\xd9\\x79\\x04\\x48\\x1a\\xd7\\x65\\x02\\xb7\\x65\\xb4\\xa8\\x60\\x03\\x7c\\xaf\\x17\\x35\\x53\\x0b\\x59\\xf4\\xe6\\x0b\\xa9\\x78\\xc2\\x5b\\x2e\\x78\\xd9\\x94\\xe6\\x8a\\x29\\x73\\xf5\\xf9\\xd2\\x07\\x21\\x2b\\xaf\\xb0\\xe2\\x13\\x8c\\xce\\x57\\xf3\\x45\\x9e\\x33\\x28\\x4e\\x49\\x79\\x61\\x4e\\x00\\x80\\x03\\x2e\\xe8\\xd2\\xb0\\x05\\xd5\\x64\\x19\\x63\\x79\\x8c\\x92\\x18\\x5a\\x05\\xff\\x78\\xec\\x29\\xc4\\x02\\x2b\\x5c\\x91\\x17\\x71\\x2f\\x42\\x9c\\xdc\\x18\\x18\\x47\\xfe\\xf8\\x87\\x5e\\x7d\\xcc\\xeb\\x2a\\xcd\\xcb\\xf9\\xea\\xfd\\xe4\\x2c\\x78\\x39\\xa9\\x70\\x0f\\x27\\x17\\x4b\\x59\\xc0\\x6e\\x50\\xfc\\x92\\xd1\\x4f\\x76\\xf8\\x8c\\xc6\\x2b\\xeb\\x51\\x8a\\x7a\\x8a\\x57\\x3c\\x56\\x17\\xed\\x7a\\xec\\x8c\\xba\\xd8\\x75\\x38\\xcd\\x61\\x2f\\xb1\\x66\\xfb\\xf1\\x23\\xa8\\x7b\\xa9\\x54\\xa8\\xf8\\xeb\\x40\\xc0\\xf4\\x0a\\x13\\xdf\\x17\\x19\\xe9\\x0a\\xc9\\xf1\\x56\\xdb\\x40\\xd3\\xb7\\x94\\x42\\x14\\x5d\\x41\\x33\\xbf\\x37\\xb0\\x7f\\xaf\\xe1\\xa1\\x3b\\x5b\\xb0\\xec\\xe6\\x3d\\x06\\xf4\\x44\\x91\\x71\\xa8\\x18\\xf3\\xaa\\xc6\\x9c\\xeb\\x45\\x33\\x3d\\xce\\x64\\x79\\x62\\x18\\x08\\xfe\\x67\\x5a\\xc8\\xe9\\x49\\x49\\x95\\x66\\xb5\\xd1\\x3e\\xec\\x1b\\x3c\\xce\\x0c\\x05\\x5c\\xcc\\x8f\\xcb\\xfc\\xe8\\xf8\\xdf\\xfe\\x2d\\x8a\\x88\\x0b\\x6b\\x7b\\xb4\\x59\\x22\\x01\\xca\\x33\\x38\\x32\\x2c\\x84\\xf8\\x94\\x19\\xf6\\x2f\\xc1\\x4c\\x18\\x54\\xa4\\x32\\xab\\x12\\x7f\\x4a\\x23\\x5e\\xdb\\xc8\\xf8\\xca\\xc7\\x8f\\xad\\x1c\\xb8\\x2d\\x49\\x60\\x0e\\x4d\\xc9\\x0c\\xf6\\x23\\x7e\\xf2\\x8b\\xc5\\x4e\\x26\\x0b\\x63\\x4e\\x10\\x33\\xb9\\x47\\xf1\\x92\\x7b\\xa3\\x70\\xec\\x4b\\x8c\\xe4\\x1e\\x96\\x37\\x4e\\x10\\x17\\x99\\x22\\x26\\x32\\x5d\\x3c\\xe4\\xbe\\x56\\x01\\xfe\\x62\\x31\\x90\\x5f\\x45\\xfc\\x63\\x42\\xef\\x40\\xa2\\xb8\\xc7\\xc7\\x88\\x79\\x4c\\x32\\xeb\\xd8\\x58\\xc7\\xc7\\x8b\\x73\\x4c\\x33\\xdd\\x94\\x4a\\x62\\xe4\\xcd\\xdd\\x41\\x5c\\xe3\\x63\\x38\\x29\\xbf\\x98\\x83\\x32\\x81\\x73\\x32\\xa5\\x63\\x32\\x99\\x53\\xf2\\x8b\\xc5\\x2f\\xc6\\xc7\\x2e\\x26\\x55\\xd9\\x1f\\x25\\x66\\x31\\x65\\xbc\\x62\\xf4\\xfe\\x72\\xc1\\x35\\xa7\\xc5\\x4b\\x56\\xd0\\xd5\\x55\\x5c\\xec\\x5a\\xaa\\x9d\\xb8\\xdc\\x88\\x6f\\x43\\xdb\\x70\\x37\\xc2\\x71\\x41\\x6d\\x59\\x6e\\x96\\xbb\\x00\\x47\\xe7\\x44\\xb6\\x92\\x2a\\xc4\\x40\\xe1\\xfc\\xa2\\xa2\\x1d\\xf7\\xcc\\x65\\x4b\\xf6\\xc6\\x06\\x8d\\xa0\\x0a\\x7b\\x72\\x6a\\x5e\\xcb\\x5b\\x22\\x67\\x9a\\x09\\x72\\xc8\\x85\\x3b\\x39\\x47\\x81\\x31\\xa5\\xf5\\x41\\x44\\x3b\\x15\\x4c\\xaf\\x2f\\x9e\\xbb\\x41\\x9e\\x9e\\x73\\x01\\xdc\\x2f\\x4a\\xed\\xb5\\x7b\\xc9\\xd2\\xf8\\x69\\xff\\x92\\xfd\\xe2\\xac\\x29\\xba\\x3e\\x26\\xf4\\x3b\\xa5\\x71\\x30\\xbd\\x68\\x0b\\xf9\\xbe\\x00\\x7a\\x3c\\x2b\\xa2\\x22\\x27\\x16\\x9c\\xe7\\xe9\\x9d\\x93\\xe8\\xe8\\xdc\\xae\\x0e\\xe2\\xc3\\x69\\x3f\\xe5\\x8e\\xba\\x3e\\x9b\\x0c\\xde\\xa8\\xfd\\xb2\\x8f\\xee\\x28\\x54\\xf4\\xe9\\x69\\x5c\\x8f\\x1f\\x1a\\x3a\\x68\\x5c\\xbf\\x15\\x8d\\x2b\\xc0\\xc5\\x7a\\x55\\xd3\\x8c\\x4d\\xf6\\x49\\x80\\x73\\x0c\\xa4\\xcd\\x6b\\x6a\\xe5\\x38\\xcf\\x2e\\x04\\x63\\x98\\xef\\xd2\\xa2\\x9e\\x01\\xc0\\xd7\\xac\\x29\\x8a\\x15\\x9a\\xfb\\x3a\\x10\\x78\\xfd\\x8f\\xd6\\xf5\\x82\\x6d\\x60\\x87\\x75\\xb2\\xae\\x02\\xea\\x5a\\xfd\\xa4\\xaa\\xa5\\x95\\x4a\\xea\\x46\\x08\\xf3\\x5a\\xd9\\xeb\\x64\\x88\\x37\\xfa\\x88\\x62\\xa2\\xbf\\xe5\\x9b\\x76\\x90\\xcd\\x14\\x9f\\x9b\\xe5\\x32\\x12\\x06\\x80\\x9e\\xb5\\x19\\x17\\x1d\\x42\\xcc\\xa8\\x33\\x59\\x67\\x7c\\x5a\\xac\\xc8\\x82\\x16\\x46\\x61\\xba\\xe5\\x7a\\x41\\x28\\xb9\\xe1\\x45\\x61\\xbb\\xe9\\xbf\\x50\\x57\\x4c\\xa3\\x73\\x17\\xa5\\x9a\\x42\\x8a\\x39\\x2c\\x06\\x45\\x42\\xd8\\x5d\\xc5\\x32\\x33\\x66\\x56\\x30\\x2a\\x9a\\x0a\\xe9\\x34\\x32\\xd2\\x4a\\x36\\xb5\\xa3\\xb3\\xff\\xf0\\xce\\xb5\\xec\\x65\\x2a\\xc1\\x8b\\x91\\x5b\\xf2\\x2e\\x06\\xde\\xe6\\x99\\x6f\\xad\\xbf\\x8a\\xe5\\x16\\xbe\\xee\\x96\\x2b\\x36\\x82\\x3e\\x7b\\xd3\\x84\\xb4\\xb8\\x72\\xd8\\x78\\x6e\\xf0\\x77\\x55\\x2d\\x97\\x3c\\x47\\xbf\\xb6\\x3b\\x16\\x46\\xda\\xe9\\x3f\\xff\\x0f\\xd0\\xaf\\x63\\xad\\x42\\x8a\\xb1\\x60\\x73\\x0a\\x22\\xb2\\x65\\x68\\x18\\xe1\\x88\\xe3\\x63\\x3c\\x9d\\xc8\\x79\\x46\\x35\\x33\\x0a\\xb4\\xac\\x3a\\xd8\\x96\\x4b\\x4e\\x7b\\x53\\x62\\xe6\\x13\\x9c\\x28\\x72\\x28\\x24\\x91\\x90\\x10\\xd5\\x08\\xae\\x57\\xe0\\x7c\\x5b\\x34\\x9a\\xe4\\xf2\\x56\\x1c\\xc5\\x5c\\x4c\\x0c\\x24\\xa0\\x64\\xca\\x34\\x6d\\xd3\\x99\\x9c\\x48\\xa6\\x08\\x13\\x74\\x5a\\x98\\xbb\\x07\\xe1\\xee\\xd7\\x5b\\x0f\\x00\\x99\\x31\\xaa\\x9b\\x9a\\x91\\x39\\xd5\\x11\\x5c\\x62\\x8b\\x44\\x8f\\xfb\\xf9\\xf1\\x63\\xc7\\x95\\x75\\xad\\xcd\\x48\\x23\\x14\\x8b\\x14\\x64\\x93\\xa9\\x01\\x3d\\x13\\xf5\\xcc\\x8d\\x96\\x8d\\xde\\x93\\x77\\xe4\\x3e\\xf3\\xd1\\xed\\x82\\x67\\x8b\\x50\\x51\\xe4\\x25\\x53\\x44\\x36\\x11\\xd6\\xbc\\x8e\\x0a\\x68\\x87\\x4b\\xa9\\xe5\\x0d\\xb6\\xa7\\xad\\xad\\xaf\\x87\\x33\\xc5\\x09\\xbb\\x0c\\xa4\\xf2\\x20\\xdd\\xda\\x05\\x34\\x61\\xe2\\xe7\\xcb\\xcb\\xab\\x5f\\xde\\x9c\\xfe\\xd7\\xf9\\x9b\\x7e\\x1b\\x7f\\x4e\\xb3\\x45\\x08\\x2e\\x2c\\x08\\x85\\x87\\x02\\x98\\xfc\\x82\\x2e\\x19\\xa1\\xa4\\x11\\xfc\\xff\\x1a\\x1b\\x55\\x76\\xe8\\xc7\\xeb\\xc9\\x56\\x13\\x56\\x41\\xef\\x29\\xf8\\x9a\\x57\\xa2\\x17\\xe7\\x48\\xb1\\xa7\\x6f\\xb8\\x02\\xa4\\x5a\\x20\\xc2\\x06\\xc2\\x4b\\xc5\\xc8\\xac\\x96\\xe5\\x9a\\xa2\\x45\\x2e\\x7d\\xf8\\xda\\x0a\\x6d\\x11\\xa0\\x9a\\x2d\\x58\\xdd\\x4f\\x22\\x7f\\xf9\\xee\\xfc\\x0a\\x52\\x87\\xab\\x1a\\x91\\x9d\\x21\\xd8\\x1e\\xfa\\x84\\xd1\\x31\\x67\\x1f\\xe9\\xc9\\x8f\\xc9\\xa9\\x58\\xe1\\x87\\xc8\\xcc\\x7a\\x8a\\x28\\x05\\x57\\x9a\\x81\\x70\\x6a\\x15\\x49\\x17\\x80\\xf7\\xec\\xf9\\x31\\xfc\\xef\\x19\\xa1\\x79\\x5e\\x1b\\x4d\\xd3\\xe7\\x2c\\x64\\xeb\\x29\\x56\\xbd\\x46\\x46\\xfd\\x95\\x4f\\x8b\\x60\\x71\\x05\\xd3\\x90\\xd6\\xd0\\xab\\xc3\\xb7\\x32\\xb7\\x3b\\x01\\x42\\x20\\x84\\xda\\xa0\\x74\\xab\\x74\\x4d\\x35\\x9b\\xf3\\x8c\\x94\\xac\\x9e\\x33\\x52\\x51\\x9d\\x2d\\x48\\x49\\x57\\x24\\x93\\x75\\xdd\\x54\\x88\\x98\\x90\\x53\\x4d\\xfb\\x8d\\xfc\\xbd\\xac\\x49\\xe9\\xb8\\xb3\\xe1\\x66\\x46\\x24\\xbf\\xda\\x1e\\x6b\\xd9\\xb2\\xec\\xf0\\x9f\\x5c\\xa9\\x86\\xa9\\x93\\x17\\xcf\\xff\\xfa\\x87\\x3f\\xf7\\x54\\xaf\\x13\\x5e\\xdc\\xbe\\x51\\x4a\\x11\\xd1\\x49\\xdd\\x48\\x2d\\x77\\xc0\\x20\\xae\\x39\\x80\\xba\\xa0\\xee\\x84\\xe0\\xc9\\x07\\x6e\\xa8\\xb8\\x98\\x17\\xd1\\x06\\x90\\x68\\x33\\x60\\xac\\x11\\x70\\xdc\\xce\\x60\\xd2\\xd7\\x16\\x18\\x6f\\x09\\xec\\xd0\\xd0\\xdf\\x94\\x92\\xce\\x0a\\xd6\\x4a\\x70\\xce\\xee\\x65\\x19\\xb2\\x14\\x81\\x62\\x77\\x31\\x71\\x5c\\x2a\\xc6\\x7e\\x04\\xda\\x84\\x37\\x4c\\x21\\x5e\\x02\\x0e\\x8b\\x31\\x0f\\x23\\xf2\\x9c\\xfc\\x27\\xb9\\x23\\xff\\x09\\x56\\xb0\\xbf\\xf4\\x1f\\x2a\\x8d\\x8d\\x29\\x45\\xa4\\xfc\\x42\\x2a\\x7d\\x31\\x49\\xb4\\xd1\\xff\\x30\\xef\\x95\\xe9\\xd1\\xec\\x87\\x96\\x64\\xca\\xad\\x39\\x82\\xdd\\x69\\x56\\x1b\\x35\\xd0\\xee\\x61\\xec\\xca\\x45\\x59\\xd4\\x0c\\x81\\x5f\\xcb\\xe9\\x8e\\x0d\\x30\\xb8\\x98\\x75\\xe3\\xeb\\x1f\\xe9\\x7c\\xc3\\xc0\\xaf\\xa5\\xd2\\x97\\x96\\x5b\\x87\\x58\\x1f\\x21\\x1d\\x25\\x3c\\xc4\\x1d\\x76\\x1f\\x33\\xea\\x5b\\x73\\xf6\\x5a\\x90\\x7d\\x92\\x4b\\x48\\x31\\xc0\\x9c\\xc6\\x05\\x8f\\x60\\x0e\\xfb\\x73\\x63\\xe3\\x42\\x3a\\xd3\\x1d\\xdd\\x8f\\x1d\\xad\\x35\\x9b\\x3e\\x58\\x64\\xac\\x92\\x12\\xd4\\xa5\\xa8\\x64\\x7e\\x0c\\xfa\\x4d\\x04\\x15\\x66\\x35\\xf2\\x40\\x18\\xf8\\x88\\x6a\\x74\\x8c\\xfa\\x9a\\xf7\\x10\\xc3\\x85\\x33\\x1c\\x2b\\xa3\\xa2\\xaf\\x0c\\x8b\\xad\\x66\\x33\\x56\\xd7\\x98\\x37\\x3b\\x5d\\xb9\\x8c\\x9e\\xe8\\xd3\\x16\\xc5\\xe5\\xaa\\x5a\\x6a\\x99\\xc9\\x62\\x1f\\x8e\\xca\\xc4\\xd2\\x02\\x6b\\x0f\\xbe\\x5a\\xef\\x21\\xff\\xe1\\xe5\\x64\\x44\\xae\\xcf\\x26\\x23\\x22\\x6b\\x72\\x75\\x16\\x17\\x00\\x15\\x9a\\x60\\x9e\\x5d\\x9f\\x4d\\x9e\\xed\\x74\\x07\\x88\\x53\\xa5\\xc0\\x9b\\xdd\\xa3\\x93\\x8e\\xdb\\xc7\\xe8\\x69\\xe3\\x92\\x56\\xe3\\x1b\\xb6\\xea\\x29\\xdd\\xa5\\x90\\x30\\xc7\\xfe\\x60\\x25\\x99\\x10\\x2e\\x73\\x49\\xab\\x07\\xf7\\x56\\x33\\x9a\\xf3\\xbd\\x86\\x31\\x71\\x89\\x7d\\x9e\\xd2\\x74\\x78\\x26\\xa5\\x5c\\xb2\\x1c\\xb5\\x66\\x37\\x0a\\x13\\x79\\x25\\xb9\\xd1\\x91\\x06\\x90\\x93\\x8f\\xb5\\x01\\xe4\\xe4\\x13\\x6d\\x00\\x39\\xd9\\xd6\\x06\\x90\\x93\\x07\\xb4\\x01\\xe4\\x04\\xdb\\x00\\x72\\xd2\\x25\\x64\\x00\\x39\\x19\\x40\\x4e\\x06\\x90\\x93\\xcf\\x6e\\x4f\\x20\\xac\\x74\\x00\\x39\\xd9\\xde\\x06\\x90\\x93\\x01\\xe4\\x64\\x00\\x39\\x19\\x40\\x4e\\xda\\xb6\\x77\\x41\\xfc\\x03\\xc8\\xc9\\xc7\\xda\\x00\\x72\\xb2\\xb5\\xed\\x8d\\xc2\\x31\\x80\\x9c\\xdc\\xd3\\x06\\x90\\x93\\x7b\\xda\\x00\\x72\\x32\\x80\\x9c\\x0c\\x20\\x27\\x0f\\x6c\\x4f\\x2f\\xe5\\x6e\\x00\\x39\\x79\\x50\\x1b\\x52\\xee\\x1e\\xd8\\x06\\x90\\x93\\x01\\xe4\\x64\\xbd\\x0d\\x20\\x27\\x9f\\x6c\\xfb\\x61\\x83\\x1e\\x40\\x4e\\x06\\x90\\x93\\x8f\\xb6\\x01\\xe4\\x64\\x00\\x39\\xf9\\x68\\x1b\\x40\\x4e\\x9e\\x8a\\x7d\\x74\\x00\\x39\\x19\\x40\\x4e\\x3e\\x36\\xc6\\xa0\\x71\\x3d\\xac\\x0d\\x20\\x27\\x03\\xc8\\xc9\\x46\\x1b\\x40\\x4e\\x36\\xdb\\x00\\x72\\x32\\x80\\x9c\\x0c\\x20\\x27\\x03\\xc8\\x89\\x6f\\x03\\xc8\\xc9\\x53\\xb7\\x3d\\xd5\\x4c\\xf1\\x7f\\xb1\\x89\\x2c\\x78\\xb6\\x8a\\x4e\\x75\\x79\\xcf\\x94\\x6c\\xea\\xcc\\xbc\\xd8\\xd0\\x2d\\xa9\\xa0\\x5f\\x6f\\x55\\x88\\x12\\xb2\\xf7\\x0c\\x3f\\xe0\\x7d\\xb0\\x70\\x21\\x8e\\x40\\x6d\\xd7\\xe0\\x4b\\x2c\\xc1\\x5e\\x60\\x09\\xb8\\x09\\x5e\\xf6\\x77\\xf6\\x8f\\x5d\\xe1\\x64\\x5c\\xbe\\x7e\\x06\\xd3\\x68\\xad\\x3d\\x9c\\xc8\\x3e\\xe4\\x32\\x86\\x98\\x3f\\xfe\\x14\\x69\\xe9\\x99\\x2d\\xbf\\xf7\\x70\\xd1\\xaa\\x2a\\x78\\x4c\\x56\\x28\\x21\\x57\\x0d\\x48\\x17\\xcc\\x7a\\xab\\xd5\\xb7\\x24\\xab\\x9a\\x11\\x29\\x59\\x29\\xeb\\x88\\x44\\x81\\x04\\x1a\\x5c\\xe7\\xa8\\xec\\xc3\\x3e\\xbd\\x47\\x82\\xdc\\xe2\\x6b\\x09\\xeb\\xbf\\x42\\x7d\\xa1\\x85\\x68\\xf2\\x7b\\xc5\\x1d\\x3b\\x8c\\x0a\\x0b\\xbb\\x98\\xad\\x87\\x7b\\x72\\xdd\\xb1\\x02\\x5d\\x4a\\xfd\\xde\\x5e\\xee\\x9d\\xed\\xd7\\x7d\\x69\\x98\\x54\\xcb\\x92\\x67\\x7d\\x1e\\x27\\x7c\\x4f\\x76\\x95\\x84\\x79\\x26\\xcb\\xaa\\xd1\\xac\\xf3\\xb0\\xe1\\x12\\xa3\\xd2\\xc1\\x55\\x2c\\x43\\xdf\\x4d\\x2a\\x64\\x26\\xc5\\x8c\\xcf\\xad\\xf6\\x7d\\x52\\x52\\x41\\xe7\\x6c\\xec\\x57\\x7b\\xdc\\xe2\\x1c\\x9c\\xf4\\x7e\\xa8\\x77\\x96\\x07\\x99\\x15\\x94\\xf7\\x8f\\xf1\\x4b\\xc5\\x26\\xce\\x80\\x0a\\xc0\\xc0\\x6a\\x63\\xd6\\x21\\x57\\xcb\\x2f\\xf3\\xc8\\x07\\x66\\x73\\xe4\\x1b\\xc7\\xee\\x23\\xfc\\xe3\\x51\\x84\\xf6\\x48\\x35\\xd8\\x2a\\x40\\x31\\xda\\x72\\x52\\xfb\\x47\\xa0\\x7b\\x8d\\x51\\x10\\x5a\\x54\\x8b\\x8f\\xeb\\x8c\\x31\\x39\\x88\\x2f\\x57\\x82\\x96\\x3c\\x73\\x37\\xef\\xb4\\x28\\x64\\x86\\xb6\\x9a\\xae\\xb6\\x19\\x39\\x15\\x24\\xdf\\xcc\\xa9\\x2c\\x1b\\x4d\\xa7\\x05\\x3b\\x26\\x17\\x08\\xdc\\x20\\x45\\xb1\\x32\\x17\\x53\\x31\\xed\\xe2\\x17\\xec\\xad\\x88\\x53\\x31\\x63\\x62\\x58\\x23\\xe3\\x57\\xb7\\x4a\\xeb\\x70\\xda\\x10\\x69\\x82\\x09\\xc3\\xe3\\xa4\\x60\\x84\\x09\\x5d\\xaf\\xcc\\xc1\\x9c\\xc8\\xfc\\xca\\x9c\\xcd\\xce\\xb7\\xa3\\x01\\x28\\x22\\xc3\\x56\\x53\\x84\\xac\\x46\\x86\\xab\\xa6\\x09\\x32\\x8d\\x0f\\x30\\x4d\\x1b\\x5c\\xda\\xfa\\x16\\x10\\x3f\\x27\\xcc\\xb6\\xe9\\x1c\\x8b\\x4a\\xe6\\xc7\\x5b\\x78\\x16\\x91\\xb3\\x48\\x0a\\xcc\\x88\\x13\\x99\\x1b\\x69\\xaa\\x66\\xc8\\xb8\\xfc\\x1d\\x45\\xcb\\xe2\\x85\\x21\\xee\\x06\\x4c\\x81\\x54\\xb7\\x62\\x16\\x5d\\x52\\x5e\\x98\\x0b\\x1c\\x49\\xc0\\x26\\x16\\x61\\x9c\\xbb\\x26\\x81\\x08\\x9c\\x1a\\xae\\x83\\xc4\\x1e\\xff\\x94\\x70\\x1b\\x04\\xa0\\x22\\x4b\\xde\\x0f\\x98\\x93\\x24\\xbc\\x02\\x6f\\x80\\x8a\\x20\\x90\\xdf\\x9c\\xc5\\x92\\xde\\x81\\x05\\x8a\\x96\\xb2\\x11\\x1a\\x71\\x38\\x50\\x28\\xf4\\x0f\\x39\\xa6\\x3b\\x3c\\x62\\x58\\xd4\\x17\\x15\\xdf\\x48\\x1a\\x26\\x4d\\x73\\x97\\x8d\\x3f\\x49\\x91\\xed\\x49\\xb5\\x66\\xb5\\xf8\\x96\\xfc\\xf7\\xe1\\x3f\\x7f\\xff\\xeb\\xf8\\xe8\\xbb\\xc3\\xc3\\x9f\\x9e\\x8f\\xff\\xf6\\xf3\\xef\\x0f\\xff\\x79\\x0c\\xff\\xf8\\x8f\\xa3\\xef\\x8e\\x7e\\x75\\x3f\\xfc\\xfe\\xe8\\xe8\\xf0\\xf0\\xa7\\xbf\\xbf\\x7d\\x75\\x3d\\x39\\xff\\x99\\x1f\\xfd\\xfa\\x93\\x68\\xca\\x1b\\xfc\\xe9\\xd7\\xc3\\x9f\\xd8\\xf9\\xcf\\x9f\\xd9\\xc9\\xd1\\xd1\\x77\\xdf\\xf4\\x77\\x30\\xc5\\x7a\\x53\\xd3\\xf9\\x52\\x13\\x79\\x52\\xbf\\x88\\x1f\\xd5\\x26\\x0e\\xed\\xfc\\xf2\\xdb\\xfc\\xd0\\x8d\\xeb\\x6f\\x0d\\xd0\\x1f\\xbb\\xfe\\x75\\xb4\\xda\\x7d\\x31\\x6b\\xc7\\xe7\\x8a\\xc8\\x92\\x6b\\xcd\\x72\\x90\\x3a\\x69\\x08\\xf7\\xb1\\xa6\\xf2\\x5b\\x86\\x05\\xb0\\x3c\\x54\\x9b\\xbf\\x0c\\x60\\x27\\x5a\\x4b\\x41\\x6f\\xb2\\xa4\\xf3\\xe1\\x81\\x91\\x43\\x10\\x5e\\x56\\x05\\x2b\\x99\\xd0\\xc0\\x78\\xc6\\x4e\\x7d\\x01\\x8b\\xd1\\x71\\x3b\\x83\\x0c\\x75\\x5a\\x76\\x97\\x31\\x96\\x5b\\x22\\x07\\xde\\x18\\xb4\\x81\\x37\\x0e\\xbc\\xf1\\x53\\x2d\\xda\\xec\\x99\\x82\\x31\\xbe\\x0f\\x89\\xb0\\xe6\\x0a\\xe5\\x0c\\xd4\\x60\\x04\\xf5\\x79\\xe6\\x72\\x06\\xbe\\xf0\\x25\\xcf\\x1b\\x5a\\x84\\x48\\x99\\x0e\\x3c\\xb1\\x1f\\x07\\x08\\x94\\xf4\\x92\\xae\\x36\\x74\\x72\\x2e\\x78\\x08\\xcb\\x39\\xf2\\x11\\x1c\\xf0\\x45\\x2b\\x97\\xb5\\xde\\xc3\\x67\\xa7\\xc5\\x2d\\x5d\\xa9\\x9e\\xe8\\x7d\\xdf\\xcb\\x1a\\x82\\x02\\xd6\\x06\\x25\\xb2\\x76\\xb1\\x22\\xa1\\xb2\\xd2\\xb5\\xd6\\xf6\\xf3\\xf6\\x6c\\x5b\\xe8\\x6e\\x42\\xbf\\x55\\x97\\x0e\\x94\\xff\\xa2\\xf3\\x09\\xd8\\x85\\x68\\xa3\\xfc\\xcd\\x39\\xef\\x37\\xf1\\x2b\\xa6\\xb5\\xb5\\xe7\\xac\\x1d\\x09\\xda\\xae\\xa9\\x77\\x71\\x75\\x97\\x07\\xc3\\x42\\x00\\x33\\xd3\\x7c\\x38\\x93\\x66\\x4f\\x00\\x6d\\x7e\\x36\\x63\\x59\\xcf\\x58\\x41\\x04\\x40\\xd8\\x32\\x0e\\x86\\x2b\\x6b\\x2e\\x1a\\x5a\\x14\\x2b\\xb7\\x26\\x2c\\x27\\x52\\xf4\\x1a\\x88\\xdd\\x71\\x4d\\x1a\\xa1\\x79\\x61\\x0e\\x13\\xa9\\xd9\\xbc\\x29\\x68\\x68\\x0a\\xb2\\x33\\x73\\x11\\x54\\xf9\\x31\\x79\\x27\\x8c\\x32\\xda\\x7e\\xb9\\x9f\\x11\\x73\\x6d\\x00\\x23\\x74\\x14\\x4c\\xb3\\x7c\\x04\\x5d\\xaf\\x9f\\x40\\x88\\x41\\xea\\x70\\x0c\\xbf\\x2d\\xbd\\x86\\x77\\x6b\\xe9\\x63\\x4c\\x8e\\xf1\\x22\\x7a\\x07\\x38\\xc9\\xf9\\x6c\\x66\\x46\\x06\\xa4\\x40\\x21\\xeb\\x92\\x6e\\x52\\x45\\x45\\xde\\x6b\\x74\\x23\\x01\\x41\\xf6\\x41\\x88\\x7e\\x0a\\x15\\x2f\\x9e\\x19\\xd5\\x3c\\xa3\\xf5\\xb3\\xb0\\x56\\xc2\\x69\\xa1\\x17\\xb2\\x99\\x2f\\xda\\x53\\x11\\xb7\\xe4\\x44\\x69\\x88\\xbc\\x31\\x8b\\xa9\\x5c\\xcc\\xd9\\xda\\x61\\x53\\x46\\xd6\\x11\\x19\\x43\\x91\\x4c\\x32\\xbc\\xee\\xb7\\xb4\\xe7\\xd8\\x1b\\xde\\x61\\x0c\\xf7\\xc5\\x3d\\x77\\x29\\x39\\x10\\xde\\xc5\\xf2\\x20\\x7f\\x4a\\xb0\\x3b\\x9d\\x60\\xc2\\xc7\\xe4\\x02\\x61\\x0b\\x46\\xdd\\x5e\\x3b\\x4b\\x82\\x8b\\x11\\x84\\x37\\xb9\\x40\\xbd\\x9e\\xb1\\x5d\\x6b\\x03\\x70\\x9f\\x81\\x04\\x78\\xad\\xd8\\x39\\x15\\x2b\\x17\\xf0\\x0f\\xe1\\x47\\x98\\xa8\\xe4\\x73\\x10\\x8a\\x7e\\x56\\x54\\x7f\\x97\\x1e\\xbd\\xfc\\x88\\x62\\x59\\x53\\x73\\xbd\\x3a\\x93\\x42\\xb3\\xbb\\x5e\\xbc\\x2f\\xc5\\xab\\x7e\\xd5\\x25\\xa3\\xf3\\xae\\x3b\\x12\\x89\\xac\\x10\\x37\\x6f\\xad\\x02\\xcd\\x42\\x36\\x45\\x0e\\x50\\xa1\\x8d\\x00\\xb6\\xd3\\xef\\x45\\xb9\\x98\\x99\\x27\\x1c\\xcf\\x1b\\xbc\\x98\\xe0\\x1a\\x59\\x27\\xcc\\x45\\xfd\\x61\\xf0\\xe3\\xff\\x35\\x7c\\x49\\x0b\\x26\\x74\\xf0\\x17\\x13\\x88\\x03\\x0b\\xff\\xe8\\x4b\\xfa\\xcf\\x34\\x55\\x37\\xad\\x86\\xc1\\xc6\\x95\\xcc\\x5b\\x85\\xe2\\xc4\\x2d\\x1d\\xfc\\x8a\\xdd\\xe9\\xaf\\xd0\\x77\\x06\\x02\\xd3\\xa4\\xe6\\x4b\\x5e\\xb0\\x39\\x3b\\x57\\x19\\x2d\\x40\\x8f\\xda\\xb5\\x72\\x7e\\x7a\\x0f\\x5d\\x70\\x32\\x6b\\x59\\x28\\x23\\x80\\x19\\x65\\xd5\\x88\\x9a\\x18\\x05\\x0b\\x2e\\x9c\\x39\\xe5\\x02\\xca\\xa7\\x44\\x98\\xf9\\xed\\xa0\\x0a\\xc3\\x70\\x8d\\xbe\\x5d\\xd1\\xda\\x9c\\x42\\x17\\x6e\\x8b\\x4f\\xe3\\x54\\xca\\xc2\\x42\\x70\\x16\\xab\\x96\\x2e\\xde\\xdf\\x1e\\x0e\\xbc\\x58\\xfe\\x22\\xd8\\xed\\x2f\\x86\\x0a\\x45\\x66\\x05\\x9d\\xb7\\x4f\\x33\\xd3\\x1b\\xb9\\x0b\\xf1\\x11\\xc0\\xf7\\x2e\\x34\\xe0\\x4b\\x36\\x46\\xb0\\x31\\x52\\x45\\x1b\\x1b\\x1d\\x72\\xf0\\xfe\\x0a\\xdd\\x8b\\x23\\xe0\\x27\\x54\\x11\\x3f\\x76\\x3f\\xd1\\xc1\\xb4\\x3f\\x1c\\xc1\\x3b\\x71\\x76\\x3a\\xf9\\xe5\\xea\\xc7\\xab\\x5f\\x4e\\x5f\\xbe\\xbd\\xb8\\xec\\x1f\\x01\\x29\\x35\\x43\\xeb\\x4a\\x20\\xdd\\x67\\xde\\x69\\x6f\\x76\\xc1\\xc7\\x7d\\x1c\\x4b\\x75\\x0c\\xce\\x12\\xc0\\xd0\\x10\\xb9\\xbc\\x8d\\xf4\\x14\\x9a\\x33\\xc5\\x68\\x3f\\xc9\\x35\\xa3\\x15\\x9d\\xf2\\x82\\xc7\\xd8\\x16\\x52\\x5d\\x5f\\x40\\x85\\x0d\\xe8\\x01\\x79\\x2e\\xcf\\x4f\\xf2\\x5a\\x56\\xb8\\x7c\\x2e\\xc2\\x3f\\xde\\xc7\\xda\\x8d\\x24\\x0d\\x21\\xd1\\xe0\\xc6\\xcc\\xba\\x84\\xcc\\x6b\\x2a\\x74\\xab\\x49\\xb5\\xa7\\xb9\\x36\\x42\\x7f\\x0c\\xa6\\xca\\x4e\\x0f\\xce\\xce\\x31\\x96\\x69\\x9e\\x0e\\x5f\\xf9\\x34\\xcf\\x59\\xde\\xd9\\xb6\\x88\\x9e\\xf7\\x13\\x46\\xea\\xcc\\x4d\\x2e\\x08\\x25\\x25\\x93\\x77\\x57\\x17\\xff\\x6f\\xed\\xde\\xac\\xaa\\x38\\xf7\\x66\\x9a\\xe2\\x03\\xb5\\xac\\x92\\xed\\xee\\x7b\\x0b\\x39\\x3f\\xec\\xef\\x5e\\xec\\xaf\\x97\\x77\\x76\\x9e\\xa8\\xfe\\xbe\\x11\\xdd\\xea\\x94\\x2d\\x69\\xa4\\x94\\x79\\x04\\x6b\\x9e\\xf8\\x7c\\xae\\x6e\\xaf\\xa1\\xe9\\xa2\\x66\\xc4\\x7c\\x45\\x68\\x0e\\x86\\xa4\\x40\\xf9\\xd0\\x12\\xf1\\xd0\\x93\\xd4\\x51\\x0a\\xdf\\xaa\\x19\\x2d\\xd4\\xd7\\xfa\\xe0\\xc4\\x48\\x2a\\x46\\x68\\x7d\\x2b\\x1b\\x91\\x26\\xf3\\x3d\\xe2\\xc4\\x79\\x42\\x48\\xce\\x84\\xd4\\x56\\x23\\x36\\x13\\x84\\x32\\x5a\\xb5\\xcc\\x08\\x7a\\x01\\x03\\x50\\x9b\\x8e\\xd4\\x10\\x21\\xb4\\x5c\\x07\\x82\\x0a\\x57\\xee\\x5c\\x4c\\x3c\\x45\\x18\\x04\\xde\\x28\\xb6\\xae\\x91\\x5b\\x41\\xa5\\xf5\\x0b\\xce\\x64\\x7f\\x77\\x48\\xcd\\x68\\x0e\\x96\\xf3\\x8a\\xea\\x05\\x02\\x2e\\x94\\x54\\xdd\\xb0\\x1c\\x7f\\x11\\x99\\x68\\xe6\\x03\\x04\\xc1\\x68\\xed\\xa6\\x76\\x6d\\xd6\\xd7\\xc5\\xf4\\x81\\x8a\\x83\\xb0\\x13\\x10\\x45\\x18\\xe3\\x54\\xdd\\xe9\\x85\\x88\\x60\\xc1\\x66\\x13\\xde\\x89\\x62\\xf5\\x5e\\x4a\\xfd\\xbd\\xaf\\xad\\xb0\\xeb\\xcb\\xf1\\x0f\\xab\\x60\\x77\\x43\\x49\\x41\\xd3\\xa2\\x40\\xf2\\x18\\x0e\\x0e\\xb0\\xc6\\xa0\\x22\\x44\\x2c\\x67\\x34\\x1b\\xf2\\x5b\\x65\\x8c\\x75\\x23\\x4e\\xd5\\xab\\x5a\\x36\\xbd\\xa5\\xad\\x94\\x0a\\xdc\\xab\\x8b\\x97\\xf0\\xf6\\x35\\x36\\x17\\x59\\xe8\\x7a\\x05\\x75\\x81\\x36\\xeb\\x54\\x47\\x9b\\x21\\x7e\\xb0\\x59\\xdf\\x21\\x67\\x8b\\x4e\\xf0\\x24\\xe4\\x2d\\x5d\\x11\\x5a\\x28\\xe9\\xb6\\xdd\\x86\\xb7\\xae\\x19\\x10\\x9d\\x75\\xd2\\x7c\\x3c\\x95\\x7a\\xb1\\x61\\x96\\xec\\xeb\\xd7\\x30\\x6d\\x73\\xbc\\x51\\x90\\xd2\\xdc\\x66\\x8f\\x70\\xb1\\x31\\xac\\x86\\xa0\\xc7\\xaa\\x66\\x19\\xcb\\x99\\xc8\\xbe\\xd6\\x1b\\xb1\\xeb\\x0c\\x5b\\xb8\\x55\\x97\\x52\\x18\\xf6\\xba\\xeb\\x7b\\x75\\xe1\\xb3\\xc7\\xed\\x6e\\x84\\xb7\\x08\\xc2\\x70\\xad\\x59\\x8c\\x82\\xe3\\x19\\x98\\x6b\\xa3\\x62\\x22\\x52\\x2f\\x66\\x60\\xc7\\xc3\\x43\\xf7\\xf7\\x66\\xca\\x0a\\xb3\\xd9\\xbc\\x28\\xb0\\x66\\x27\\xd5\\x68\\x6c\\xe7\\x25\\x9d\\x33\\x42\\xb5\\xbf\\x84\\x5a\\x12\\x26\\x54\\x53\\xdb\\x73\\xd3\\xd3\\xe5\\x64\\x9a\\xf7\\x96\\xd9\\xa9\\xfd\\x70\\xf1\\x92\\x3c\\x27\\x87\\x66\\x6e\\x47\\x20\\x71\\xcc\\x28\\x2f\\x20\\xc1\\x1d\\xdc\\xd9\\x6b\\x46\\xc6\\x99\\x73\\xb8\\x45\\x2d\\x01\\xf0\\x11\\x22\\x6b\\x7c\\x5a\\x46\\x44\\x48\\xa2\\x9a\\x6c\\xe1\\xd6\\x80\\x4b\\xe1\\xed\\xac\\x16\\xf1\\x2c\\x2a\\xba\\x73\\x60\\x3b\\xe9\\xde\\xc3\\x1f\\x14\\xab\\x77\\x7d\\x6d\\xcd\\x73\\xf8\\xc3\\x23\\x3e\\x87\\xa1\\x96\\x68\\xae\\x7f\\x77\\xc3\\xf0\\xae\\x96\\x4c\\xd3\\x9c\\x6a\\x6a\\x9f\\x49\\xf7\\x85\\xe1\\xd4\\x0e\\x8f\\x65\\xc4\\x63\\xa9\\xd8\\x1b\\x2e\\x9a\\x3b\\xc4\\x13\\xda\\x0b\\x3f\\xc2\\xd5\\x39\\x50\\x44\\x32\\xb7\\xd1\\x70\\x40\\x31\\x03\\x3a\\x77\\x26\\xff\\x04\\xa9\\x1b\\x17\\x9d\\x6b\\x34\\xba\\x47\\xeb\\x86\\x57\\x82\\x62\\x6e\\x1a\\x33\\x8a\\x10\\x15\\xb9\\x2c\\x37\\x88\\x9c\\xc9\\x9a\\xb0\\x98\\x72\\xc4\\x41\\xac\\xc6\\x70\\x31\\x6d\\xfb\\x6d\\x7b\\x58\\x0a\\xb6\\x64\\x11\\x25\\x98\\xd7\\x2e\\xe5\\x1b\\xd3\\x9b\\x59\\x1c\\x77\\x72\\xa1\\x7b\\x52\\xd0\\x29\\x2b\\x6c\\x3a\\x29\\x62\\x0c\\x24\\xbc\\x61\\x89\\xbc\\x11\\xb5\\x2c\\xd2\\x81\\x5e\\xbf\\x97\\x05\\x43\\x40\\x24\\xb7\\x10\\xa6\\xfb\\xaf\\x62\\x1d\\xa0\\x93\\x54\\xeb\\x00\\x46\\xb9\\xce\\x3a\\x80\\x19\\xf4\\x6b\\x58\\x87\\x26\\x42\\x40\\x24\\xeb\\xeb\\x60\\xa4\\xcd\\xee\\x3a\\x80\\xfc\\xb5\\xef\\xeb\\xa0\\x58\\x96\\xc9\\xb2\\x9a\\xd4\\x72\\xc6\\xfb\\xdf\\x8e\\x94\\xcf\\xb6\\xa5\\xa8\\x0d\\x2b\\x43\\x13\\xfa\\x66\\x6e\\x3a\\x3e\\x5b\\xdd\\x2f\\xd3\\xa8\\x00\\x1e\\x8b\\x12\\x47\\x35\\xbe\\x83\\x0e\\x2a\\xee\\xdf\\x83\\xe7\\x1c\\xb8\\xdd\\xfa\\x1b\\x6f\\x47\\xef\\x3d\\x72\\x27\\x7a\\xcd\\x8c\\x68\\x3b\\xfc\\x2d\\xbe\\x78\\x29\\x20\\x7e\\x23\\x9c\\xa3\\x49\\x1e\\x5c\\x99\\xd1\\x62\\x21\\x95\\x8e\\xbc\\x55\\x24\\x71\\xd2\\xf6\\x3a\\x5d\\x01\\x24\\x21\\x04\\xc3\\xc1\\xef\\x02\\xa4\\x09\\x0a\\xe6\\x79\\xe7\\xbe\\x14\\x32\\x67\\x41\\x54\\x27\\x64\\x58\\x47\\x91\\x73\\x8d\\xa0\\x70\\x30\\x86\\x43\\x52\\x34\\xd2\\x9e\\x0b\\x9a\\xcc\\x3b\\x23\\x6b\\x89\\x75\\x98\\xa3\\x86\\x74\\x70\\xe1\\x14\\xd6\\x95\\x09\\x08\\x91\\xae\\xa8\\x5e\\x8c\\x48\\xcd\\x0a\\xc4\\x6f\\xb4\\xec\\xf9\\x06\\x2d\\x5e\\x07\\xc0\\x71\\x1c\\x41\\x8e\\xdd\\x38\\xb2\\x1d\\xd2\\x44\\x1a\\xaa\\x40\\x06\\x9f\\xe1\\xfb\\xc9\\x15\\x79\\xf6\\xc6\\xed\\xd7\\x33\\x0b\\x74\\x7e\\xf9\\xee\\x3a\\x4c\\x69\\xa1\\x62\\x85\\x89\\x77\\x11\\x09\\x1b\\xd8\\xf6\\x4f\\xac\\x88\\x3c\\xea\\xb8\\x86\\xfe\\x78\\xa3\\x4f\\xf4\\x86\\x8b\\xdc\\x22\\x14\\x76\\x76\\xd1\\x19\\xf0\\xac\\x6a\\x18\\xb7\\x99\\x1f\\x68\\xc1\\xf3\\xf0\\x3d\\xfa\\x36\\xb2\\x8a\\xa7\\x3f\\x05\\x64\\xbc\\x93\\x6b\\xfa\\x1e\\x15\\x58\\xe7\\x65\\x1b\\x7f\\xdc\\xab\\xec\\x09\\x4c\\x49\\xc2\\x0f\\x02\\xee\\xa0\\x99\\xef\\x98\\x08\\xb9\\x65\\x8c\\x04\\x5b\\x17\\x7d\\x07\\xec\\xdb\\xb9\\x47\\x16\\x90\\x7f\\x20\\x45\\x4e\\xcd\\xce\\x0c\\xe7\\xd0\\x5c\\xcc\\x55\\x68\\x05\\xa1\\x45\\x91\\x24\\x2e\\x61\\x9b\\x19\\xc4\\x5d\\x03\\xc8\\xfd\\xb1\\x09\\x68\\xeb\\x6a\\x7e\\x07\\x0c\\x38\\x66\\xf4\\x4f\\x98\\x30\\xbe\\x6e\\x53\\x44\\x61\\x54\\x8a\\xaf\\xdc\\x10\\x31\\x2f\\x15\\x3d\\xab\\xcd\\x0a\\x6a\\x4e\\x8b\\xab\\x8a\\xf5\\xae\\xa5\\x4e\\x12\\x3f\\x17\\xaf\\xde\\x5e\\x9d\\x76\\x29\\x03\\x61\\xd8\\x02\\xcb\\x30\\xf8\\x9c\\xd0\\xbc\\xe4\\x4a\\x81\\xc7\\x87\\x4d\\x17\\x52\\xde\\x44\\x0d\\x79\\xb8\\xa5\\x3a\\x74\\x90\\x18\\xac\\xf8\\x5c\\x9d\\x58\\x8e\\x32\\x36\\x0b\\x77\\x44\\xb8\\x28\\x7c\\xf2\\x0d\\x98\\x0b\\x85\\x56\\xd6\\x85\\x10\\x3d\\x79\\x92\\xf9\\xd9\\xc3\\xd1\\x03\\xc8\\x17\\x1f\\xec\\xbc\\xb9\\x3c\\x80\\xfe\\x03\\x87\\x77\\xe7\\x62\\xc7\\xe6\\xa9\\x8a\\x83\\xe9\\x5c\\xaf\\xd4\\xbf\\x7d\\xee\\x5b\\xea\\x8b\\x6f\\x5d\\x47\\xd4\\x5e\\x77\\xbe\\x48\\x56\\xea\\xcf\\x98\\x4a\\x57\\xe5\\x37\\x41\\x71\\x66\\x4b\\x12\\xc9\\x19\\xe6\\xc5\\x32\\x80\\xa8\\xa0\\xf7\\xa6\\x91\\x81\\x7f\\xfb\\x00\\x4a\\x9d\\xd8\\x3f\\x3d\\x48\\x05\\xbe\\x74\\x5a\\x14\\x66\\x23\\xa9\\xcd\\x91\\x0e\\x22\\x3c\\x41\\x37\\xf1\\x69\\xc9\\x50\\x9f\\x14\\x33\\x92\\x8d\\xb6\\x10\\xce\\x22\\xbe\\x7a\\xe7\\x21\\xd7\\x2e\\x21\\xdc\\x65\\xa4\\x6b\\x89\\x63\\x53\\x52\\xf2\\x3b\\x43\\x61\\x38\\x62\\x37\\x85\\x16\\x3c\\xff\\xdb\\x3f\\x8e\\x40\\x7e\\x27\\x10\\x7d\\xe0\\x91\\x28\\x46\\x66\\x87\\xc2\\x41\\x5c\\xbe\\x8f\\x36\\xcf\\x96\\xf9\\xe0\\x92\\x69\\xa3\\xa9\\xe1\\xba\\x85\\xee\\x07\\xa3\\x59\\xd5\\x4d\\x82\\xcb\\x10\\xe3\\x1a\\x26\\xa1\\x7b\\x38\\x29\\xa7\\x88\\xbc\\x0f\\xe0\\x2a\\xb6\\x34\\x19\\x19\\xc4\\x09\\x6f\\x8f\\xe5\\x3a\\x26\\x5b\\x12\\x62\\x1e\\xcd\\x85\\x4c\\x3e\\xdf\\x8d\\xfc\\x05\\x9d\\x55\\x64\\x5f\\x1c\\x56\\xb1\\xd9\\xc3\\x41\\x26\\xf4\\xce\\x52\\x87\\xc3\\x6c\\x6c\\xbe\\x19\\xbd\\x34\\x91\\xf9\\x46\\x92\\xb6\\xab\\x8b\\xd9\\x1f\\x01\\xd9\\x1c\\x8e\\x56\\x05\\x11\\xd2\\xda\\x47\\x82\\xd2\\x94\\xec\\x8e\\x65\\x8d\\x66\\xb9\\xc5\\x6a\\xb0\\x36\\x65\\xcc\\xf3\\xee\\x52\\xd3\\x9b\\x02\\xe8\\xb3\\x2d\\x88\\xa3\\x46\\x2d\\x54\\xa1\\xd5\\x75\\x3c\\xda\\xc4\\x88\\xfc\\x2f\\x70\\x49\\x0b\\xcd\\xd4\\x56\\xd3\\x9c\\xf8\\x3f\\xef\\xbb\\x14\\x10\\x48\\x9d\\x51\\xe1\\x2b\\xca\\x6b\\xe9\\x4c\\xdc\\x16\\x93\\xc1\\xa6\\xa6\\x4e\\x19\\xa9\\x68\\x4d\\x4b\\xf3\\x06\\x2b\\x62\\xb7\\x67\\xca\\xe6\\x1c\\x13\\xed\\x82\\x47\\xd1\\x83\\x3a\\xf4\\x03\\x29\\x01\\xc5\\x86\\x6b\\x52\\xf2\\xf9\\x02\\x6f\\x0b\\xa1\\x50\\xb9\\x86\\xb8\\xc0\\xb1\\x42\\xd2\\x9c\\x00\\x63\\x91\\x35\\xb9\\xa5\\x75\\x69\\x64\\x01\\x9a\\x2d\\x20\\x0a\\x8d\\x0a\\x92\\x37\\xe6\\x3e\\x10\\x80\\x20\\x58\\x8d\\x95\\xa6\\xda\\xe8\\x98\\xac\\x8e\\x30\\xc2\\xb9\\x65\\xda\\x01\\xb6\\xf2\\x97\\xae\\x1b\\xb1\\xe3\\x14\\x71\\x73\\xd3\\x92\\x58\\x41\\xce\\xef\\x58\\x16\\x54\\x27\\x34\\xc7\\xd3\\x96\\x27\\x34\\xcf\\x14\\xbd\\x89\\x0c\\x34\\xdb\\xb9\\x5e\\x9c\\xc9\\xb2\\xa4\\x22\\x5d\\x1a\\x64\\xa4\\x20\\x72\\x86\\xe4\\x38\\x15\\xc7\\x52\\x47\\x8c\\xf2\\x09\\xc1\\x9d\\xc8\\x40\\x1d\\xfa\\x69\\x47\\x0a\\x41\\x4e\\x67\\xce\\xb5\\xb9\\xa6\\x98\\xe3\\x2e\\x6b\\x5f\\xd3\\x22\\x8a\\x2c\\x47\\x07\\xa0\\xe4\\x4b\\xa9\\xc9\\xe1\\xc1\\xc9\\xc1\\x91\\x43\\x5d\\xf1\\x24\\x1c\\xa8\\x30\\xa9\\x00\\x13\\x8a\\xdb\\x09\\x29\\x5e\\x56\\xc5\\x0a\\xe6\\x70\\x80\\xc0\\xf8\\x11\\x05\\xa7\\x4c\\x73\\xe1\\xa9\\x1e\\x0b\\x56\\x2d\\x58\\x51\\x8c\\x88\\x32\\xb2\\x2e\\x75\\xe0\\x6d\\xf8\\x5b\\xf3\\x25\\x5d\\x37\\x19\\xda\\xc4\\x0e\\x0f\\x7e\\x3d\\x18\\x11\\xa6\\xb3\\x23\\x72\\x2b\\xc5\\x81\\x46\\xf7\\x06\\xb9\\x06\\x85\\x31\\x8a\\x26\\x4f\\xc4\\x4a\\x36\\x50\\xbb\\x0d\\xb7\\xcd\\xe3\\xfd\\x65\\xd4\\xe8\\x3a\\x0d\\x0a\\xe4\\xe6\\x3d\\x86\\xaf\\xc7\\x09\\x6f\\xe7\\x77\\x5c\\x1b\\xb9\\x43\\x37\\x60\\x93\\x78\\x8e\\x6a\\x01\\x33\\xbc\\xd4\\xbc\\x6e\\xe6\\x59\\x3b\\x59\\x30\\x5a\\xe8\\xc5\\xca\\xab\\x2a\\x58\\x16\\x4b\\x91\\x46\\xd8\\x4f\\xe2\\x05\\xa6\\x3d\\x48\\xe7\\x8c\\xd6\\xd7\\x6d\\x11\\xbd\\xbd\\xae\\x03\\x6c\\x69\\xfc\\x64\\x19\\x60\\x14\\x60\\xba\\x25\\x80\\x41\\xc6\\x62\\x79\\xaa\\x2a\\xc0\\x7f\\x7c\\x7a\\x15\\x7e\\xe7\\x75\\x95\\xe6\\xe5\\x7c\\xf5\\x7e\\x72\\xf6\\xc9\\xba\\xbe\\xf0\\xa5\\xa1\\xb0\\x6f\\x34\\xb8\\x66\\xca\\x7a\\xb6\\x13\\x59\\x6b\\x22\\x7c\\x4d\\x35\\x73\\xc3\\xe6\\xb0\\x97\\xac\\x5e\\xf2\\x8c\\x1d\\x3f\\x42\\xf9\\xd8\\x54\\xb0\\x99\\xf1\\xd7\\x81\\x40\\x9c\\x12\\x4c\\x7c\\x5f\\x64\\xa4\\x2b\\x24\\x67\\x9b\\x19\\xd8\\x52\\x0a\\xea\\x56\\x41\\x33\\xbf\\x37\\xb0\\x7f\\xaf\\xe1\\xa1\\x3b\\x5b\\xb0\\xec\\xc6\\x82\\xe0\\xc6\\xd9\\x0b\\x15\\x63\\x64\\x8b\\x23\\xc1\\x30\\x10\\xfc\\xcf\\xb4\\x90\\xd3\\x93\\x92\\x2a\\xcd\\x6a\\xa3\\x7d\\xd8\\x37\\x78\\x9c\\x19\\x0a\\xb8\\x98\\x1f\\x97\\xf9\\x51\\x4c\\x65\\x0c\\x12\\x68\\xbc\\x1b\\x48\\x96\\x1d\\x4c\\x95\\x7b\\x50\\x29\\xcd\\xaa\\xec\\xd4\\x3a\\x6e\\x56\\xef\\x55\\xa2\\x5a\\xea\\xaf\\xaf\\xaf\\x27\\xaf\\x3a\\x95\\xd4\\x21\\xef\\x5f\\xeb\\xca\\x81\\x57\\xc3\\xa9\\xc0\\x3c\\xa1\\x81\\xdb\\xee\\x4d\\x19\\xf5\\x04\\x9e\\x8c\\x87\\x94\\x5e\\x27\\x3f\\xca\\x06\\x04\\x26\\x3a\\x2d\\x56\\xe4\\x96\\x22\\x4e\\x80\\x62\\x71\\xbc\\xe0\\x99\\x21\\xe3\\x99\\xe1\\x36\\xe6\\xc0\\xbd\\x66\\x34\\x47\\x4c\\x5d\\x30\\x96\\xec\\xde\\x01\\xd5\\xd2\\x94\\x6c\\xdb\\xce\\x1a\\xa5\\x65\\x49\\x16\\x76\\xaa\\xb8\\x86\\xfe\\x29\\xc4\\x0b\\x77\\x0c\\x97\\x12\\xbd\\x29\\x8a\\xd4\\xac\\x42\\x95\\xc4\\xfe\\xcd\\x93\\x50\\x38\\x36\\x58\\x10\\xae\\x73\\x00\\x4f\\x4f\\x49\\x16\\x2e\\x95\\x15\\xd3\\xb1\\x16\\xae\\xc0\\x05\\x8a\\x2a\\x4e\\x8a\\x2d\\x49\\xbd\\x1e\\x92\\xa8\\x66\\x0f\\x89\\xaf\\xdb\\xe3\\x3a\\x89\\x77\\xeb\\xa5\\xa9\\x00\\x44\\x92\\x54\\x01\\x22\\xc9\\x2b\\x01\\x11\\xeb\\xbc\\xb2\\x87\\x0b\\x43\\x5a\\x0c\\xa1\\x71\\x16\\x05\\xd7\\x31\\x6f\\xeb\\x85\\x67\\x54\\x48\\xc1\\x33\\x74\\x10\\x60\\xdd\\x79\\xd9\\xe8\\xaa\\xd1\\x60\\x6f\\xc9\\xa8\\x62\\xe3\\x25\\xad\\xb9\\x61\\xa8\\x58\\x44\\xcd\\xc7\\x16\\x09\\x73\\xdb\\xb5\\x94\\x60\\x8c\\xf0\\x6e\\x5c\\xa4\\x38\\x9e\\xcc\\x24\\x1c\\x12\\x1b\\x1c\\xb6\\xc4\\x3b\\xbc\\xb1\\x39\\xf1\\x27\\x9a\\xa4\\x9a\\x75\\x45\\xf5\\x22\\x9d\\xd6\\x44\\xf5\\x02\\x42\\xda\\xc0\\x89\\xe3\\x22\\x22\\x81\\xbf\\x19\\xa9\\x7c\\x0f\\x52\\x4e\\x92\\x2a\\x89\\x91\\x37\\x17\\xab\\xc8\\xd6\\x6b\\x6a\\xa6\\xa1\\x70\\x73\\x0d\\x13\\x05\\x59\\x7c\\x79\\xad\\x35\\x2c\\x4c\\x36\\x65\\x84\\x0a\\x72\\x71\\x7a\\x79\\xfa\\xcb\\xd5\\x87\\xb3\\x5f\\x2e\\x4f\\xdf\\x9e\\xc7\\x74\\x1d\\x5d\\x8a\\x22\\x65\\x31\\x8a\\x64\\xe5\\x28\\xbe\\x50\\xb1\\x1e\\xd3\\x54\\xb6\\x60\\xfb\\x13\\x5f\\x71\\x05\\xd4\\x84\\x88\\x5c\\x56\\x54\\x0f\\x60\\xd2\\xe3\\x20\\xda\\xc8\\x9a\\x65\\xd2\\x30\\x9e\\x9d\\x72\\x1c\\xeb\\x4e\\x7f\\xc9\\x0a\\xba\\xba\\xc2\\xb2\\xfc\\xbb\\x36\\x26\\x5f\\x7a\\x66\\x83\\x85\\xfb\\x95\\x47\\x87\\x67\\x6b\\x58\\x51\\xae\\x1e\\x83\\xc5\\xb4\\x77\\x8e\\xf1\\xd0\\x97\\x8f\\xf3\\xeb\\xed\\xae\\x25\\xfb\\xe7\\xb2\\x25\\x7b\\x63\\x83\\xae\\x58\\xcd\\x21\\x14\\x66\\x1f\\x4e\\xcd\\x6b\\x79\\x6b\\x0b\\x3d\\x1c\\x72\\xe1\\x4e\\xce\\x51\\x60\\x4c\\x69\\x7d\\x10\\xf1\\x38\\x62\\x5a\\x92\\x17\\xcf\\xdd\\x20\\x4f\\xcf\\xb9\\x60\\x43\\x5c\\xf6\\xda\\xbd\\x64\\x69\\xfc\\xb4\\x7f\\xa9\\x8d\\xd7\\xe9\\xfa\\x98\\x62\\x02\\x67\\xc8\\x1a\\x1b\\x7f\\x71\\xec\\x33\\xb4\\x5e\\x00\\x3d\\x9e\\x15\\x51\\x91\\xbb\\x58\\xab\\xa7\\x77\\x4e\\x74\\x56\\x5d\\xc9\\xec\\x26\\x91\\x69\\xf4\\xfa\\x6c\\x82\\xbd\\x7d\\xd2\\x1d\\x75\\x7d\\x36\\x19\\xbc\\x51\\xfb\\x65\\x1f\\x3d\\xc0\\x9c\\x26\\x5a\\x7c\\xfb\\x60\\x5b\\xe7\\xc1\\xa0\\x71\\xb5\\xcd\\x09\\x3f\\x75\\xc7\\x61\\x34\\x68\\x5c\\xf7\\xb5\\x41\\xe3\\x7a\\x40\\x73\\x95\\xc5\\xb8\\x14\\xaf\\x6a\\x9a\\xb1\\xc9\\x3e\\x09\\x70\\x8e\\x81\\x90\\xdc\\xd6\\xdb\\x24\\xad\\x1c\\xe7\\xd9\\x85\\x60\\x2c\\x47\\xfe\\xe1\\x8a\\xa4\\x91\\xb9\\x99\\x09\\xc6\\x06\\x83\\xb9\\xaf\\x8d\\xaa\\x6d\\xea\\x08\\x51\\xef\\x7a\\x61\\xbb\\xb6\\x62\\xae\\xf3\\xe3\\x6e\\xa3\\xae\\xd5\\x4f\\x2a\\x8f\\x06\\xee\\x8a\\x50\\xd8\\xeb\\x64\\x88\\x37\\xfa\\x88\\x62\\xa2\\xbf\\xe5\\x9b\\x86\\x3b\\x48\\x14\\x9f\\x9b\\xe5\\x72\\xb5\\xf9\\x10\\x42\\xca\\x95\\x52\\x69\\x09\\x31\\xa3\\xce\\x64\\x9d\\xf1\\x69\\xb1\\x22\\x0b\\x5a\\x18\\x85\\x09\\x4a\\xbc\\x51\\x72\\x03\\xa5\\xc9\\xa0\\x9b\\xfe\\x0b\\x75\\xc5\\x6c\\xa2\\x22\\x4a\\x35\\x85\\x14\\x73\\x58\\x0c\\x6a\\x13\\x12\\xee\\x2a\\x96\\x99\\x31\\xb3\\x82\\x51\\xd1\\x54\\x48\\xa7\\x91\\x91\\x56\\xb2\\x49\\x90\\x93\\xe0\\x5c\\xcb\\x5e\\xa6\\x12\\xdc\\x82\\x6f\\x54\\x10\\x90\\xfc\\xd1\\x33\\xdf\\xcd\\x2c\\x25\\xef\\x5c\\x89\\xda\\x51\\xff\\x52\\x64\\xc4\\x59\\x68\\x3d\\x64\\x87\\x0a\\x92\\x03\\x3c\\x80\\x88\\x4d\\x9b\\x33\\xc7\\x02\\xf2\\x38\\x7b\\x8f\\xf5\\x01\\xfa\\x75\\xac\\x55\\x48\\x31\\x16\\x6c\\x8e\\x30\\x05\\x96\\xa1\\x61\\x84\\x23\\x8e\\x8f\\xf1\\x74\\x3e\\xd4\\x5e\\x69\\x59\\x75\\xea\\xb0\\x2d\\x39\\xed\\x4d\\x09\\x40\\x22\\xb4\\x27\\x8a\\x1c\\x0a\\x49\\x64\\x65\\x9e\\xae\\x46\\x70\\xbd\\x02\\xe7\\x9b\\x2b\\x01\\x18\\x91\\x6c\\x74\\x6d\\x03\\x09\\x28\\x99\\x32\\x4d\\xad\\xb9\\xda\\x5c\\x02\\x8f\\x08\\x0e\\x60\\xdf\\xe6\\xee\\x41\\x84\\xfc\\xf5\\xd6\\x03\\xe0\\x41\\xc2\\xe7\\x54\\x47\\x70\\x89\\x2d\\x12\\x3d\\xee\\xe7\\xc7\\x8f\\x1d\\x57\\xd6\\xb5\\x16\\x89\\x42\\xbc\\x1f\\xb8\\x7e\\xe6\\x46\\xcb\\x46\\xef\\xc9\\x3b\\x72\\x9f\\xf9\\x08\\x01\\x1e\\x02\\x45\\x91\\x97\\x4c\\x11\\xd9\\x24\\x2a\\xb8\\xf0\\xc2\\x0e\\x97\\x52\\xcb\\x1b\\x6c\\x4f\\x5b\\x9b\\xd2\\x39\\xef\\x55\\x45\\x2e\\xc5\\x11\\xbb\\x07\\xba\\xde\\x26\\xa1\\x06\\xe8\\x8d\\xd3\\x66\\x36\\x63\\x35\\xbc\\x74\\x40\\xf0\\x46\\x18\\xba\\x2f\\x0b\\xe5\\xde\\xb0\\x7e\\x06\\x5c\\x1b\\x52\\xc5\\xf4\\x08\\x90\\xf3\\x2d\\x92\\xc2\\x3d\\x43\\x5a\\x88\\x49\\x28\\xbb\\x56\\x33\\x05\\x48\\xe8\\x82\\x9c\\xbf\\xfb\\xbe\\xdf\\x11\\x4d\\x81\\xab\\x1f\\x97\\xaf\\x09\\xf3\\x7c\\x27\\xfa\\x85\\xfd\\xa5\\x3d\\x0f\\xdb\\x20\\x4f\\xec\\xb1\\xc8\\x0a\\xa9\\x6c\\x6e\\x30\\xec\\x4b\\xb6\\xa0\\x42\\x30\\x67\\x90\\xe2\\x1a\\xac\\xd9\\x53\\xc6\\x04\\x91\\x15\\xc3\\xb0\\xb7\\x5e\\xc4\\x50\\xa2\\xb8\\x98\\x17\\x8c\\x50\\xad\\x69\\xb6\\x38\\x36\\xd4\\x09\\x77\\x16\\xda\\x24\\x5c\\xfb\\x1b\\xa5\\x6b\\x46\\x4b\\x3c\\x13\\x35\\x2b\\x29\\xc7\\xe1\\x09\\xcd\\x6a\\xa9\\x14\\x29\\x9b\\x42\\xf3\\xca\\x77\\xd6\\xcf\\x92\\xc8\\x00\\x0e\\x41\\x61\\x4e\\xa6\\xdb\\x2b\\x48\\xb3\\x68\\xb3\\x7d\\x47\\x2d\\x85\\x76\\xfa\\x52\\xac\\x97\\x8b\\x1d\\x99\\x4f\\x59\\x59\\xe9\\x95\\xcf\\xca\\xeb\\xa7\\x03\\xcd\\x78\\xad\\x34\\xc9\\x0a\\xce\\x84\\xb6\\x33\\x43\\xc0\\x3d\\xa0\\xc1\\xd7\\xfc\\x16\\x76\\x45\\x94\\x5d\\x12\\x91\\x83\\xf2\\x5d\\x69\\x85\\xc9\\x67\\x9e\\x08\\xd7\\x55\\xce\\x95\\xb5\\x75\\xa8\\x7e\\xa9\\x6f\\xd4\\xd5\\x65\\xc1\\x83\\xe3\\x56\\x04\\x8e\\x8e\\x13\\x70\\x90\\x22\\xfb\\xab\\x80\\x84\\xb0\\xf2\\xad\\x4f\\x1c\\x8c\\xe3\\x2b\\x50\\x3c\\xc5\\xdd\\xeb\\x51\\x27\\xe1\\xbe\\xd5\\x2d\\x20\\x35\\x64\\x83\\xeb\\xc0\\x81\\x12\\x6c\\x69\\xee\\x01\\xcb\\x98\\x11\\x45\\x69\\x42\\x26\\xf3\\xe8\\x3c\\x26\\x90\\xe5\\xde\\x32\\xa5\\xe8\\x9c\\x4d\\x7a\\x86\\x24\\xa4\\x60\\x38\\xad\\xa1\\x0d\\x62\\x19\\xda\\x63\\x03\\xd5\\x6f\\x0b\\x84\\x41\\xf3\\xbf\\x09\\x93\\x9e\\x42\\xe5\\xb1\\xc4\\x89\\xf4\\xa2\\xc0\\x29\\x4d\\xb7\\x35\\xd7\\x9a\\xc1\\x29\\x85\\x52\\x46\\x10\\x2b\\xb6\\x0e\\x5d\\xd9\\x4d\\xb6\\xea\\x35\\x9e\\x5d\\xf4\\x70\\x3c\\x23\\x7e\\x88\\x1c\\xd3\\x96\\xa6\\x8c\\x4c\\x6b\\xce\\x66\\x64\\xc6\\x21\\x8f\\x0a\\x32\\x8c\\x46\\x88\\xc1\\x4f\\xd1\\x84\\xac\\x14\\xab\\x61\\xda\\xd6\\x2c\\xe0\\xa6\\xdf\\x8f\\x9e\\x7f\\xd8\\xf9\\xeb\\xba\\x11\\x19\\x0d\\x2a\\x3e\\x02\\xb0\\x16\\x9f\\x91\\x39\\x64\\x35\\x59\\x25\\xf8\\x4f\\xcf\\xff\\xf6\\x17\\x32\\x5d\\x19\\x79\\x0d\\x14\\x31\\x2d\\x35\\x2d\\x1c\\x01\\xa4\\x60\\x62\\x6e\\x76\\x11\\x58\\x6e\\x3f\\xbe\\xd1\\x01\\x67\\xf2\\x9b\\x53\\xf0\\x92\\x6b\\x5c\\xa0\\x17\\x7f\\xb8\\x99\\x46\\x5d\\x3d\\xe0\\x8f\\x27\\x39\\x5b\\x9e\\x04\\x47\\x68\\x5c\\xc8\\x79\\xbf\\x5e\\xcf\\x52\\xa4\\xd2\\x46\\xd9\\xd9\\xb6\\xdc\\x68\\x28\\x74\\xbf\\xab\\x3b\\xed\\x4a\\x77\\x90\\x85\\xbc\\x45\\x63\\xce\\xe6\\x55\\x0d\\x70\\x4e\\x2a\\x59\\x35\\x05\\x2c\\x1c\\xf9\\xde\\xa3\\xd3\\x35\\x8a\\xad\\xe3\\xfe\\xc4\\x1a\\x09\\x03\\x6e\\x07\\x8e\\x54\\x3b\\xec\\x7a\\x19\\x6f\\x4c\\xe9\\x73\\x64\\x4a\\x8b\\xba\\x60\\xfd\\x6e\\xbe\\x0a\\x47\\x6f\\x6b\\xdc\\xf7\\xb4\\x28\\xa6\\x34\\xbb\\xb9\\x96\\x6f\\xe4\\x5c\\xbd\\x13\\xe7\\x75\\x2d\\xeb\\xee\\x9c\\x0b\\x6a\\xde\\xf4\\x45\\x23\\x6e\\xa0\\x28\\x6b\\x0b\\xc5\\x2a\\xe7\\x36\\xfc\\xcf\\x25\\xcf\\x07\\xb3\\xeb\\x45\\x8c\\x9b\\x25\\x82\\x63\\x3a\\x91\\xc4\\xd9\\xe0\\xda\\x91\\xd9\\x1d\\x6f\\x0d\\x6d\\x82\\x30\\x43\\x73\\xdf\\xec\\x73\\xd6\\x99\\x87\\x0a\\xaf\\xf6\\x1f\\x9e\\xff\\xe9\\xaf\\xc8\\x5c\\x88\\xac\\xc9\\x5f\\x9f\\x43\\x0a\\xae\\x1a\\xe1\\x03\\x00\\x2f\\xb0\\x11\\xb5\\x4a\\x5a\\x14\\x7d\\xbd\\x04\\x21\\x0b\\x30\\x87\\xed\\xab\\xbd\\xf2\\x7a\\x67\\xb7\\xfb\\xb3\\x55\\xc6\\xeb\\xeb\\x1f\\x41\\x5f\\xe4\\x5a\\xb1\\x62\\x36\\x42\\xa8\\x13\\x6f\\xd6\\x3a\\x00\\xe9\\xea\\xc0\\x3e\\x79\\xfd\\x61\\x72\\x76\\xaf\\xb4\\x2d\\x65\\xd1\\x94\\xec\\x25\\x5b\\xf2\\xac\\x9f\\x03\\xb3\\xb3\\x2b\\x9d\\xde\\x9c\\x99\\xbe\\xe0\\x0a\\x10\\x70\\xa6\\x85\\xcc\\x6e\\x48\\x6e\\x3f\\x0c\\xa2\\xda\\xd7\\x8b\\x34\\xf7\\x5f\\x85\\xbe\\xf1\\xfd\\x11\\x71\\xfd\\xf7\\xce\\xbf\\x13\\xd1\\x5f\\xd2\\xaa\\xf2\\xf0\\x1c\\x35\\xbd\\xed\\x2c\\x06\\xb0\\x26\\x80\\x06\\x8d\\x74\\x23\\x46\\x3b\\xd3\\x63\\x5d\\xe9\\x63\\x3b\\x23\\xf3\\x4c\\xf5\\xee\\xa2\\x77\\x1a\\x40\\xbc\\x27\\xbe\\xa5\\xbe\\xbf\\x1f\\xb3\\x73\\x20\\xda\\x0e\\xdd\\x6d\\xa8\\xe0\\xdf\\x88\\x3f\\xb0\\x01\\x0b\\xe5\\xf1\\x76\\xfc\\xc1\\x40\\x09\\xd2\\x1c\\x1f\\x78\\x65\\xfa\\x9b\\x2f\\x13\\x38\\x43\\xe3\\xd2\\x19\\x3a\\xeb\\x22\\xbc\\x13\\xba\\xa4\\xda\\xea\\x47\\xce\\xcb\\x4e\\x49\\xc5\\x6a\\xc5\\x95\\x11\\x9d\\x3e\\xc0\\x85\\x3a\\x2b\\x28\\x2f\\x03\\xf7\\xdd\\x6e\\x16\\x01\\x2f\\x37\\xd4\\x36\\x8d\\xe7\\x94\\x3d\\xdf\\xaf\\x89\\xcc\\x2d\\x1d\\xc0\\x41\\xb1\\x6c\\xed\\x17\\xd1\\xf4\\x12\\x8a\\x09\\xbb\\xe6\\xca\\x1f\\xda\\x8d\\xfb\\xff\\xd9\\xfb\\xf7\\xe6\\xc6\\x6d\\x2c\\x6f\\x1c\\xff\\xff\\x79\\x15\\x28\\xcf\\x56\\xd9\\xce\\x48\\x72\\x77\\x32\\xb7\\xed\\x67\\x7e\\x33\\xe5\\xb4\\xdd\\x19\\x3f\\xe9\\x76\\x7b\\x6d\\x27\\xa9\\xfd\\x25\\xb3\\x3b\\x10\\x09\\x49\\x18\\x93\\x00\\x03\\x80\\x72\\x6b\\x36\\xfb\\xde\\xbf\\x85\\x73\\x00\\x10\\x94\\xe5\\x8b\\x40\\xda\\x92\\x3b\\xe6\\x54\\x4d\\xc7\\x12\\x45\\x1c\\x02\\x07\\x07\\xe7\\xfa\\x39\\x6d\\xa1\\x6c\\x3f\\x09\\x52\\x19\\xef\\xfa\\x9c\\x64\\x31\\xbc\\xdf\\x73\\x15\\xc5\\x81\\xf8\\x9e\\x24\\x4e\\xa7\\x64\\x20\\x10\\xe0\\x8e\\x33\\xda\\x12\\xbb\\xe5\\xf3\\xc1\\x9d\\x19\\x59\\x87\\xce\\x17\\x33\\x42\\xd4\\xf8\\x0e\\x04\\xd8\\xad\\xe8\\x06\\x25\\xbb\\x6f\\x76\\x37\\x7a\\x0c\\xe0\\xca\\x28\\x59\\xd1\\x29\\x18\\x6f\\xdb\\xb0\\x40\\xcb\\x34\\xc5\\x18\\xa5\\xd6\\x90\\x87\\xef\\x31\\x01\\xa3\\x72\\x77\\xb1\\xbc\\x01\\xba\\x9e\\xc9\\x4e\\xab\\x83\\xc9\\x75\\x9e\\x23\\x9c\\x01\\x8a\\x58\\x76\\xd7\\x74\\x41\\xa8\\x92\\xb5\\xe8\\x54\\xd4\\x0b\\xb1\\x83\\x10\\x5b\\xfa\\xb0\\xf4\\xb2\\xa7\\x52\\x30\\x1f\\xc7\\xee\\x32\\xca\\x65\\x83\\x71\\xcd\\x35\\x86\\xf4\\xb9\\x20\\xaf\\x47\\xaf\\x5f\\x7d\\x2e\\x6a\\x07\\xbc\\xe1\\x92\\xda\\x71\\x1a\\xd4\\x0e\\x3c\\x01\\x36\\xfa\\xae\\xbe\\x47\\xf8\\x36\\xec\\xa9\\x0f\\xce\\x91\\xdc\\x34\\x01\\xe7\\xbe\\xc9\\x2c\\x7c\\x74\\xad\\xb8\\x71\\x6c\\x7e\\xcd\\x35\\x23\\x7b\\x60\\xc2\\x12\\xa9\\x62\\x90\\xd1\\x4e\\x50\\xb6\\xb1\\xc3\\xa3\\x63\\xb3\\xf0\\x3e\\xa0\\x68\\x75\\x3d\\xde\\xd6\\x03\\xc9\\x9d\\x3c\\x20\\xd0\\x56\\x47\\x1c\\x6e\\x3d\\x9b\\x7a\\x5a\\x9f\\x9d\\x1d\\xb2\\x87\\x63\\xec\\x22\\xe2\\x5b\\x87\\x95\\xef\\x61\\x23\\xb9\\xb5\\x3a\\xfe\\x54\\x75\\x68\\x1a\\xd6\\xdf\\x7a\\x1d\\x7f\\xaa\\x28\\x04\\x49\\xaa\\xad\\x58\\xb8\\xaf\\xd9\\x8c\\xce\\x19\\x00\\xec\\xf1\\x82\\xaa\\x02\\x32\\xc2\\x2e\\x70\\xca\\xc8\\xb8\\x36\\x84\\x89\\x39\\x57\\x52\\x94\\x4c\\x18\\x02\\x45\\xda\\xe3\\x82\\x11\\xc5\\x00\\x86\\x34\\x63\\x9a\\xfc\\xdb\\xde\\xf7\\x87\\xe7\\x90\\x31\\xbc\\xef\\x70\\x5a\\xdd\\xfb\\xd5\\x1a\\x0a\\xf4\\x96\\xde\\x21\\x7a\\xdc\\x36\\xf2\\x1b\\xf1\\xef\\x6e\\xd9\\x05\\x0e\\x70\\x3f\\x17\\xf6\\xdd\\xca\\xda\\xd4\\xb4\\x00\\x1c\\xc2\\xac\\xa8\\x35\\x9f\\x6f\\xea\\x88\\x70\\x48\\x8d\\x47\\x3c\\x89\\xa5\\xfb\\x60\\xe6\\xb7\\xd1\\x9a\\xde\\xc0\\x8d\\x4c\\x46\\xe0\\x5d\\x81\\x43\\x74\\x23\\x7d\\x63\\x57\\x07\\x6c\\xa2\\x38\\x51\\xd4\\xb9\\xd7\\xd3\\xe2\\x07\\x00\\x6c\\x8b\\x15\\x4a\\xbe\\x65\\xd4\\x0d\\xfd\\x1e\\x10\\xb4\\x37\\x6e\\x41\\xaf\\xcd\\x30\\x42\\xe6\\x6c\\x7d\\xb8\\xf4\\x6e\\x2c\\x72\\xea\\xc6\\xc4\\x8c\\xd0\\x08\\x42\\x49\\x67\\x33\\x96\\xd7\\x05\\x73\\x50\\xcb\\x32\\x27\\x52\\x18\\x49\\x68\\xd3\\xe9\\xc6\\x92\\x0b\\x39\\x12\\x1e\\x51\\x5f\\x0c\\x21\\x9a\\xb3\\x6e\\xfa\\x06\\x24\\xd4\\xb8\\xd1\\x94\\x87\\x0f\\xf5\\x1f\\xe8\\xa5\\xf1\\xc1\\xd9\\x66\\x47\\x1e\\x10\\xaa\\x75\\x5d\\xa2\\xe0\\x82\\x26\\xf8\\x64\\xc2\\x0d\\xa4\\x6f\\xc8\\x5a\\x65\\xeb\\x5a\\xc0\\xce\\x70\\xb7\\xc2\\x6e\\xcd\\x64\\xea\\x0e\\x8b\\x7d\\xc1\\x0a\\xd8\\x85\\x4f\\xbd\\xe0\\x7e\\x5c\\x5c\\x74\\xed\\xff\\xc2\\xa3\\xcc\\xa7\\x42\\x43\\xb2\\x53\\xa8\\x0d\\x94\\x10\\x2e\\x9b\\x70\\x43\\xa4\\x20\\x14\\xd7\\x7e\\xcd\\x91\\x2f\\x56\\x8c\\x83\\x1a\\x3d\\x3e\\x6f\\x57\\x63\\x2b\\x4f\\xbd\\x3c\\xea\\xb8\\xe1\\x0f\\xd7\\xb0\\xce\\xf1\\xc0\\xba\\x14\\xac\\x99\\x0d\\xea\\x45\\x0c\\xd8\\x6b\\x07\\x54\\x6b\\x3e\\x15\\xc3\\x4a\\xe6\\x43\\x3b\\xf6\\x41\\x02\\x93\\x24\\x38\\x96\\x7c\\x4f\\x08\\x5a\\x9c\\x25\\x7b\\x67\\x92\\xcf\\xaf\\x56\\x11\\x4d\\x49\\xab\\xa1\\x73\\x0d\\x1a\\x59\\xf2\\x6c\\x8d\\x27\\xc9\\x35\\x49\\xee\\xc6\\xe1\\x17\\x2d\\x68\\xb8\\x8f\\x17\\x37\\x3c\\xf6\\x3a\\xf2\\x4a\\xaf\\xcd\\xc4\\xb2\\x74\\xc5\\x28\\x22\\x8f\\x4e\\x1c\\x30\\xc0\\xd1\\x55\\xa1\\x98\\x9d\\x69\\x28\\xd9\\xe0\\x0d\\x6c\\x1f\\x24\\xa9\\xaf\\x0b\\x02\\x78\\x32\\xf1\\xaf\\x10\\x0c\\x7c\\x97\\xf6\\x07\\xbd\\xaa\\xf0\\xd4\\x9d\\xc8\\xa2\\x90\\xd7\\x50\\x91\\x8b\\x44\\xf8\\x0d\\x0c\\x99\\xf1\\xeb\\xf2\\xca\\x50\\x2f\\x35\\x83\\x68\\xb7\\x5c\\xeb\\xf1\\x15\\xdc\\x83\\x07\\x7d\\xbf\\x00\\xd6\\x0f\\x40\\x37\\x9e\\x93\\xa3\\xf4\\x1f\\x9f\\x9c\\xbd\\x4d\\xff\\xf1\\x77\\x9a\\xa9\\x75\\xb3\\x91\\xdc\\xcf\\x97\\xe7\\xbf\\xdd\\xf4\\xbf\\xaf\\x67\\xc6\\x1d\\x89\\xfb\\x79\\xe6\\x44\\x7f\\xa3\\x64\\x5d\\xf5\\xfa\\xb0\\xb7\\x33\\x2a\\x7c\\x6a\\x51\\x4f\\x6f\\xbe\\xd0\\x99\\x29\\x52\\xa7\\x71\\x46\\x15\\x73\\x3d\\x79\\xac\\xce\\xa4\\x2b\\xba\\xb6\\x9e\\x71\\x0b\\x5d\\xa1\\x5d\\x4e\\x8f\\x8f\\xeb\\x71\\x3d\\x74\\x5d\\x55\\x05\\x28\\x47\\xb4\\x80\\xc7\\x26\\xce\\x60\\x23\\x82\\x7f\\xfc\\xe2\\xef\\x8f\\xc2\\xea\\xf7\\x8d\\xd0\\x9d\\xf1\\xef\\x1e\\x21\\xa3\\x15\\x1d\\xf3\\x82\\xdb\\x73\\xfa\\x31\\x9e\\xef\\x7d\\x8d\\xe7\\x52\\x9a\\x77\\x21\\x5a\\xf8\\x18\\x23\\x55\\x8a\\xcf\\x79\\xc1\\xa6\\x6c\\xdd\\xc8\\xed\\x83\\x9e\\x0e\\x68\\x91\\x67\\x7e\\x88\\x63\\x9d\\xd1\\x22\\x25\\xa9\\xec\\x81\\x6f\\x22\\x33\\xf0\\x8b\\x3e\\xca\\x82\\x74\\xdb\\xb9\\x0f\\x78\\xf8\\xfa\\xfb\\x38\\x59\\xdb\\x4c\\x0d\\x5f\\x26\\x04\\x1d\\xd3\\x83\\x8d\\x69\\xa1\\x85\\xee\\x9e\\x94\\xdb\\x9a\\x12\\xba\\xee\\x38\\x62\\x4a\\x5a\\x1d\\x31\\x6a\\xa5\\x98\\x30\\xd6\\x94\\xad\\xa1\\x88\\x93\\x39\\x50\\x40\\xd4\\x12\\x41\\x81\\x03\\x25\\xb2\\x43\\x3f\\xf8\\xc3\\x60\\x1c\\xb8\\x62\\xb9\\x92\\x2e\\xac\\xe2\\x14\\x75\\x2e\\x9e\\xd4\\x50\\xa5\\x09\\xda\\x2a\\x36\\x2a\\x92\\xc2\\x52\\x9e\\xe2\\x8c\\x5a\\x81\\x82\\x2d\\x2b\\x26\\x1a\\x16\\x3e\\x70\\x7e\\x9f\\xa1\\x65\\xed\\x16\\x2e\\x36\\x9a\\x52\\xa3\\x32\\xff\\x4d\\x55\\x50\\x33\\x91\\xaa\\x1c\\x7a\\x3f\\xc2\\xb0\\x65\\x66\\x25\\x90\\xf5\\x16\\x0a\\x48\\xb4\\x77\\xb6\\x62\\xc1\\x34\\x36\\xf5\\x13\\x79\\xc1\\x22\\x13\\x2a\\x2c\\x80\\xc8\\xb1\\x73\\x06\\xa9\\x85\\x62\\x99\\x9c\\x0a\\x40\\xbb\\x74\\xdf\\x82\\x71\\x10\\x82\\x6a\\x54\\x5b\\xf3\\x85\\x88\\xba\\x28\\xd6\\xcf\\x99\\x4c\\x33\\xbc\\xe4\\x9c\\xa9\\x19\\xa3\\x6b\\xee\\xc2\\x6e\\x0c\\xfe\\xd1\\x8d\\x49\\x14\\xab\\x14\\xd3\\x30\\xa1\\x88\\xf1\\x8b\\xee\\x94\\x40\\x14\\xa1\\x5a\\xcb\\x0c\\x20\\xc1\\x30\\x3b\\xd7\\x17\\xea\\x53\\x30\\x8b\\xa0\\x69\\x3a\\x99\\xf2\\x39\\x13\\xbe\\xad\\xf5\\xdb\\x82\\xae\\x5f\\xa0\\x1e\\x85\\x35\\x43\\xef\\xf0\\xda\\xc8\\x90\\xb9\\x4d\\xa8\\x89\\xba\\xc5\\x42\\xc9\\x8f\\xcb\\x48\\x8c\\x47\\x8d\\x6e\\xb1\\x5c\\xaa\\x24\\xe4\\xf1\\x92\\x93\\x75\\x33\\xbb\\x1f\\xf4\\x5c\\x48\\x67\\x16\\x74\\x5c\\xb0\\x7c\\xd0\\x4c\\x17\\x18\\x33\\x51\\xeb\\x61\\x6c\\xb9\\x47\\x32\\x28\\x71\\xf0\\x0e\\xb7\\x84\\xe9\\x79\\x08\\x41\\xae\\x32\\xcd\\x1e\\x03\\xab\\x06\\x75\\x8e\\x98\\xd0\\x77\\xb3\\x59\\xe2\\xc2\\xaa\\x19\\xeb\\xaa\\xdc\\xd6\\xc4\\xb5\\xf6\\x5e\\x8b\\x2e\\xde\\x6a\\xee\\x0f\\x68\\x4e\\xe0\\x06\\x6a\\xdc\\xb6\\x67\\x32\\xb7\\x16\\xfb\\xa0\\x61\\x41\\xbf\\xe0\\xbe\\xc4\\xcd\\x57\\xdf\\xaf\\x49\\x4f\\x24\\x05\\xd1\\xfc\\x57\\x8a\\xe9\\x4a\\x8a\\xdc\\x72\\x6b\\x4c\\xe4\\x20\\x8a\\x87\\x72\\xd3\\xaa\\xe7\\x03\\x13\\xb4\\x91\\x17\\xd8\\x69\\xe7\\x5f\\x4c\\xad\\x9d\\xd3\\xb7\\xc2\\xf5\\x34\\xe5\\x66\\x74\\xf5\\x27\\xf0\\x3b\\x31\\x31\\xa3\\x22\\x43\\xef\\xe3\\xc1\\x15\\xab\\xf4\\x81\\xe6\\x53\\x74\\x33\\xfd\\xe1\\x4f\\x7f\\x02\\x9f\\x93\\x5f\\x9c\\x83\\xf3\\xe3\\xc3\\xa3\\x0f\\xc7\\xa3\\x72\\x3d\\xb5\\x6c\\xa3\\x0e\\xa8\\x8a\\x1a\\xc3\\x94\\x78\\x43\\xfe\\x6b\\xef\\xa7\\xdf\\xfe\\x32\\xdc\\xff\\xeb\\xde\\xde\\x8f\\xaf\\x86\\xff\\xfe\\xf7\\xdf\\xee\\xfd\\x34\\x82\\xff\\xf8\\x62\\xff\\xaf\\xfb\\xbf\\xf8\\x3f\\x7e\\xbb\\xbf\\xbf\\xb7\\xf7\\xe3\\xb7\\x1f\\xbe\\xb9\\x3c\\x3b\\xfe\\x3b\\xdf\\xff\\xe5\\x47\\x51\\x97\\x57\\xf8\\xd7\\x2f\\x7b\\x3f\\xb2\\xe3\\xbf\\x3f\\xf0\\x21\\xfb\\xfb\\x7f\\xfd\\xb7\\x35\\x09\\x4d\\x44\\xc3\\xe9\\x8a\\x80\\xd3\\x09\\xf5\\xa6\\x47\\xa4\\x9b\\x4a\\x31\\x56\\xc2\\x09\\x92\\x52\\xce\\xd3\\xed\\x00\\x3a\\x5b\\x1a\\xdb\\x6b\\x5a\\xee\\x2f\\x7b\\xae\\x78\\xf2\\xc4\\xd4\\x1e\\x35\\x1a\\x8f\\x9f\\x42\\x5e\\x43\\x49\\x25\\x97\\x56\\x71\\x5e\\x77\\x5b\\x7e\\x04\\x65\\x88\\x9c\\xb2\\x39\\x53\\x03\\x4f\\xc3\\x7b\\xfb\\xc8\\xb3\\xc4\\x27\\xc6\\xe1\\xce\\x55\\xcf\\x4b\\xc4\\xac\\x48\\x64\\x10\\x3f\\x2f\\x4f\\xb9\\x92\\x97\\x00\\x11\\xe1\\xde\\x16\\x04\\xf7\\x88\\x7c\\x4f\\x15\\x97\\xb5\\x76\\x1a\\x32\\x74\\x03\\x95\\x02\\x94\\x0c\\x2c\\x41\\x0a\\x87\\x3d\\x04\\x19\\x30\\x19\\x6b\\x5d\\x21\\xe3\\x87\\x0c\\x98\\x5f\\xb9\\xab\\xdf\\x0e\\x53\\x7f\\x18\\x0e\\xc9\\xb7\\xab\\x4f\\x6d\\xbe\\xae\\x89\\x58\\x29\\x36\\xf7\\xaf\\xa1\\x7c\\x11\\x2f\\x33\\x08\\x78\\x1b\\xde\\x0a\\x2d\\x82\\x95\\x47\\xb4\\x57\\x68\\xd6\\x75\\x16\\x44\\x53\\x06\\x83\\xfa\\x77\\x84\\x03\\xed\\x34\\x01\\x19\\x1e\\x10\\xcc\\xf9\\xd4\\x97\\xe2\\xc3\\xba\\xa1\\x83\\x39\\xfa\\x34\\x6d\\x9b\\xa5\\x0b\\xc7\\x54\\x9c\\x8b\\x6a\\x79\\x36\\x9e\\x92\\xff\\xdb\\x0d\\x72\\xe3\\xbe\\xbc\\x1e\\x53\\x29\\x4c\\x23\\xd9\\xc1\\x0d\\x01\\x47\\xfd\\x30\\x53\\xdc\\xf0\\x8c\\x16\\x3b\\x09\\x1d\\x96\\xfd\\x83\\xb2\\xa2\\xb6\\x06\\x57\\xfc\\x2c\\xc5\\x88\\xb9\\x96\\x48\\x13\\x2d\\xc8\\x15\\x5b\\x5c\\x4b\\x95\\x7b\\xed\\xcf\\xd3\\x97\\xb0\\xe3\\x80\\x31\\xb4\\xf1\\xaf\\xc3\\x99\\x13\\xc9\\x18\\x95\\x50\\x25\\x53\\x64\\xcc\\x7c\\x66\\xc9\\xd2\\xcd\\x8b\\x11\\x39\\x14\\x0b\\x54\\xbc\\x12\\xec\\xff\\x10\\x23\\x88\\xfa\\x1c\\x81\\x76\\x8b\\x96\\x48\\x6b\\x37\\x38\\xad\\xc7\\xd3\\x46\\x4d\\x52\\xe7\\x84\\xd5\\x29\\x0f\\xd6\\xe4\\x09\\x82\\xc7\\xeb\\xad\\x3e\\xe7\\x41\\x2a\\x87\\x17\\x05\\x02\\x49\\x21\\xba\\x96\\x5c\\x5f\\x8b\\xb5\\x0f\\x7b\\x92\\xd3\\xc2\\x6a\\xfd\\x5c\\x30\\xad\\xbf\\xb1\\x0c\\xbb\\xb9\\x3d\\x43\\x41\\x01\\x77\\xb4\\x00\\xc2\\x54\\x53\\x97\\xcd\\xac\\x64\\xc2\\x44\\x60\\xab\\x12\\xc8\\xbc\\xb9\\x73\\xdd\\x25\\x3d\\x84\\x9f\\x03\\xe4\\x03\\xcd\\x17\\x88\\xfd\\x66\\x87\\xe6\\xa6\\xdd\\xf6\\x1f\\x82\\x7a\\xf6\\x8e\\xc3\\xd3\\x75\\x03\\x4a\\xae\\xb8\\x1c\\x55\\x68\\xdd\\xee\\x6d\\x8e\\xe6\\x75\\xfb\\x2d\\xc1\\x16\\x73\\x05\\xc1\\xec\\xe7\\x9a\\x16\\x90\\x35\\x75\\xa9\\x6a\\xb6\\xf3\\x14\\x06\\x07\\x33\\xd7\\x52\\x5d\\x1d\\xfc\\xfe\\x4f\\xaf\\xc0\\xe6\\x08\\xd4\\x0d\\xa7\\x6b\\x1f\\x51\\xa9\\x55\\x24\\x49\\xf5\\x23\\x4b\\x8d\\xfd\\xf2\\xf3\\x98\\x91\\xfd\\x5a\\x7a\\x87\\x86\\xcb\\x87\\x03\\x3c\\x50\\xe0\\x80\\xb0\\x40\\x49\\x71\\xf5\\xa4\\x6a\\x91\\xf4\\x3a\\x91\\x61\\x43\\xee\\xe5\\xa2\\x5a\\x5f\\x49\\x4a\\x2f\\xf1\\x68\\x8d\\xdb\\x39\\x99\\xed\\x6d\\xfc\\x34\\x5c\\x15\\x8d\\x4b\\x12\\xc6\\x89\\xc2\\xf4\\xbb\\x3a\\xfa\\x18\\x6a\\x53\\x41\\x9a\\x43\\xfa\\x08\\x9c\\x30\\x8b\\xaa\\x43\\x1d\\x6e\\x82\\xa0\\x44\\xaf\\x18\\xd4\\xb8\\x3d\\xa9\\xa0\\x3c\\x6f\\x8d\\xec\\x8e\\x3f\\x7f\\x96\\x2f\\x7d\\x19\\xf0\\x62\\x5d\\x85\\xf4\\xba\\x3a\\x05\\x62\\xe6\\x40\\x5b\\x97\\xd0\\x23\\xc0\\xb7\\xd9\\xe7\\x1a\\x1b\\x7e\\x61\\x19\\x3d\\x20\\xe6\\xa0\\x96\\xeb\\xa7\\x66\\x5d\\x85\\xb6\\xa9\\x9a\\xcc\\x19\\xa1\\x73\\xca\\x0b\\x48\\x5f\\x05\\xff\\x8f\\xd4\\xad\\xec\\x0d\\x7c\\xd9\\x4c\\x0a\\x5d\\x97\\x40\\xd1\\xba\\xf1\\xaf\\xf1\\xc2\\xa9\\x00\\xeb\\x66\\x33\\x04\\xec\\x44\\x7b\\x50\\x54\\xb3\\xbb\\xd1\\x13\\xd7\\x57\\xa8\\x8e\\x16\\x82\\x96\\x3c\\xf3\\xcb\\x78\\x88\\xeb\\x06\\xb8\\x2b\\x2d\\xb4\\xc5\\x24\\xb2\\x43\\xfe\\x05\\x2f\\xcb\\xda\\xd8\\xc9\\x4d\\xd1\\x29\\x36\\x21\\xd0\\x13\\xa2\\x35\\x70\\x06\\x44\\x9b\\x21\\x4e\\x83\\x66\\x9f\\x68\\x66\\x8a\\x05\\x04\\x42\\xda\\x37\\x99\\x99\\x92\\xf5\\x74\\x46\\x28\\x81\\xbf\\x2f\\xe0\\xab\\xf5\\xc5\\xca\\x89\\x21\\x34\\xcf\\x35\\xa1\\x01\\xc5\\x9b\\x1b\\x54\\x3c\\x6b\\xc1\\x7f\\xae\\x59\\xb1\\x20\\x3c\\x67\\xc2\\x34\\x49\\x4a\\x6d\\x32\\xa2\\xb6\\xef\\x67\\xeb\\x67\\x28\\x45\\x09\\xbf\\x0e\\x60\\x0a\\xfa\\x93\\x3b\\xe8\\x6b\\xe7\\x4f\\xbd\\x65\\x72\\xd0\\xfd\\x09\\x6a\\xb2\\xd5\\x55\\x13\\xd4\\xe4\\x0d\\x9d\\x89\\x09\\x35\\x8f\\x5d\\x8e\\xc2\\xd4\\xea\\xa6\\x3e\\xd2\\xb9\\x21\\x0c\\xb9\\x9a\\x91\\x78\\x93\\xfe\\x4a\\xb2\\x65\\x56\\x4a\\x48\\x76\\xc3\\xab\\xa9\\xbf\\xb2\\x67\\x09\\x39\\x3a\\xbd\\xf8\\xef\\xf7\\x87\\x5f\\x1f\\xbf\\x7f\\x72\\x08\\x12\\x7c\\xb3\\xce\\xf3\\x8e\\xdb\\x3a\\x2a\\x2a\\xbe\\x06\\xe3\\x2c\\xf2\\x3c\\xb5\\xb7\\x47\\xfa\\x7b\\x26\\x17\\x12\\x77\\xad\\xc4\\x6d\\xe9\\x27\\xeb\\xfb\\x3f\\x9a\\xab\\xaf\\x62\\x9a\\xf3\\x65\\x82\\x96\\x03\\xe9\\x74\\x49\\x24\\x39\\x9b\\xdd\\x69\\x80\\xba\\x4b\\x93\\x49\\xe1\\x53\\xb5\\xb0\\x31\\x21\\x66\\x93\\x77\\x43\\x0c\\xee\\x50\\xe5\\xd4\\x5a\\x9a\\x4b\\x56\\x56\\x05\\x35\\x09\\x59\\xff\\xcd\\xf5\\x28\\x4b\\x14\\x13\\x76\\xcf\\x52\\xf9\\x5b\\x93\\x07\\xbe\\xb9\\xd4\\xb7\\x2d\\x59\\x7a\\x13\\x6d\\x00\\x8e\\x73\\x84\\xb6\\x6a\\x51\\xa0\\x0c\\x18\\xc3\\xa2\\x94\\x08\\x76\\xdd\\x7e\\x37\\x57\\xa9\\x02\\xbf\\x48\\x1e\\x7b\\xcc\\xc8\\x58\\xd6\\x22\\xc7\\xb3\\xd7\\xbd\\x0b\\x7a\\xa6\\x43\\x6d\\x03\\x74\\xec\\x2e\\x98\\xf1\\x7e\\xa5\\x16\\x15\\xc9\\x23\\x3b\\xb4\\x5a\\x2d\\xd1\\x2b\\x05\\xcf\\x47\\x2d\\x1d\\x7a\\x01\\xd8\\x99\\x76\\x3a\\x3e\\x8a\\x44\\xfb\\xc9\\x80\\xd0\\x42\\x8a\\xa9\\x43\\xde\\x4a\\x1e\\x7a\\xca\\x04\\x53\\xe0\\xa6\\x09\\xbe\\xfe\\xc1\\x8d\\x89\\x87\\xb6\\x52\\xd4\\x1d\\x66\\x48\\x8f\\x4b\\xfd\\xef\\x87\\x8b\\xe3\\xe5\\xb3\\xe3\\x2a\\x96\\x49\\x95\\xa3\\xf7\\xc5\\x2e\\x02\\x3a\\x5a\\x46\\xad\\x2d\\x79\\x01\\x9f\\x31\\xdd\\x8d\\xdb\\x56\\xea\\xdb\\x30\\xd9\\x42\\x02\\x7a\\xed\\x34\\x72\\x69\\x81\\xc9\\x83\\x8a\\x59\\xf2\\x90\\x4b\\xd1\\xed\\x96\\x2c\\x8d\\xa0\\x9a\\x94\\x2c\\x48\\x55\\x50\\xc1\\x1c\\x74\\x6e\\xf0\\x99\\xf6\\x36\\xe7\\x4f\\x2e\\x58\\x5b\\xf1\\xcf\\x82\\x6b\\x03\\x95\\x0a\\x57\\x6c\\xb1\\xf6\\xd9\\x99\\xa0\\x46\\xde\\x1c\\x1c\\xdf\\xa3\\xa4\\xeb\\x64\\xec\\x39\\xc8\\xd9\\xa7\\x0f\\xba\\x9e\\xe3\\xc0\\xa4\\x6a\\x82\\xac\\x37\\xe0\\x30\\x43\\xd5\\x6b\\xc2\\xa9\\xe9\\xc2\\xab\\x87\\x00\\x98\\x3d\\x20\\x1f\\xc5\\x3b\\x04\\x32\\x1c\\x60\\xc4\\x75\\x44\\x4e\\x04\\xd1\\xb2\\x74\\xa0\\x8b\\x9f\\x8c\\x1e\\x10\\xa8\\x59\\xa7\\x44\\xd7\\x63\\xcd\\x0c\\xc6\\xf2\\xac\\xf9\\xef\\x72\\xb3\\x5c\\x82\\x5b\\xc5\\x54\\xc9\\x4d\\x42\\x75\\x5e\\xd4\\x80\\x0e\\x89\\x7a\\xe4\\x12\\xa2\\xbb\\x00\\xe5\\x0f\\x7e\\xe3\\xd6\\x7d\\x58\\xad\\x9f\\xe1\\x9e\\xea\\xb8\\x8a\\xd2\\x5e\\x9e\\x3a\\x2e\\x76\\xbe\\x34\\x76\\xcb\\xe9\\xd7\\x4a\\x1a\\x6a\\x6b\\x04\\x50\\xe9\\x85\\x7e\\x6b\\x32\\x55\\xb2\\xae\\xbc\\x58\\x6f\\xaa\\xab\\xed\\x81\\xb2\\xae\\xa1\\x2a\\xed\\x64\\x44\\x07\\x32\\x46\\x78\\xda\\x84\\x84\\x93\\x11\\x1c\\x8d\\xac\\xd1\\x83\\x72\\x6b\\x5f\\x69\\xdd\\x04\\x81\\x10\\xb3\\x19\\xd3\\xbc\\x54\\x2d\\x12\\xa2\\x4b\\x98\\x6a\\x24\\x15\\x42\\x62\\xe2\\x93\\x77\\x0a\\x36\\xa5\\xd9\\x62\\xa7\\x4d\\xd5\\x8a\\x5a\\x5a\\xe7\\x94\\xe2\\x65\\x55\\xf0\\x8c\\x1b\\xa4\\xce\\xa3\\x67\\xae\\x49\\x0b\\x42\\x72\\x82\\x67\\x11\\xfd\\xad\\xe8\\xba\\xd0\\xee\\xf5\\x7d\\x74\\xcb\\x43\\xb4\\x63\\x96\\xe5\\xda\\x80\\x4b\\xc9\\x09\\x51\\xbf\\xff\\xd3\\xef\\x87\\x3e\\xcf\\x14\\x5e\\xf3\\x29\\xf6\\x4d\\xa8\\x4f\\xdd\\x6c\\x30\\xb9\\xc5\\x6d\\x56\\xa7\\xe3\\xba\\x02\\xce\\x84\\x00\\x68\\x13\\x5d\\x0a\\xe4\\xf6\\x17\\xe5\\x5c\\x3d\\xa4\\x67\\x86\\xc4\\x01\\xbb\\xad\\x06\\x17\\xd3\\x27\\x0f\\x54\\x5e\\xb4\\x87\\x76\\xfb\\x4e\\x56\\xd4\\x6a\\xb0\\x1e\\x34\\xd3\\x1d\\x56\\x58\\x97\\x1c\\x2d\\xa0\\x9b\\x44\\x40\\x91\\x6c\\xde\\x21\\xf5\\x70\\xb5\\xac\\x71\\x93\\x1a\\xbb\\x7c\\x91\\x04\\x09\\x4b\\xa7\\x0d\\x5d\\x78\\x89\\xda\\x7e\\x09\\x68\\xb0\\x69\\x98\\xc7\\x40\\x5a\\x37\\xeb\\x33\\x54\\x6e\\x07\\x11\\x48\\x8d\\x35\\xb5\\x96\\xab\\xc8\\x59\\x9a\\x0d\\xb7\\x3c\\xe1\\x99\\x9d\\x6e\\xab\\x23\\xb8\\x04\\x51\\x6a\\x30\\x86\\x07\\x8a\\xac\\x4b\\x05\\xc6\\x2e\\x04\\xa0\\xf0\\x97\\x72\\x0e\\x45\\xc3\\x56\\xa9\\xb0\\x1a\\xef\\x35\\x55\\x79\\x82\\x6e\\xbf\\xdc\\x34\\xc9\\xb9\\xe3\\x5d\\xe2\\x90\\xd7\\xb0\\xcf\\x64\\xde\\x90\\x1b\\x62\\x90\\x1d\\x5a\\x25\\x6d\\x34\\x88\\xda\\x9e\\x79\\x78\\xfb\\x26\\xf5\\x1b\\x0e\\xed\\x33\\xac\\xcf\\x9e\\xd6\\x54\\xe5\\x10\\x35\\x6f\\xf8\\xf1\\xc5\\x6f\\xbc\\xea\\xda\\xb8\\xdf\\xd8\\xe5\\xc6\\x45\\xc2\\x27\\xbd\\x7f\\xd7\\x31\\xb5\\x3a\\x58\\xfb\\x49\\xe8\\x27\\x86\\x2c\\x86\\x25\\xbb\\x1e\\xf2\\xe0\\x9e\\xd2\\x63\\xfc\\x19\\xd8\\x85\\x4b\\xe5\\x60\\x4f\\x7a\\xce\\xb5\\x87\\x26\\x33\\x59\\xe4\\xa0\\x28\\x0f\\x0b\\x36\\x67\\x45\\x20\\xcd\\x0a\\x7b\\xc5\\xc7\\xb5\\x71\\x65\\x35\\x99\\x2c\\xcb\\x76\\xf7\\x19\\xcc\\x86\\x5c\\xdb\\xd0\\x6a\\xda\\x74\\xc4\\x19\\xb5\\x70\\xb2\\x8d\\x2c\\x79\\x0c\\x38\\x23\\x7e\\x4b\\x30\\x5f\\xbd\\x42\\xe2\\x8e\\x60\\x39\\x21\\xcc\\xb2\\x69\\x02\\xfb\\x25\\x4b\\xa4\\x74\\x01\\xe1\\xca\\x9e\\x37\\x51\\xdc\\x76\\x18\\xf2\\x03\\xe3\\x5a\\x5f\\xb4\\xb7\\x50\\x91\\xa1\\x55\\x55\\x70\\x44\\xb0\\x5d\\xf2\\x11\\x00\\xf2\\x6a\\xa2\\x4f\\x1d\\xf0\\x14\\x1c\\x5a\\x96\\x9d\\x71\\x97\\x56\\x00\\x52\\xea\\xdb\\x7a\\xcc\\x0a\\xac\\x01\\x41\\x97\\x19\\x56\\xa9\\x5c\\xdb\\x41\\x67\\xbc\\x42\\x61\\x46\\x8d\\xfb\\x79\\x8a\\x6c\\x01\\xc7\\xa8\\x7d\\x60\\xdc\\x50\\xf2\\x4d\\x92\\xe7\\xef\\x35\\x3a\\x56\\xe5\\x35\\x14\\x43\\x7d\\x73\\x72\\x14\\x34\\x66\\xfb\\xd8\\x77\\x17\\x29\\xd5\\xd8\\xf6\\xfa\\x12\\x9f\\xab\\x99\\x99\\xf2\\x9c\\x8c\\x11\\x6b\\xc7\\x2a\\x3e\\x7b\\x82\\x5d\\x23\\x60\\xb0\\x73\\x60\\x87\\xa4\\xb2\\xb9\\x07\\xc5\\xc5\\xf1\\xc3\\xfb\\x39\\x22\\xf6\\x13\\xa8\\xf8\\xca\\xb9\\x8d\\x99\\xf2\\x39\\xcc\\x63\\xee\\xa0\\x39\\x3f\\x9e\\xef\\xfa\\x4a\\xb0\\xeb\\xa1\\xba\\x1e\\x0e\\x87\\xc3\\xa4\\x09\\xf4\\x26\\xf0\\xa0\\xb5\\xf6\\x41\\xa9\\x2c\\x65\\xce\\x27\\x8b\\x25\\x0e\\xb0\\x12\\xa7\\xa1\\x09\\xb6\\x3b\\x15\\x0b\\x37\\x01\\x29\\xec\\x78\\x2a\\x21\\x13\\x96\\x9a\\x38\\xc1\\x3a\\x0b\\x98\\x50\\x76\\xde\\x21\\x4d\\x10\\x6a\\x77\\xa5\\x1e\\x09\\x17\\x1f\\x49\\x2e\\xe2\\xec\\x56\\x38\\xd2\\xa5\\xf7\\xe4\\x0a\\x8c\\x85\\x4d\\x08\\x9e\\x15\\x64\\x84\\xac\\xa6\\x31\\x9b\\xd1\\x39\\x97\\xd0\\x8c\\x12\\x24\\x00\\xe0\\x3e\\xdf\\xb2\\xfa\\x5e\\xb7\\x49\\x96\\x06\\x2e\\xc3\\x09\\x53\\x96\\xd9\\xa7\\x0a\\x9a\\x84\\xb9\\x00\\xfa\\x99\\x84\\xc0\\x49\\xbb\\x26\\x11\\xad\\x8a\\xaa\\x02\\x24\\xbe\\x84\\x01\\x5b\\x62\\xcf\\xb9\\xb4\\xb0\\x56\\xd8\\xcf\\x0a\\x19\\x53\\x4b\\x44\\x78\\xe5\\xbd\\x25\\x86\\x4f\\x82\\xcf\\x3b\\x71\\xbb\\x0a\\xb4\\x34\\x21\\x09\\x9b\\x4c\\x58\\x06\\xb8\\x4e\\xac\\x9a\\xb1\\x92\\x29\\x5a\\xb4\\x49\\x73\\x9d\\xa0\\xde\\xd8\\x43\\x5f\\xd9\\x0d\\x8a\\x15\\x7d\\x25\\x5d\\x1b\\x06\\x82\\xb8\\xac\\x32\\x38\\xc6\\x73\\x9e\\x84\\xd2\\xfd\\x3d\\x2d\\x78\\xab\\x94\\x7a\\xe7\\xa3\\x38\\x97\\xd2\\x7c\\xe0\\x1a\\xbc\\x74\\x90\\x3d\\x4f\\x76\\xd0\\xbd\\xbb\\x33\\x5a\\xe1\\xd2\\xf0\\xdf\\x75\\x81\\xdf\\xdd\\x90\\xa0\\x48\\x0a\\x3c\\x37\\x28\\x02\\x9b\\xd8\\xe0\\xf6\\xdc\\xb0\\xc7\\x61\\x70\\xb8\\x5a\\xb3\\xd9\\xa8\\x45\\x25\\xb9\\x30\\x37\\xbb\\x29\\x74\\x68\\x68\\xfd\\x9d\\xeb\\x1b\\x0e\\x6e\\x49\\xaf\\x08\\x76\\x69\\x11\\xfc\\x81\\x2e\\x42\\xf8\\xd4\\xd5\\xee\\x2e\\xe9\\xc5\\xe8\\x36\\x76\\xdf\\x41\\xdb\\xa6\\x65\\xc5\\x79\\xfd\\x52\\x0e\\x82\\xf9\\x6b\\x4b\\x0f\\x1a\\x44\\x5d\\xb0\\x5b\\x69\\xe4\\xcb\\x03\\x1a\\x7a\\xc5\\x34\\xa9\\x14\\xcb\\x58\\xce\\xc4\\xda\\x00\\x35\\x04\\x8f\\x15\\xe4\\xed\\x4e\\x70\\xfa\\xbf\\xa2\\xb3\\x14\\x76\\xd8\\xa9\\x04\\x39\\xb4\\x89\\x3d\\x76\\x12\\x15\\x19\\xb9\\x66\\x24\\xcd\\x8e\\x02\\x93\\xdc\\x6e\\x3d\\x0a\\x29\\x89\\x52\\x0c\\x95\\x94\\xe0\\xd0\\x4f\\x5a\\xd6\\x13\\x8f\\x27\\x7d\\x43\\x4d\\x9b\\x5b\\xc9\\xec\\xfb\\x9b\\x01\\x06\\x27\\xa1\\x4d\\x9c\\xc0\\x5a\\x6f\\x42\\xd7\\x8a\\x79\\xbc\\xc6\\x14\\x3f\\x88\\x64\\xe8\\xe1\\x74\\xaf\\xf3\\xdd\\xc9\\x11\\x79\\x45\\xf6\\x00\\x49\\x36\\x34\\x4a\\x0b\\x09\\xc9\\xcb\\xa8\\xa0\\x80\\x54\\x69\\x1f\\x91\\xf8\\xda\\x21\\x42\\xe3\\x7a\\x7a\\x0a\\x89\\x47\\xa3\\x7b\\x6f\\xab\\x83\\x78\\x9d\\xbb\\x62\\x0a\\x2a\\xa0\\x92\\xce\\x96\\xcf\\x42\\xec\\xa4\\x6e\\xdf\\x34\\xb4\\xef\\x80\\xc2\\xb3\\xa9\\x13\\xee\\xbb\\x27\\x39\\xe1\\x62\\x57\\x88\\xdd\\xbf\\xed\\x25\\xc1\\x2d\\x57\\x32\\x43\\xa1\\xc5\\x2e\\x9e\\x7c\\xfe\\x86\\x5f\\x2d\\x23\\xbe\\x9c\\x7f\\x0f\\xbb\\xba\\x9c\\x7f\\x6d\\xe4\\xb6\\x4d\\xed\\xc1\\x8b\\x63\\xa0\\xc2\\x27\\x93\\x38\\xf7\\x0e\\xfa\\xad\\xf2\\x9b\\x7e\\xab\\xf4\\x53\\xe0\\x1e\\xd8\\x6b\\x9f\\x77\\x17\\xfa\\x12\\x2a\\x2a\\x72\\x59\\xde\\xa0\\xcf\\xb2\\x19\\x4b\\xeb\\x0c\\xde\\x30\\xe6\\xba\\xbb\\x34\\xc5\\x30\\xbe\\x65\\x5f\\x77\\xd8\\xa5\\x29\\xce\\xba\\xa5\\x7d\\xfd\\xbc\\x77\\x69\\x62\\x6a\\x78\\xb7\\xc4\\x70\\x70\\xdd\\xf7\\xd0\\x9b\\xeb\\x3d\\x84\\x00\\xb8\\x0e\\x1c\\x8d\\x31\\x01\\x40\\x6f\\xbe\\xe1\\x2c\\xee\\xdc\\x25\\xb2\\x73\\xd2\\xb5\\x92\\x45\\x62\\x76\\x75\\xeb\\xad\\xcf\\x65\\xe1\\x60\\xd2\\xfd\\x6b\\xdb\\x07\\x6f\\xed\\x5b\\x9b\\xc4\\x2a\\xcd\\xe5\\xee\\x3b\\x8b\\x6a\\xe9\\xad\\x21\\xee\\xb2\\xad\\x6f\\x5d\\x27\\xe9\\x80\\x64\\xf9\\xad\\xad\\x2a\\xd9\\x7e\\x6b\\x50\\xb7\\xb6\\xf1\\xad\\xdb\\x98\\xa6\\x9b\\x3a\\x7b\\x1d\\x15\\x44\\xa2\\x0a\\xe0\\x14\\xd4\\x1b\\x5d\\x62\\x1b\\x74\\xbd\\xc4\\x78\\xd1\\xf3\\x12\\xd7\\x5d\\xda\\x01\\x22\\x28\\xd4\\x53\\x9f\\x10\\x32\\xa3\\x05\\x60\\x67\\xa7\\xb2\\x13\\xe9\\xad\\x24\\x65\\x99\\x96\\x08\\x4a\\x85\\xda\\xd7\\x84\\xcf\\x22\\x90\\x37\\x8a\\x4d\\xc5\\x65\\x93\\x35\\xba\\x94\\x21\\x9a\\x9a\\x9a\\x8e\\x80\\x46\\x38\\x9e\\xaf\\x83\\xb3\\x7a\\x48\\x83\\x6b\\x17\\x8f\\x69\\x24\\x74\\x59\\x49\\x1d\\xec\\x43\\x28\\xb4\\xb3\\xb3\\xc8\\x30\\x9f\\xbf\\xa2\\x66\\x36\\x20\\x8a\\x15\\xd4\\xf0\\xb9\\xaf\\x15\\x20\\x57\\xe8\\x7c\\xd9\\x6d\\x41\\xec\\xf9\\x8d\\xe8\\x09\\xf6\\x25\\xc4\\x5d\\xe9\\x01\\xed\\x71\\x82\\xc2\\x9f\\x6b\\xb2\\xf3\\xde\\xaf\\xce\\xce\\x08\\xef\\x39\\xfd\\x78\\xe9\\xef\\x83\\x3c\\x72\\x8f\\xee\\x92\\x5c\\x9b\\xbf\\x2d\\x27\\x60\\x32\\x03\\xe3\\x5c\\x05\\xa6\\xc5\\x08\\xcf\\x15\\x17\\x39\\x91\\x93\\x1b\\xeb\\x14\\x50\\x2e\\xd1\\x5c\\x49\\x5d\\x2e\\x8c\\x8e\\x78\\x29\\x4c\\x15\\x4b\\x8b\\x66\\xdb\\x2b\\xac\\x30\\x19\\x3e\\xf1\\x86\\x73\\xd9\\xce\\x3e\\x59\\x7f\\x78\\x8b\\x99\\xe5\\x5d\\xfc\\x9e\\xb4\\x7e\\x06\\xff\\x4e\\xc0\\x6e\\xb2\\xef\\x38\\x24\\x42\\xae\\x78\\x7a\\xa7\\x25\\xea\\x72\\xd2\\xdf\\x40\\x61\\xdf\\x4c\\xa6\\x88\\x4f\\x73\\x85\\xe4\\x10\\x1d\\x1b\\xd8\\x80\\xfc\\xc4\\x15\\xc0\\x3c\\x81\\x93\\x0b\\x1c\\x62\\x5c\\x60\\x12\\x4e\\x58\\xc1\\x01\\x70\\x4f\\x9e\\x04\\xba\\x42\\x30\\x6f\\x63\\xb9\\x59\\x59\\xa5\\x78\\x49\\xd5\\x82\\x7c\\x73\\x72\\xe4\\xda\\x62\\xb8\\x08\\xea\\x5e\\x9c\\x80\\xbb\\x8f\\x99\\xa1\\x98\\xd5\\x52\\xb2\\x72\\x8c\\x61\\xd5\\x94\\x30\\xe6\\x0d\\x74\\xd1\\x56\\xf3\\xa9\\xd0\\xc2\\xa6\\xe6\\xf9\\xed\\x1e\\xc0\\x65\\x77\\x42\\x02\\x19\\x42\\xc6\\xf8\\xc6\\x7e\\x45\\x14\\xa0\\x1e\\x3b\\xa7\\x87\\x58\\xc4\\xee\\x82\\x46\\x81\\xda\\x92\\x59\\x00\\x6a\\xb5\\xb1\\xe2\\x0f\\x23\\xd1\\x7c\\xce\\x52\\x66\\x82\\xcd\\x99\\x70\\x50\\x5b\\x0b\\x78\\xa6\\x55\\x09\\xb9\\xc8\\x8a\\x3a\\xf7\\x04\\x72\\x0d\\xbc\\xfb\\x8c\\xf4\\xce\\xb4\\x2e\\xdc\\xc9\\x3d\\xb8\\xbb\\x79\\x10\\x3b\\xfa\\x10\\xb1\\x35\\xc7\\x26\\x44\\xda\\x05\\x0e\\x0d\\x49\\x8e\\x84\\x06\\xf9\\x16\\xaa\\x90\\x73\\x4f\\x1c\\x56\\xae\\x46\\xed\\xa9\\x46\\xe4\\x2c\\x20\\x91\\xd6\\x22\\x20\\xbd\\x27\\xd0\\xe0\\x47\\xd8\\x5b\\x36\\x99\\xfc\\x71\\xb7\\xef\\x7a\\xdf\\xf9\\x10\\x57\\x41\\x6b\\x91\\xcd\\x5e\\x78\\xf9\\xb6\\xab\\x8d\\xf9\\x00\\xb3\\x1b\\x12\\x8b\\x28\\xb9\\x62\\x4a\\xb0\\x82\\x54\\x54\\xd1\\x92\\x19\\xab\\xa5\\x7a\\xff\\x69\\xf2\\xb6\\x49\\x46\\x7b\\xe8\\xd6\\x34\\xbe\\x43\\xc3\\xf7\\x61\\x12\\xae\\x36\\xe9\\x01\\xa0\\xa2\\x4b\\x7b\\xe8\\xd6\\xc2\\x36\\x8d\\xa0\\x1d\\x49\\xd0\\x15\\x35\\x6d\\x19\\x49\\x1f\\xf8\\x0e\\x30\\xa3\\xbd\\xbc\\xda\\xf7\\xe0\\x45\\xdf\\x8e\\x77\\x6b\\x77\\x01\\xdb\\x94\\x93\\xe9\\x07\\xa4\\xa2\\x69\\x41\\xe9\\x93\\xcb\\x1f\\x3f\\xc8\\xe3\\x2d\\x2a\\x57\\x0f\\x4d\\x5b\\xca\\xe7\\x72\\x6c\\x24\\x2e\\xd0\\x4c\\x24\\xe0\\x9e\\x90\\xea\\x66\\x23\\xf5\\xe9\\x47\\x08\\xb4\\x3d\\x79\\x56\\x31\\x93\\x69\\xa9\\xe9\\x5b\\xc5\\x00\\x66\\x89\\x16\\x17\\x15\\xcb\\x36\\xe9\\x52\\xf8\\xe6\\xc3\\xc5\\x61\\x9b\\x1a\\x38\\x98\\x11\\xc0\\x68\\xc6\\xe0\\xfb\\x08\\x68\\xfa\\x9a\\x8d\\x67\\x52\\x5e\\x25\\x0e\\xb6\\xb7\\xa2\\xe1\\x4b\\x54\\xd6\\xa2\\xf9\\x54\\x1f\\x38\\xc1\\x30\\xb4\\xd3\\xb4\\x4f\\xb8\\x28\\xe0\\x7c\\xf5\\x0a\\x0c\\x40\\x63\\xa3\\xe2\\xdf\\xe1\\x85\\x49\\x16\\xde\\x18\\x18\\xca\\x55\\x60\\x3b\\x45\\xe9\\xe6\\x94\\x9c\\x76\\x2a\\x38\\xea\\x7c\\x06\\xdc\\xe4\\x98\\x74\\x78\\x9f\\x16\\xd7\\xdc\\xf2\\xa6\\x2b\\x5a\\x12\\xad\\x9c\\x35\\x74\\xc9\\x6f\\x64\\x4a\\x9c\\x17\\xd7\\x9a\\x7b\\x9b\\xdc\\x3d\\x7f\\x6b\\xc8\\x20\\xb9\\xd5\\xfa\\x4a\\xe0\\x56\\x3e\\x89\\xe5\\x79\\xe4\\xe8\\x09\\x49\\x73\\xbb\\xf6\\x97\\xc4\\xfd\\x74\\xb7\\x6b\\xb0\\x87\\x90\\xc3\\xa2\\xc0\\x83\\xfd\\xcc\\x43\\x9b\\xfa\\xf0\\x48\\x53\\x3f\\x17\\xc0\\x90\\x82\\x55\\xdc\\xa2\\x3f\\x55\\x73\\xb3\\xd7\\x9e\\xef\\xd8\\x6c\\x62\\x10\\x4f\\x57\\xb5\\x57\\xf2\\x4f\\x96\\xb6\\x78\\xac\\x18\\x0c\\x19\\x20\\x6c\\xc4\\x70\\xf5\\xd7\\xc9\\xed\\xdc\\x4f\\x1a\\x7f\\xd0\\xc0\\xae\\x47\\xfc\\x78\\xcb\\xdf\\xaa\\x86\\x09\\x11\\xf0\\xc5\\x29\\xc2\\x14\\xe3\\x5c\\xc5\\x99\\x0f\\x46\\xc2\\x9d\\x5d\\x58\\x3c\\x2d\\xfd\\x8c\\xc4\\x29\\x68\\x3d\\xed\\xf6\\x64\\x2e\\x87\\x74\\x34\\x47\\x87\\x3d\\xff\\xbd\\xd6\\xf4\\xf8\\xe9\\x69\\x64\\x29\\x45\\x0d\\x5c\\x3f\\x8f\\x9f\\xa6\\x46\\x56\\xa7\\xaa\\xdd\\x54\\x91\\x46\\x8f\\x93\\xac\\x46\\x36\\x9d\\x39\\x49\\x3a\\x40\\x29\\x30\\x35\\xe7\\x19\\x3b\\xcc\\x32\\x59\\x8b\\x27\\xad\\x30\\x3d\\x62\\xf6\\x95\\xa9\\x61\\xf9\\x45\\x8b\\x06\\x0c\\xbb\\xe7\\xf0\\x2d\\xd6\\x9a\\xd3\\x82\\x53\\x6c\\x0a\\xde\\xbe\\x33\\xa5\\xcd\\x45\\x33\\x2a\\x04\\xf9\\x97\\xde\\xdf\\x6d\\x19\\x6d\\x18\\x4d\\xaa\\x16\\xed\\x38\\xfd\\x4f\\x0d\\x2e\\x72\\x73\\x3a\\x57\\x29\\x13\\x4b\\xcb\\xe3\\x22\\xfb\\xcb\\xf8\\x39\\x6b\\x0e\\xfd\\x30\\x1c\\x25\\x43\\xf5\\x55\\xd3\\x87\\x9d\\x01\\x28\\x7d\\x90\\x54\\xd1\\xe7\\x6e\\x1a\\x87\\x14\\x69\\x4c\\xe9\\xcd\\x9e\\xb0\\x74\\xc6\\x1e\\x46\\x76\\xa6\\x0e\\xf5\\xbb\\xff\\x38\\x3a\\x7d\\x62\\x58\\x18\\x7f\\x26\\x3a\\x78\\xf4\\x99\\xa3\\x25\\x18\\x9f\\x71\\xdb\\xb5\\xb8\\xf9\\x88\\x25\\x75\\x40\\x14\\xc5\\xd8\\xec\\x8c\\xe2\\x89\\x50\\x30\\x8a\\x0e\\x4f\\xb2\\x17\\x81\\xfc\\xac\\x7d\\x9e\\x9f\\x08\\xd2\\xe4\\x38\\xa2\\x4e\\x30\\x40\\x1e\\x29\\x19\\x15\\x3a\\xea\\x8d\\xc3\\x80\\x10\\x1f\\x38\\x08\\xd4\\xa3\\x25\\xe9\\x38\\xcf\\x39\\xe9\\xf6\\x7c\\x78\\xb1\\x7d\\x87\\x36\\xaa\\xce\\x0c\\xa9\\x8d\\xb6\\x9f\\xa7\\x90\\xea\\x4f\\xc6\\x07\\x10\\xab\\xd8\\x94\\x6b\\xa3\\x5c\\x43\\x23\\x3b\\x7c\\x43\\xb2\\x73\\x07\\x87\\x5b\\xae\\xd8\\x82\\xfc\\xed\\xdb\\xe3\\xff\\xfc\\xef\\xf7\\x1f\\xdf\\x1e\\xbe\\xff\\xef\\x0f\\x87\\x6f\\xff\\x76\\x72\\x7a\\xfc\\xd3\\x4f\\x17\\xff\\x79\\x71\\x79\\xfc\\xe1\\xa7\\x9f\\xde\\x62\\x6b\\x50\\xd7\\x83\\xe8\\x82\\x99\\x9f\\x7e\\x72\\x7b\\x4c\\xff\\xf4\\xd3\\x65\\x56\\xf1\\xea\\xa7\\x9f\\xce\\xbc\\x63\\x12\\x0e\\x52\\x3b\\x55\\x09\\xf0\\x30\\xd8\\xde\\x20\\x14\\x4d\\x80\\x82\\x87\\xcb\\x0f\\x6f\\x39\\xa3\\xba\\xa9\\xff\\xeb\\x80\\xa4\\x06\\xe5\\x10\\x29\\xe2\\x72\\x7d\\x65\\x6b\\x65\\x0b\\xee\\x27\\x15\\x99\\x33\\x08\\xae\\x11\\xcd\\xc5\\xb4\\x60\\x21\\x86\\xd5\\x00\\x96\\x8e\\x99\\xb9\\x66\\xae\\x91\\xc8\\xb2\\x6e\\x95\\x5e\\x2a\\xdf\\xa0\\x85\\xba\\xea\\xef\\x16\\x44\\x9f\\xcb\\x1c\\x70\\x78\\xf9\\x73\\xce\\xae\\xb1\\xd3\\x22\\x9f\\x0a\\x5a\\x78\\x1a\\x99\\x6b\\x4f\\x85\\x49\\x19\\xcd\\xef\\xd7\\xa4\\x24\\x86\\x69\\xad\\x64\\x3e\\xf0\\xb0\\x41\\x4b\\x71\\xdf\\x1b\\x31\\xdf\\x16\\x42\\x1a\\xd5\\x96\\x36\\x96\\x93\\xb3\\x93\\x23\\xf2\\x7a\\xdd\\xc9\\xf8\\x1b\\xf6\\xf6\\x87\\x91\\x2f\\x56\\x31\\x44\\xf0\\x44\\x59\\x1d\\x0f\\x15\\xc2\\xce\\xf0\\x13\\x4f\\xcd\\xe8\\xf5\\x38\\x97\\x25\\xe5\\x62\\xb3\\x60\\x63\\x93\\xba\\x28\\x16\\xe4\\xe7\\x9a\\x16\\xa8\\xbe\\x9e\\xc9\\xfc\\xe6\\x49\\xb3\\xf3\\x67\\xff\\xd1\\x5f\\x46\\x7f\\x0e\\x84\\xff\\x65\\xf4\\x67\\x8f\\x32\\x0b\\x8b\\xf2\\x97\\x91\\x9e\\x67\\xa3\\x3f\\xbb\\x06\\x55\\xc4\\xdd\\xb4\\xd3\\x33\\x42\\x59\\x90\\x73\\xd4\\x8d\\x80\\x28\\xb7\\x60\\xe8\\x3e\\x89\\x46\\x87\\x5e\\x05\\x48\\xb9\\xfa\\x46\\xd1\\x8c\\x9d\\x31\\xc5\\xc1\\x36\\x90\\x22\\x7f\\x52\\xa4\\x32\\xcf\\xc1\\x24\\x77\\xad\\x95\\xed\\x9e\\xd4\\x48\\x47\\x98\\x33\\xc1\\x58\\x8e\\xa6\\x9a\\x23\\x9b\\x91\\xa9\\xa5\\x1a\\xd6\\x7d\\x04\\x56\\x15\\x40\\x07\\x67\\x8a\\x51\\x2c\\x87\\x77\\x38\\xc2\\xbe\\x89\\xec\\xba\\xcb\\x87\\x41\\x0d\\x9f\\x45\\x27\\xa4\\x18\\x0a\\x36\\xc5\\xac\\x36\\x17\\x76\\x46\\xa4\\x09\\x3c\\x66\\xb1\\x7d\\x56\\xc8\\xa0\\xd2\\x46\\x56\\x84\\x97\\x25\\xcb\\xad\\x61\\x50\\x2c\\xc8\\x9c\\xaf\\x8b\\x50\\x0c\\x6a\\x05\\xe0\\xa1\\xa1\\x70\\xdc\\x13\\x92\\x48\\x88\\xda\\xd6\\x82\\xbb\\x00\\xcb\\xac\\x36\\x24\\x97\\xd7\\x62\\x7d\\x95\\x62\\x82\\x32\\x1a\\x89\\xe7\\x9a\\x08\\x5e\\x0c\\x5a\\xa0\\x89\\x30\\xb9\\xa4\\x02\\x9e\\x68\\xc3\\x21\\x27\\x59\\x1d\\x68\\xec\\xb7\\x1e\\xea\\x14\\xf8\\x55\\x8b\\x8e\\x90\\xbf\\xd8\\xc7\\xcf\\x1f\\x09\\xbe\\x7b\\x73\\x83\\xf1\\x8a\\xf9\\x18\\x6c\\xed\\x6e\\xf9\\x34\\x66\\x7d\\x3f\\xbd\\xfe\\x70\\xc0\\xb2\\x18\\x3c\\xc4\\xe2\\xe1\\xed\\x58\\x13\\xa9\\x32\\x3e\\x2e\\x16\\x64\\x46\\x8b\\xd0\\x55\\x9a\\xc6\\xab\\xb4\\xee\\xa4\\x5c\\x30\\x13\\x2f\\x44\\x21\\xc5\\x34\\xd6\\x75\\xb1\\x43\\x38\\x60\\x78\\x32\\x2a\\xea\\x0a\\xa9\\xb3\\x6a\\xdc\\x42\\xd6\\xc9\\x0e\\x90\\xd8\\xf1\\xf1\\xd5\\x2b\\x3f\\xe9\\x1b\\xe8\\x94\\xb8\\x56\\xe6\\x85\\x91\\x05\\x43\\x4e\\xe9\\x22\\x9c\\x56\\xa2\\x54\\xee\\xea\\xf8\\xe9\\xcf\\x05\\xf8\\x2e\\xc1\\xed\\xe6\\x01\\xd5\\x81\\xe5\\x2e\\xc3\\x2b\\x83\\x23\\xc3\\x18\\x0a\\x58\\x99\\x56\\xc4\\xe2\\x37\\x00\\x94\\xb5\\x20\\x56\\x2b\\x72\\x5d\\x61\\x1c\\xb8\\xec\\xfa\\x51\\x31\\xbb\\xb1\\x14\\xaf\\x0a\\x46\\xfe\\x7c\\xc5\\x16\\x03\\xec\\xd9\\x89\\xea\\xfc\\x5f\\x48\\xad\\xbd\\xed\\x12\\xba\\x64\\xc9\\xca\\x12\\x20\\x15\\xf9\\xb3\\xff\\xaf\\xbf\\x3c\\x21\\x4e\\x5f\\x97\\x38\\x1c\\xbe\\xd4\\xa6\\xa0\\xf3\\x8e\\x11\\x21\\xa5\\xdd\\xca\\x13\\x17\\xd0\\x81\\xa7\\x18\\x89\\xb3\\x3c\\x22\\xc7\\x80\\x9e\\x8b\\x06\\x24\\x7c\\x04\\x96\\x40\\x7c\\x73\\xa2\\x6b\\xf5\\x07\\x1f\\x4f\\x6d\\x9a\\x24\\x82\\xe7\\x3e\\x42\\x42\\x39\\x95\\x0e\\xb3\\x91\\x41\\x2f\\xe3\\x09\\x53\\xcd\\x27\\x20\\x8a\\x4f\\xe5\\xf1\\x27\\x96\\xd5\\x69\\x88\\x7f\\x9d\\x62\\x40\\x57\\x2c\\x01\\x5d\\xa8\\x9f\\xd5\\xfb\\x96\\x85\\x66\\xd2\\xb8\\x0c\\xd6\\x3e\\x0f\\x38\\x09\\x8d\\x88\\x8a\\x4a\\x7a\\xee\\x5e\\xc6\\x2b\\xb6\\x3e\\x6e\\x38\\x5e\\x27\\xde\\xaf\\x01\\x14\\x39\\x98\\xd6\\xb0\\x2b\\xbd\\x56\\x74\\xfc\\x89\\x6b\\xa3\\xff\\x2f\\xca\\x93\\x4c\\x96\\x63\\x7f\\xa8\\x22\\x39\\x9e\\xd7\\x80\\x22\\xbf\\xfa\\x22\\x87\\x3f\\x53\\x49\\xeb\\xb4\\xb6\\xfe\\x05\\x36\\xb5\\xc0\\x1f\\xfd\\x04\\x2a\\x56\\x29\\xa6\\x21\\xe8\\x4c\\xed\\x54\\xec\\x6a\\x57\\x33\\x21\\x05\\x00\\x46\\xb9\\x90\\x04\\xf6\\xa4\\x4e\\x1a\\xca\\xa7\\xd7\\xe3\\x80\\xb8\\xeb\\x70\\xb9\\x60\\x09\\x8e\\xad\\xa5\\x34\\x6a\\xa9\\x02\\xf8\\x51\\x9a\\xd8\\xc1\\x07\\x73\\x68\\x05\\xca\\xe7\\xb4\\x60\\xe8\\x7e\\xbd\\xe6\\x45\\x9e\\x51\\x85\\x89\\x88\\xae\\x51\\xb3\\x96\\xae\\x2c\\x0d\\xd1\\x70\\x93\\x22\\x58\\x41\\x1b\\x60\\x0d\\xb3\\x6b\\x97\\x80\\x44\\x95\\xe1\\x59\\x5d\\x50\\x45\\xac\\x04\\x9c\\x4a\\xb5\\x76\\x63\\x74\\xd2\\x95\\xcd\\x9a\\x9d\\x9a\\x64\\x4d\\xe1\\xd5\\x07\\xbf\\x5d\\x2e\\x13\\x12\\x33\\x9e\\x99\\x05\\x55\\x5c\\x4e\\x50\\xb3\\x5c\\x12\\x33\\x7b\\x58\\x08\\xe2\\x76\\x7b\\x12\\x05\\x72\\xe2\\x0f\\x9e\\x20\\xd1\\x07\\xe8\\xd8\\xb9\\xe6\\xed\\x7e\\xea\\x5c\\x13\\x3e\\x15\\x52\\xb1\\x7c\\x3f\\x52\\x40\\x82\\x2c\\x1c\\x91\\xaf\\x03\\x88\\x77\\x4a\\xd2\\xb5\\xd5\\xb8\\x7c\\x28\\x19\\xb0\\xfb\\xdc\\xbb\\x39\\x41\\xe5\\xb8\\xa9\\x11\\xbd\\x13\\xa9\\xd8\\x9c\\x29\\xb2\\x97\\x4b\\x44\\xaa\\x9e\\xf3\\xcc\\xec\\x8f\\xc8\\xff\\xdf\\x1a\\x7a\\xa9\\xd1\\xb7\\x60\\x41\\x3a\\x61\\x18\\x80\\x17\\x1d\\x2c\\x22\\xd5\\xe4\\x15\\xd9\\x83\\xa1\\x62\\xeb\\x71\\xdf\\x67\\x90\\x60\\xeb\\xec\\x74\\x7e\\xde\\x4c\\xbe\\x74\\x87\\x54\\xc3\\x3e\\x36\\xc1\\xf7\\xde\\xc6\\x6d\\x16\\x17\\xad\\xad\\x25\\x6e\\x0f\\x9d\\x13\\x64\\xa7\\x23\\x33\\x1c\\x92\\x5c\\x3b\\xb9\\xd8\\x8a\\xaf\\x86\\x94\\x0d\\x7f\\xa6\\x86\\xbd\\xf0\\x4f\\x48\\x12\\x20\\x8a\\x4d\\x41\\x7a\\xa1\\xec\\x79\\x42\\xd9\\x65\\x64\\x25\\x0b\\x39\\x5d\\x5c\\x54\\x8a\\xd1\\xfc\\xad\\x14\\xda\\x28\\x10\\xac\\x4f\\xe9\\x0b\\xba\\xbc\\x8d\\x88\\xa8\\x0b\\xde\\x4c\\x5e\\x13\\xea\\x8a\\x42\\xe4\\xc4\\x1e\\x23\\x9a\\xc8\\x7a\\x3a\\x43\\x1c\\x77\\xf8\\x21\\xa1\\x99\\x92\\xd0\\x44\\x12\\x1f\\xb7\\xae\\x9d\\x05\\x0e\\x39\\x3d\\xf2\\x98\\xee\\xde\\x29\\x1c\\x40\\xe2\\x61\\x4c\\x70\\x91\\x5f\\xd3\\x85\\x13\\x25\\x74\\xcc\\x73\\xa6\\xa3\\x42\\x62\\x4f\\xfa\\xda\\xdd\\xbe\\xed\\x91\\x76\\xeb\\x3c\\xd8\\x83\\xfc\\xf0\\xf4\\x68\\xdd\\x04\\x84\\xcd\\xd9\\xa9\\xb7\\x2d\\x69\\x30\\x11\\x70\\x45\\x9b\\xb5\\x0b\\x56\\x20\\xcc\\x32\\x2d\\xa5\\xb3\\x0e\\xa7\\x7c\\xce\\x44\\x98\\x99\\x67\\x82\\xdb\\x5e\\xd2\\x4f\\x17\\x57\\xec\\x3a\\xe1\\x97\\xfe\\x45\\xbf\\x65\\xeb\\xd7\\x22\\x0c\\xc1\\x85\\xf5\\x9d\\xd0\\xd4\\x70\\x3d\\xe1\\x74\\x5c\\x3c\\x25\\x78\\x3c\\x80\\x0f\\x5c\\xb0\\x82\\x65\\x1b\\xd4\\xb5\\xdf\\xc7\\x44\\x78\\x00\\xcd\\xd0\\x3b\\xb3\\xc5\\x63\\x69\\xf2\\x1e\\xea\\x69\\x1a\\xb7\\x88\\xab\\xda\\x02\\xdc\\x05\\xed\\x87\\xb5\\x9b\\x15\\x02\\xfd\\x38\\x74\\x48\\xe5\\xc3\\xd4\\x85\\xba\\x1c\\x33\\xe5\\x45\\x58\\x9a\\x4e\\x03\\x7e\\x42\\xae\\x96\\xba\\xaa\\x79\\xd6\\x71\\x82\\xec\\x19\\xf6\\x05\\x85\\x29\\x3d\\xfe\\x64\\x95\\x55\\x9d\\x96\\xc8\\x8f\\x57\\x8b\\x93\\x96\\x1f\\x8a\\x09\\x3c\\xbe\\x88\\x6a\\x69\\xe9\\xdc\\xa6\\x87\\xc6\\x3e\\xbe\\x61\\x78\\xf3\\x49\\xaa\\x18\\x6e\\xae\\x2e\\xa5\\x46\\x78\\x25\\x17\\x1c\\xe1\\xd5\\x57\\x3b\\x4e\\x28\\xb4\\xbd\\x75\\xee\\x70\\x8e\\xc3\\x37\\x31\\x0c\\x92\\xf3\\x7a\\xeb\\x01\\xda\\xc0\\x18\\xa0\\x85\\x1e\\x35\\x4e\\x83\\xb2\\x37\\x77\\x20\\x0b\\x2c\\x6a\\x67\\x43\\x5c\\xb1\\x05\\x3c\\x1e\\x47\\x4c\\x5d\\xb3\\xce\\xdb\\xc2\\x13\\xd6\\xa5\\x8c\\x0a\\xaf\\xa1\\x7d\\xa5\\x4e\\xbf\\xf7\\xd3\\x9c\\xfc\\x90\\xae\\x7b\\x1c\\xaf\\x44\\x7f\\x5b\\x73\\xb5\\xf8\\xf8\\xaa\\x71\\xa1\\x21\\x4f\\xb6\\x5c\\x68\\x8d\\x5c\\x6e\\x1c\\x68\\x9d\\xc6\\xee\\x5c\\x84\\x85\\x57\\x17\\xbf\\x54\\x73\\xf5\\xb7\\xa1\\x63\\x9a\\x1e\\xe2\\xab\\xa2\\xc4\\xb5\\x40\\xec\\xba\\xbd\\xf0\\x5a\\xe5\\xbb\\x3a\\x11\\x03\\x72\\x2a\\x8d\\xfd\\x27\\x72\\x63\\x1d\\x49\\xa6\\x4f\\xa5\\x81\\x4f\\xb6\\x62\\x25\\x71\\x02\\xb6\\x69\\x1d\\x9d\\xab\\x01\\xdb\\x7f\\xc1\\x71\\xe3\\x52\\xd2\\xac\\xa2\\xe0\\xd6\\x6b\\x95\\xed\\x7a\\x22\\x88\\x54\\x6e\\xca\\x3b\\x92\\x10\\xcc\\x5f\\xed\\x08\\x88\\xa3\\xea\\xae\\x51\\xca\\xad\\xd6\\xb3\\xa5\\x22\\x5e\\xe6\\x47\\x23\\xc6\\x11\\x02\\xd8\\xf9\\xf8\\x0d\\x74\\xa9\\xaf\\x0a\\xa8\\xab\\xce\\x6b\\x98\\x30\\x6a\\x67\\x8e\\x1a\\x36\\xe5\\x59\\x47\\x3a\\x4a\\xa6\\xa6\\x8c\\x40\\x87\\xba\\x3e\\x38\\xb7\\x8b\\x22\\x81\\x57\\x47\\x75\\x22\\x26\\xa6\\xc3\\x36\\x02\\x1d\\x0d\\x74\\xf7\\x7e\\x74\\xbe\\x0e\\xfb\\x27\\x22\\x05\\xb5\\x98\\x92\\x82\\xc3\\xe1\\x7f\\x42\\x08\\xf3\\x7f\\x49\\x45\\xb9\\xd2\\x23\\x72\\xe8\\xd3\\xec\\xe2\\xef\\x5c\\xa6\\x42\\xf4\\x98\\x0e\\xa4\\x54\\x37\\xbd\\xeb\\x54\\x10\\x86\\x28\\x2b\\x96\\xaa\\x65\\xe5\\x76\\x40\\xae\\xa1\\x1f\\xad\\x3d\\x00\\x83\\x87\\x75\\xe7\\x8a\\x2d\\x76\\x06\\x9d\\x7a\\x28\\xc7\\x3b\\x74\\xe7\\x44\\xec\\x34\\x79\\x75\\xad\\x5d\\x15\\x74\\x3c\\xe8\\x3d\\xb1\\x03\\xdf\\xed\\x3c\\x9e\\x1e\\xdd\\x49\\x23\\x6b\\x70\\x49\\xce\\x7a\\x50\\x69\\x3a\\x6e\\x81\\x56\\x43\\xae\\x92\\x56\\xae\\x1f\\x17\\x35\\xb2\\x4c\\x90\\x39\\x0d\\xf3\\x7d\\x9b\\xd0\\x4f\\x8c\\xf4\\xb4\\x9b\\x3e\\xb4\\xa8\\xf0\\x26\\x81\\x71\\xa6\\x6f\\xa3\\xa9\\x69\\x2c\\x1b\\x2f\\x20\\x50\\x3d\\x73\\x6e\\x36\\x39\\x67\\x0a\\x5d\\x6c\\x49\\x63\\xa3\\x53\\x89\\x43\\xa3\\x78\\x97\\x6f\\x4e\\x8b\\xac\\xb6\\xa6\\x81\\x6b\\x31\\x0f\\x03\\x5b\\x3e\\xf4\\x1e\\x82\\x42\\xca\\xab\\xba\\xf2\\xfc\\x0c\\xb9\\xa8\\xa9\\x3b\\x86\\x8b\\x4c\\x96\\xce\\xcf\\x80\\xef\\x09\\xee\\x60\\xb7\\x31\\x87\\x2e\\xed\\x07\\x65\\x4c\\xd8\\x0a\\x98\\x58\\xd4\\xf2\\xa2\\x24\\x06\\xc9\\xe2\\xc9\\x0c\\x0e\\x53\\x66\\x8f\\xd1\\xe0\\x5f\\x6b\\xa6\\xf7\\xce\\xa9\\x4a\\x22\\xc0\\x27\\x9c\\xc7\\xb3\\xe0\\xba\\x44\\xd1\\x32\\x44\\x97\\x27\\x52\\x8d\\x79\\x9e\\x83\\x6f\\x0f\\x89\\x0b\\x65\\x4f\\x4b\\x8c\\x63\\x25\\x4d\\xcb\\xaf\\x93\\x26\\x34\\x96\\x9e\\xba\\xa2\\x1a\\x7c\\xd9\\x79\\x24\\x76\\x4d\\x4a\\x6e\\x2e\\x5e\\x30\\x08\\xd8\\x20\\xb9\\xb4\\x0f\\x0a\\xaf\\xb8\\x3c\\x35\\x9e\\x11\\xec\\xec\\x27\\x8d\\x34\\x66\\x3e\\x86\\x66\\x8f\\x24\\x51\\x17\\x45\\x68\\xd3\\x8c\\x6e\\x0e\\x0c\\x77\\x81\\x48\\x76\\x91\\xf9\\xa9\\x15\\xd2\\xa6\\xcd\\x6c\\xeb\\x77\\x1d\\xc5\\x6b\\xb9\\xf7\\x28\\x9c\\x3a\\x76\\xcd\\x9c\\xc4\\x47\\xbb\\xac\\x3d\\xfb\\x27\\xe2\\x4c\\xe6\\x6d\\x17\\x71\\xab\\x0d\\xa9\\x83\\x3b\\xf1\\xfd\\x4b\\xf7\\xa2\\x46\\xa6\\xa9\\xa5\\x1f\\xa4\\xb3\\xd2\\xd4\\x41\\x55\\xea\\xf3\\x74\\x88\\xda\\x35\\x26\\x1f\\x0f\\xe0\\x9d\\xde\\xdc\\xb9\\x00\\xc3\\x47\\xb1\\x1d\\x4c\\x41\\x9d\\x2a\\x86\\xf0\\x94\\x20\\x96\\x40\\x4c\\xb9\\x7e\\xfa\\xb5\\x60\\x73\\x66\\xd9\\x37\\xe7\\xda\\xb5\\x73\\x4c\\xd4\\x1c\\x20\\x4b\\xe9\\x1f\\x37\\xdc\\xe4\\xff\\xbf\\x23\\x79\\x2a\\x8d\\x8f\\xfb\\xfc\\x63\\xe0\\xc2\\xc6\\xa8\\xc8\\x7d\\xe2\\x65\\x5d\\x36\\x3d\\xfd\\x49\\xce\\x27\\x13\\xa6\\x12\\xb1\\xfb\\x49\\xa8\\xc0\\x68\\x3b\\x83\\xdb\\xe1\\x0f\\x27\\x26\\x0c\\x55\\x53\\xa8\\x1b\\x76\\x8e\\x5d\\xaf\\x73\\x4d\\x0b\\x39\\xa6\\x05\\x29\\xb9\\xb0\\xa4\\xa5\\xcd\\xc4\\xe5\\x8d\\xe7\\x84\\x37\\x76\\x7f\\xde\\x41\\x1c\\x28\\xa1\\x7c\\xca\\xc7\\x05\\x73\\xde\\xe6\\xb4\\x3c\\x01\\xe5\\x52\\xa8\\x27\\x4b\\xb3\\xb1\\xf4\\x70\\x90\\x2f\\x05\\xd3\\x1a\\x93\\x64\\x3f\\x70\\x71\\xe4\\x62\\x75\\x49\\xc3\\xbe\\xb3\\xe2\\xf1\\x13\\x2d\\xab\\x82\\x21\\xd4\\x1f\\xf9\\x6a\\xf8\\x2f\\x29\\x18\\x71\\xc9\\xff\\x83\\xc0\\xa2\\xae\\x9a\\xc5\\x48\\xf2\\x1a\\x35\\xde\\x2a\\xc0\\x69\\xf9\\x2a\\x93\\x24\\x0a\\x5a\\x82\\x37\\x44\\x2f\\x35\\xf9\\xf2\\xe0\\xcb\\x83\\xd7\\x69\\x22\\xe6\\xc4\\x15\\xe0\\x64\\x54\\xbb\\xe6\\x37\\x37\\x57\\x77\\xed\\x52\\x16\\xbc\\x7e\\x21\\x76\\x76\\x5e\\xbb\\x7f\\xbf\\x74\\xff\\x7e\\x45\\x7e\\x49\\x7c\\x1a\\x39\\x23\\x67\\xad\\x7f\\xed\\x3f\\x89\\x4f\\x1b\\x5a\\xe6\\x89\\x96\\xeb\\xf5\\xa0\\x7d\\xb8\\xb6\\xfa\\x71\\xbb\\xfd\\x0d\\xea\\x1e\\xbe\\x02\\x9c\\x33\\x99\\x2c\\x19\\x4c\\xfd\\x97\\xff\\x37\\x4d\\xd9\\x6c\\x9a\\x0c\\x73\\x43\\xa4\\x70\\x4f\\x7f\\xbd\\x07\\xd3\\xb5\\x4f\\xae\\x21\\xfa\\x5f\\xd2\\x2b\\x8c\\x00\\x1d\\x66\\xa6\\xa6\\x85\\x25\\x78\\xef\\xab\\xe1\\xeb\\x7d\\x22\\x45\\xeb\\xf6\\x24\\x12\\xe6\\x5c\\x5a\\x85\\xcd\\xcf\\xc4\\xde\\xeb\\x44\\xa8\\x83\\xe5\\xe9\\xfc\\x72\\xc5\\x74\\xb6\\x66\\x12\\xde\\x96\\x8a\\x05\\xbc\\x42\\xbf\\x32\\xd9\\x8b\\xe3\\x43\\xb1\\xb8\\xa6\\x8b\\x20\\x94\\xbd\\xbe\\x3e\\xe5\\x73\\x46\\x66\\x7c\\x3a\\x03\\x50\\x80\\x0e\\xed\\x54\\x10\\xb0\\x13\\x65\\x2c\\xf7\\x3d\\xaa\\x90\\x90\\x05\\xe1\\x89\\xea\\xdf\\x89\\xd9\\xd5\\x90\\xd7\\x81\\x4e\\x7f\\x87\\xf7\\x12\\xaa\\xb5\\x42\\x09\\xc6\\x6b\\x10\\x2b\\xaf\\x96\\xf0\\x2e\\x36\\x9c\\xec\\xf3\\xd5\\x97\\xeb\\xeb\\x14\\x41\\x26\\x6f\\x4c\\xad\\x08\\x14\\xb4\\x90\\xb8\\x6f\\x9e\\x66\\xcb\\x87\\x4b\\x07\\xae\\xbd\\xe7\\xd4\\x82\\x83\\x22\\x1c\\x9e\\xe1\\x18\\xbf\\x72\\xe6\\x70\\x73\\xa2\\x35\\xb3\\x97\\xe6\\xe8\\x3c\\x93\\x79\\xc8\\xb8\\x20\\x4e\\x9f\\x86\\xf4\\x32\\x4d\\x76\\xda\\xc7\\xc0\\x0e\\xa4\\x9b\\x05\\xf7\\x8d\\xc3\\x45\\x75\\x06\\x9f\\x6b\\x53\\xea\\x37\\x7f\\xa7\\x2e\\x61\\x84\\x1c\\x8a\\xbc\\xa9\\xa9\\x49\\x9c\\x25\\xf6\\x73\\x4d\\x0b\\xf0\\x06\\x4f\\x21\\x5b\\x4e\\xf5\\x33\\x5f\\x51\\xf5\\x4d\\xab\\xca\\xd8\\xca\\xe2\\x46\\x9a\\x27\\xbe\\x36\\xee\\x7b\\x5d\\x17\\x90\\x6f\\x78\\xff\\xfb\\xf7\\xca\\x09\\xba\\xc9\\x5d\\x02\\xb3\\x33\\x24\\x2f\\x95\\x12\\x5b\\xdb\\x09\\xaf\\xfe\\xbb\\x54\\x06\\xe9\\x1c\\x13\\x9d\\x36\\xc3\\xc9\\x64\\x45\\x51\\x59\\x93\\x0c\\x85\\x9d\\x72\\xed\\x76\\x04\\x34\\xa3\\x78\\xa7\\xba\\x25\\x06\\x15\\xab\\x4b\\xce\\x73\\x54\\x66\\xe0\\x44\\xa0\\x6e\\xb3\\xcc\\xab\\x0e\\xdb\\xbc\\x79\\x37\\x69\\xf0\\xfd\\x7e\\x58\\x3e\\xad\\x42\\x40\\xa1\\x65\\x49\\xa4\\xda\\xd4\\x29\\x1a\\xea\\x97\\x83\\xa5\\x89\\x75\\x9f\\xff\\xfe\\xa9\\x14\\xd7\\x2f\\xd3\\x14\\xd7\\x47\\xd7\\x2e\\xf1\\xdf\\x64\\x23\\xa9\\xd9\\xb9\\x2b\\x37\\xec\\xef\\xf7\\x9a\\x59\\xdf\\x87\\x44\\xf7\\x1b\\x12\\x17\\x10\\xa2\\x9a\\x5c\\xdf\\xc4\\x2d\\xe6\\xf4\\x7b\\xcd\\x4d\\x4d\\x11\\x88\\x4a\\xb0\\x6b\\x57\\x59\\x1c\\x2d\\xeb\\xd2\\x12\\x45\\x6e\\x2e\\xaf\\xb3\\xa5\\x09\\x96\\x31\\xcb\\x68\\xad\\xed\\xae\\x2e\\x2b\\x6b\\x7f\\x13\\x6d\\xd9\\xcf\\xbb\\x0c\\xbf\\xda\\xfb\\x8a\\x0c\\xc9\\xab\\x7d\\xbb\\xbd\\x05\\xca\\x16\\x60\\xc1\\x58\\xe3\\x86\\x96\\x0b\\x68\\xe9\\x99\\x99\\xb5\\xf5\\xed\\x3a\\x27\\x8a\\x39\\xee\\x7b\\x7a\\xb6\\xf5\\xde\\x47\\xf6\\x61\\x85\\x85\\xde\\xa8\\xff\\x6a\\x53\\x2a\\x9e\\x90\\x39\\x3b\\x9c\\x4c\\xb8\\xe0\\x66\\x91\\xda\\x90\\xbd\\x1f\\x55\\xef\\xf4\\x06\\x25\\x91\\xca\\x37\\x93\\xd7\\xe4\\xda\\x55\\xff\\xc3\\xb6\\x73\\x28\\x76\\x31\\xf9\\x07\\xf6\\x8f\\x4e\\x5e\\x76\\x38\\xd8\\x83\\xde\\xe4\\xac\\xa3\\xa0\\xbb\\x38\\xc1\\x68\\xb7\\xc8\\xc8\\x55\\xba\\xbb\\x6e\\x17\\x29\\x63\\x0d\\xc9\\xdf\\xa4\\x90\\xea\\x0d\\x1a\\xb2\\x96\\x74\\xdd\\xe8\\x4b\\xb7\\xbe\\x96\\x3b\\x0b\\x63\\x80\\xf9\\x96\\xa6\\x97\\x78\\xd4\\x0f\\xc9\\x09\\x38\\x9b\\xdf\\xdc\\x37\\x72\\x70\\x49\\x03\\xec\\x41\\x1e\\x0e\\xe7\\xbb\\x08\\x4a\\xdb\\xbd\\xb7\\xd7\\xb5\\x87\\x0e\\xfd\\x37\\xc2\\xa8\\xf6\\x5b\\x98\\x55\\x52\\x01\\x03\\xa5\\x3a\\xd1\\x62\\xb9\\x31\\xc4\\x3e\\x73\\x5e\\x10\\xf8\\xa2\\xfa\\x68\\xf3\\xdb\\x51\\x2d\\xf3\\x9e\\xd8\\x59\\xd0\\x5c\\x0a\\xe4\\xde\\xbb\\xc4\\xc9\\xa4\\xa0\\x4f\\x59\\x0f\\x80\\x97\\x5d\\xaf\\x4b\\xc8\\x3c\\xdf\\xfc\\x46\\x8f\\xe9\\xb8\\x73\\x9b\\x63\\x7b\\x23\\xcc\\x97\\x5f\\xde\\x9e\\x49\\xa3\\x3f\\xc5\\x96\\xc6\\x9d\\x61\\x4f\\x70\\x59\\x1b\\x47\\xfd\\x80\\xd0\\x42\\x42\\x3c\\xce\\x9e\\xeb\\xf6\\x23\\x96\\xbb\\x1b\\x27\\xd2\\x87\\xed\\x96\\xc3\\x48\\x49\\x64\\xcc\\x00\\x3e\\xb4\\x29\\x87\\x19\\xb4\\xf6\\x68\\x1f\\x02\\xc2\\x2f\\xc8\\x03\\x44\\xc2\\x53\\x6f\\x7f\\x24\\xf3\\x65\\xff\\xaf\\xfa\\x71\\x53\\x85\\xb0\\xb9\\x2a\\xc6\\x40\\x82\\x0f\\x4c\\x5c\\x31\\x50\\x20\\x81\\xad\\x30\\x68\\x3a\\x82\\xd9\\x74\\x2e\\x3b\\x87\\xab\\x83\\x79\\x05\\x4e\\x27\\xe6\\x3a\\x39\\x63\\xd6\\xaa\\x7f\\x1c\\x10\\x8a\\x33\\x5a\\xc4\\xf6\\xa5\\xb5\\x6b\\x79\\xce\\x14\\x6a\\xb5\\x63\\xd6\\xc2\\x9c\\x4a\\x2d\\x54\\xc1\\xeb\\x87\\xe6\\xe9\\x88\\x4f\\x05\\xc0\\x09\\x38\\xf8\\x5f\\x10\\xeb\\x77\\x67\\x5c\\x67\\x57\\xcc\\xf8\\x0c\\x1c\\x05\\x98\\x30\\x55\\x6d\\xc8\\x98\\x16\\x54\\x64\\x56\\x52\\x80\\xc1\\x92\\x16\\x90\\x99\\xf8\\x10\\x8f\\x91\\x48\\x00\\x8e\\x96\\xfc\\x36\\xd8\\xd1\\x22\\xa0\\x1d\\xe1\\x2b\\x44\\xd5\\xba\\x5c\\x68\\x63\\xa9\\xc6\\x32\\xde\\x6e\\x93\\x77\\x58\\x68\\x39\\xb0\\x67\\x82\\x1f\\xf4\\x46\\x90\\x0a\\x87\\x77\\xff\\x8d\\x89\\x52\\x4e\\x9b\\x62\\xcc\\x38\\x90\\xbc\\x28\\x4b\\x49\\x4e\\x92\\xe8\\xb8\\xa9\\x27\\x3b\\x58\\xe2\\xf6\\x59\\x96\\xf6\\x92\\x6c\\x34\\x85\\xb4\\xc9\\xa5\\xed\\xb1\\xd3\\x46\\xa7\\xf4\\x80\\x57\\x3b\\x03\\x5c\\x45\\xbb\\x4b\\x1c\\x70\\x29\\xbe\\x3c\\xd8\\x61\\xd4\\x74\\x9d\\x71\\x91\\x03\\x1c\\xf2\\x32\\x31\\xe1\\xa9\\x6d\\xaa\\xac\\xbd\\xe7\\x29\\x02\\x6f\\x46\\xff\\x14\\xad\\x76\\xbb\\x3f\\xb5\\xf8\\xbc\\x11\\xcb\\xd8\\x94\\x10\\xbd\\xe9\\xa6\\x6a\\x2b\\x50\\x50\\x9d\\x44\\x0b\\x8f\\x69\\x64\\x15\\x1e\\x3e\\xb1\\xc6\\x75\\x2e\\x19\\xa6\\xbf\\x60\\x18\\x24\\xd1\\xc9\\xca\\xbc\\xd6\\xd4\\xb8\\x02\\x53\\x75\\x8a\\x96\\x5b\\x8d\\xec\\x79\\x2b\\x9a\\x18\\x56\\x14\\x78\\x3a\\x34\\x9e\\x4f\\x21\\xb1\\x28\\xd4\\xdf\\x9d\\x1a\\xc3\\x19\\x92\\x76\\x08\\x6a\\xe5\\x60\\xf1\\x40\\x1e\\xa2\\x0a\\x22\\xe4\\x8b\\xd0\\xdb\\x32\\x35\\x79\\x79\\x5c\\x1b\\x32\\xe5\\x73\\xab\\xe0\\xdd\\x88\\x73\\xad\\x8a\\x59\\x61\\x9c\\x71\\xc6\\x8a\\x8a\\x28\\x96\\xd7\\x19\\xeb\\x90\\xf2\\x09\\x7a\\x6e\\x9a\\x50\\x88\\x1d\\xbf\\x80\\x10\\x12\\x8e\\xcb\\x9d\\x16\\x2f\\xee\\xb8\\x46\\x9c\\xdd\\xd5\\x58\\x3e\\x01\\x09\\x0b\\xe6\\x31\\x9f\\x10\\x36\\x67\\x6a\\x41\\x2a\\xa9\\x35\\xc8\\x7e\\xd0\\x17\\x10\\xd2\\x11\\xd2\\x66\\x43\\x63\\x76\\xf0\\x9d\\xc1\\x9c\\x39\\x37\\x52\\xd2\\xe0\\x3b\\xce\\xf7\\xb4\\x03\\xc1\\x03\\xd9\\x59\\x07\\xd8\\xde\\xec\\x84\\xaf\\x0e\\x5e\\xa7\\x66\\x27\\xf4\\xed\\xe4\\x3d\\x83\\xff\\x85\\xd4\\x81\\x4e\\x29\\x04\\x27\\x93\\x55\\x72\\x32\\xcc\\x6d\\x4b\\xf2\\x3c\\x24\\xbb\\x20\\x35\\x04\\x0d\\x33\\x03\\x49\\x00\\x5f\\xed\\x47\\x89\\x09\\x5f\\x1d\\x7c\\x79\\xf0\\x7a\\xcf\\xce\\xfd\\x97\\xfb\\x76\\x15\\xa2\\xf4\\x81\\x2f\\xa3\\xf4\\x81\\xf0\\x4b\\xf7\\x16\\x09\\x80\\x5d\\xa4\\x49\\xce\\xda\\x7b\\xbd\\x3f\\x82\\x62\\x10\\x40\\x63\\xbd\\x96\\x2a\\x77\\x80\\x06\\x1e\\x1f\\xd3\\xbe\\x39\\x76\\x45\\xb4\\x0a\\x70\\xe9\\x95\\xcf\\x01\\x08\\xad\\x20\\x1d\\xd3\\x5c\\x6b\\x10\\xb8\\x82\\x74\\x09\\x6e\\xc8\\x17\\xa5\\x54\\xec\\x8b\\x68\\x88\\xe7\\xaa\\x18\\xdc\\x4c\\xe2\\x2b\\x69\\x35\\xbc\\x4a\\x48\\xd0\\xee\\x52\\x25\\xde\\xb5\\x46\\xfc\\xb6\\x54\\xc4\\x92\\x56\\x6b\\x3c\\x67\\x2e\\x8b\\xba\\x5c\\x37\\xdd\\xbe\\x9b\\x42\\xf4\\xde\\x15\\xfc\\xba\\xa1\\x5d\\x4d\\x2a\\xa6\\xb3\\x94\\xae\\x58\\x7b\\xbc\\x88\\x81\\x8b\\xc7\\xac\\x90\\x62\\x8a\\x31\\xe9\\xd0\\x50\\x71\\xcd\\x51\\x1f\\x86\\x23\\x9f\\x49\\x91\\xb1\\xca\\xe8\\x03\\x6d\\xa4\\xa2\\x53\\x76\\xe0\\x88\\x5c\\x6b\\xb0\\xcd\\x61\\x3d\\x7c\\x0f\\xd4\\xb6\\x4b\\x06\\xb1\\x07\\x12\\xbe\\x47\\x80\\x95\\xf6\\x85\\xf3\\x20\\x2f\\x69\\x06\\x20\\x9b\\x30\\xeb\\xad\\x26\\xb0\\x11\\xd8\\xe7\\x33\\x81\\x7b\\x48\\xe8\\x70\\xd8\\xa5\\x8c\\x96\\x5e\\xeb\\xe3\\x82\\x6a\\xc3\\xb3\\xaf\\x0b\\x99\\x5d\\x5d\\x18\\x99\\xe6\\x86\\xec\\xc3\\xc2\\x58\\x45\\x4b\\x8b\\x13\\x04\\x39\\xfc\\xe1\\x82\\x1c\\x71\\x7d\\x45\\x14\\xd3\\xb2\\x56\\x99\\xeb\\xcc\\xb6\\x04\\x3f\\xb9\\x2e\\x52\\x2e\\x5e\\x4d\\x8f\\x79\\xe8\\x04\\x5e\\xd2\\x6c\\x86\\xa6\\xbf\\xcb\\x6e\\x61\\x9f\\x2a\\xa9\\x9b\\xe6\\xcf\\x09\\x2c\\x85\\x57\\xb7\\x7d\\xfc\\x1b\\x7a\\xad\\x19\\xce\\xd2\\xd8\\xce\\x92\\xfd\\x3a\\x45\\x35\\xdb\\x70\\x23\\x4f\\x7c\\x9b\\x93\\xa3\\x84\\x9f\\x77\\xad\\x1a\\x9f\\xe8\\xcb\\xe4\\x6e\\xf9\\xfd\\xd5\\x06\\x22\\x15\\xde\\x1d\\x39\\xe1\\x05\\x43\\x6c\\x2e\\x6c\\xa5\\xef\\x62\\xdb\\x4e\\xe6\\x01\\x8f\\x2f\\x64\\x4d\\xae\\x29\\xba\\x9c\\xe1\\x90\\x49\\x2f\\xfa\\xbc\\xe4\\xd5\\x1b\\x72\\x2c\\x74\\xad\\x58\\x53\\xda\\xbe\\x4c\\x82\\xd5\\x5a\\x7d\\x93\\x5f\\xef\\x6f\\x86\\x8d\\x81\\xf5\\x7b\\xf6\\x2c\\x4b\\x47\\x13\\xc3\\xeb\\x18\\x4d\\x13\\xfd\\x86\\xec\\xb0\\x4f\\xe6\\x77\\x3b\\x03\\xb2\\xf3\\x69\\xa2\\xed\\x3f\\xc2\\x4c\\xf4\\xce\\x88\\x9c\\x94\\x55\\xc1\\x33\\x6e\\xac\\x2d\\x26\\x26\\x4c\\x35\\x7e\\x52\\xfc\\x41\\x4f\\x1d\\x95\\xb6\\x65\\x4f\\xe2\\x75\\xf9\\xf1\\xe8\\xe3\\x1b\\x70\\xa9\\xe4\\x92\\x5c\\x33\\x6b\\xa8\\xcf\\xad\\xad\\xc9\\x94\\x92\\x2a\\xe4\\xf3\\x47\\xcb\\x05\\xf5\\x65\\x99\\x2c\\x2b\\x25\\x4b\\x1e\\x41\\xe1\\x82\\xfc\\x4a\\x24\\xa3\\x73\\x19\\x2e\\x38\\x66\\x61\\x97\\x6c\\x78\\xa3\\x05\\x42\\xfc\\x5e\\x8b\\x3e\\x10\\x8f\\xb9\\xcb\\x4e\\x26\\x44\\x62\\x99\\x47\\x1b\\x18\\x9d\\xeb\\xf0\\x70\\xbb\\xaf\\xdc\\xe8\\x22\\xa1\\xc3\\x53\\x73\\x35\\x3b\\xc9\\x9a\\xfc\\xee\\x91\\x07\\x39\\x9b\\x1f\\xe8\\x9c\\xbe\\x1e\\xc0\\x6b\\xe1\\x36\\x59\\x2c\\xcd\\x01\\xd5\\x64\\xe7\\xf5\\xda\\xad\\x09\\x9a\\xeb\\x82\\x97\\xbc\\xa0\\xaa\\x58\\x0c\\xe2\\xb9\\x6c\\x9e\\x3f\\x91\\x2a\\x10\\x02\\x0e\\xdd\\x57\\x3b\\x64\\x0f\\xf1\\xc7\\x41\\x65\\x2e\\x98\\xef\\x00\\x18\\x3a\\xff\\x42\\xb9\\x59\\x72\\x7f\\xbd\\xae\\x89\\x2d\\xa4\\x73\\x72\\x0b\\x81\\xf3\\x91\\xe6\\x1f\\x45\\x91\\x8c\\x4c\\xd2\\x17\\xf7\\x7b\\x3a\\x3c\\x62\\xa1\\xaa\\x5d\\x9c\\x7b\\x22\\x51\\x7b\\x62\\xcd\\x2d\\xbe\\x09\\x10\\x17\\x4e\\x0d\\xff\\x60\\x79\\xb4\\x03\\x18\\xc7\\xf6\\x48\\xd5\\xae\\x1d\\x0f\\x49\\x50\\x58\\x36\\xbd\\xa0\\x9e\\x0e\\x28\\x5f\\x10\\xfc\\xe7\\x9a\\x91\\x93\\x23\\xaf\\x2f\\x54\\x4c\\x69\\xae\\x8d\\x3d\\x2d\\xf2\\x96\\x96\\xcc\\x51\\x75\\xde\\x3b\\x2c\\xe9\\xbf\\xa4\\x20\\xc7\\x5f\\x5f\\xb8\\x07\\x25\\x6f\\xb3\\xed\\x5b\\xdd\\xc4\\xc3\\x8a\\xfe\\xab\\x56\\xcc\\xda\\x14\\x9d\\xcd\\x9e\\xf0\\xa4\\x65\\xa3\\xc5\\x7e\\x4e\\x8e\\xa8\\xa1\\x68\\xbb\\xa0\\xe8\\x97\\x4d\\x3b\\x30\\xb0\\x31\\xc6\\x80\\x2a\\xe7\\xfb\\xce\\x75\\xb0\\x30\\x36\\xac\\xd9\\x5b\\xc6\\x3b\\x4d\\x6f\\xd3\\x6f\\x7f\\xfe\\xdd\\xf9\\xc9\\x06\\xec\\x82\\x0c\\x14\\xa6\\xe9\\x07\\x99\\xf7\\x63\\x1c\\xec\\x46\\x0f\\xf4\\xba\\x07\\x34\\xd7\\x7d\\x8b\\x9f\\x93\\xd2\\x8e\\x44\\x4e\\xa5\\x60\\x03\\x72\\xce\\x68\\x4e\\xac\\x14\\x76\\xff\\xf9\\x83\\xe2\\x86\\x8d\\x76\\x37\\xa5\\xbd\\xf9\\x45\\xec\\x65\\x22\\xfc\\xc3\\xfc\\x24\\x9c\\x46\\x1d\\x17\\xa1\\x2f\\x2a\\xc8\\x2a\\xa7\\x8c\\x8d\\x0b\\x39\\x26\\x4e\\x56\\x6c\\xf2\\xed\\xbf\\x3b\\x3f\\xe9\\xed\\xe5\\xbf\\x3b\\x3f\\xf1\\xef\\x6e\\xff\\x53\\x4e\\xb6\\xf3\\xb5\\xb7\\xcd\\x30\\x7e\\xb7\\x64\\x91\\x76\\x57\\xc9\\x3f\\xb8\\xc2\\x0a\\x7a\\xc3\\xda\\x7d\\x7c\\x53\\x77\\xb4\\x61\\x23\\xb7\\x33\\x7b\\x5c\\x71\\x91\\x0c\\x38\\xd8\\x16\\x8c\\xf6\\x49\\x4d\\x6b\\xa2\\x28\\x1d\\x0a\\x5a\\xdc\\xe5\\x6f\\x48\\x59\\x17\\x06\\x9a\\xbd\\xc0\\xb6\\xb0\\xfb\\x04\\x2a\\xc8\\xfc\\x06\\x21\\xae\\xf9\\x29\\x21\\x47\\x0c\\x53\\x10\\xf2\\x37\\x1e\\x3f\\x29\\xfc\\x62\\xf5\\x0f\\x3e\\x50\\x41\\xa7\\xf6\\x76\\x38\\xac\\x49\\x89\\x7f\\x46\\xfb\\x71\\x0f\\x23\\xbf\\x22\\x7c\\x45\\xe7\\x94\\x17\\x74\\xcc\\x0b\\x6e\\x40\\x45\\xde\\x1f\\x79\\x4b\\x0e\\xc1\\x66\\x80\\xe4\\x8d\\x09\\xea\\xad\\xb3\\x33\\xe2\\x86\\x10\\xd0\\x44\\x90\\xec\\xd9\\xef\\x0e\\xae\\xed\\x81\\xb6\\x3f\\x82\\xd3\\x0d\\x6e\\x9c\\x31\\x15\\x9b\\x22\\xc9\\x23\\xdb\\xcd\\x7a\\xfe\\x48\\x26\\x4c\\x37\\xb3\\x01\\x58\\xcc\\x0a\\xb1\\x7e\\x34\\x4b\\xfb\\xa4\\x95\\x9a\\x25\\x7c\\xe1\\xda\\xaa\\x7e\\xe6\\xca\\xa5\\x66\\x99\\x62\\xa6\\x83\\x7a\\x09\\xdb\\x35\\xf1\\xf7\\x5d\\x15\\xcc\\xad\\xdb\\xab\\xf9\\xcb\\x5e\\x8d\\xaf\\x86\\xb9\\x7a\\x59\\xa1\\xe6\\x71\\x5e\\xf9\\x0b\\xbd\\xc6\\xf1\\xab\\x25\\x2c\\x63\\xdc\\xcc\\x17\\xee\\xc4\\xf2\\x3d\\xc8\\xe1\\xf7\\x76\\x0b\\xa7\\xa0\\xb8\\xe3\\xd5\\xf9\\x90\\x09\\x9b\\xa6\\x9f\\x79\\xf1\\x4f\\xf3\\xd3\\x82\\x47\\x31\\x7c\\x4c\\x92\\xb7\\x76\\xc7\\xd7\\xcc\\x58\\x35\\x9b\\x74\\xc7\\x1b\\xb0\\x8f\\x79\\x77\\xd1\\x0e\\x5f\\xbf\\x65\\xd5\\x8c\\xbc\\xbb\\x58\\x21\\x99\\x11\\x1d\\xc2\\xbe\\xb7\\xc6\\xa0\\xf6\\xae\\x26\\x05\\x9f\\x30\\xc3\\x93\\x26\\x61\\xc3\\xb2\\xb9\\x94\\x82\\x1b\\xb9\\x76\\x97\\x65\\xd2\\x07\\xd8\\xbb\\x1b\\x7a\\xd3\\x92\\xd5\\xd3\\x61\\x39\\xfb\\xdc\\x4f\\x27\\xf9\\x10\\x7d\\x4a\\x49\\x26\\x8b\\x82\\x65\\x1e\\x1f\\x01\\x98\\xa3\\xc3\\xcc\\xe1\\xb5\\xc2\\x15\\xe7\\xd2\\xfe\\xf4\\xe8\\xea\\x4f\\xe0\\x8c\\x73\\x6e\\xb7\\x03\\x64\\xf4\\x83\\xf3\\xe3\\xc3\\xa3\\x0f\\xc7\\xa3\\x32\\xff\\xcd\\x4c\\x5e\\x0f\\x8d\\x1c\\xd6\\x9a\\x0d\\x79\\x2a\\xfe\\xe5\\xc6\\xa1\\xe8\\x7b\\x08\\x57\\x99\\x59\\x3f\\xc6\\x8d\\x7d\\x92\\x5d\\xe9\\xa6\\xad\\xf6\\x77\\x1a\\xab\\xb5\\x21\\x2a\\xe7\\xd2\\x83\\x94\\x94\\x66\\x40\\x14\\x85\\x9c\\xb8\\xd0\\xae\\x75\\x52\\x17\\x05\\xb2\\x84\\x51\\x8c\\x0d\\xe2\\x90\\xd1\\xc1\\x8b\\x89\\xe1\\x15\\x87\\xd6\\xe4\\x7e\\x56\\xf6\\xc6\\xb6\\xec\\xe4\\xee\\x5a\\x54\\xaa\\xd9\\x43\\x7a\\x64\\x98\\x86\\x92\\x36\\xcb\\x5c\\xb4\\x3e\\xc7\\x70\\xa8\\x99\\x59\\x06\\xba\\x62\\x0b\\x02\\x28\\xdd\\x13\\xa9\\xec\\xb6\\x55\\xed\\x2d\\xc8\\x4c\\x06\\xb3\\x7e\\x50\\x6b\\xa6\\x46\\xf8\\xf8\\x67\\xbe\\xd2\\x5d\\xb4\\x42\\x78\\xff\\x73\\x36\\xd9\\x8e\\x75\\x3e\\x67\\x93\\x55\\xcb\\xec\\x3e\\x86\\x16\\xb1\\xa1\\xd8\\xc1\\x2a\\x9d\\xb5\\x99\\x61\\x41\\x1e\\x36\\xf1\\x46\\x8d\\x7c\\xe5\\xba\\x23\\xae\\xfb\\x33\\x5f\\xe8\\x4e\\xf8\\xd6\\x7d\\x34\\xea\\x10\\x1d\\xec\\x07\\xd2\\x73\\x53\\x83\\x38\\x02\\xe1\\x38\\xa3\\x63\\xf7\\x87\\x35\\x83\\xa1\\x72\\xce\\xd4\\x9c\\xb3\\xeb\\x83\\x6b\\xa9\\xae\\xb8\\x98\\x0e\\xaf\\xb9\\x99\\x0d\\x71\\x8d\\xf4\\x81\\x9d\\x2a\\x7d\\xf0\\x1b\\xf8\\xa7\\x13\\x55\\x98\\x4a\\x74\\x98\\xe7\\x2e\\xf9\\xbe\\xd6\\x6c\\x52\\x17\\x98\\xb0\\xae\\x47\\x84\\x56\\xfc\\x7b\\xa6\\x34\\x14\\x6b\\x5f\\x71\\x91\\x0f\\x48\\xcd\\xf3\\xbf\\x76\\x18\\xb1\\x87\\x1e\\x18\\xfd\\xa2\\x97\\xdb\\xcb\\x0a\\xeb\\x4d\\x8b\\x28\\x4b\\x83\\x15\\x25\\x32\\x56\\x0a\\x95\\x3f\\x7e\\x14\\xcd\\xa5\\xc6\\x7b\\xec\\x9a\\xb7\\x84\\x0f\\xcd\\xcb\\x44\\x44\\x54\\xb2\\x35\\xb2\\x27\\xd5\\x26\\xe7\\x22\\x4f\\x5b\\xba\\x3e\\x96\\x0d\\x47\\x6f\\x9b\\xf2\\xee\\x33\\x97\\xe4\\x14\\x52\\x8e\\xa9\\x77\\xae\\x02\\x88\\xa5\\x4f\\x24\\x6e\\xe7\\x11\\xf7\\x96\\x2b\\xbc\\xbc\\x7e\\xe5\\x42\\xff\\x5c\\x0c\\x91\\xb2\\x61\\x95\\x37\\x0b\\xf8\\xfc\\x3c\\x08\\x2f\\x49\\xc1\\x77\\x26\\x05\\x3f\\xef\\xf8\\xe7\\x16\\xa7\\xfa\\x3e\\xe6\\x96\\x22\\x9f\\xa5\\x09\\xfe\\x59\\x45\\x0e\\x36\\xc8\\x13\\xdd\\x0d\\xed\\x6d\\xb3\\xbf\\x1a\\x0d\\xa7\\x92\\x80\\xd6\\xe3\\xba\\xbb\\x81\\x79\\x85\\x27\\x8b\\x0f\\x79\\x40\\xe5\\x2b\\x55\\xb4\\x64\\x86\\xa9\\x06\\x8c\\x39\\x93\\x42\\x74\\x69\\x8e\\x68\\x24\\xf9\\x58\\x31\\x71\\x61\\x68\\x76\\xb5\\xc1\\x9e\\x40\\x2f\\x36\\xd3\\x7d\\xd7\\x8b\\xcd\\x44\\xb6\\xd5\\x66\\xda\\xba\\x6c\\x67\\x2f\\x1c\\x10\\x45\\xc9\\x55\\x31\\x34\\x25\\xa1\\x28\\x97\\x9f\\xe1\\x01\\x90\\x6a\\x1a\\x49\\x31\\xe1\\xd3\\x0f\\xb4\\xea\\x1e\\xb1\\xf4\\x4f\\x5a\\xb2\\x74\\xc2\\xc7\\x2e\\x48\\x09\\xd8\\x16\\x95\\xac\\xa0\\x99\\x93\\x03\\x49\\x83\\xe9\\x7f\\x7a\\x33\\xa3\\xab\\x64\\x75\\xca\\x4b\\x6f\\x89\\xbe\\x1d\\xf8\\x3b\\x22\\xa5\\x7d\\x78\\x96\\xf6\\x93\\x31\\x37\\xcd\\xb1\\xa8\\x99\\xc1\\xc6\\x31\\xae\\xf5\\xb4\\x14\\x24\\x73\\x48\\xc0\\xa0\\xcc\\x47\\x80\\xb0\\x3d\\x18\\x08\\x82\\xc8\\xcc\\x78\\xac\\xb2\\xd0\\x67\\xe6\\xd5\\xab\\x57\\xaf\\xb0\\xc9\\xc0\\x1f\\xff\\xf8\\x47\\x22\\x15\\xa1\\x24\\x67\\x19\\x2f\\x6f\\xde\\x08\\x77\\xfd\\xfe\\x75\\x22\\x0e\\xb7\\xbd\\xfe\\xf3\\xf0\\xc3\\x7b\\x28\\xec\\xae\\x8c\\xc6\\x5e\\x5e\\x48\\x91\\x7d\\x70\\x6b\\x50\\x3d\\x20\\xff\\xef\\xe2\\xe3\\x69\\x83\\xaf\\xdb\\xfe\\x16\\x7c\\xba\\x61\\x3a\\xd3\\xe9\\x89\\x03\\x4d\\xaf\\xfe\\xf0\\xbb\\xdf\\x75\\x78\\x12\\x57\\x00\\x87\\xc2\\x1d\\x5a\\xa3\\xaf\\x51\\xa7\\x66\\x06\\x59\\x90\\xd0\\xbc\\x01\\x30\\xe4\\xbd\\x39\\x86\\x08\\x22\\x26\\x19\\x47\\x9e\\x78\\x7c\\xc1\\x92\\x4f\\x67\\xc6\\xe1\\xcc\\xd9\\x2d\\x5e\\xf0\\xcc\\x20\\xca\\x0b\\x1e\\x76\\xd2\\x81\\x51\\xc2\\xa6\\x47\\x1a\\x82\\x29\\xda\\x21\\x2a\\x9e\\xb3\\x01\\x29\\xf8\\x15\\x23\\x13\\xfd\\x8d\\x92\\x75\\xd5\\xb4\\x7c\\x44\\x70\\x7b\\x0f\\x9e\\x80\\x44\\x34\\xbc\\x9f\\xdc\\x31\\x6d\\x5b\\xca\\xc0\\x3a\\x85\\xb5\\xfb\\x12\\x32\\x40\\xc4\\x92\\xfd\\xec\\xa0\\xd3\\x9a\\x16\\x82\\x15\\xe5\\x01\\x2d\\x01\\x4a\\x55\\x10\\xb8\\xba\\xad\\xf0\\x65\\x89\\x88\\x34\\xf6\\x7a\\x1b\\x4e\\x14\\x0f\\xf4\\x5d\\x29\\xf9\\x4f\\x64\\x72\\xc0\\x08\\x8c\\x4e\\x74\\xc0\\xd6\\xb3\\x3c\\xe7\\x91\\xf5\\x9a\\x6c\\xa1\\xe4\\xf1\\x7d\\x03\\x77\\x6b\\x7c\\xb8\\xb6\\xf2\\xa1\\xe7\\x28\\xc0\\xe0\\x45\\x73\\x03\\xdd\\xbf\\xb9\\xb6\\xa4\\x41\\xeb\\x08\\x47\\x71\\xf2\\xd8\\x2b\\xde\\x34\\x8c\\x06\\xfb\\x5e\\xe3\\x8e\\xa8\\xc5\\x8d\\x51\\x11\\x71\\xbd\\xc3\\xc8\\x70\\xa4\\xc3\\x0b\\x52\\xdf\\x2f\\xb1\\x19\\x1b\\xf1\\x5f\\x5d\\x37\\x02\\x77\\xaf\\xe7\\x82\\xb0\\x60\\xe9\\x0d\\x93\\xa3\\x25\\xd5\\xcc\\xd4\\x6e\\xe9\\xa1\\x90\\xd9\\xbe\\x2b\\xd3\\xda\\x35\\xe2\\x29\\xa9\\xba\\x62\\x79\\x38\\xff\\x46\\xe4\\xcc\\x4e\\x8a\\x6f\\x84\\xd0\\xc1\\x5f\\x51\\x50\\xc3\\xe7\\x98\\x40\\x57\\xd2\\x05\\xbc\\xa6\\xb3\\x3e\\x81\\xb8\\xdd\\xd1\\x68\\x17\\x05\\xaf\\x54\\x44\\x1b\\xaa\\x9c\\x34\\xb4\\x9f\\x77\\x93\\x3c\\x1b\\x4c\\x86\\x69\\xc9\\x8d\\x0f\\xb4\\xd2\\xd8\\x74\\xda\\x9a\\xdb\\xd0\\xcc\\x5e\\x02\\x6e\\xa6\\x99\\xf9\\xc3\\x87\\xba\\x35\\x4a\\x3f\\x5b\\x7a\\x30\\x97\\xbb\\x7a\\x8f\\xf1\\x1a\\x26\\x43\\xb4\\xfa\\xdf\\xdb\\x89\\xe9\\xb2\\xcf\\x3b\\xdb\\xfc\\x20\\xa9\\x7a\\xec\\xff\\x7e\\xd5\\x06\\xbd\\x35\\xd2\\x4b\\xa3\\xad\\x68\\x77\\x5f\\x76\\x50\\xc2\\xf1\\xea\\xb7\\xd9\\x7d\\xe9\\x34\\xf1\\x8f\\xeb\\x69\\xe2\\xa0\\xa2\\xd9\\x03\\xab\\xdb\\xa4\\x6e\\x95\\x02\\x8e\\xd7\\xb6\\xa9\\xe1\\x78\\x9d\\x4c\\x40\\x94\\x2f\\x1d\\xd9\\xee\\xa8\\x89\\x8d\\x2a\\xaf\\x6b\\xd8\\xb5\\xeb\\x3a\\xe8\\xe6\\x34\\x68\\xbc\\x36\\xa2\\x47\\xe3\\xd5\\x87\\x36\\x8d\\x57\\x77\\x9d\\x1a\\xaf\\x2e\\x09\\x9b\\x78\\xf5\\x2b\\x38\\x7c\\xda\\x27\\x2e\\x86\\x53\\x3b\\x50\\xb3\\x98\\x04\\x06\\x80\\x10\\x1e\\xf8\\x54\\xbc\\x30\\xee\\x2c\\x2f\\x9c\\x52\\x83\\x22\\x83\\x8e\\xb5\\x2c\\x6a\\x83\\x03\\xf7\\xf5\\xe8\\x58\\x5f\\x82\\x17\\x62\\x05\\x80\\x5a\\x77\\x52\\x92\\x96\\x07\\x89\\x74\\x2f\\xd0\\x8e\\x51\\x5d\\xe9\\x3e\\x42\\xe7\\x63\\xaa\\x8b\\x0b\\xbe\\x2f\\x0e\\xeb\\xd7\\xf5\\xbe\\x7d\\x6e\\xf7\\xa7\\x74\\xb9\\x77\\x66\\x88\\xe0\\xa3\\xeb\\x83\\x29\\xfc\\xc3\\x02\\x38\\xcf\\xf5\\x8c\\xb9\\x94\\xf0\\xc8\\x00\\xb3\\x07\\xbd\\x15\\xe3\\x60\\x15\\xfa\\xe6\\x70\\x88\\x4c\\xbf\\xa9\\xf0\\x63\\xbf\\x21\\x87\\x4c\\xf3\\xee\\x8e\\x6c\\xcd\\xc9\\xde\\xdb\\x00\\xfc\\xe8\\xeb\\xa8\\x4e\\x84\\x61\\x6a\\x42\\x33\\xb6\\x1f\\x3b\\xb8\\x59\\x35\\x63\\x25\\x53\\x76\\xe2\\xdd\\x7d\\x1e\\x47\\x70\\x46\\x45\\xee\\x3a\\x6c\\x64\\x4c\\x81\\xe0\\x63\\x9f\\x0c\\x53\\x76\\x91\\xde\\x5e\\x9c\\x90\\x5c\\xf1\\x39\\x53\\x9a\\xec\\x7d\\x0d\\xdd\\xbd\\xb0\\xb3\\x46\\x87\\x0e\\x5c\\x9b\\xc3\\xe9\\x80\\x17\\xd9\\x84\\xfb\\x1d\\x06\\xde\\xb4\\x4c\\x45\\x2a\\xfc\\x89\\x2d\\x22\\x09\\xdb\\xac\\xb2\\xef\\x05\\x62\\x39\\x42\\xc7\\x31\\x8f\\x74\\xe1\\xfb\\x56\\x0a\\x50\\xd4\\xe0\\xa4\\x5b\\xc8\\x5a\\x61\\x82\\x9f\\x03\\x12\\x67\\x24\\x93\\x4a\\x59\\x95\\x11\\x08\\xa2\\x9a\\x28\\x36\\xe5\\xda\\x00\\xe2\\xb9\\xef\\x72\\x85\\xa8\\xc9\\x1b\\x83\\x01\\xd8\\xaa\\x4c\\xa9\\x90\\x12\\x75\\x07\\xc0\\x42\\xf2\\x18\\xce\\xc8\\xa8\\x94\\x9c\\xf3\\xdc\\xdb\\x18\\x90\\x0c\\xde\\xf4\\x07\\xaa\\xa8\\x8e\\x30\\x41\\xa9\\xd6\\x32\\xe3\\x10\\x93\\x69\\xb8\\x28\\x79\\x7c\\x74\\xce\\x81\\x05\\x93\\x33\\x63\\x0d\\x4e\\xc1\\x5a\\x48\\x72\\x71\\x12\\x97\\x24\\xb4\\xaa\\x8a\\xe4\\x34\\xf5\\xee\\x7a\\x92\\xcc\\xd9\\x59\\x3d\\x2e\\xb8\\x9e\\x5d\\x6c\\x4b\\x62\\xca\\x2a\\x9a\\xb0\\x08\\xef\\x46\\x39\\xc0\\x6d\\x09\\x2a\\x1d\\x92\\x62\\x84\\xe6\\x60\\x04\\x58\\x55\\xcb\\xda\\x3c\\x5c\\x0a\\xf0\\xbe\\x50\\xad\\xfd\\xa8\\xb1\\xa8\\x91\\x00\\xe1\\x58\\x30\\xc3\\xfc\\x57\\xe9\\xfa\\x62\\xf3\\xde\\x0e\\x4f\\xd9\\x9a\\x89\\xf6\\xd3\\xef\\x44\\xd5\\xfa\\x3c\\xa3\\x45\\xd1\\xc1\\x18\\xbf\\x44\\xb7\\x07\\x2b\\xf2\\x38\\x7a\\x89\\x56\\xa9\\xc7\\x66\\xc6\\x0d\\xc3\\xed\\x5e\\xf2\\xb3\\x0c\\xf5\\x18\\x78\\x7a\\x8d\\xb0\\xe5\\x56\\xba\\x69\\xbc\\x72\\xe1\\x74\\xd4\\xa2\\x58\\x0a\\xbf\\xba\\x03\\x42\\x8b\\xc2\\xff\\x20\\x70\\x00\\x22\\x8f\\xe0\\x3e\\x7e\\x49\\x17\\x7a\\x49\\x17\\x5a\\xf3\\x7a\\x49\\x17\\xda\\xc6\\xfc\\x54\\xef\\x18\\x44\\x59\\x4f\\xf3\\x21\\xa0\\xfa\\x60\\x52\\x4b\\x8d\\xfd\\x09\\x83\\xca\\xd5\\x55\\xa5\\xbb\\xa7\\x02\\x75\\x63\\xf9\\xa1\\xf8\\x5e\\x87\\xc6\\x28\\x3e\\xae\\x4d\\xba\\x5c\\xe9\\x37\\x97\\xab\\xa1\\x07\\x4c\\x2f\\xa6\\xdd\\x01\\x38\\x74\\x4b\\x96\\x45\\x92\\xd0\\x39\\x51\\x83\\x78\\x8e\\x8e\\xcd\\x8e\\x7a\\xff\\x28\\x28\\xe2\\xa0\\x83\\xe3\\x87\\xbb\\x9a\\xe4\\x32\\xab\\x4b\\x26\\x4c\\xc3\\x21\\x4d\\x62\\x3c\\xfa\\xb1\\x37\\x78\\x44\\xd0\\x3c\\xe7\\x78\\xc2\\x9e\\xf5\\x70\\x58\\x74\\x12\\x24\\xb9\\xbc\\x16\\xd7\\x54\\xe5\\x87\\x67\\x49\\x28\\x79\\x6d\\x84\\xbc\\xe6\\x59\\xb1\\x89\\xee\\x3f\\x26\\xf6\\x73\\x3a\\x86\\x96\\xa6\\xae\\x27\\xd6\\x4b\\x4a\\xda\\xca\\x47\\xf4\\xb3\\x4d\\x57\\x45\\xbe\\x8c\\xb4\\xe7\\xda\\x9d\\x29\\x67\\x4d\\xe4\\xaa\\xd7\\x91\\x5f\\xb2\\xdf\\xb6\\x23\\xec\\xf6\\x92\\xfd\\x96\\x3a\\xf2\\x4b\\xf6\\x5b\\xda\\xf0\\x2d\\x79\\x76\\x82\\x29\\x6c\\x56\\x9d\\x2b\\x5c\\xf3\\xa5\\xd6\\xf9\\xe0\\x22\\xbf\\x1d\\x16\\x6a\\xbb\\xb2\\x76\\x8e\\x9a\\x33\\x11\\x2d\\xf5\\x65\\xf0\\xbf\\x25\\xa7\\x02\\xca\\xc2\\x26\\xce\\x18\\x55\\xd8\\xf8\\x43\\x13\\x2c\\x92\\xcf\\x21\\xc3\\x67\\x0b\\x32\\x74\\x60\\x2e\\x3b\\x38\\xb8\\xf0\\x6a\\xe3\\x06\\x35\\x78\\x51\\xd8\\x2e\\x11\\x53\\x20\\xa3\\x1c\\xcc\\x4a\\xe6\\x6f\\xb0\\x43\\x20\\x15\\x42\\xa2\\x8a\\xaa\\x07\\xae\\x7b\\xf5\\xc0\\x79\\x8c\\x45\\x0e\\xff\\xa1\\x2b\\x9a\\x31\\x10\\xa7\\x41\\x7f\\x4d\\x06\\x93\\xc6\\xab\\x17\\x06\\x20\\x3d\\x31\\x01\\x01\\x46\\x80\\xd9\\x39\\xeb\\xc2\\x0d\\xa4\\x37\\x8e\\xb0\\x57\\x63\\xeb\\x77\\x7d\\xd2\\x72\\x53\\x34\\x7c\\xaa\\x67\\x04\\x9d\\xcd\\x58\\x49\\xe1\\x3f\\xdf\\xf9\\x29\\xb0\\xb2\\xd1\\x1a\\x9c\\x86\\x61\\x5b\\x13\\xa6\\x4a\\x4d\\xe4\\x64\\xd0\\xaa\\xd4\\xdc\\x99\\x77\\xe9\\xf4\\xe1\\xaf\\x9e\\x32\\xbf\\x88\\xdf\\x47\\x67\\x9d\\x33\\x39\\xc8\\xf2\\x84\\x9d\\xb5\\xf2\\x2e\\xec\\x1e\\x02\\x15\\xd2\\x6e\\xab\\xd0\\x61\\x3d\\xe4\\xc0\\xc2\\xf9\\x81\\x33\\xbc\\x45\\x93\\xd3\\xbf\\x93\\x06\\xaf\\x6d\\x4b\\xb8\\x4b\\x4d\\xb4\\x1b\\x84\\x40\\x78\\x5b\\x5b\\xef\\x48\\xce\\x4b\\xa2\\x5d\\xfb\\x7a\\x49\\xb4\\x7b\\x49\\xb4\\xeb\\x35\\xd1\\x2e\\xd2\\x73\\xfc\\xb9\\xb5\\x22\\x67\\x2e\\x8e\\xc7\\xfb\\xc4\\xb9\\x31\\xf3\\x26\\xbf\\x73\\x36\\xf8\\xbc\\x37\\x9f\\xf4\\x26\\x55\\x3b\\xb7\\x7f\\x77\\x34\\xda\\xc5\\xec\\xfe\\xc6\\x3b\\x51\\x9b\\xc9\\xf0\\x4f\\x84\\x89\\x4c\\xe6\\xf6\\x39\\x97\\xf0\\x7c\\xa5\\x0d\\x68\\xef\\x4d\\xbc\\x22\\xa6\\xa5\\xf4\\x63\\xc5\\xf5\\x01\\xf0\\xec\\x3e\\x34\\xaa\\xce\\x47\\x85\\xef\\xf1\\xf3\\xae\\x7f\\x9d\\xb4\\xb3\\x70\\x6f\\x34\\xd9\\xd0\\x89\\xc8\\x4d\\x71\\xe8\\xd0\\xea\\x54\\x5a\\xff\\xbd\\x26\\x05\\x2f\\x39\\xa0\\x9b\\xe7\\x20\\xe1\\x98\\x36\\xdd\\x02\\x34\\x84\\xec\\xe1\\x23\\x47\\x59\\x55\\x0f\\xdc\\xe3\\x47\\x25\\x2b\\xa5\\x5a\\x0c\\xc2\\x10\\xf6\\xcb\\xd6\\x98\\xee\\x8e\\x7d\\x50\\xa2\\xb3\\x5a\\x29\\x26\\x4c\\xb1\\x88\\xd4\\xe9\\xcf\\x4d\\x9b\\xf6\\x2b\\xb0\\x25\\xca\\x74\\x60\\x90\\x2e\\xb8\\xd3\\xcd\\xd5\\x96\\x41\\x4d\\x9a\\x18\\x84\\x4c\\xa3\\x56\\xde\\xa1\\x7b\\x9e\\x1e\\x34\\xc9\\x79\\xf6\\x53\\x26\\xe6\\x64\\x4e\\x95\\xee\\xb6\\xe7\\x49\\xbf\\xfa\\x73\\xce\\xe7\\x5c\\xcb\\xe4\\x5c\\xaa\\xe8\\x41\\xf1\\xf4\\x5c\\x84\\xe0\\x99\\xdd\\xa9\\xb2\\x36\\x55\\x6d\\xdc\\x71\\xe2\\xb7\\xaf\\xef\\x85\\x1b\\xb6\\xed\\x92\\xa1\\xf1\\x7a\\xa7\\x33\\x49\\x15\\x35\\x86\\x29\\xf1\\x86\\xfc\\xd7\\xde\\x4f\\xbf\\xfd\\x65\\xb8\\xff\\xd7\\xbd\\xbd\\x1f\\x5f\\x0d\\xff\\xfd\\xef\\xbf\\xdd\\xfb\\x69\\x04\\xff\\xf1\\xc5\\xfe\\x5f\\xf7\\x7f\\xf1\\x7f\\xfc\\x76\\x7f\\x7f\\x6f\\xef\\xc7\\x6f\\x3f\\x7c\\x73\\x79\\x76\\xfc\\x77\\xbe\\xff\\xcb\\x8f\\xa2\\x2e\\xaf\\xf0\\xaf\\x5f\\xf6\\x7e\\x64\\xc7\\x7f\\x7f\\xe0\\x43\\xf6\\xf7\\xff\\xfa\\x6f\\x9d\\x49\\xa7\\x62\\xf1\\xb1\\xa3\\x1c\\xc6\\x6b\\xd8\\xa3\\x3e\\xd0\\x7e\\x62\\x2f\\xec\\xb7\\x64\\xa5\\x70\\x61\\x86\\x52\\x0d\\xf1\\xd1\\x6f\\xa0\\xd7\\x60\\xc7\\x01\\x3c\\x7b\\xf5\\xbd\\xff\\x1b\\x1d\\xa4\\xe9\\x23\\xed\\x0d\\xc4\\x2d\\xda\\xe0\\xfd\\xda\\x80\\x90\\x88\\x73\\xc4\\x37\\x06\\xa8\\xe7\\xc7\\x6f\\x03\\x4d\\x18\\x56\\x56\\x52\\x51\\xb5\\x20\\xb9\\x0b\\x0c\\x2c\\xee\\xc4\\xc5\\xdf\\x48\\xcf\\x6d\\x20\\x3d\\xe7\\x29\\x1b\\x70\\xc3\\x81\\xc5\\x92\\xe5\\xbc\\x2e\\x37\\x1d\\x53\\x44\\x2a\\xe2\\x85\\xbf\\x86\\xb6\\xd3\\xae\\xd5\\xb5\\xcf\\xc1\\x76\\xb7\\xb9\\xc8\\xee\\x98\\x66\\x57\\x68\\xef\\x07\\xce\\xe8\\x12\\xff\\x69\\x35\\xe0\\xdd\\xd9\\x71\\xd9\\x95\\x25\\xa3\\x22\\xc4\\x37\\x21\\x13\\x58\\xe6\\x6c\\x57\\x87\\x7b\\x91\\xa4\\x5e\\x42\\x8a\\x98\\x08\\xe7\\x2a\\x5b\\xf6\\xdc\\x00\\xfb\\xd6\\x6a\\xf9\\x00\\xaa\\xe6\\xc6\\x3a\\x71\\x76\\xe0\\x6e\\xd2\\x0b\\x90\\x34\\xff\\x17\\x7b\\x6f\\xd5\\xf2\\x4d\\xb3\\x69\\x20\\xc4\\xa7\\x85\\x1b\\x09\\x1e\\x18\\xd7\\xb9\\x63\\x42\\x0a\\x99\\x45\\x25\\x03\\x2d\\xad\\x11\\x18\\xf5\\xd8\\x8b\\xb8\\xae\\x39\\x45\\x96\\x5d\\x2d\\x35\\x68\\xae\\x40\\xe0\\xab\\xd0\\x98\\xe2\\xcb\\x33\\x3a\\x2e\\x18\\x7a\\x79\\x80\\x6f\\x3a\\xf3\\xe8\\x25\\x74\\x0b\\xff\\xc4\\xcb\\xba\\x24\\xb5\\xb6\\x6f\\x26\\x45\\xfb\\xd9\\xcd\\x8b\\x5d\\xe3\\xd6\\xc4\\xbd\\x52\\x72\\x01\\x3f\\x6a\\x79\\xc4\\xd2\\x43\\x4c\\x33\\x46\\x2e\\xc2\\x0a\\x34\\xfe\\x59\\x80\\x10\\xf4\\xee\\x17\\x5d\\x83\\x95\\xee\\xa8\\x73\\xb6\\xa2\\x9c\\x40\\x66\\x67\\x30\\x19\\xa0\\x49\\x3a\\x4d\\x6d\\x71\\xd5\\x4c\\x4a\\x24\\x30\\x04\\x2f\\xda\\x12\\xc3\\xb7\\xcd\\x0f\\x0b\\x54\\x0b\\x57\\x91\\xf3\\x5c\\xf7\\xf1\\xb3\\x53\\xb8\\x3b\\xaa\\xd9\\x7d\\x29\\xd7\\xbd\\xa8\\xd4\\xbd\\x2b\\xd2\\xa1\\xc2\\x69\\x63\\xea\\x5e\\x28\\xb1\\x6a\\xe9\\x7b\\x71\\xb3\\xfd\\x76\\xb9\\x15\\xf5\\xa5\\x2d\\x41\\xc0\\xba\\x5c\\xbd\\xa4\\xe1\\x2f\\x83\\x9b\\xda\\x29\\x8f\\xd9\\x22\\x73\\x0d\\x1f\\x78\\x93\\x49\\x18\\xb2\\xc9\\x70\\xef\\x02\\x1c\\xc9\\xd0\\xfe\\x9f\\x77\\x67\\xfb\\x24\\xa3\\x31\\x9b\\x60\\x46\\x39\\xfe\\x06\\x5c\\x81\\x3a\\x0d\\x18\\x05\\x1d\\xfa\\x05\\x33\\x80\\xbf\\xc2\\x44\\x78\\x28\\xa4\\xc5\\x97\\x72\\x6e\\x45\\xc8\\xff\\x49\\x7a\\xf4\\x77\\xda\\xe5\\xc1\\xf1\\xc4\\x7d\\x41\\xf7\\x5b\\xc0\\x7a\\x1a\\x9d\\x73\\x82\\xb1\\x1c\\xc1\\x62\\x8a\\x66\\x0a\\x54\\x2d\\x12\\x27\\x60\\xbc\\xef\\xeb\\xe6\\x40\\x74\\x0b\\xa9\\x20\\x7a\\x81\\x52\\x0c\\xdd\\xee\\x8a\\x59\\x1e\\x80\\x4e\\x1c\\x4a\\x96\\x44\\x0b\\x5a\\xe9\\x99\\x34\\xe0\\xe2\\xa5\\x15\\xcd\\xb8\\x49\\x46\\xf9\\x30\\x8a\\x66\\x57\\xf6\\xc9\\x90\\x6c\\x04\\x6f\\x96\\xf6\\x1a\\xd9\\xbe\\x2b\\x55\\x8e\\x99\\xb5\\x0d\\xaf\\x63\\x66\\x4a\\xd6\\xd3\\x19\\xe0\\xaf\\xe0\\x5d\\x59\\x41\\x35\\x82\\xfd\\xa4\\xe5\\x09\\xae\\x1c\\xd3\\x39\\x25\\x35\\xc9\\x17\\x82\\x96\\x3c\\xf3\\xeb\\x07\\x95\\x4b\\x9a\\x4b\\x97\\x07\\x02\\xb4\\xa4\\x4e\\x1b\\x25\\x67\\xa1\\xb9\\x3c\\xa6\\xa4\\xbc\\x2d\\x28\\x2f\\xc9\\x9e\\x66\\x8c\\x1c\\xfb\\xbd\\x8e\\xdf\\x5c\\xa0\\x49\\x8d\\x81\\xa8\\xe4\\xae\\xee\\xad\\x1c\\x17\\xd7\\x36\\xcd\\x61\\xc3\\xda\\x4f\\x7c\\x00\\x2e\\xca\\xfb\\x04\\x41\\x9c\\xfc\\x82\\x22\\x5f\\xfd\\x8a\\xfb\\x5d\\x76\\xe3\\xea\\x49\\x93\\x0a\\xca\\x52\\x9c\\x33\\x6d\\xce\\x44\\x2e\\x9b\\x04\\xe8\\xa4\\xb1\\x0e\\xcf\\x4e\\x74\\xec\\xbd\\x44\\xa9\\x56\\xe1\\xe8\\xf0\\x45\\x21\\xc5\\x34\\xee\\x35\\x15\\x64\\x62\\xd2\\x78\\x56\\xe5\\x12\\x84\\x8b\\x9c\\xcf\\x79\\x5e\\xd3\\x02\\x95\\xad\\xf4\\x79\\x7a\\x7b\\x71\\x82\\x54\\xf2\\xe9\\xcc\\x0c\\xaf\\x19\\x04\\xff\\x50\\xdd\\x6e\\x0e\\x12\\xff\\x6e\\xfc\\x46\\xa1\\x26\\xd7\\xa0\\x97\\x19\\x62\\x64\\x9a\\x48\\x62\\x2e\\xe8\\x6c\\x67\\xed\\x9a\\x2e\\xa0\\xd5\\xa8\\x2b\\xb6\\x6b\\xa5\\x84\\xfb\\xb6\\xe5\\x38\\xec\\x44\\xa6\\xa9\\x0d\\xa5\\x57\\xf4\\x1c\\x7b\\xa7\\xce\\xdc\\x21\\x48\\xe2\\x8c\\x0a\\x30\\x5f\\x21\\x68\\x6c\\xb7\\x00\\x88\\xd5\\x9b\\xd3\\x96\\x2a\\x74\\xaa\\xc0\\xc3\\xcd\\xa3\\x50\\xf9\\xd5\\xd4\\x6e\\xba\\x44\\xaf\\xcc\\x86\\x3d\\x23\\xf3\\x66\\x3f\\x5e\\xb2\\xb2\\x2a\\xa8\\xd9\\x78\\xea\\xf5\\x0f\\x51\\x0c\\x3d\\xca\\xea\\xb3\\xa7\\x07\\x15\\xf9\\x90\\x16\\x56\\x68\\x9c\\x7d\\xff\\xd6\\x81\\x38\\xa1\\x6c\\xef\\xa5\\x86\\xe5\\xd2\\xab\\x20\\xc2\\x59\\x39\\x68\\xce\\xae\\x14\\xeb\\xd0\\x11\\x69\\xcc\\x72\\x50\\x09\\x1c\\xc5\\x5d\\x2a\\xf8\\xe4\\xb5\\x60\\xca\\x6f\\xac\\xb3\\xef\\xdf\\x0e\\x08\\x1f\\xb1\\x91\\xff\\x2b\\x0c\\xe1\\x55\\x26\\x23\\xa7\\x08\\x91\\xe0\\xc1\\x42\\xd2\\x73\\x01\\x65\\x3e\\xc2\\x57\\x8f\\xc3\\xcd\\xf1\\x98\\xff\\xf8\\xb3\\x9d\\x14\\xfb\\xed\\x5f\\x86\\x7f\\x76\\x67\\x0c\\xfc\\xf5\\x0f\\xab\\xb9\\xa5\\x9f\\x6c\\xe4\\x1f\\x4b\\x4f\\x8b\\xcb\\xd0\\x41\\xe3\\xb1\\x7f\\xfd\\xe3\\x4c\\xe6\\x17\\x15\\xcb\\x46\\x38\\xfd\\xfa\\x1f\\x9d\\xd2\\x53\\x09\\x61\\xc2\\xa8\\xc5\\x88\\x9c\\x49\\xa8\\x65\\xe1\\x39\\x4a\\x34\\x78\\x57\\xc5\\xfe\\xe9\\xf3\\x27\\x80\\x0d\\x42\\x90\\x36\\xa3\\x86\\x09\\xd0\\x80\\x45\\x7a\\x67\\x56\\xe2\\x11\\x06\\x61\\x58\\x90\\xf3\\x14\\xe6\\x79\\x0f\\x22\\x6b\\x08\\xb4\\x3c\\x20\\x46\\x4a\\x38\\xa5\\x92\\x0f\\x5c\\x7b\\x1d\\x0a\\xc2\\x3e\\x71\\x0d\\xfd\\x01\\x70\\x29\\x81\\x4b\\xa8\\x2b\\xa9\\xf7\\x76\\x87\\xa5\\xc6\\x32\\x5e\\xe8\\x77\\x51\\xc9\\xf4\\xe4\\x58\\x98\\xc2\\x2f\\x84\\x34\\x5f\\x84\\xdd\\xeb\\x8b\\xcb\\xc0\\xc0\\x90\\x84\\xce\\x25\\xcf\\x49\\xad\\x41\\xef\\x14\\xa4\\x16\\x90\\x62\\xd0\\x01\\x4d\\xd3\\xb1\\xcf\\x78\\x41\\x4a\\xae\\x0d\\xbd\\x62\\x23\\x72\\x61\\x6d\\x92\\x38\\xe3\\x17\\x99\\x4a\\x90\\x71\\x21\\xb3\\x2b\\x96\\x93\\x5a\\x18\\x5e\\x74\\x72\\xcf\\x04\\xba\\x61\\x6a\\x23\\x7b\\x05\\xf0\\x33\\xeb\\xcc\\x6a\\xba\\x95\\x62\\x43\\x6f\\x35\\xe1\\x5d\\x1d\\xdc\\xc6\\x78\\xa4\\x87\\x59\\x6d\\xd6\\x6a\\x10\\xf6\\xea\\x8c\\xa2\\xff\\xb6\\xca\\x61\\x48\\x58\\xef\\xc4\\x8a\\x39\\x12\\xa4\\xd1\\x8d\\xfa\\x70\\x3b\\x9f\\x12\\xfe\\x76\\x7f\\x00\\x93\\xe9\\x11\\x39\\x05\\xeb\\xa5\\x48\\xdf\\x95\\x58\\xdf\\x80\\x2e\\x6f\\x97\\xd1\\x22\\x58\\xc6\\xb4\\xa6\\x6a\\x31\\x20\\xe3\\xda\\x58\\x73\\xd4\\xd5\\x52\\xbb\\xe2\\x52\\x6b\\x35\\xa6\\x4f\\x2a\\x15\\xb5\\x25\\x98\\x28\\x96\\x49\\xa1\\x8d\\xaa\\x33\\xe0\\x1a\\x4a\\xc6\\x4a\\x5e\\x31\\xd1\\x00\\x4c\\xa4\\x6f\\xc2\\x76\\x5d\\x78\\x53\\x80\\x09\\xe9\\xc9\\x92\\x64\\x33\\x2a\\xa6\\x2c\\xc0\\xaa\\x92\\x92\\xe6\\xc0\\xca\\xdf\\x06\\x17\\x48\\xfa\\x6c\\xca\\xc0\\x18\\x74\\x62\\xac\\x66\\x68\\x80\\x43\\xc6\\xd6\\x54\\xf0\\xe9\\x43\\x1d\\xde\\xcc\\x47\\x0e\\x07\\x4d\\x5a\\x90\\x5d\\x30\\x5e\\x6c\\xb0\\x2e\\xb0\\x7b\\x0e\\xc8\\x10\\x6c\\xd6\\x54\\xbf\\x61\\x0f\\x39\\x1f\\x25\\x33\\x34\\xa7\\x86\\x6e\\x4b\\xf5\\xfa\\x07\\xba\\x08\\xb9\\x64\\x98\\x60\\x0f\\xbc\\x1b\\x25\\xde\\x3b\\x53\\xc1\\xbb\\x89\\x64\\xc5\\x63\\x74\\xdf\\xb3\\xef\\xdf\\x76\\x1a\\x1f\\xfc\\x42\\xc0\\xae\\xd0\\xe7\\xc6\\x58\\x39\\xe3\\x92\\x0d\\xb1\\xb2\\x1c\\xbc\\x17\\xb4\\x28\\xe4\\xb5\\xeb\\x3f\\xe6\\x29\\xc1\\x93\\x9c\\xe5\\x24\\xaf\\x3b\\xc7\\x9f\\x1b\\x2d\\xa1\\x4b\\xb6\\x53\\x2f\\xb9\\x4e\\x96\\x3f\\xb7\\x85\\x39\\x2e\\x9b\\xf4\\xf1\\xac\\x5d\\x4a\\xbe\\xd2\\xda\\xc7\\x2c\\x43\\x26\\x0c\\x57\\x2c\\x42\\x9f\\xee\\x44\\x82\\xe3\\xb7\\x5a\\xa0\\x28\\x6d\\x73\\x1e\\xb2\\xe6\\x94\\x19\\xdd\\xd4\\x48\\xa2\\x4e\\xd9\\x71\\x54\\xe3\\xec\\x24\\x7c\\x23\\x30\\xfe\\x3c\\x37\\xba\\x90\\xcb\\xca\\x09\\xe8\\x34\\x26\\xf2\\xb9\\x96\\x4e\\x77\\xb4\\x5a\\xf7\\xc6\\x99\\xb1\\xbf\\x3c\\x37\\x9a\\xd9\\x93\\xfe\\x83\\xcc\\xbb\\x27\\xcc\\xf5\\x9b\\xb9\\xd9\\x22\\xad\\x81\\x55\\x41\\xf4\\x21\\x0d\\x51\\x4f\\xbc\\x01\\x92\\x9f\\x75\\x0b\\xe9\\x1b\\x75\\x99\\x19\\x9d\\x77\\x46\\xc3\\x4d\\x0e\\x89\\x35\\x2e\\x8b\\xa1\\x8f\\x8e\\x21\\xb9\\x43\\x20\\x77\\xf8\\xba\\x23\\x61\\xdd\\xab\\x05\\xfd\\xd5\\xb1\\x6a\\xb0\\x4d\\x50\\x0f\\x39\\x47\\xf6\\x14\\xbe\\xe8\\x25\\xe9\\xaa\\x6f\\x86\\x6c\\x28\\x73\\xaa\\xa5\\xcb\\xc1\\x0f\\xd5\\x22\\x0e\\x42\\x91\\x71\\x7b\\x4e\\x76\\x9f\\xd2\\x2f\\x5a\\xb6\\xa4\\x73\\x81\\x84\\x40\\x04\\xe2\\x0d\\xed\\xf9\\xc8\\xc4\\xc8\\x71\\x9e\\xef\\x16\\xd4\\xbe\\x7d\\xbf\\x67\\x62\\xc0\\x76\\x5e\\xed\\xac\\xee\\x3c\\xd2\\x89\\xab\\x36\\xf4\\xfe\\x25\\xa6\\xa0\\xfc\\x25\\x82\\x41\\xb4\\xd2\\x40\\xc9\\xa2\\x60\\x0a\\x96\\xc0\\x45\\x1f\\x96\\xaa\\xaa\\xec\\x6a\\x11\\xcc\\xad\\x4b\\xef\\x1f\\xe0\\x2f\\x1f\\x90\\x0b\\x0e\\x31\\xc1\\xae\\x83\\x09\\x4c\\x35\\xb6\\x5d\\xf5\\x69\\xe5\\x10\\x68\\xf4\\xa5\\x72\\xab\\xe8\\xe9\\x2e\\x95\\x7e\\xf0\\x61\\xbb\\x43\\xb1\\xc0\\xc9\\x3f\\x8a\\x98\\x13\\x63\\x5b\\x64\\x6a\\x49\\xe5\\x9a\\x30\\x41\\xc7\\x85\\xb5\\x18\\x22\\x06\\x0e\\x74\\x2e\\x29\\x90\\x46\\x46\\x77\\x9d\\xb3\\x49\\xf7\\xa9\\x83\\x68\\x63\\xfc\\xc8\\x87\\x8d\\x8d\\x1a\\x68\\xeb\\x87\\xa3\\xa6\\xb0\\xd4\\x39\\x50\\x7a\\xe8\\xc6\\xe9\\x2f\\xc7\\x75\\xad\\x21\\xda\\x45\\x47\\x4b\\xd4\\xc4\\xdd\\x31\\x56\\xbe\\x41\\x57\\x9a\\x7a\\x4b\\xd1\\xef\\x2f\\x49\\x1f\\xfa\\x1b\\xf0\\x44\\x2f\\x7e\\xfb\\x31\\x9d\\xbc\\x79\\x78\\xf5\\x97\\xeb\\x0f\\xa5\\xb3\\x50\\x67\\xd5\\x47\\xd2\\x74\\xdf\\xe7\\x0e\\xc1\\xf0\\x1a\\xd0\\xe7\\x1d\\xb5\\x53\\xf8\\xc3\\xab\\xfd\\x21\\x89\\x78\\xcc\\xac\\x74\\x6e\\x9a\\xe5\\x74\\xdf\\x17\\x04\\xf7\\x46\\x3c\\xfe\\x8a\\x7a\\xbc\\x46\\xcc\\x7d\\xcb\\x45\\x1e\\x2a\\x23\\x3d\\x62\\xa8\\xd5\\xa1\\x0e\\xcf\\x4e\\x90\\xea\\x7e\\x68\\x7a\\x07\\x67\\xc2\\xc2\\xd9\\xa4\\x66\\xc6\\x55\\x3e\\xac\\xa8\\x32\\x0b\\x0c\\x40\\x0d\\x5a\\x14\\x07\\xb0\\xbf\\x1e\\x86\\xee\\x35\\x7d\\xdd\\x6e\\xa6\\xde\\x59\\x0e\\x96\\xc0\\x27\\x10\\xba\\x0c\\xd7\\x5b\\x39\\x64\\xdb\\x66\\xa4\\x2b\\x84\\xa0\\xbf\\x5a\\x33\\x72\\xda\\xb4\\x6f\\x0a\\xa1\\x96\\x67\\x32\\x23\\x8f\\x55\\x86\\x4d\\xda\\xa7\\xd9\\xf6\\xea\\xda\\xf6\\xa8\\xd5\\xed\\x82\\x20\\x54\\x7d\\xc1\\xa5\\xe0\\x82\\x85\\x32\\x86\\xe1\\x0a\\x86\\x20\\xb8\\xe2\\xed\\x93\\x06\\x84\\x4f\\xac\\xd2\\x26\\xc5\\x10\\x72\\x14\\x3b\\x93\\xd7\\xe4\\x27\\x39\\x63\\x74\\xe4\\x6a\\x86\\xd1\\x4d\\x0e\\x82\\x29\\xa2\\x32\\x1a\\xba\\x91\\x83\\x64\\x4f\\xc8\\x74\\x2f\\xba\\xbf\\x40\\xb6\\xe2\\x58\\xfb\\x58\\x26\\x7e\\x4b\\xc6\\xc7\\xb8\\x7b\\xcb\\x1d\\xd2\\x68\\x9e\\xb1\\x7b\\x3d\\x3a\\x0b\\xbc\\x4a\\xcc\\x45\\x6e\\x37\\x15\\xa8\\x48\\xe0\\x78\\xd7\\x75\\x96\\x31\\x16\\x02\\x7b\\x4e\\x2c\\x75\\xb7\\x3a\\x5b\\x67\\x8f\\x9b\\xf2\\x92\\x9a\\x6c\\xc6\\x34\\xd1\\x12\\x7a\\xb3\\x6a\\x43\\x8b\\x82\\xe5\\x21\\x27\\x09\\x19\\x45\\x82\\x55\\xe1\\xf2\\x95\\x3a\\xd3\\x11\\x19\\x2b\\xdd\\xa7\\x38\\x0a\\x5e\\xb8\\xd8\\x68\\x55\\x50\\x17\\xf9\\x99\\xd4\\x22\\xc3\\xa2\\x40\\x6e\\x16\\x21\\x19\\x64\\xd9\\x30\\x05\\x57\\xb1\\x86\\x80\\x58\\x77\\xd3\\x67\\x82\\x79\\x1d\\x91\\xdb\\x37\\x30\\x33\\x1c\\xfe\\x0b\\x3c\\xee\\x67\\x74\\xce\\x9a\\x9c\\x0c\\xd7\\xd5\\xce\\x9e\\xd2\\x63\\x9a\\x5d\\x5d\\x53\\x95\\x77\\xad\\xa2\\x25\\x80\\x4f\\x4c\\x0d\\x1f\\x73\\xfb\\xf2\\x03\\xb4\\x10\\x62\\x85\\x5d\\xec\\xc6\\x69\\xdb\\x5c\\xf4\\x6d\\xca\\xc4\\xf3\\xb0\\x17\\x4d\\xfa\\x0d\\x13\\x67\\x3f\\x98\\x36\\x9a\\x99\\x80\\xf0\\xdc\\x5d\\xe3\\x25\\x2e\\xd3\\x9d\\xd6\\x46\\x96\\xd4\\xf0\\x0c\\xe2\\x68\\x7c\\x12\\x25\\x73\\x95\\x98\\x1e\\x61\\x25\\x8d\\x4f\\x59\\x47\\x15\\x09\\x14\\x37\\xb7\\x6e\\x3d\\x89\\x81\\xd5\\xc6\\xd2\\x23\\x4c\\x7c\\x34\\xd7\\x6e\\x95\\xdb\\xd3\\xea\\xa7\\x25\\x52\\x3d\\x7b\\x7a\\xcf\\x4b\\x4c\\xfe\\x87\\xcc\\x5b\\xc5\\x18\\xe1\\x65\\x25\\x95\\xa1\\xc2\\x90\\x9c\\x4f\\x02\\x80\\xb3\\x4f\\x05\\xbc\\x8b\\x27\\xfa\\xf0\\x07\\xfd\\x00\\x09\\xb0\\xd1\\x28\\x18\\xd4\\x2c\\x0a\\x79\\xad\\x89\\xb9\\x96\\x21\\x2a\\xd0\\x64\\x61\\x39\\xbc\\xe1\\x41\\x9b\\x98\\x1e\\x74\\x1c\\x37\\xaa\\x3d\\xea\\x2c\\x5f\\x45\\xe7\\xd0\\xc0\\xca\\x9e\\x6b\\x56\\x14\\xf6\\xdf\\xbb\\x4e\\xa3\\xce\\xe0\\x20\\x2b\\xe7\\x84\\x4f\\x05\\xc2\\xba\\x72\\xed\\xe3\\x53\\x0e\\x98\\x64\\x2f\\x57\\xb2\\xaa\\x5c\\x86\\x42\\xb9\\xdf\\xff\\x9c\\x40\\x9a\\xb9\\x9a\\x33\\x0d\\xe5\\x20\\x1e\\x2c\\xc5\\xb2\\xc2\\x94\\x09\\xa6\\xa8\\x81\\x24\\x38\\xd7\\x7f\\x12\\x54\\x92\\x65\\x22\\xbb\\xc6\\x65\\xf0\\xea\\xd1\\x2f\\x72\\x0f\\xd3\\x61\\x86\\xe4\\x6a\\x26\\xf3\\xf7\\xb8\\x6f\\x7b\\x78\\x2f\\x2e\\x90\\xdf\\xbc\\xdc\\xe9\\x81\\x81\\xa0\\x8d\\xca\\x3e\\xf9\\x4e\\x23\\x5b\\x84\\x93\\x37\\x80\\xdb\\x3c\\xc8\\xcb\\x86\\x29\\x22\\xce\\xd1\\xd6\\x03\\x51\\x87\\x45\\x35\\x8b\\xa8\\x8a\\xfd\\x52\\x01\\x92\\xad\\x3d\\xd7\\x2d\\x7a\\xdf\\x2a\\xa9\\xf5\\xa9\\xff\\xc9\\x13\\x92\\xfe\\xe2\\xb3\\xba\\xe7\\x7a\\xf1\\x59\\xbd\\xf8\\xac\\x5e\\x7c\\x56\\x70\\xbd\\xf8\\xac\\x96\\xaf\\xcf\\xc5\\x67\\x45\\x9a\\xe3\\x6a\\x5b\\x65\\xd3\\x69\\x6c\\xba\\xb4\\x0f\\xd8\\x47\\x9e\\x67\\x42\\x4e\\xa5\\x71\\x79\\xc0\\x60\\xc1\\xd2\\x5b\\x83\\x4e\\x14\\x4e\\xe8\\x6b\\xba\\x18\\x09\\x66\\x5c\\x17\\x11\\x1f\\xdf\\x3d\\xf7\\x34\\x7d\\xa3\\xac\\x35\\xe2\\x5c\\x1f\\x91\\xdc\\xf0\\x82\\xcc\\xf7\\x3e\\x89\\x46\\x31\\x12\\x55\\xb3\\x26\\x2d\\x19\\x3e\\xdf\\xd5\\x2e\\xf9\\xd4\\x7e\\x0f\\x38\\x80\\xa4\\xd5\\x7a\\x7f\\x44\\x2e\\x5c\\x49\\xca\\xd2\\xe0\\x37\\x9b\\x16\\xe4\\xcc\\x50\\xde\\xa5\\xb1\\x4f\\x7c\\x79\\x6d\\xe8\\xf2\\x16\\xed\\x6c\\x63\\xda\\x0e\\xe9\\x73\\xdb\\x04\\x24\\xa3\\x6d\\x73\\xc5\\x36\\xc8\\x68\\x51\\x1d\\x6d\\x5c\\x7d\\xdf\\xdc\\xf0\\x58\\x49\\x38\\x27\\x13\\x72\\xce\\x32\\x39\\x67\\x0a\\x57\\xf7\\xf8\\x53\\x45\\x85\\xe6\\x52\\xbc\\xa3\\xbc\\xb0\\x6b\\xeb\\xd7\\xb8\\x89\\x76\\x93\\x5a\\x33\\xd5\\xce\\x52\\x8c\\x52\\x34\\xc2\\x06\\x77\\x8c\\x64\\xb9\\xb7\\xbb\\x81\\x12\\xba\\x85\\xd8\\xf1\\x5c\\xa5\\x5b\\xa5\\xd8\\x9c\\xcb\\x5a\\x7b\\x8c\\x82\\xda\\xa0\\xa6\\xa1\\x8d\\xf3\\x10\\xcd\\xf8\\x74\\xe6\\x6f\\xf6\\xa5\\xa5\\x90\\x1a\\xad\\xf2\\xb0\\x89\\x3b\\x53\\xa6\\x0d\\x35\\xb5\\x6e\\xc3\\x39\\x67\\x90\\x1b\\xb8\\x45\\x09\\x52\\x81\\x8f\\xb6\\xc7\\x08\\xe9\\x53\\x5d\\x47\\xac\\x88\\x6d\\x3d\\x10\\xdf\\x23\\x92\\x05\\x3e\\x7a\\xec\\xf6\\xb2\\x07\\xe5\\x68\\x00\\x48\\x32\\x59\\x56\\xb5\\x61\\xd1\\x9e\\x77\\xbb\\xab\\x1f\\x51\\xbf\\x26\\x33\\xb5\\xfa\\x29\\x1d\\x94\\x54\\xd0\\x29\\x1b\\x06\\xd2\\x86\\x0d\\x1e\\xc7\\x41\\x6f\\x92\\xbe\\x17\\xb6\\x22\\xbd\\x37\\xd3\\x89\\xaf\\x67\\x87\\xa3\\xd1\\xbe\\x7a\\x03\\xaf\\x23\\x8f\\x02\\x60\\x47\\xfa\\x07\\xb1\\x23\\x8f\\x0f\\x64\\x47\\x02\\xae\\xe8\\xb6\\x0a\\xa0\\x73\\x47\\xdf\\xb2\\x08\\x72\\x4a\\xc6\\x5d\\x22\\xa8\\x4f\\x53\\xd9\\x29\\x1b\\x8e\\x16\\xae\\x89\\x2c\\xb9\\x31\\xcc\\x17\\x0d\\x06\\x91\\x32\\x20\\xdc\\xb4\\x20\\x27\\x9d\\x00\\x85\\x00\\x27\\x96\\xf8\\xb1\\x4f\\x55\\xc1\\x33\\x6e\\xa2\\x76\\x70\\x89\\x48\\x0f\\xcb\\x17\\x38\\x10\\xae\\xb9\\x46\\x55\\x5e\\x10\\x5e\\x56\\xd8\\x12\\x1f\\x04\\xe1\\xd0\\xe1\\x00\\xf9\\x20\\x5c\\x78\\x9b\\x0c\\xca\\x47\\x08\\xfb\\x04\\xa1\\x58\\x24\\xf8\\x45\\x6e\\xaf\\x79\\xbd\\xc8\\xed\\x5b\\xae\\x17\\xb9\\xdd\\xbb\\xdc\\x46\\x40\\xd0\\xee\\xf8\\xba\\x2d\\x79\\xed\\x1f\\xea\\xba\\x19\\xd1\\x31\\x2b\\xc8\\xcf\\x35\\x53\\x0b\\x62\\x0d\\xac\\x06\\xbf\\x43\\x5a\\x61\\xa7\\x79\\x8e\\x30\\x13\\x3e\\xa7\\x63\\x8b\\x22\\x04\\x7d\\x2a\\xe7\\x90\\x33\\x72\\xfc\\xc9\\xda\\xb7\\xd0\\xea\\xa1\\xf7\\x53\\x72\\x79\\x80\\x76\\x2f\\x29\\x5c\\x85\\xb0\\x32\\xb1\\x55\\x8a\\xb5\\x4e\\xf1\\x27\\x60\\x62\\x1e\\x9e\\x1e\\xf5\\xe9\\xc0\\xe8\\xa3\\x92\\x84\\xf4\\x57\\x4d\\x42\\x1e\\x49\\xc9\\x20\\xe4\\xf0\\x8e\\xb9\\xc6\\x35\\x09\\xdf\\xc0\\x39\\x1e\\x2a\\x8f\\x42\\x34\\x97\\x5c\\xb1\\xc5\\xc0\\x55\\x63\\x12\\xcb\\x81\\xd4\\xdf\\xdc\\x13\\x89\\x58\\xe2\\x8e\\xea\\xcf\\x15\\xc3\\x3c\\x8e\\x6e\\xbd\\x3f\\xdb\\x57\\xcf\\x07\\x62\\x9f\\xa1\\x3a\\xbc\\x86\\xf6\\xb5\\x7b\\x7b\\x96\\x5f\\xa2\\x7e\\xce\\xe8\\x9e\\xcf\\x7c\\x62\\x5f\\xb5\\xaf\\x47\\x2d\\xed\\x19\\xcb\\x3b\\xce\\xbb\\x8d\\x3c\\x6f\\x3f\\x08\\xb8\\x91\\x81\\xcd\\x01\\xd3\\x13\\x04\\x7e\\x3f\\xec\\x45\\xfa\\x0e\\x26\\xe0\\xe5\\x97\\xf1\\x91\\x26\\xab\\x37\\x01\\x43\\x22\\x5a\\xdb\\xc8\\x83\\x57\\x6c\\xb1\\xab\\x5d\\x6f\\x0f\\x29\\xf4\\x8c\\x57\\xa0\\xbe\\x43\\x32\\x93\\x9c\\xf4\\xba\\xc5\\xf1\\xfa\\x1e\\x2a\\x56\\x3d\\x31\\x78\\x6e\\x9c\\x88\\x01\\x39\\x95\\xc6\\xfe\\x73\\x0c\\x08\\x12\\x20\\x5e\\x8e\\x24\\xd3\\xa7\\xd2\\xc0\\x27\\x5b\\xcd\\x05\\x38\\x49\\xcf\\x81\\x07\\x5c\\xce\\x11\\x87\\x8c\\x1f\\x38\\x5e\\x11\\x69\\x1a\\x40\\x05\\xdd\\x5a\\xfb\\xaa\\xa3\\xc0\\x2f\\x5c\\x93\\x13\\x41\\xa4\\x72\\x4b\\xd4\\x23\\x39\\xe0\\x9a\\x47\\x92\\x90\\x18\\x1f\\xef\\x6e\\x92\\x02\\x57\\x51\\xe3\\x78\\x44\\xaa\\x16\\x8b\\x3c\\x09\\x61\\x8e\\x28\\x88\\xfa\\xe0\\x37\\x10\\xdd\\x82\\x5c\\x58\\x8f\\x2e\\x00\\xd0\\x54\\x8a\\x1a\\x36\\xed\\x21\\x89\\xb7\\xb9\\x4a\\xa6\\xa6\\xd0\\x7c\\x27\\x9b\\xf5\\xbd\\x1b\\xfa\\x52\\xb4\\xf0\\xea\\x51\\xdd\\xc2\\xab\\xd7\\x2d\\x0b\\x3a\\xef\\x7b\\x40\\xaf\\xd8\\x56\\xaf\\x53\\x44\\x22\\x6a\\x7f\\x25\\xad\\xec\\x3e\\xfd\\x1f\\xab\\xe4\\x01\\x5b\\xfe\\x2f\\xa9\\x28\\x57\\x7a\\x44\\x0e\\x89\\xe6\\x62\\x5a\\xb0\\xd6\\x77\\x2e\\xc8\\x1a\\x3d\\xa6\\x27\\xb2\\x20\\x07\\xc4\\xea\\x55\\x73\\x5a\\x30\\x04\\x21\\xa2\\x82\\x30\\x74\\xf3\\x00\\x02\\xf5\\x92\\x41\\x31\\x20\\xd7\\x33\\xa9\\x51\\x63\\x0c\\xa9\\xf9\\x3b\\x57\\x6c\\xb1\\x33\\xe8\\x25\\x84\\x44\\xe2\\x73\\xcd\\x3e\\xfa\\x44\\xec\\x34\\x5d\\xc9\\x5a\\x3b\\x38\\xe8\\xcc\\x90\\x29\\xb8\\x03\\xdf\\xed\\x3c\\x8d\\x1d\\xf3\\x0c\\xdc\\x3c\\xcf\\xa2\\x38\\xc8\\x85\\xe9\\xde\\x16\\x14\\x43\\xeb\\xdb\\x16\\x94\\x5e\\xa6\\x6f\\x39\\x53\\x06\\xb0\\xdc\\xa3\\x7b\\x9a\\xb4\\x08\\x07\\xe1\\xb5\\x75\\xd1\\x4f\\x00\\xe6\\xed\\x09\\x17\\xa2\\x07\\xe6\\x42\\xb2\\x0e\\x8d\\x51\\x7c\\x5c\\x1b\\xa6\\xb7\\x96\\x13\\x6e\\x25\\x34\\xc2\\x2c\\x0b\\xcd\\x3c\\xed\\xca\\x7f\\xbf\\xea\\x07\\x11\\xbc\\x1b\\xd7\\x7d\\x31\\xc7\\xc9\\x64\\x39\\xe7\\x30\\x42\\x8c\\x8d\\xf1\\x04\\xa4\\x72\\xf0\\x71\\x37\\xaa\\xd7\\xec\\xdf\\x34\\x90\\xea\\x50\\xc2\\xbb\\xa7\\x21\\x35\\x49\\x8e\\x8a\\xe9\\x4a\\x62\\xb5\\xd6\\xca\\x89\\x71\\x0a\\xd8\\x8c\\x6a\\xc8\\x56\\x9f\\xb8\\x64\\xa2\\xaa\\x56\\x95\\x04\\xb0\\x6f\\x2a\\x6e\\x6c\\xc6\\x5e\\xf0\\x16\\x1c\\xb8\\x86\\xc7\\x17\\x42\\x30\\xb5\\xb0\\x73\\xed\\x7e\\x0f\\xcd\\x18\\x0f\\x97\\x7a\\x9b\\x60\\xaa\\x45\\xd4\\x27\\x41\\xc8\\xd5\\x2f\\xd7\\x99\\x4e\\x5f\\xe6\\x83\\x36\\x74\\x40\\x75\\x47\\x12\\x11\\x3a\\x6f\\x17\\x93\\x4f\\xa3\\x24\\x14\\x6b\\x11\\x9a\\x38\\xd7\\xdc\\xc8\\x36\\xfd\\x80\\xf3\\x87\\x4d\\x1d\\x3a\\xf7\\xf3\\x24\\xc8\\x87\\xb5\\x68\\xd2\\x5d\\xfd\\x99\\xbd\\xba\\x34\\x03\\x3a\\x49\\x8c\\x65\\x2d\\x1c\\xcb\\xfa\\x1e\\x14\\x8f\\x3b\\x81\\x76\\x46\\x3c\\xb8\\x62\\x20\\xcb\\x6d\\x84\\x08\\xee\\x83\\x4f\\xec\\xbc\\x38\\xe8\\xc3\\x3e\\xe6\\xa5\\x95\\x89\\x0c\\x99\\x6e\\x0a\\x17\\x69\\xbc\\x58\\x2d\\x59\\x48\\x2e\\x19\\xae\\x28\\x50\\x31\\xc0\\x75\\x5c\\x3d\\x95\\xee\\xe5\\xba\\x1f\\x76\\x58\\xed\\x44\\xc9\\x19\\xc3\\x9d\\xaa\\x0d\\x35\\x0c\\xca\\x6c\\x14\\x9b\\x14\\x08\\xb7\\xe6\\x66\\xaf\\x94\\x39\\x9f\\xb8\\x6a\\x85\\x8b\\x28\\xeb\\x67\\x80\\xe8\\x9b\\x0e\\x24\\x33\\xee\\x88\\xd9\\x99\\xbc\\xbe\\x96\\xa3\\xbf\\xb3\\x14\\xff\\x6d\\xe4\\x66\\xd6\\x0b\\xaf\\x2e\\x57\\x65\\xac\\xce\\x46\\x5c\\x7d\\xbc\\x3c\\x76\\xc9\\x45\\x6f\\x27\\xfe\\x87\\xce\\xed\\xb9\\x1f\\xeb\\x88\\x87\\x2e\\xcf\\xbe\\x4d\\x46\\xab\\x7d\\x57\\x53\\x8d\\xfd\\x48\\x5a\\xde\\xf7\\x70\\xa0\\xc8\\x09\\x79\\xc7\\x0b\\xa6\\x17\\xda\\x60\\x99\\x25\\x2f\\x51\\xea\\x63\\x21\\xaa\\x34\\x84\\x8b\\xac\\xa8\\x5d\\xda\\x1e\\x9e\\x01\\x56\\xea\\x6e\\xd9\\x0a\\xf7\\xae\\xc4\\x35\\x8f\\xf5\\x5a\\xb8\\xaf\\xff\\xbe\\x81\\x62\\xbb\\x2c\\x27\\xa1\\x38\\x38\\xec\\xa6\\x5e\\x56\\xab\\xd3\\x6c\\x4d\\x92\\x30\\x1e\\x5b\\xb3\\x31\\xc9\\xda\\x5e\\xdf\\x77\\x7c\\xac\\x18\\x79\\x3b\\xa3\\x42\\xb0\\x22\\x6a\\xf7\\xe8\\x92\\x44\\xa8\\x31\\x34\\x9b\\xe1\\x99\\x43\\x89\\x95\\x77\\x05\\xb3\\x3a\\xc3\\x4c\\x6a\\x43\\x4a\\x9a\\xcd\\xb8\\x08\\xcd\\xa7\\x44\\x68\\x7b\\xda\\x80\\x02\\x3f\\x43\\xe0\\xfb\\x89\\xbe\\xb4\\x04\\x24\\xae\\x73\\x5f\\xc2\\x05\\xa9\\xf0\\x1c\\x3b\\x69\\x36\\x36\\x48\\x15\\x23\\x09\\x24\\x1c\\xf5\\xd0\\x78\\xef\\xc6\\xb3\\x43\\x0b\\x67\\x2f\\xa5\\x60\\xad\\xd1\\xb7\\x02\\xa7\\x3b\\xdc\\x9b\\x3e\\xf2\\xf1\\xa7\\x11\\xd9\\x61\\x9f\\xcc\\xef\\x76\\x06\\x64\\xe7\\xd3\\x44\\xdb\\x7f\\x84\\x99\\xe8\\x9d\\x11\\x39\\x29\\x43\\x4a\\x12\\x17\\x91\\xb2\\xc3\\xdc\\x0f\\xac\\x82\\x15\\xa9\\x8a\\x1d\\xf0\\xfc\\x3f\\x1e\\x7d\\x7c\\x43\\x66\\xf2\\x9a\\xe4\\x92\\x5c\\x33\\x48\\x83\\xb6\\x76\\x03\\x94\\xbe\\x6a\\x6f\\x7f\\x44\\x33\\x03\\x38\\x19\\x99\\x2c\\x2b\\x25\\x4b\\x1e\\xca\\x1e\\xdd\\x06\\x48\\x24\\xa3\\xb3\\xe0\\x2c\\x6a\\xd1\\x0b\\x9b\\xee\\x16\\xb5\\xb0\\x9c\\xf6\\xd1\\x35\\x74\\x7e\\x43\\xde\\xbd\\x25\\x86\\xaa\\x29\\x33\\x76\\x0c\\x22\\xea\\x72\\xcc\\x54\\x6a\\xe3\\xd7\\x3e\\x32\\x65\\xba\\x37\\xeb\\x57\\x8c\\xe6\\x1f\\x45\\x91\\x1c\\xcc\\xec\\x6b\\x5f\\x7b\\x3a\\xda\\xf3\\x7d\\x14\\x65\\xea\\x4d\\x68\\xa1\\x19\\xd9\\xb3\\x37\\x1e\\x5c\\x2b\\x6e\\xd8\\xfe\\x88\\x9c\\xfb\\x5f\\x41\\xbd\\x3f\\x28\\xee\\x13\\xd9\\x45\\x39\\xc6\\x32\\x19\\xf7\\x50\\xcd\\x0c\\xe2\\x28\\x0b\\xa7\\x1e\\x7e\\xb0\\xb2\\x25\\x59\\x65\\xc6\\x05\\x1f\\x4b\\x59\\xb0\\x44\\xa0\\x79\\xe4\\xbd\\x1f\\x7e\\x38\\x4d\\xf6\\x69\\xb6\\xf9\\xbb\\x79\\xde\\x6d\\x6c\\x7e\\x2d\\x55\\x91\\x5f\\xf3\\xdc\\x55\\x5a\\x91\\x3d\\x7b\\xf3\\x7e\\x37\\x96\\xef\\x12\\x4b\\xe9\\x18\\x39\\xe9\\x2c\\x5a\\xae\\xaf\\x79\\xde\\xcf\\xe4\\x77\\xd8\\x2b\\x40\\x44\\x7b\\xb9\\xbc\\xf3\\xc9\\x2e\\x17\\x81\\xf5\\xe2\\x39\\x13\\xc6\\x1e\\x07\\x4a\\x93\\x3d\\xf8\\x45\\x3a\\xc6\\xe7\\x31\\xc7\\xce\\x29\\x30\\xae\\x54\\x56\\xe0\\x8f\\xb9\\x68\\x3a\\x1b\\x35\\x6c\\x64\\x55\\x1e\\x2b\\x1a\\x7d\\x34\\x50\\x33\\x83\\xcd\\x08\\x00\\x71\\x51\\x9a\\x19\\xd1\\xbc\\xac\\x0b\\x43\\x05\\x93\\xb5\\x2e\\x92\\xa1\\x3e\\x9e\\x37\\x27\\x4d\\x0a\\xf6\\x09\\x25\\xca\\xa6\\xba\\x2c\\x36\\x14\\xb4\\xd5\\x5e\\x00\\xbc\\x68\\x3a\\xc1\\x2d\\xeb\\xbd\\x49\\x63\\x35\\x28\\x4b\\xf9\\x41\\xd0\\x9b\\x43\\x4f\\x13\\xf6\\x89\\x65\\x0e\\x8c\\xb5\\x2a\\xea\\x29\\x4f\\xc2\\x8c\\xef\\xa8\\x1a\\x77\\xcb\\x84\\x1a\\x3a\\xdf\\xf0\\x06\\x74\\x72\\x1c\\xb8\\x17\\x79\\xd4\\x74\\x44\\x5b\\x0e\\xc8\\xb8\\x6f\\x5c\\xb3\\xeb\\xd0\\xb4\\xb8\\x5b\\xef\\xa8\\xce\\x92\\xf8\\xc5\\x1c\\xd9\\x98\\x39\\x12\\xf7\\x38\\x8e\\xc8\\xca\\x59\\xc5\\x84\\x3d\\x20\\x04\\x79\\xd7\\x88\\x17\\x9c\\xe7\\x8d\\xb1\\x89\\x84\\x35\\xee\\x49\\x5f\\x72\\x0f\\x6b\\x2b\\x4b\\x91\\x47\\x71\\x26\\x8b\\x5c\\x13\\xf6\\xc9\\x28\\x6a\\xcf\\xc8\\xd2\\x9e\\x86\\xe1\\x37\\x13\\x42\\xc5\\x62\\xd4\\x4d\\x75\\xea\\x14\\x27\\xef\\x37\\x36\\xde\\x79\\x65\\xb6\\xdb\\xf2\\xc8\\x5f\\x2c\\x8f\\xf8\\xd2\\x2c\\x53\\xcc\\x74\\xc0\\x43\\xeb\\xad\\xd7\\xbe\\x27\\xa4\\xbd\\x5c\\xad\\x8f\\x6f\\xf8\\x2f\\xf1\\x5b\\x8f\\xb6\\xe0\\xf2\\x5c\\xba\\xb8\\x65\\x35\\x13\\x9a\\x1b\\x3e\\x6f\\x75\\xe3\\x04\\x3c\\x53\\xaa\\x75\\x70\\xf3\\x81\\x3a\\xe3\\x04\\xa0\\x6e\\x41\\x8d\\x26\\x0f\\x8c\\x01\\x47\\x3e\\x21\\x42\\x2e\\xbd\\x55\\x8c\\x41\\x11\\x72\\x02\\x5b\\xb7\\x24\\x0f\\x1a\\x12\\x83\\x4a\\xec\\x65\\x4d\\x05\\x20\\x17\\xe2\\xc3\\x07\\x00\\x9a\\x86\\xff\\x8d\\xb9\\x41\\x76\\x0e\\x22\\x67\\x27\\xcc\\x42\\xfa\\x4c\\xbb\\xd9\\xdb\\x9c\\xd8\\xec\\x23\\x77\\xbc\\x2b\\xd4\\x4c\\x9f\\xa1\\x99\\xd3\\x48\\xb5\\xf3\\x28\\x23\\xdd\\xbc\\xf7\\x6b\\x46\\x00\\xe5\\x9c\\xa9\\x39\\x67\\xd7\\x07\\x0e\\x1b\\x65\\x78\\xcd\\xcd\\x6c\\xe8\\xe0\\xe6\\x0e\\xc0\\xcf\\x70\\xf0\\x1b\\xf8\\xa7\\x13\\x55\\xe8\\xcb\\x3c\\xcc\\x73\\x07\\xdc\\xe4\\x9a\\xe0\\x21\\x10\\xe8\\x88\\xd0\\x8a\\x7f\\xcf\\x94\\x35\\x4b\\x06\\x80\\x8d\\x34\\x20\\x35\\xcf\\xff\\xda\\x61\\xc4\\xbe\\xbb\\xf9\\x77\\x4e\\x0c\\x9b\\x40\\xff\\xc6\\x24\\xeb\\xa0\\x1d\\x1a\\xc1\\xe7\\x2c\\xc5\\x47\\xdc\\x87\\xce\\x50\\x7c\\x48\\x3c\\xc4\\x49\\xc0\\x48\\x4d\\xb4\\x2c\\xe8\\x1f\\xe4\\xd2\\x05\\x88\\xb6\\xcc\\xd1\\x60\\xf8\\xd4\\x22\\x51\\x50\\x6f\\x38\\x5a\\x92\\x53\\x43\\x35\\x33\\x5d\\xa2\\x76\\x7d\\x6d\\xfa\\x88\\x14\\x7b\\x4a\\xc4\\xfb\\xdf\\x7d\\x05\\xa9\\x40\\x0c\\xc0\\x87\\x7d\\x47\\x3d\\x32\\xfc\\x8b\\x33\\x02\\x45\\xeb\\x4e\\x6b\\xfe\\xb9\\x25\\x4b\\x97\\xe9\\x08\\x32\\x03\\x0d\\x38\\xb0\\x54\\x11\\xc7\\xce\\x2d\\x83\\x65\\x1d\\xfa\\x9b\\x76\\xde\\x82\\xee\\x2d\\xbf\\xfb\\xee\\xe4\\xa8\\x1f\\xa3\\xba\\x79\\x9e\\xb7\\x11\\xe1\\xbf\\xdb\\xd3\\xef\\x36\\x06\\xa4\\xf0\\xf0\\x9f\\xeb\\xd8\\x77\\x07\\x0d\\xd3\\xc3\\x1e\\x71\\xf7\\x6f\\x62\\x76\\xa6\\x19\\x6b\\xa2\\xc0\\x47\\x5c\\x5f\\x6d\\xca\\x73\\x75\\x83\\x90\\xb6\\x5c\\xfa\\xe6\\xed\\x31\\x71\\x9f\\xde\\x15\\xb2\\x4d\\x1a\\xfa\\x69\\xc2\\xbc\\xc9\\x19\\x35\\x3e\\x8d\\x66\\x9a\\xb1\\x26\\xb9\\x26\\xe7\\xfa\\xea\\xf9\\x39\\xd4\\xaa\\xfc\\x34\\x0d\\xb4\\xf3\\x73\\x0b\\x72\\x2f\\x7b\\x7d\\x9c\\xe0\\x70\\xa7\\x2e\\xb0\\xf6\\x42\\xd6\\xe4\\xda\\x35\\x3c\\xee\\xe8\\x6d\\xba\\xe4\\xd5\\x1b\\x72\\x2c\\x74\\xad\\x58\\x53\\x71\\xb8\\x4c\\x82\\x35\\x34\\x1e\\xdd\\xf7\\x04\\xad\\xbd\\xf5\\x9b\\x8d\\x07\\xc4\\xb7\\x60\\x2b\\xe2\\xf5\\x79\\x44\\xe6\\x2b\\xaa\\x0c\\xf8\\xa0\\x36\\xbd\\xc3\\x02\\x21\\xfe\\x58\\x8e\\x3e\\x10\\x8f\\xb9\\xc5\\x4e\\x26\\x1e\\x9a\\xa6\\x9d\\xa7\\xcb\\x75\\x78\\x78\\x93\\xc4\\x0a\\x1a\\x58\\x1f\\xdb\\xe8\\x9d\\x0c\\x9a\\xfa\\x41\\xce\\xe6\\x07\\x3a\\xa7\\xaf\\x07\\xf0\\x5a\\x1e\\x5a\\xaf\\x3d\\x07\\x54\\x93\\x9d\\xd7\\x3b\\xe9\\x23\\x5f\\xf0\\x92\\x17\\x54\\x15\\xd8\\x6a\\x22\\xf4\\xf0\\x08\\xcf\\xb7\\x5a\\xa4\\x27\\x04\\xaa\\x92\\x5e\\xed\\x90\\x3d\\xa9\\x80\\xa2\\x8c\\x0a\\x52\\x30\\xdf\\x96\\xc2\\x09\\xf4\\x05\\x7a\\x3e\\xf6\\x9f\\xfd\\x4e\\xde\\x8e\\xac\\x0f\\x3c\\x5f\\x37\\xbe\\x09\\x73\\x6f\\x93\\x38\\xbd\\x37\\x8e\\x3a\\x9d\\x1d\\x35\\x2a\\x1c\\x17\\x56\\xaf\\x1b\\x91\\xef\\x9c\\x76\\xe5\\xf4\\x63\\xe4\\x5a\\xbb\\x18\\xfe\\x8e\\xcf\\x83\\x3b\\x3e\\x27\\xa7\\xfa\\x92\\x7b\\xfc\\x51\\xdd\\xdc\\xe4\\x66\\xbe\\xd0\\x67\\xc2\\x11\\xa9\\xae\\xfb\\x29\\x37\\xe7\\xac\\x92\\x1b\\xb3\\xd5\\x70\\xf8\\xa5\\x14\\x03\\x6e\\xec\\x07\\x52\\x73\\x23\\xd5\\x82\\x50\\x43\\x28\\x9e\\x0c\\x59\\x5d\\x50\\x45\\x14\\xc3\\x64\\x81\\xb4\\x95\\x3b\\x3a\\x3e\\x3b\\x3f\\x7e\\x7b\\x78\\x79\\x7c\\xf4\\x86\\x7c\\xe3\\x46\\xe7\\xb1\\x67\\x61\\x44\\x2e\\x65\\x93\\x91\\x10\\x43\\xc3\\x61\\xe5\\x56\\x43\\xdf\\xc0\\x9d\\xc6\\x89\\x11\\x93\\x63\\x7b\\x5e\\x1d\\x71\\x85\\x2d\\xd6\\xa9\\x20\\x27\\x82\\x9b\\xb7\\x61\\x30\\x44\\xa9\\x29\\xa4\\x70\\xf5\\x07\\x76\\x44\\x97\\x14\\x31\\xe5\\xc6\\x75\\x2e\\x45\\x02\\xec\\xd7\\xfe\\x69\\x49\\xa4\\x34\\x4d\\xde\\x65\\xbe\\xab\\x9b\\x37\\x7e\\x86\\x99\\x16\\x0d\\xe3\\x6c\\xc2\\xa7\\xc7\\x15\\x60\\xaf\\x6c\\x5c\\xba\\x06\\x42\\x02\\xf6\\x3e\\x66\\xeb\\x35\\x9f\\x77\\x53\\x1c\\x21\\xeb\\x40\\xc8\\x10\\x2a\\x23\\x52\\x11\\x6d\\xa8\\x32\\xb8\\x47\\x76\\x47\\xa3\\xdd\\x11\\xa8\\xb2\\xbb\\xa3\\x5d\\x6f\\x0f\\x16\\xa1\\x5a\\xd2\\x69\\x7b\\x0d\\x31\\xbe\\x5a\\xac\\x4b\\x3d\\x7b\\x5b\\x6a\\x8c\\x08\\xf9\\xe8\\xc1\\x14\\xa1\\x4b\\xe0\\x52\\xc1\\x66\\xa8\\xc5\\x2c\\x8a\\xf0\\x0e\\xd0\\xcb\\xa2\\x2d\\x7b\\x3a\\xc4\\xa5\\x20\\xba\\x56\\x8f\\xe3\\x97\\x74\\x75\\x9f\\x53\\x3e\\x77\\x4d\\xb6\\x36\\x96\\xf4\\xd0\\xbc\\x62\\x2f\\x9c\\x1a\\xcf\\x98\\x73\\x62\\x9e\\xbf\\xdf\\xdc\\xbb\\xa1\\xe8\\xee\\xe9\\xcd\\xdc\\x39\\xe0\\xde\\x2b\\x93\\x65\\xc9\\x0d\\x99\\x51\\x3d\\x0b\\x1d\\x4f\\x9a\\x0a\\xcc\\x6e\\x47\\x53\\x57\\x07\\x6c\\x51\\x6b\\xc3\\xd4\\x24\\x49\\x76\\xf5\\x72\\x98\\x7b\\x02\\x96\\x1c\\xae\\xe1\\x63\\x07\\xf5\\x2a\\x1a\\x8f\\x10\\x1c\\x72\\x7a\\x46\\x15\\xb3\\x77\\x56\\x70\\xfa\\x14\\x7c\\xc2\\x0c\\x4f\\xdd\\x1c\\x2b\\xb4\\x32\\xe6\\xac\\x5c\\xdf\\x62\\xc1\\x69\\x60\\x07\\x81\\xde\\x83\\xf3\\xe3\\xc3\\xa3\\x0f\\xc7\\xa3\\x32\\x25\\xac\\xb0\\xe1\\xf3\\x8e\\x89\\xbc\\x92\\x3c\\x15\\xe5\\x7e\\x48\\x2a\\x6a\\x52\\x7a\\x49\\x76\\x3d\\x29\\x03\\xd9\\x9b\\x3e\\x29\\x03\\x21\\x7e\\x87\\xfb\\x0f\\xd0\\xd6\\x04\\x06\\x75\\x5d\\x2f\\x22\\x4e\\x36\\xb2\\x92\\x85\\x9c\\x76\\x68\\x44\\xd8\\x8d\\x4f\\x7f\\x83\\x35\\xf2\\x43\\x3a\\xac\\xe4\\xc6\\x62\\x61\\x96\\x75\\x36\\xbd\\x7c\\x96\\x06\\xbf\\x72\\xcd\\xf2\\x04\\x77\\x92\\xe9\\x80\\xf3\\xf4\\x19\\xac\\xd0\\xb3\\x30\\xf6\\x6f\\x2c\\x1b\\xfa\\xe9\\xe1\\xb0\\x60\\x39\\xaa\\x4d\\xf6\\x01\\x43\\x40\\x1d\\xaa\\x98\\x2a\\x39\\x22\\x23\\x6d\\xab\\x17\\x60\\x23\\x5c\\x92\\xea\\x00\\xb0\\xc7\\xf0\\x59\\xe2\\x46\\xee\\x83\\x3d\\xfc\\xf8\\x6d\\x9d\\xa1\\x52\\x6c\\x08\\xf0\\x03\\xd6\\xdc\\x9d\\xf0\\x02\\xa0\\x54\\x1a\\x55\\x3a\\x52\\x21\\x92\\x06\\xf5\\x81\\x59\\x1f\\xf9\\xc5\\x27\\x17\\x8b\\xe5\\x00\\x6d\\x63\\x08\\x87\\x00\\x3c\\x36\\xfc\\x2c\\x8a\\xb4\\xaa\\x12\\x40\\xa3\\xb1\\x7a\\xa3\\x8b\\xc1\\xd0\\x29\\xbc\\xb0\\x54\\x2e\\x05\\xa9\\x52\\x7c\\xce\\x0b\\x36\\xb5\\x24\\xcc\\xb8\\x98\\xea\\xa6\\xf7\\x8c\\x03\\x1a\\x49\\x1a\\x16\\x50\\x72\\x58\\xa3\\x76\\x85\\x7c\\x9b\\x0f\\xf6\\xaf\\x06\\x96\\x1d\\xb7\\xe6\\xe9\\xc7\\x4b\\x22\\x18\\x92\\x90\\xb8\\xc9\\x3a\\xfa\\xc6\\x2c\\x91\\x89\\x8a\\x09\\x21\\xc3\\x61\\x1a\\x27\\x5e\\x7e\\x3c\\xfa\\xb8\\xf7\\x4f\\x29\\x98\\xce\\x8b\\x7d\\xf2\\x03\\x73\\x73\\x00\\xb8\\x2e\\x46\\xf1\\xcc\\x90\\xeb\\x99\\x84\\xe0\\x43\\xad\\xdd\\x3c\\x36\\x1c\\x09\\xd2\\x0a\\xab\\x9b\\xdc\\x5d\\x07\\xf6\\x4e\\x21\\x13\\x19\\x14\\x34\\xe5\\xd6\\x18\\xdc\\xaa\\xc8\\x9a\\x34\\x39\\xc6\\xcf\\xd0\\x39\\xb3\\x21\\x65\\x73\\x6b\\x14\\x15\\x9f\\xd5\\xb3\\x4a\\x90\\x75\\x8a\\x18\\x62\\x70\\x0e\\x55\\x21\\x4a\\xf4\\xa2\\x2c\\xb8\\xb8\\x82\\x56\\x16\\xee\\xb0\\x75\\x6d\\xe1\\x18\\xb1\\x5f\\x78\\xf1\\xa6\\x18\\x2d\\xfa\\x57\\x92\\x9e\\x6c\\xa3\\xf7\\xa0\\x20\\x99\\x2d\\xc8\\xe5\\x80\\x9c\\x09\\x7b\\x26\\xfc\\xcd\\x1f\\x85\\x18\\xea\\xe8\\x45\\xbb\\xd9\\xd9\\xf9\\x35\\x2e\\x2d\\xd7\\x99\\xe6\\x9b\\xd2\\x68\\x60\\xf0\\x96\\x3a\\x23\\xc8\\xc9\\xc5\\xdb\\x8b\\x93\\xcf\\x31\\xed\\xec\\x36\\x5d\\x17\\x26\\xe1\\x39\\xfb\\x55\\xf8\\xcf\\x69\\xae\\xdf\\x21\\x29\\xea\\xd4\\x5f\\xa2\\x93\\xfe\\x4c\\x2a\\x43\\x8b\\x0d\\x1c\\x93\\xd9\\x8c\\x56\\x87\\xb5\\x99\\x1d\\x71\\x0d\\x3d\\x19\\xfb\\x31\\x1b\\x6f\\x3c\\x35\\xc2\\x7a\\x62\\xa0\\xf4\\xba\\x64\\x31\\xc2\\xfd\\x26\\x71\\xf7\\xbd\\xfd\\xdb\\xe1\\x19\\xa1\\xb5\\x65\\x61\\xc3\\x33\\xa8\\xa0\\xd9\\x88\\x89\\x44\\xa2\\xb9\\xb9\\x40\\x54\\xde\\x5e\\x67\\xc6\\x3d\\xf3\\x9e\\x79\\xf1\\x77\\x6d\\xd3\\xac\\x6c\\x5b\\x32\\xe4\\xaa\\x6c\\xc4\\x97\\x84\\xc8\\x67\\x95\\x10\\x09\\x07\\xc7\\xaf\\x3c\\x09\\x92\\x0b\\x6e\\x38\\x35\\x52\\x6d\\x43\\x0e\\x56\\x8b\\x98\\x10\\x06\\xab\\xb5\\x91\\xa5\\x93\\x4c\\x27\\xfe\\x0e\\xa8\\x1c\\xe9\\x64\\xc7\\xdc\\x18\\xac\\x89\\xad\\x81\\x1f\\x10\\xb8\\xe3\\x44\\x18\\xa6\\x26\\x34\\x63\\x4b\\x50\\x21\\x03\\x22\\xd8\\xb5\\xa3\\x89\\xfb\\x7b\\x92\\xa9\\xf9\\xb3\\x0b\\x99\\x57\\x70\\x1c\\xff\\xe5\\xcd\\x9f\\xa3\\x8c\\xcb\\xbf\\x84\\x88\\xb5\\xc3\\xaa\\x0d\\xb1\\xc0\\x4c\\x0a\\xc1\\x32\\xb3\\xa9\\x18\\xa0\\xbd\\xf8\\xcf\\xfd\\x1c\\x4f\\xfc\\x67\\xb1\\x94\\x3d\\x80\\x53\\xfb\\x1f\\x35\\x2d\\x70\\x49\\xba\\x2c\\x77\\xf7\\xd7\\x6c\\xb1\\xc2\\xc6\\x77\\x49\\x9b\\x31\\xdd\\xbc\\x05\\x2e\\xc4\\x9a\\x2a\\x38\\x20\\x6a\\xcd\\xc0\\x24\\xc0\\xc9\\x34\\x8a\\x0a\\x6d\\x59\\xac\\x1f\\x67\\xf6\\xae\\xcb\\x16\\xde\\x25\\x7b\\x26\\xab\\x92\\x93\\x61\\xb7\\x06\\x60\\xad\\xa8\\x45\\x6c\\x49\\xe1\\x9c\\x5d\\x22\\x37\\xbe\\x0f\\x00\\x6b\\xdd\\x5e\\x73\\xe3\\xa9\\xb6\\x20\\x60\\x36\\x1e\\x08\\x75\\x64\\x04\\xd6\\x8d\\xa7\\x1a\\x4d\\x12\\xf2\\x9e\\x6b\\x83\\xe0\\x1e\\x78\\x33\\xb4\\xb2\\x40\\xe4\\x27\\x6b\\xe3\\x9e\\x11\\xa9\\x08\\xaf\\xfe\\x9b\\xe6\\xb9\\x7a\\x83\\x9a\\xab\\xf3\\x4c\\x49\\x95\\x5e\\x5b\\xce\\xb5\\xf3\\x8d\\x43\\x59\\xb9\\xcf\\x86\\xdf\\x33\\x8b\\x8a\\x67\\xb4\\x28\\x16\\xe4\\xf2\\xed\\x19\\x8c\\xa0\\xc9\\x9f\\xfe\\xf0\\x0a\\x8c\\xde\\xaf\\xbe\\xfc\\xc3\\xab\\x8e\\xbc\\xff\\x5c\\x81\\xa3\\xc8\\x73\\x89\\xfa\\x3d\\x83\\x14\\xdf\\x6d\\x03\\xc5\\x68\\x41\\x58\\x40\\xd7\\x01\\x6b\\x0a\\x5e\\x20\\x82\\x83\\x55\\x40\\xdc\\x91\\x82\\x7b\\xd6\\x6e\\x84\\xa0\\x4e\\xf5\\x69\\x30\\xbe\\x60\\x25\\x44\\xd7\\x0b\\x56\\xc2\\xaf\\x04\\x2b\\x81\\x04\\x74\\x4d\\x3c\\x0c\\x37\\x2d\\x5c\\x63\\x5a\\x00\\xb3\\xfc\\xe6\\x79\\x8d\\x47\\xf5\\xd9\\xe7\\x7e\\x54\\x27\\x32\\x49\\xaa\\x14\\xe9\\x63\\x01\\xe3\\x32\\xa6\\x2e\\x28\\x79\\x0d\\xf8\\xdb\\xd1\\xe9\\xc5\\x7f\\xbf\\x3f\\xfc\\xfa\\xf8\\x3d\\xcc\\xaa\\xab\\x96\\xb2\\xa2\\xc0\\xb9\\x3c\\x9e\\xaa\\xd4\\xfc\\x51\\xc5\\x51\\xb7\\xf5\\xde\\x5c\\x62\\xac\\x58\\x4a\\x89\\x15\\xe4\\xf4\\xdd\\xc5\\x9a\\xd9\\xb0\\x9b\\x48\\xc3\\x10\\x93\\xf4\\x55\\x7a\\x6e\\x39\\x06\\xf6\\xa7\\x9a\\xa9\\xcd\\xa0\\x74\\x6e\\x4d\\x82\\x82\\x8f\\x49\\xb2\\x4f\\x6d\\x6f\\xb5\\xe5\\x57\\x9c\\x9d\\x8d\\x39\\x86\\xd3\\x98\\x91\\xfc\\x6a\\x0c\\x2a\\xbb\\x44\\xb8\\x6c\\xcf\\x3e\\x81\\xf2\\x29\\xd9\\xa2\\x9b\\x79\\xa7\\xfa\\x02\\xd7\\xed\\x04\\x78\\xa8\\x22\\x5c\\x5e\\x7b\\x90\\xa0\\x7a\\xa1\\xac\\x9a\\x67\\x15\\x3c\\xa6\\xb5\\x57\\x36\\x7e\\xbd\\xfb\\xb8\\x5a\\xd5\\xc9\\x6b\\x53\\x0a\\xc1\\x4a\\x62\\x5c\\x6f\\x2f\\xdf\\xb2\\x2c\\xca\\x86\\x6d\\xc1\\x55\\xa6\\xa5\\x88\\xdc\\xd2\\x13\\x0e\\x95\\x0f\\x4d\\x5d\\x5c\\x43\\x57\\x34\\xeb\\xaf\\xee\\x26\\xb1\\xc9\\xd7\\x72\\x9f\\x38\\xe8\\x1e\\xf4\\x0c\\x15\\x11\\xa0\\x7b\\x43\\x28\\x45\\x61\\xec\\x4d\\x0b\\xa7\\x40\\xc8\\x32\\x6e\\x38\\x5d\\x87\\x25\\x09\\xd5\\xde\\x8a\\x71\\x25\\xd0\\x3d\\x00\\x8c\\x6f\\x25\\xcf\\x92\\xcf\\x52\\x5f\\xf9\\xe1\\x89\\x7d\\xbf\\x9b\\xf4\\xfb\\x56\\x33\\x69\\xa4\\xe8\\x19\\x0a\\x6f\\xd5\\x43\\xdb\\x67\\xc4\\x19\\xdc\\xf1\\xb6\\x69\\xa9\\xd9\\xb0\\x24\\x02\\xa0\\x84\\x34\\x43\\x2a\\xf2\\xa0\\x1b\\x4a\\xe1\\x93\\x07\\xdb\\xb9\\x83\\xcf\\x4f\\xda\\x56\\xf9\\xc9\\xd1\\x06\\x04\\xed\\x73\\xc8\\x80\\xfa\\x4c\\x9b\\x0c\\x3c\\x51\\x46\\x53\\xf7\\x32\\xc9\\xbc\\x27\\xac\\x50\\xfb\\x20\\xbf\\xc6\\x27\\x47\\xce\\x56\\xf7\\x40\\xa0\\xda\\x49\\x00\\x72\\xbb\\x08\\xd8\\x88\\xda\\x2d\\x95\\xb9\\x96\\xaa\\xaf\\x66\\x36\\xed\\xc7\\x2d\\xd5\\x8c\\xb9\\xef\\x6e\\x20\\x0e\\x7f\\x9e\\x02\\x0f\\xdf\\xf2\\xd7\\x2c\\xf4\\x2e\\x40\\xe8\\x45\\x3c\\x70\\x97\\xf0\\xfb\\x1c\\x64\\xdf\\xf3\\x91\\x79\\x5b\\xa7\\x81\\xbe\\x74\\xeb\\x68\\x5d\\x5e\\x78\\xf4\\xb2\\x3e\\xfe\\x61\\x2e\\xec\\x64\\x79\\xb3\\x39\\x95\\x28\\x04\\x20\\x23\\xb9\\xbc\\x91\\x53\\x48\\xc9\\x7f\\x42\\x37\\xf5\\xee\\x07\\x90\\x7f\\x12\\x66\\xf9\\x40\\xda\\x05\\x2d\\x0a\\xbb\\xb2\\x52\\x34\\xed\\xd0\\xb4\\xef\\x77\\x31\\x20\\x99\\x14\\x13\\x3e\\x2d\\x69\\xa5\\x07\\x70\\x12\\xe5\\xf2\\x5a\\x5c\\x53\\x95\\x93\\xc3\\xb3\\x93\\xa7\\x3f\\x75\\x3a\\x23\\x5c\\xe1\\x3e\\xea\\xd2\\x4d\\xbc\\x37\\x8c\\xab\\x86\\x14\\x28\\x90\\x76\\x5d\\xf2\\x19\\x19\\x73\\xa3\\xb1\\xd2\\x1a\\xea\\x9e\\x4d\\xec\\xf2\\xb6\\x0a\\x40\\xc8\\xd9\\xb5\\xf2\\xdc\\xca\\x6e\\xf7\\xa4\\x1e\\xf4\\x63\\x41\\x64\\x66\\x68\\x41\\xe6\\xd0\\x58\\x7c\\xcc\\xcc\\x35\\x63\\x82\\xbc\\x7a\\xf5\\x0a\\xa3\\xdd\\xaf\\xfe\\xf8\\xc7\\x3f\\x12\\xcb\\x31\\x24\\x67\\x19\\x2f\\x6f\\xde\\x08\\x77\\xfd\\xfe\\xf5\\xeb\\x74\\x52\\xfe\\xf3\\xf0\\xc3\\x7b\\x42\\x33\\xf0\\x58\\x60\\x3f\\x45\\xa4\\x08\\x58\\x2f\\x1e\\x54\\x0f\\xc8\\xff\\xbb\\xf8\\x78\\xda\\x34\\xb9\\x6f\\x7f\\x0b\\x9c\\x1d\\xa6\\xb3\\x83\\x45\\x1e\\x95\\x2f\\xc7\\xf1\\x68\\x6a\\x66\\xb0\\x6a\\x42\\x1a\\x42\\x27\\x13\\xdc\\x53\\x70\\x8e\\x72\\xed\\xe5\\x65\\x87\\xb2\\x0c\\xe8\\xa4\\xc3\\xa7\\x33\\x58\\x16\\x2e\\x60\\x17\\x16\\x50\\xc3\\xcd\\xed\\x94\\x40\\x96\\x82\\x6f\\xbc\\x85\\x25\\xf6\\x40\\x43\\x50\\x21\\x92\\x47\\xb6\\x53\\x36\\x20\\x05\\xbf\\x62\\x64\\xa2\\xbf\\x51\\xb2\\xae\\x06\\xbe\\x10\\xcf\\x4a\\x87\\xba\\x30\\x50\\x42\\x3e\\x66\\x8e\\x88\\x86\\x63\\x35\\xeb\\xd8\\x04\\x6d\\xd3\\x89\\xac\\x4e\\xf4\\xf5\\x93\\xeb\\xe6\\xc4\\xa8\\x33\\x77\\x0a\\x6e\\x35\\xab\\x49\\x00\\x76\\x41\\x29\\x6c\\x57\\xef\\xb9\\x66\\x79\\xb6\\xde\\xf6\\x2c\\xbc\\x0f\\x32\\x23\\xf6\\x80\\x8a\\x0e\\x1b\\x5a\\x48\\x31\\x8d\\x79\\xb7\\xd1\\x3d\\x7d\\x61\\xd3\\xa2\\xea\\x90\\xe2\\xd5\\x43\\x66\\x5f\\x3f\\xb9\\x7d\\x84\\x64\\x88\\x92\\x72\\xa9\\x6a\\x6d\\xbe\\xae\\x45\\x5e\\x74\\xca\\xf5\\xeb\\x37\\xdb\\x8f\\x90\\xb7\\x37\\xa8\\x43\\x60\\x0e\\x97\\xb0\\x01\\x01\\x9a\\x2c\\x63\\x1a\\xd9\\xf6\\x1f\\x23\\xab\\x8a\\x8f\\x4c\\x73\\xf7\\x3f\\x30\\x65\\xae\\x23\\x15\\x72\\xb2\\x8a\\x10\\x97\\x65\\x63\\xc5\\x1d\\x15\\x84\\xd6\\x46\\x0e\\xeb\\x2a\\xa7\\x01\\x43\\x65\\xf4\\x7f\\xfe\\x4f\\xc7\\x71\\x0f\\x8b\\x6a\\x46\\x07\\x64\\x4a\\x23\\xa3\\xe7\\x26\\x21\\x11\\x37\\x4f\\x18\\x35\\xb5\\x62\\xf0\\x8b\\xee\\xc3\\xdf\\xf1\\xce\\x56\\xa6\\xba\\xfc\\x36\\x68\\x2a\\x5c\\x84\\x03\\x45\\xd0\\x92\\x0d\\xec\\xa1\\x8b\\xf4\\x76\\x24\\x61\\xa9\\xb1\\xb1\\xe6\\x53\\xc1\\x14\\x06\\x35\\xac\\x94\\xa7\\xa4\\xa0\\x63\\x56\\x38\\x02\\xa4\\xea\\xfe\\xce\\xdf\\xa2\\xb7\\xc2\\xea\\x30\\x56\\x42\\x6b\\x42\\xa7\\x53\\xc5\\xb4\\xe6\\x73\\x7b\\x76\\xaa\\x92\\x16\\xfc\\x5f\\x4d\\x9f\\xe5\\x19\\x23\\x67\\xc7\\x1f\\x00\\xd1\\x05\\x2c\\x62\\x6b\\xde\\x18\\x96\\x0e\\x62\\x89\\x57\\x80\\x87\\xb5\\x1c\\xde\\x58\\xc1\\x23\\x42\\x8e\\xb5\\x34\\xd0\\x0e\\xd8\\x8e\\xea\\x16\\x5b\\x13\\x5d\\x67\\x33\\x42\\x35\\x96\\xbf\\x0c\\xc7\\x85\\xcc\\xd2\\xdb\\x1a\\xe0\\x95\\xc9\\xb2\\x64\\x1e\\x60\\x05\\x1e\\x48\\x66\\x8c\\xe6\\x4c\\x61\\x43\\x39\\x6b\\x16\\x54\\x15\\xcb\\x47\\x84\\xbc\\xb5\\x12\\x68\\xc2\\x33\\x6a\\x18\\x7e\\x97\\xb3\\xbc\\xb6\\x46\\x33\\x60\\xfb\\x76\\x24\\xe3\\x72\\xc6\\x88\\x54\\x39\\xb3\\x46\\x88\\x9d\\xef\\x2c\\x1e\\x2c\\xd2\\x6e\\x00\\xb1\\x88\\xdb\\xf1\\xc7\\xdc\\x28\\xaa\\x16\\xa8\\x03\\xb8\\xb5\\xec\\x48\\x84\\x3d\\x1c\\xb2\\x19\\x15\\x53\\x54\\x79\\x81\\x1e\\x22\\xa1\\x01\\x6f\\x32\\x6a\\xa2\\xbf\\x7a\\x39\\x07\\x48\\x67\\xef\\x56\\x73\\x75\\xc8\\xe7\\xf2\\x57\\x3f\\xc7\\x92\\xbd\\x60\\x6f\\x5f\\xb8\\xad\\xdd\\xf5\\x61\\x7d\\x9f\\x4c\\xf6\\x42\\xda\\xc0\\x20\\xbd\\x29\\x2b\\xb5\\xd7\\x2d\\x4c\\x36\\x43\\x35\\x7b\\x49\\x56\\x11\\x82\\x1e\\x10\\xda\\x2d\\x55\\x1c\\x2f\\x86\\xfa\\x34\\xf7\\x32\\x32\\x14\\x74\\x32\\x33\\xb2\\x06\\x93\\xa9\\x69\\x51\\x2c\\x86\\xec\\x93\\x3d\\xef\\xad\\x30\\x03\\xe5\\x06\\x40\\x71\\xa1\\x12\\xb4\\x16\\x9a\\x99\\x41\\x0f\\x84\\x80\\x10\\xaa\\x14\\x33\\xd8\\x42\\x6c\\x07\\xdf\\x5f\\x48\\xc0\\xd7\\xda\\xc1\\xc1\\xac\\x91\\x38\\xae\\x0d\\xb6\\x90\\x18\\xac\\xfe\\x49\\x1f\\x73\\x32\\x67\\x6a\\xe1\\xc6\\xed\\xfc\\xb8\\xde\\xb6\\x2a\\xe9\\x75\\x8f\\x10\\x90\\x50\\x26\\x9b\\x1d\\x7f\\xaa\\x14\\x42\\x16\\xf4\\xf2\\xcc\\xa5\\xed\\xb2\\x3c\\x04\\x02\\x1f\\x79\\x33\\xa1\\xcd\\xd8\\x5e\\x18\\xc1\\x09\\x82\\x49\\xf1\\xf1\\x27\\x70\\x4a\\x1c\\x9e\\x1e\\x75\\x3f\\x1e\\xf0\\xea\\x6e\\x5a\\xb4\\xaf\\x8e\\x86\\x46\\xfb\\xea\\x5f\\xe6\\xe0\\x75\\x78\\xc7\\x9c\\x3b\\x50\\x2a\\xff\\x0d\\x02\\xdb\\xfb\\x8e\\xb1\\xde\\x17\\x41\\xc9\\x15\\x73\\xc7\\x24\\x15\\xce\\x89\\xee\\x6e\\xee\\x8d\\x48\\xc5\\x0a\\x38\\xa9\\xed\\xb1\\x79\\xc5\\x16\\x30\\x18\\x8e\\xdf\\xcf\\xca\\xf7\\xbc\\x29\\xf1\\xea\\xeb\\x24\\x6d\\xae\\xa1\\x7d\\xf9\\x1e\\x9f\\xe6\\x17\\xab\\xa7\\x47\\xf6\\x2b\\x8b\\xf0\\xba\\x62\\xc9\\xa1\\x88\\x55\\x57\\x6b\\x17\\x59\\x4e\\xf2\\x6e\\x0a\\xd8\\x03\\xf6\\x83\\x80\\x05\\x12\\xd8\\x9e\\x02\\x02\\xbe\\x26\\x46\\xf6\\xc5\\x6c\\xa4\\x9f\\x3a\\xa9\\x9b\\x97\\x5f\\xd0\\x47\\x9b\\xb2\\x1e\\x05\\x0f\\x89\\xe8\\x6d\\xc7\\x83\\xaf\\xd8\\x62\\x57\\xe3\\x9e\\xb7\\x27\\xc4\\x8c\\x57\\xd8\\x7b\\xd6\\x1e\\xf6\\x72\\xd2\\xf3\\xc6\\xc7\\xeb\\x7b\\x5a\\xf0\\x3c\\x90\\x83\\x27\\xcb\\x89\\x18\\x90\\x53\\x69\\xec\\x3f\\xc7\\x9f\\xb8\\x76\\x36\\xcc\\x91\\x64\\xfa\\x54\\x1a\\xf8\\x64\\xeb\\xf9\\x01\\xa7\\xea\\xb9\\x70\\x83\\xf3\\x5f\\x73\\x28\\xb4\\x81\\x63\\x18\\x2c\\x75\\x98\\x12\\xbf\\xea\\x1e\\x33\\x31\\x70\\x0e\\xd7\\xe4\\x04\\xba\\x58\\xe0\\x52\\xf5\\x4a\\x10\\x54\\x79\\x21\\x51\\x48\\x4e\\xe9\\xc2\\x05\\x42\\x8a\\x21\\xa8\\x9c\\x2b\\xe9\\x71\\xdc\\x22\\x55\\x8b\\x59\\x9e\\x88\\x34\\x47\\x16\\xf8\\xd1\\xf1\\x1b\\x68\\x9b\\x5f\\x15\\x34\\x63\\x39\\xc9\\x6b\\x98\\x4c\\x6a\\x67\\x95\\x1a\\x36\\x4d\\xac\\xa7\\xbc\\xed\\x2a\\x99\\x9a\\x42\\x88\\x20\\xeb\\x80\\x4c\\x79\\xf3\\xea\\x5b\\x31\\xc3\\xab\\x57\\xf5\\x0c\\xaf\\x9e\\x37\\x31\\xe8\\xca\\xef\\xed\\xd1\\xf4\\x18\\x9a\\x78\\x6f\\xbb\\x37\\x22\\x13\\x35\\xc6\\x92\\x56\\x76\\xe7\\xfe\\x8f\\x55\\x0c\\x81\\x49\\xff\\x97\\x54\\x94\\x2b\\x3d\\x22\\x87\\x44\\x73\\x31\\x2d\\x58\\xeb\\x3b\\xe7\\x7b\\x89\\x1e\\xd3\\x1b\\x61\\x15\\xd4\\x44\\xfd\\x5c\\xf3\\x39\\x2d\\x18\\xe2\\x86\\x51\\x41\\x58\\x81\\xea\\xad\\x9c\\xdc\\x30\\x47\\x06\\xe4\\x7a\\x26\\x35\\x6a\\x99\\xe0\\xf0\\x85\\x1e\\x86\\x57\\x6c\\xb1\\x33\\xe8\\xc1\\x09\\xe9\\xaf\\x58\\x5a\\xec\\x9c\\x88\\x9d\\x26\\xd2\\xd4\\xda\\xd3\\x41\\xd7\\x86\\xfa\\x9f\\x1d\\xf8\\x6e\\xe7\\xa9\\xec\\xa0\\x1e\\x75\\x61\\x9a\\xe7\\xd0\\x1c\\x92\\x16\\x67\\xbd\\xab\\x88\\xbd\\x6e\\xb9\\xfe\\x2b\\xcf\\x9b\\xab\\x2b\\xf8\\x01\\x5e\\x8f\\xe7\\x7a\\xf2\\x3b\\x73\\x85\\xaf\\x7e\\xbc\\x70\\xdc\\xe0\\xdd\\x3c\\x37\\xbd\\x40\\x3d\\x10\\x02\\x7e\\xa4\\xc8\\xe7\\x64\\xb7\\x44\\xcb\\x71\\xd7\\x97\\xeb\\xa5\\x17\\x66\\xc1\\x18\\x74\\x3a\\x9c\\x40\\x73\\xf5\\xbf\\xa4\\x56\\x27\\x51\\x35\\x1b\\x90\\x5c\\x8a\\x5d\\xe3\\xdc\\xee\\x95\\xcc\\xb1\\xd3\\x57\\x5d\\x79\\xcc\\x80\\x50\\x9e\\x94\\xaf\\x58\\xf5\\x3d\\xbd\\xdf\\x03\\x29\\x54\\x31\\x4b\\x02\\x9d\\x53\\x5e\\xd0\\x71\\xe1\\x7d\\x84\\x50\\x0a\\x82\\x01\\x1e\\x00\\xba\\xf5\\x05\\x26\\xab\\x08\\x21\\xbc\\x8f\\xf3\\xc0\\xa1\\xf0\\x43\\xda\\x82\\x91\\x04\\x7a\\x14\\xc4\\xc4\\x34\\x8c\\x17\\x91\\xd4\\x0e\\x1a\\xf5\\x40\\xc5\\x5d\\xec\\x0d\\x67\\xa7\\xa3\\xd2\\x48\\xe7\\xee\\xfd\\x17\\x53\\xb2\\x87\\x71\\x57\\x38\\x95\\xfb\\xda\\x4d\\x5d\\xb2\\xd9\\x9a\\xab\\x4b\\x21\\x75\\x73\\xb5\\xb6\\xd2\\x39\\x18\\x90\\x73\\x97\\xb2\\x02\\x78\\x91\\x11\\x9e\\xa8\\x92\\xc8\\x08\\x90\\x47\\x08\\x5f\\x8c\\x61\\x5e\\xb6\\x4a\\xc8\\x34\\xec\\xb2\\x8d\\x62\\x66\\xcd\\xa0\\x45\\x14\\x72\\xed\\x43\\x4f\\xb9\\x27\\x12\\x71\\xe9\\xba\\x80\\x60\\x9b\\x8e\\x09\\x50\\xe9\\xa3\\xcb\\x8f\\xb3\\xa1\\x02\\xb4\\x64\\x2d\\x10\\x65\\x11\\x33\\xb7\\xfa\\x0b\\x62\\xf6\\xc6\\x5a\\x98\\xd9\\xf8\\x81\\x56\\x3d\\x26\\x68\\x84\\x67\\x42\\x5d\\x9e\\x2a\\x51\\x68\\xd2\\xb1\\xac\\x8d\\xc7\\xd7\\x74\\xdf\\xe7\\xd4\\x50\\xbb\\xf3\\x5c\\x92\\xcc\\x76\\x84\\x3d\\xfb\\xf3\\x5d\\xf6\\x64\\x56\\xf6\\xbf\\x5d\\x31\\xef\\xb5\\x9d\\x67\\x3e\\x20\\x8c\\x66\\x33\\x6b\\xed\\x0c\\x31\\xa1\\xd1\\xda\\x69\\xde\\x20\\x3b\\xb2\\x0b\\x85\\x46\\x90\\x5c\\x56\\x18\\xfa\\xd8\\x42\\x81\\x23\\xfc\\xc6\\x89\\x72\\x74\\x7d\\xe2\\x82\\x2f\\x09\\xd1\\x2e\\x8d\\xdf\\x99\\x67\\xa2\\x29\\x4c\\xed\\x81\\x12\\x1f\\x52\\x70\\xf2\\xc2\\x3b\\x85\\x61\\x46\\xc0\\xc3\\xb3\\xd4\\x83\\xb4\\xe0\\xda\\x12\\x79\\xc5\\x16\\x61\\xd3\\xf7\\x40\\xc5\\x8a\\xb7\\x6f\\x40\\x74\\xed\\x19\\xe6\\xf2\\x90\\x6b\\x71\\x63\\x7c\\xab\\xd4\\xf4\\x44\\x03\\x78\\x61\\xe1\\xa5\\xa9\\x77\\x90\\x47\\x50\\xbe\\x33\\x9e\\x41\\xab\\x12\\x3b\\xa0\\xbb\\xd7\\x73\\x4b\\x58\\xce\\x3e\\x1c\\x5d\\xd1\\xd2\\x6b\\x66\\x35\\x56\\x78\\x4d\\x00\\x83\\xb6\\xef\\xcf\\xb4\\x26\\x1c\\xd6\\xa9\\xa4\\xea\\x8a\\xe5\\x41\\x1b\\x1f\\x91\\x33\\x3b\\x51\\xde\\x1b\\xd6\\x03\\x25\\xca\\x6b\\x11\\x50\\x8c\\x44\\x17\\xad\\xe6\\xb9\\x96\\xcc\\xdd\\xd1\\x68\\xd7\\x35\\x89\\xb9\\xd9\\x4a\\xb7\\x27\\x89\\xdf\\x8f\\xeb\\xab\\x37\\x87\\x57\\x4b\\x36\\x7d\\xa0\\x95\\x46\\x87\\xa2\\x55\\xa3\\x21\\x84\\x22\\xa1\\xef\\xb7\\x99\\xf9\\xcc\\x1a\\xda\\xb9\\xe0\\xbb\\xb9\\x7a\\x76\\x4e\\xf4\\x1b\\xa4\\xeb\\x2f\\x40\\xd7\\x43\\xfa\\x0c\\x5e\\x7d\\x07\\xe5\\x7a\\x0c\\xc8\\xdd\\x16\\x8c\\x73\\x3c\\xe4\\xe4\\x61\\xbf\\x11\\xde\\x1e\\x03\\x2c\\x65\\x87\\x52\\x8a\\xe5\\xeb\\xb1\\xc2\\x2a\\x90\\xa4\\xce\\x35\\xf9\\xe8\\xbd\\x15\\x0f\\x2b\\xb4\\x00\\x7d\\x1d\\x33\\x4f\\xfb\\xa2\\x64\\x8b\\x2a\\x2d\\x96\\xaf\\x6d\\xab\\xbc\\x58\\xbe\\x4e\\x26\\x70\\xe8\\xac\\x6e\\x84\\x1e\\x17\\xd3\\x04\\x03\\x44\\xf7\\xe5\\x0a\\x26\\x1b\\x2d\\xc9\\x58\\xbe\\x36\\x52\\xa2\\xb1\\x7c\\xf5\\x51\\xb2\\xb1\\x7c\\x75\\x2f\\xe1\\x58\\xbe\\xfa\\xf1\\xa7\\xe0\\xf5\\x58\\xc2\\x29\\x6e\\x01\\xac\\x5a\\xce\\x1a\\x67\\x6e\\x80\\xc2\\x0f\\xae\\xb0\\x2a\\x3a\\x18\\x7a\\x94\\x49\\x4e\\x9d\\x43\\xb1\\x44\\xc7\\x5a\\x16\\xb5\\xe9\\xda\\x7d\\xf8\\xb6\\x41\\x62\\x9d\\x11\\x5e\\xd2\\x47\\xa1\\xfa\\x51\\x14\\x97\\x87\\x8b\\x34\\x51\\xb0\\x24\\x50\\x3d\\xeb\\x73\\xac\\x1e\\x0f\\xd4\\x6d\\x8d\\x8d\\xf4\\x0f\\x12\\x8d\\xd7\\x36\\x61\\xb3\\x2e\\x5f\\x4f\\x0d\\x18\\x8d\\xd7\\xf6\\x47\\x66\\xfc\\x63\\xdd\\x39\\xbc\\x08\\xdd\\xbe\\x5a\\xc6\\x2f\\xc0\\x33\\x1b\\x8d\\xb6\\xb9\\xcf\\xc9\\xc0\\xfe\\x60\\xdd\\x7d\\x26\\xfd\\x39\\xdc\\x1f\\x2b\\xd0\\xe9\\x6b\\xa4\\x0f\\xcf\\x4e\\x7a\\xf4\\x2d\\x46\\x4f\\xbd\\xc5\\xbb\\x18\\xdf\\xf1\\xe2\\x5f\\x7c\\xc8\\xd5\\x9a\\xe0\\x13\\x74\\x0d\\xc6\\x99\\xd8\\x47\\xcd\\x8c\\x3a\\xcc\\x96\\x5e\\x54\\xb9\\xed\\xf7\\x67\\xdc\\x78\\xf1\\x77\\x56\\x0b\\x89\\x7b\\xd9\\x44\\x1c\\x68\\xa4\\x2b\\x4a\\x6f\\xf4\\x15\\x77\\xce\\xfb\\x8e\\x64\\x58\\x79\\xd5\\xbd\\x72\\x90\\x6c\\xbf\\xef\\x63\\x4b\\x3d\\x16\\x30\\xfb\\x1d\\x5a\\x79\\x2c\\x5f\\x2d\\x6e\\xd9\\x3d\\xf7\\x93\\xe8\\xc2\\x61\\xe8\\xa8\\x8e\\x7c\\xe6\\x95\\xcc\\xdf\\x60\\x02\\x0f\\x15\\x42\\x1a\\xcc\\x69\\x1d\\x60\\xe8\\x57\\x0f\\x9a\\x0a\\xc4\\x08\\x33\\x51\\x45\\x10\\x35\\xa3\\xdd\\x5f\\x57\\x86\\x3b\\xcc\\xdd\\x59\\x3f\\x9c\\x44\\x1e\\x29\\x29\\xbd\\xd1\\x81\\x1e\\x2d\\xb5\\xd6\\x3d\\xdf\\x33\\x91\\xce\\x66\\xac\\xa4\\xf0\\x9f\\xef\\xfc\\x04\\x59\\x79\\xed\\xca\\x44\\xc1\\x07\\xcf\\x54\\xa9\\x89\\x9c\\x0c\\x5a\\x90\\x39\\x3b\\xf3\\xd7\\x3d\\x94\\x2c\\x35\\xd7\\xa3\\xa4\\x29\\x87\\x35\\x7f\\xb4\\xe9\\x3c\\x6b\\x59\\x95\\x76\\x77\\x82\\xe3\\x0b\\xe2\\xd7\\x1e\\xb8\\x34\\x44\\x39\\xac\\x12\\x31\\xc7\\xf9\\xdf\\xf2\\xa9\\x7b\\xcc\\x7c\\x35\\xbc\\x9e\\x83\\x93\\x33\\xd5\\xb9\\x39\\x08\\x0a\\x7a\\xdb\\x29\\xd9\\x1b\\x61\\x2f\\xce\\xcd\\xfb\\xaf\\x17\\xe7\\xa6\\xbb\\x5e\\x9c\\x9b\\x0f\\xbe\\x1e\\xcd\\xb9\\x19\\x69\\x73\\xfe\\x84\\x5d\\xe1\\x9d\\x8c\\x9b\\x00\\x79\\x17\\x65\\xd3\\x51\\x76\\x84\\xa1\\x0e\\xef\\x57\\xf4\\x4e\\x45\\xa9\\xda\\x51\\xe3\\xdd\\xd1\\x68\\x17\\xe3\\xc6\\xa3\\x10\\x1b\\xa9\\xcd\\x64\\xf8\\x27\\xc2\\x44\\x26\\x73\\xfb\\x9c\\x4b\\x78\\xbe\\xd2\\x06\\x2c\\x9d\\xc6\\x0f\\x15\\xd3\\x52\\xfa\\xb1\\xe2\\xc8\\x33\\x3c\\xbb\\x5f\\xbd\\xb1\\xc7\\x63\\xcb\\x43\\xad\\xbd\\x7b\\x4c\\xbd\\xbc\\xc7\\xe3\\xa5\\xd1\\xeb\\x3d\\xe5\\x7e\\x29\\xdc\\x82\\x32\\xe5\\x14\\xfc\\x06\\x44\\xae\\xe0\\x25\\x77\\x05\\x63\\x56\\x9e\\x32\\x6d\\xfa\\xaa\\x69\\x20\\x64\\x0f\\x1f\\x3e\\xca\\xaa\\x7a\\xe0\\x06\\x1a\\x95\\xac\\x94\\x6a\\x31\\x08\\x83\\xd9\\x2f\\x5b\\xa3\\xbb\\x3b\\xf6\\xc1\\xb8\\xc8\\x6a\\xa5\\x98\\x30\\xc5\\x22\\x32\\x33\\x7e\\x5d\\x56\\x86\\x5f\\xa9\\x2d\\x36\\x32\\x02\\x73\\xf5\\x93\\xfe\\xd9\\x5c\\x6d\\x89\\xf7\\xd6\\x0f\\x83\\x4e\\xf8\\x30\\xdb\\x70\\xde\\x3b\\x94\\xfc\\x41\\xe3\\xfc\\xb4\\x9f\\x32\\x31\\x27\\x73\\xaa\\x74\\x5f\\x12\\x86\\x3c\\x96\\x5d\\x91\\xf3\\x39\\xd7\\x8f\\x58\\x0d\\x7b\\xe1\\x94\\x16\\x0c\\x61\\xc9\\xda\\x54\\xb5\\x71\\xc7\\x9d\\x17\\x11\\xec\\x53\\x25\\xad\\x2a\\x1a\\x44\\xc3\\x92\\x79\\xf6\\x7a\\xa7\\x47\\xe2\\x2a\\x6a\\x0c\\x53\\xe2\\x0d\\xf9\\xaf\\xbd\\x9f\\x7e\\xfb\\xcb\\x70\\xff\\xaf\\x7b\\x7b\\x3f\\xbe\\x1a\\xfe\\xfb\\xdf\\x7f\\xbb\\xf7\\xd3\\x08\\xfe\\xe3\\x8b\\xfd\\xbf\\xee\\xff\\xe2\\xff\\xf8\\xed\\xfe\\xfe\\xde\\xde\\x8f\\xdf\\x7e\\xf8\\xe6\\xf2\\xec\\xf8\\xef\\x7c\\xff\\x97\\x1f\\x45\\x5d\\x5e\\xe1\\x5f\\xbf\\xec\\xfd\\xc8\\x8e\\xff\\xfe\\xc0\\x87\\xec\\xef\\xff\\xf5\\xdf\\x7a\\x7c\\x09\\x2a\\x16\\x1f\\x7b\\x3b\\x13\\xf0\\x1a\\x3e\\x8a\\x5e\\xd3\\x7e\\x76\\xcf\\xac\\xbb\\x64\\xdb\\x71\\x61\\x86\\x52\\x0d\\x71\\x90\\x37\\x50\\xdd\\xd1\\xdb\\x50\\x9e\\x35\\x1f\\x4f\\xc6\\x34\\x5a\\x55\\x38\\x41\\x83\\xf9\\xbd\\xe5\\x42\\xe4\\xb1\\x2c\\x6c\\x44\\x99\\xed\\x31\\x46\\x82\\x0f\\xbc\\x25\\x3c\\xe2\\xbe\\x7c\\x89\\x8c\\x3c\\xe4\\xfa\\xfc\\x33\\xaf\\x5d\\xe7\\xe9\\x97\\xb4\\x6b\\xf2\\xfc\\xd3\\xae\\x71\\x2d\\x5f\\x72\\xae\\x5f\\x72\\xae\\x5f\\x72\\xae\\x3b\\x3f\\x69\\x4b\\x23\\x98\\x2f\\x39\\xd7\\xfe\\x7a\\x0e\\xe1\\x88\\x97\\x9c\\xeb\\x07\\x5c\\x2f\\x61\\x89\\x3b\\xaf\\x97\\xb0\\x44\\xeb\\xfa\\x95\\x87\\x25\\x5e\\x72\\xae\\x13\\x07\\x79\\xc9\\xb9\\xbe\\xfd\\x7a\\xc9\\xb9\\x7e\\xc9\\xb9\\x7e\\x36\\x39\\xd7\\xe8\\x0b\\x59\\x95\\x79\\xed\\x7c\\x19\\x4d\\xda\\xf5\\xaf\\x30\\xeb\\x5a\\x5b\\x56\\xcd\\xd8\\x61\\x96\\xc9\\x5a\\x98\\x4b\\x79\\xc5\\x3a\\x26\\xa6\\x2d\\x79\\x16\\x6f\\x3c\\xdd\\x9e\\x20\\xb7\\x79\\x1a\\x6f\\xde\\xbc\\x95\\x6e\\xc7\\xcf\\x12\\xe7\\x9e\\xd6\\x39\\x67\\xa2\\x0f\\x57\\x7e\\xff\\x72\\xdd\\xd3\\xe6\\xb5\\x0f\\xab\\xcd\\x89\\x9c\\xe5\\xcd\\x17\\x4e\\xe8\\x1b\\xcb\\x34\\x23\\x72\\x48\\x14\\xcb\\x78\\xc5\\x1d\\x50\\x1f\\xc5\\xcf\\x7b\\x20\\x04\\xe4\\x83\\x6b\\x74\\xb7\\xb0\\x52\\x83\\x15\\x13\\x3c\\xb4\\xa9\\x68\\x1a\\xe0\\xa9\\xc8\\xff\\xe6\\x34\\x88\\x25\\x42\\xfb\\x70\\xac\\xd8\\x57\\x42\\x7d\\x1a\\x04\\xff\\x35\\xd7\\x8c\\xe8\\x99\\xac\\x8b\\x9c\\x28\\xf6\\x4f\\xaf\\xd0\\xbb\\x19\\xb9\\x8c\\x69\\x88\\xa3\\x88\\xfd\\x10\\x13\\xbd\\xba\\x5b\\x09\\x5a\\x71\\xbb\\x9f\\xd9\\x76\\x21\\xaf\\xb1\\x4f\\x15\\x57\\x20\\x77\\x2e\\x58\\x26\\x45\\xbe\\x95\\x2e\\xff\\x1b\\x44\\x36\\x4a\\x37\\x24\\x64\\x20\\x16\\x6b\\xe8\\xff\\x32\\xa7\\x05\\xcf\\xb9\\x59\\x84\\x7c\\x5f\\x14\\xa3\\x7d\\x6c\\x3b\\x94\\xc4\\x61\\x57\\xe9\\x86\\xa3\\x08\\xad\\x2a\\x25\\x69\\x36\\x63\\x3a\\xa2\\x17\\x2d\\x5d\\xd7\\x6b\\xb7\\x5b\\xeb\\xc7\\xf8\\xaa\\x8a\\x7a\\xca\\x05\\x9a\\xcb\\x30\\xaa\\xb5\\x3c\\x8a\\x05\\x51\\xd2\\xf8\\xf2\\x09\\xf7\\xd2\\xcb\\x24\\x5f\\x46\\xe4\\xd8\\x9f\\xf7\\x40\\x0c\\x2a\\xea\\x46\\x2d\\xa0\\x4a\\x43\\xc6\\x44\\xe0\\xcc\\xf0\\x49\\xfc\\x87\\x26\\xb2\\xc8\\x41\\xdf\\xa0\\x82\\xfc\\xe9\\x15\\xa9\\x98\\xca\\x50\\x2c\\xf5\\x12\\x1c\\xd2\\xd0\\xff\\xc5\\xd2\\x51\\x58\\x6b\\xcc\\xaa\\x32\\xb7\\x0f\\xff\\xe5\\xef\\xc8\\x4c\\xd6\\x4a\\x8f\\x8e\\x22\\x01\\xf0\\x1a\\x3e\\xeb\\x83\\x5b\\x44\\xde\\x24\\xc5\\x1a\\x52\\x30\\xaa\\x0d\\x79\\xfd\\x8a\\x94\\x5c\\xd4\\xa6\\x3f\\xcc\\xb8\\xbe\\x2c\\xf9\\xc8\\x86\\xff\\xc3\\xef\\x3a\\x3e\\xed\\x11\\x10\\xe8\\x7a\\x91\\x24\\xb1\\xc5\\x0e\\xff\\x1d\\xcc\\x76\\x17\\xad\\x82\\x2e\\xc9\\xa4\\x92\\x5c\\x98\\x65\\x23\\xde\\x69\\x5c\\x7d\\x9e\\x56\\x10\\x25\\xdb\\xf0\\x79\\xf0\\x73\\x2d\\xc7\\x0b\\xd3\\xbd\\x29\\xb9\\x7b\\x4e\\x1b\\x7d\\xfe\\x3f\\xdc\\x87\\x38\\xad\\x52\\x34\\x0d\\xa2\\xc1\\xcf\\xa6\\x67\\x54\\x31\\xd7\\x34\\x6e\\x57\\x93\\x82\\x4f\\x98\\xdd\\xbd\\x09\\xa4\\x6c\\xb8\\x0d\\xb9\\x62\\x53\\xae\\x8d\\x4a\\x0b\\x9d\\x0c\\xd3\\x0f\\x86\\xae\\xda\\xee\\x54\\xc9\\x3a\\x19\\xb8\\xae\\xaf\\xed\\x09\\x44\\x78\\x37\\x99\\x0f\\x96\\xbb\\xf6\\x81\\xe9\\x78\\x9d\\x4e\\xa4\\x63\\xa4\\x17\\xc7\\x48\\x7c\\xd6\\xe7\\xd7\\x07\\x7c\\xa9\\xbd\\x37\\xec\\x4a\\xbf\\x55\\x7d\\x27\\x4d\\x48\\xc3\\x86\\x7d\\xcb\\x72\\xd4\\xe8\\xed\\xcf\\x87\\x90\\x9b\\x1b\\x45\\x5b\\x3a\\xf4\\xc4\\x5d\\x6e\\x46\\xbe\\xb9\\x46\\xe0\\x7e\\xfb\\x6e\\x7e\\x81\\x90\\x8e\\xb6\\x10\\x75\\x58\\xd2\\x52\\x91\\xb2\\x2e\\x0c\\xaf\\x8a\\x66\\xb1\\xce\\xfd\\x0f\\x9c\\xba\\x97\\xee\\x3f\\x6b\\x0c\\x34\\x1a\\x45\\xc3\\xa9\\x06\\x69\\xfd\\xa6\\x92\\xca\\x60\\x52\\xcd\\x5e\\xa0\\x81\\x09\\x03\\xfd\\x8c\\xa1\\xc2\\x92\\x55\\x54\\xd1\\xc0\\x29\\x99\\x2c\\x4b\\xda\\x01\\xf2\\x18\\x73\\x34\\x28\\x24\\x8a\\xe3\\x61\\x6d\\x55\\x44\\x45\\x8b\\x66\\x86\\xa2\\x8c\\xda\\x4d\\x6d\\x6b\\xc3\\x04\\x15\\xc9\\x69\\x67\\x7d\\xf1\\x0c\\x52\\x41\\xe4\\x75\\xa8\\x92\\x9e\\xf2\\x39\\x13\\xcb\\xfb\\xd9\\x99\\xdd\\x5f\\xd3\\xec\\x8a\\x89\\x74\\x3f\\xde\\x77\\xda\\xaf\\x71\\xbe\\x10\\xb4\\xe4\\x19\\x2d\\xac\\x3c\\x50\\x72\\xce\\xad\\x38\\x60\\xf9\\xd2\\xb8\\x7a\\xe0\\xc2\\x9f\\xd8\\xf4\\xce\\xb7\\x4b\\x45\\x03\\x66\\x53\\x0b\\x57\\x6b\\x96\\x9c\\xc7\\xdc\\xd7\\xb2\\x59\\x1a\\x1e\\xeb\\xcc\\xd3\\x18\\x15\\x57\\x7c\\x9e\\x31\\x6f\\xff\\xd9\\xf1\\x36\\x35\\xdf\\xf8\\x7e\\xbd\\xcc\\xb8\\xe7\\xe6\\x48\\x46\\x81\\x26\\x19\\x52\\xfa\\xb0\\xdf\\x4d\\x61\\xcf\\xaa\\x45\\xe8\\x71\\xbf\\xb4\\x17\\x5c\\x3f\\xdc\\x6e\\xe7\\x4d\\xe2\\x7c\\xa8\\x71\\x92\\x92\\xd9\\x07\\xdb\\xa9\\x71\\xde\\x3e\\x58\\xce\\x69\\x2e\\x35\\xf9\\x1a\\x10\\xed\\x8f\\x18\\xb8\\x0b\\xd6\\x53\\xd4\\xd3\\x66\\x70\\x45\\xf0\\x88\\x7d\\xa2\\x65\\x55\\x30\\x3d\\xba\\xfa\\x13\\x84\\x8f\\x9c\\xf0\\x38\\x50\\xe3\\xfc\\xe0\\xfc\\xf8\\xf0\\xe8\\xc3\\xf1\\xa8\\x4c\\x11\\x5a\\x1b\\x36\\x0b\\x78\\x49\\xa7\\x69\\xc6\\xe2\\x90\\x94\\x52\\x70\\x23\\x55\\xca\\xe9\\xd6\\xd5\\x2a\\x98\\xe8\\x4b\\x3b\\x6f\\x1b\\x96\\x90\\x48\\x85\\xb7\\xd6\\x9b\\x86\\xcb\\xb0\\xa8\\xde\\x38\\xf7\\xda\\xaa\\x65\\xd2\\x85\\xac\\xc9\\x35\\xc5\\xc6\\x34\\xc0\\xc7\\xe9\\xba\\xe9\\x25\\xaf\\xde\\x90\\x63\\xa1\\x6b\\xc5\\x9a\\x26\\x76\\xcb\\x24\\xd8\\x23\\x2d\\x34\\xa0\\x77\\x07\\x1b\\x6c\\x19\\xec\\x48\\x03\\x8d\\x10\\xb0\\x45\\x74\\x32\\x1d\\xc7\\x6e\\x5f\\xbc\\x21\\x3b\\xec\\x93\\xf9\\xdd\\xce\\x80\\xec\\x7c\\x9a\\x68\\xfb\\x8f\\x30\\x13\\xbd\\x33\\x22\\x27\\x65\\x55\\xf0\\x8c\\x9b\\x62\\x61\\x77\\x14\\x53\\x0a\\x53\\xa2\\xc6\\xcc\\xfd\\x60\\x29\\x51\\x3a\\x9d\\x92\\x35\\x23\\xbe\\xda\\x48\\x45\\xa7\\xcc\\x6f\\xe4\\xdf\\xa8\\x71\\xba\\xce\\x81\\x01\\xdd\\x99\\xbc\\x26\\xb9\\x24\\xd7\\x8c\\x54\\x8a\\xcd\\x99\\x30\\x98\\x4d\\xab\\x49\\xd4\\x6d\\xda\\xad\\x0e\\xb4\\x27\\xc8\\x64\\x59\\x29\\x59\\x72\\xed\\xd5\\xa2\\x92\\x66\\x33\\x2e\\x52\\x7d\\x37\\x9d\\x0f\\x41\\x90\\x05\\x9b\\xde\\x53\\x40\\x44\\xf0\\x9e\\x83\\xf8\\xc7\\x8f\\xba\\x35\\x12\\x48\\x95\\xe8\\xbf\\x99\\xc9\\xeb\\xa1\\x91\\xc3\\x5a\\xb3\\x21\\x4f\\x0d\\x41\\x76\\x5e\\x99\\x2b\\xb6\\x80\\x4a\\xa0\\x0d\\xaf\\x8d\\x23\\xa3\\xe5\\x9e\\x34\\x12\\xa2\\xf0\\xf0\\xb9\\xb5\\x78\\xce\\xbf\\x3e\\xfa\\x4e\\x77\\x09\\x21\\x45\\x5e\\x91\\x03\\x66\\xb2\\x83\\x8c\\x55\\xb3\\x03\\x37\\xf2\\xaf\\x75\\xfd\\xfd\\x49\\xbb\\x69\\x06\\xf0\\x74\\xa0\\x76\\x9b\\xc9\\xa2\\x60\\x99\\x8f\\x69\\xbd\\x65\\xd5\\x2c\\xdc\\xf0\\xac\\x17\\xaa\\x4b\\x29\\x40\\xc7\\x02\\x80\\xce\\x9c\\x52\\x49\\x99\\x9c\\x95\\xd3\\x17\\x97\\x58\\x1a\\xda\\x12\\x1c\\x3e\\xe9\\x26\\xc0\\x23\\xb1\\xa0\\xc6\\xfd\\x6a\\x09\\xcf\\x48\\x10\\x3c\\x0b\\x3f\\xed\\xb9\\xff\\x52\\x33\\x03\\x3a\\x26\\x17\\x04\\xb1\\xf5\\x3e\\x58\\x9d\\x77\\x1b\\x1c\\xb2\\x5b\\xc1\\x07\\x5d\\xfc\\xc1\\x58\\xe2\\xd9\\x01\\x4e\\xa3\\x2f\\x4e\\x08\\x84\\x40\\x18\\x23\\x4a\\xe6\\xa4\\xb5\\x99\\x31\\x61\\x78\\x86\\x59\\x0f\\xae\\x26\\x35\\x56\\x11\\xc8\\xc9\\x04\\xfd\\x72\\x79\\x87\\xb4\\x3d\\x39\\x67\\x4a\\xf1\\x9c\\x69\\xd2\\x59\\x47\\x88\\xe3\\x31\\xbc\\x78\\xd6\\xac\\xd5\\x29\\x63\\xae\\x8f\\x04\\xb5\\xae\\xe9\\xc6\\x7d\\x06\\xd6\\xfb\\x4f\\x31\\xde\\xce\\xe4\\xe2\\xa7\\x4e\\x2b\\xee\\x21\\xc9\\xab\\xff\\x14\\xd9\\xad\\xf1\\x9c\\xb7\\x14\\x20\\xf8\\xa4\\x37\\x05\\x88\\xe6\\x25\\xef\\x80\\x55\\xb8\\x05\\xf2\\x29\\x91\\x69\\x74\\x46\\x0b\\x76\\xf2\\xb1\\xb3\\x7b\\xda\\x3d\\xa7\\xed\\x6b\\xbe\\x70\\x1f\\x56\\x76\\x93\\x68\\x28\\x51\\xf7\\x61\\x0f\\x63\\x68\\x36\\x73\\x2d\\xfe\\x7c\\xc0\\x59\\x0a\\xf2\\x6d\\xe0\\x5d\\x22\\x64\\x9e\\x96\\x2f\\xb5\\x61\\xff\\xef\\x94\\x1a\\x76\\x9d\\x68\\xed\\x0c\\x9b\\xc3\\x3f\\xf5\\xf7\\xe0\\x0d\\x7b\\xf1\\x1f\\xaf\\x74\\xde\\x76\\xf7\\x11\\x87\\x82\\xd0\\x1b\\xcf\\x7e\\x7c\\xaf\\xf0\\xe8\\x16\\x7f\\x70\\x1f\\xf2\\x0f\\x9e\\xb8\\x91\\xd8\\x98\\xbd\\xdc\\x96\\xe9\\x85\\x79\\xdc\\xb3\\x3c\\x0b\\xc0\\x2a\\xd0\\x3c\\x57\\x4c\\x6b\\xaf\\xb1\\x78\\xb1\\x74\\x78\\x76\\x42\\xbe\\xc1\\xdb\\x37\\xf6\\xea\\x95\\x92\\x06\\x3d\\x3e\\x47\\xb2\\xa4\\x3c\\xb9\\xec\\xa4\\x35\\x07\\xcb\\x0f\\xf5\\x93\\x11\\x1b\\x13\\x7e\\x12\\xce\\xc2\\xbd\\xc4\\xdd\\x6c\\x0d\\x8a\\xa6\\xe1\\x68\\xad\\x58\\x4e\\x9c\\x67\\x7f\\x63\\xb3\\xb4\\x75\\x46\\xfa\\x0d\\xb3\\x99\\xec\\xd9\\xef\\x0e\\xa0\\x19\\xf2\\xfe\\xa8\\x31\\xd8\\x97\\xac\\xf9\\x74\\x37\\xd6\\x23\\x7a\\x01\\x3e\\x4b\\xdb\\x39\\x4a\\x0e\\xf0\\xa0\\x34\\x8d\\xbd\\xec\\x99\\x1f\\x94\\xc8\\x50\\x3c\\xd2\\x61\\x54\\xa1\\x39\\x64\\x14\\x47\\x35\\x5d\\x60\\x8c\\x03\\x26\\x41\\xc0\\x9d\\x41\\xc3\\x7c\\x40\\xde\\xcb\\x29\\x17\\xfe\\x6c\\x90\\x2e\\xa7\\x7f\\x42\\xd3\\x2d\\xe4\\x17\\x13\\xf5\\xc6\\xf5\\x62\\xa2\\xfe\\x8a\\x4c\\x54\\xad\\x8b\\x63\\x41\\xc7\\x45\\x7a\\x35\\x62\\xdb\\x98\\x09\\x8f\\x23\\xef\\x0a\\x3a\\x25\\x0c\\xfe\\x38\\xc8\\xb9\\xb6\\xff\\x92\\x8b\\x8b\\xf7\\x90\\xed\\x58\\x0b\\xef\\x8a\\x83\\xe4\\x38\\xa7\\x4a\\x04\\x7c\\x4a\\x3c\\x18\\x36\\x27\\x93\\xf1\\xcc\\xfe\\xd0\\x01\\xf0\\xa5\\x37\\xa9\\xdc\\x90\\x42\\xb8\\xc8\\xa1\\x99\\xbb\\x6e\\x15\\x21\\xbb\\x3b\\x40\\x38\\xd3\\x00\\xa2\\x85\\x75\\x7c\\x63\\x46\\x2e\\x67\\x3c\\xbb\\x3a\\x8b\\x12\\x0e\\xa5\\xb2\\x9f\\x89\\xe8\\xa3\\x5e\\xd4\\xe0\\x9e\\x9e\\xd9\\x79\\x8f\\xb8\\xe9\\x38\\xeb\\x2b\\xf4\\x14\\x3d\\xcf\\xeb\\x82\\xfe\\x08\\xbc\\x70\\x33\\x0f\\xdf\\x51\\xad\\x65\\xc6\\x9b\\x9c\\x5e\\x88\\x49\\x37\\x0a\\x62\\x0e\\x0a\\xe2\\xe6\\x66\\x05\\x4c\\xa8\\x7e\\x26\\x04\\x2d\\xb7\\x15\\x7a\\xb1\\xe7\\x44\\x77\\x07\\xd5\\xb1\\x1e\\xcc\\x85\\x9f\\xb7\\x8d\\x4d\\x02\\xee\\x8d\\x2e\\x90\\xc6\\x7d\\xed\\xea\\x86\\x92\\xe5\\x79\\x0c\\x3b\\x78\\x39\\x27\\xd3\\x43\\xee\\x39\\xde\\x4b\\x76\\x56\\xe0\\x05\\x49\\x5a\\x5c\\xaf\\xe0\\x5a\\xae\\x83\\x0c\\x01\\xb4\\xd4\\x8d\\xac\\x56\\x3a\\x42\\x69\\x1f\\x2b\\xe4\\xb4\\xdd\\x76\\x51\\x01\\x7e\\xe6\\xb2\\x3b\\x41\\xb8\\x56\\xb2\\xaa\\x0b\\x2c\\xdd\\x0c\\x93\\xd6\\x5b\\x86\\xe7\\x3a\\xc9\\x62\\x48\\xdb\\xd3\\xbb\\xfb\\xba\\xea\\xbd\\x11\\x94\\xd5\\xa6\\x37\\x64\\x8c\\xaa\\xb5\\x3e\\x7c\\x9a\\xdf\\xa3\\xe0\\xd8\\x22\\xe3\\x85\\x7f\\x5c\\x0f\\xce\\xb2\\xcd\\xa3\\xa7\\xf5\\x85\\x96\\x96\\xee\\x98\\x6c\\xa1\\xac\\xb5\\xfc\\x07\\xaf\\xfe\\xf0\\xbb\\xdf\\x75\\xd0\\x5e\\xb8\\x62\\x99\\x91\\x50\\x95\\xe3\\x90\\x2b\\x43\\x26\\x19\\x55\\x0c\\x2c\\x4f\\x84\\x36\\xf3\\xae\\x49\\xac\\xca\\x30\\x9d\\x02\\xbb\\x9b\\x83\\x57\\xdb\\x08\\x9c\\x5a\\x1f\\x45\\xd7\\xdd\\xe1\\xd2\\x3a\\x65\\x42\\xf5\\x96\\x4d\\x0a\\x50\\xcc\\x27\\x1b\\x86\\x62\\xde\\x28\\x00\\xf3\\x26\\x61\\x97\\x37\\x07\\xb6\\xbc\\x41\\x88\\xe5\\x4d\\x03\\x2b\\x6f\\x04\\x4e\\x79\\xe3\\x99\\x93\\x4f\\x0f\\x98\\xdc\\x0b\\x36\\x55\\x1f\\xb8\\x54\\x5d\\x21\\x91\\x3b\\x62\\x5a\\xf5\\x83\\x67\\xd5\\x19\\xf4\\xf8\\x29\\xa0\\x8e\\x7b\\x82\\x35\\xea\\x0e\\x6b\\xdc\\x2f\\xee\\xc8\\xa6\\x21\\x8c\\xb7\\x48\\xf5\\xc6\\x6b\\x3b\\xe1\\x8a\\x37\\x02\\x52\\xbc\\x69\\x68\\xe2\\x0d\\x02\\x12\\xf7\\x07\\x5e\\xd4\\x17\\xf8\\x70\\x77\\xd0\\xa2\\x7e\\x05\\xc7\\x86\\xe0\\x85\\x1f\\x11\\x54\\xf8\\x49\\xa0\\x84\\x1f\\x1b\\x40\\xb8\\xf3\\x31\\xd5\\x15\\xdf\\xb5\\x33\\xaa\\xab\\xee\\x09\\xd6\\xb5\\xaf\\x64\\x81\\x6d\\xf0\\x60\\x37\\x94\\xac\\x8c\\x04\\xf8\\x86\\x50\\xbe\\x0b\\xfd\\xae\\x8e\\x7a\\xcc\\x1b\\x69\\x0f\\x83\\x8d\\xd5\\xd6\\x26\\xbb\\x4b\\x49\\x67\\xb7\\x36\\x52\\x22\\x93\\x74\\xd3\\x55\\x51\\xa9\\x8f\\x17\\x4b\\x59\\xa3\\xe1\\xe3\\xed\\x4f\\x16\\x7d\\xc9\\x9a\\x7c\\xc8\\xb5\\x8d\\x59\\x93\\x4f\\x55\\x45\\xff\\xf9\\xe5\\xbe\\xe5\\x2f\\xb9\\x6f\\xf1\\xb5\\x85\\xb9\\x6f\\xba\\xd5\\x56\\xd5\\x47\\xfd\\xe0\\xc0\\x02\\xfb\\x49\\x8e\\xad\\x26\\xe6\\x31\\x12\\x1a\\x79\\x7b\\x78\\x76\\x92\\x3c\\x7a\\xa6\\x18\\xc0\\x1f\\xd3\\x42\\x8f\\x56\\x19\\x56\\x3e\\x29\\xc6\\x99\\x71\\xde\\xa0\\xa2\\xc6\\xb0\\xb2\\xea\\xd0\\x3f\\xf9\\x25\\xf5\\xed\\xc6\\xf5\\x92\\xfa\\xf6\\x2b\\x4a\\x7d\\xdb\\xe6\\x7c\\x90\\x59\\x5d\\x52\\x31\\xb4\\x87\\x03\\xe4\\xcd\\xb5\\xd2\\xcf\\x97\\x94\\xbc\\x11\\x71\\xe2\\xbc\\xd3\\x0e\\x44\\x60\\x42\\x80\\xab\\xac\\x05\\xff\\xb9\\x66\\x8d\\x6f\\x3a\\x68\\xee\\x5b\\x90\\xb9\\x03\\x74\\x6c\\xcf\\x72\\xa1\\x41\\xb3\\x74\\x68\\x64\\xf2\\x06\\xe0\\x92\\x9b\\xcb\\xb0\\x74\\x5e\\xce\\x77\\x5b\\x32\\x18\\xbc\\x15\\x4a\\x32\\x33\\x86\\x36\\xd7\\xd9\\x92\\xcd\\xd5\\xf2\\xc2\\x39\\x47\\x1a\\x2d\\x0a\\x79\\xdd\\x2d\\x9e\\x17\\xdb\\x11\\x96\\x45\\xed\\xbb\\x3b\\x5c\\xf3\\x31\\x23\\x25\\x57\\x4a\\x2a\\x97\\x5b\\x14\\xbf\\x3e\\x16\\x4a\\xf0\\xe9\\xcc\\x30\\x85\\x3e\\x2d\\x4c\\xe7\\x4e\\x17\\xb5\\x17\\xcc\\xb8\\x5d\\x00\\xbb\\xc8\\x48\\x42\\x05\\xc2\\xd6\\xd9\\xff\\xf6\\x75\\xd9\\x30\\x35\\xfe\\x38\\x1d\\xb3\\x19\\x9d\\x73\\x59\\x77\\x80\\x87\\xb9\\x40\\xe5\\x60\\xc7\\x3d\\x12\\x14\\xdf\\x85\\xac\\x43\\xf6\\x40\\x0d\\x68\\x4a\\x61\\x15\\xf4\\x4d\\x3e\\x48\\x1e\\xfa\\xb4\\x79\\x28\\x38\\x3a\\x73\\xe9\\xc3\\x87\\x43\\xf6\\x89\\x6b\\x73\\x73\\xce\\x3d\\x0b\\xb8\\x6c\\x95\\x8d\\x6c\\xe6\\xb9\\xae\\xac\\x6a\\xfb\\x7d\\x32\\xc2\\x61\\x1b\\xdd\\x30\\x7e\\x5a\\xdb\\x12\\x9e\\x5f\\xc0\\x57\\xf7\\xd9\\xc1\\x0e\\xdb\\x1f\\x61\\x5b\\x3b\\x40\\x5e\\x6d\\xb8\\x70\\x12\\xdf\\xf2\\x2c\\x2d\\x70\\xf6\\xb9\\x19\\xe2\\x2f\\x46\\xf8\\x56\\x19\\xe1\\x21\\x81\\xba\\xe0\\xd9\\xe2\\xe4\\xa8\\xdf\\xa4\\x6c\\x7c\\xa6\\x57\\x9a\\x74\\x48\\xc8\\xb6\\x9f\\x93\\xaf\\xa9\\x66\\x39\\xf9\\x40\\x05\\x9d\\xa2\\xbb\\x7c\\xef\\xe2\\xec\\xeb\\x0f\\xfb\\x96\\xe1\\x21\\x14\\x70\\x72\\xb4\\x32\\x6b\\xfb\\x22\\x7e\\xf8\\xe9\\xa6\\x80\\x4f\\xc9\\xf2\\xd4\\xf5\\xa6\\xa7\\xde\\x78\\x6a\\xe2\\xf4\\x6d\\x0c\\x13\\x96\\x04\\x15\\xec\\xac\\x43\\x08\\x6a\\x05\\x4e\\xee\\xd9\\x72\\xbb\\x0b\\x4c\\x93\\xf6\\xbd\\x89\\xf4\\xf2\\xa9\\x32\\x2f\\xf3\\xab\\xc7\\x9c\\x80\\x28\\xc4\\x7d\\xd7\\x5b\\x3e\\x2c\\xdd\\xe5\\x01\\x29\\x2d\\xad\\x29\\xb9\\x30\\x8a\\x1a\\x36\\x5d\\x1c\\xb1\\xaa\\x90\\x0b\\xcb\\x00\\x67\\x51\\xc4\\x1d\\x6f\\x1d\\xa3\\x46\\xa5\\xc6\\x34\\x23\\xaa\\x2e\\x00\\x4d\\x38\\xbf\\xd1\\x4b\\x47\\x30\\x96\\x37\\x12\\x92\\x0b\\x6d\\x68\\x51\\xd8\\x77\\x87\\xe7\\xdf\\x49\\xd1\\x83\\xcf\\xd5\\x87\\x9e\\xa0\\x43\\xa4\\xf3\\xde\\xbb\\xda\\xbd\\xe4\\xec\\x2e\\xb9\\xf3\\x27\\x0f\\x3f\\x43\\x61\\xf8\\xfb\\x79\\x76\\x9d\\x14\\xa6\\x07\\x27\\x2b\\xa5\\x9c\\xb5\\x28\\x0c\\xce\\xeb\\xc2\\x9e\\x6d\\x45\\xde\\xee\\xbd\\x87\\x9a\\xa7\\x63\\x05\\xc4\\x3b\\x06\\xd1\\x61\\x5f\\x72\\x40\\xc6\\xb5\\x55\\x4b\\x99\\x6e\\xc5\\x30\\xa3\\x9f\\x3f\\x68\\x7c\\x6c\\xef\\x77\\x3d\\xc3\\x84\\x3d\\xfb\\x60\\x42\\xab\\xaa\\xe0\\x58\\x9c\\x2a\\x95\\xcb\\x9e\\x8b\\xa2\\x4b\\x37\\x6f\\x7b\\x88\\x94\\x5a\\x53\\x83\\x5b\\x4f\\x63\\x1b\\x92\\x39\\x53\\xe3\\x87\\xb8\\x6c\\xd6\\x55\\xc6\\x68\\xc5\\x21\\x0f\\xe1\\xc1\\xba\\x5b\\xaa\\xbe\\x75\\x78\\x76\\x82\\x03\\xad\\x8a\\xf7\\xf9\\x2f\\x91\\x21\\xdc\\x52\\xfb\\x48\\x3c\\xd6\\x91\\x38\\xd7\\x66\\x68\\x87\\x70\\x78\\x76\\x82\\x5d\\x46\\x5c\\x47\\x84\\xc6\\xdd\\x69\\x0d\\x37\\x8a\\x55\\x53\\x4d\\xc3\\x32\\x3a\\xb5\\x4f\\x34\\x44\\x0a\\xb6\\x4e\\xeb\\x2b\\x4b\\x01\\x13\\x75\\xc9\\xb0\\xdb\\x42\\x20\\x86\\x70\\x01\\xe3\\x04\\x2a\\x1a\\xaf\\xaa\\x35\\x8a\\xad\\x8d\\xbc\\xb3\\x13\\x5b\\x14\\x58\\xd5\\xaf\\x22\\xba\\x41\\xd4\\xed\\x7c\\xd1\\xba\\xcb\\xca\\xb5\\xe6\\xc5\\x1e\\x7a\\x38\\xae\\x9f\\xae\\xb8\\x66\\x7a\\xe2\\xda\\xa7\\xad\\x90\\xe2\\xdc\\x4d\\xd5\\x77\\xe7\\xef\\x1f\\x9d\\xb7\\x4e\\xdb\\xc3\\x39\\xb8\\x7a\\x06\\x2d\\xa5\\x2a\\xaa\\x0c\\xa7\\x05\\xa9\\x55\\xe1\\x53\\x7a\\xb0\\xf6\\xdc\\x55\\xe1\\xcc\\xe8\\x3c\\x6a\\x05\\x30\\x22\\xe4\\x0b\\x64\\x28\\xb7\\x8e\\x28\\x85\\xc0\\xad\\xe5\\x5a\\x63\\x4c\\xea\\xa2\\x18\\x90\\x09\\x17\\xd4\\x9e\\x41\\xac\\x22\\x51\\x62\\xc5\\x83\\x29\\xbe\\xe0\\x22\\xb3\\x26\\xbe\\x18\\x7a\\x96\\x22\\x40\\xb9\\x37\\xfc\\x83\\x38\\x82\\xbc\\x28\\x30\\x4a\\x58\\x91\\x43\\x3b\\x35\\x20\\xc5\\x8a\\xa6\\x0c\\x3c\\x7b\\x13\\xa9\\xc8\\xdb\\xa2\\xd6\\x86\\xa9\\x73\\x69\\x4f\\xd0\\x26\\xc5\\x1b\\x81\\x99\\x69\\xfc\\xf5\\xd7\\x5c\\xe4\\x6b\\x55\\x1f\\x9c\\xc3\\xa9\\x9c\\x51\\x41\\x18\\x07\\x4f\\xaf\\x1d\\x1a\\x72\\x10\\x2d\\x9f\\x36\\xfb\\x61\\x4f\\xd7\\xd9\\xcc\\x4e\\xd1\\x4e\\x25\\x73\\xbd\\x63\\x05\\xeb\\x0e\\x46\\x3f\\xf4\\xce\\xbe\\xfd\\x6b\\xf9\\x5d\\x31\\x63\\x3a\\xfa\\xdd\\x01\\xad\\xf8\\xce\\xfe\\x80\\xc0\\x84\\x43\\x42\\x8c\\x7c\\x78\\x06\\xcc\\xf6\\x6d\\x01\\xff\\xae\\xe0\\x67\\x49\\xda\\x00\\xe7\\xf1\\x13\\x80\\xa7\\x45\\x93\\x7e\\x72\\x3d\\xe3\\x06\\xd3\\xdb\\x2d\\x93\\xa3\\x03\\x36\\x20\\xa7\\x2f\\x1f\\x5f\\x84\\x1c\\x0a\\xc2\\xca\\xca\\x40\\x0c\\x8f\\x94\\x8c\\xfa\\xf4\\x36\\x36\\x67\\x6a\\x61\\x66\\x0e\\x07\\xd9\\xcb\\xae\\x67\\x3f\\xe9\\xdd\\x26\\xdc\\x09\\x10\\x3f\\xb9\\x0d\\x93\\xc3\\x4e\\xbc\\x31\\xb9\\xbb\\x5f\\xec\\x2e\\xcb\\xf0\\xe6\\xd0\\x7a\\xb6\\x53\\x09\\x0a\\x47\\xd2\\x34\\x7e\\x6f\\x7f\\xd9\\x9e\\x42\\xfc\\x08\\xa5\\x6f\\x90\\x1f\\xef\\xdf\\xbb\\xf0\\x32\\xce\\xd5\\xb7\\x5c\\xe4\\xda\\x9f\\xfd\\xbe\\x60\\xd5\\xcd\\xf7\\xca\\x49\\x06\\x0a\\x9f\\xe3\\x04\\xdf\\xb4\\x0d\\x1e\\xaa\\xcf\\xdf\\xf1\\x78\\x6f\\x0e\\xdd\\xf6\\xa8\\x3b\\x1f\\xe0\\x6c\\xaa\\x0f\\x32\\x5f\\xbd\\x75\\x5a\\xeb\\x7b\\x12\\xdd\\x1c\\x12\\xe0\\x1a\\x47\\x96\\x7b\\x96\\x53\\xf0\\x17\\xd5\\x4a\\x63\\xe9\\xee\\xe5\\xb8\\x63\\xea\\x6f\\xa3\\xa4\\xf1\\xc4\\x80\\x9c\\x8c\\xbe\\x01\\xb7\\x1e\\xb6\\x48\\x26\\x93\\x82\\x4e\\x1b\\x36\\x02\\xa9\\x87\\x0a\\xe8\\xdb\\x8b\\xef\\xfd\\x2b\\x68\\x72\\x0b\\x1c\\xe0\\xbd\\x1a\\xfe\\x7d\\x3a\\xfd\\xb0\\x99\\xa5\\x5b\\xef\\xb0\\x83\\xac\\xfc\\xf2\\x7e\\xc5\\x3e\\x3c\\xfc\\x76\\x6e\\x7a\\x48\\xca\\x85\\xb9\\xd3\\x19\\x7b\\xdb\\xfc\\x7b\\xe7\\x29\\x8d\\x38\\xc1\\x37\\x0e\\xf1\\x16\\x3b\\x64\\x33\\x83\\xbe\\x72\\xf1\\x7d\\x8b\\x4d\\xee\\xa1\\xf7\\x16\\xa6\\xbd\\x62\\x8b\\x6b\\xa9\\x56\\xb7\\x50\\x6e\\x91\\x79\\x18\\xe4\\x90\\xff\\x89\\xb7\\x39\\x7d\\x1e\\x06\\x3a\\x5c\\xe5\\xca\\x48\\x4e\\x32\\xab\\xde\\x49\\x7c\\x41\\xc7\\xac\\xb8\\x9f\\xf4\\x5b\\x94\\xe0\\x0f\\xb4\\xb2\\xaf\\xd3\\x94\\x04\\xa1\\xe3\\xc4\\x25\\x78\\xa0\\x11\\x85\\x79\\xe4\\xbe\\xe2\\x41\\xaa\\x29\\x15\\xfc\\x5f\\x58\\x47\\x95\\x59\\x49\\x21\\x15\\xff\\xd7\\x6a\\x56\\xdb\\xc3\\x08\\x24\\xba\\x62\\x0a\\x96\\x99\\x7d\\xc7\\xf5\\x2b\\xa5\\xed\\x3d\\xdb\\x82\\xe6\\x39\\x47\\x9d\\xe5\\xec\\x1e\\x0e\\xbe\\x7b\\xbe\\xb8\\xb8\\x5a\\x67\\xa5\\xe1\\x7e\\x4c\\xe3\\xc6\\x09\\x78\\xe4\\x65\\xbe\\x43\\x2c\\xdc\\xbf\\x73\\xef\\xce\\x60\\x79\\xc0\\xc9\\x52\\xab\\x3b\\xb2\\x9b\\xef\\xfc\\x7d\\x49\\x39\\x1e\\xb8\\xab\\xfb\\x31\\xdc\\x32\\xbb\\x8e\\x9b\\xa8\\x53\\x46\\xad\\x2c\\xb5\\xef\\x17\\x9e\\xf6\\x04\\xfb\\xaa\\xd3\\x84\\xb3\\x92\\xf2\\xd4\\x19\\xc3\\xab\\xc3\\x92\\x95\\xd4\\xd4\\x8a\\x9b\\x95\\x27\\xf5\\xdd\\x3f\\xe4\\xe2\\xdb\\x7a\\xcc\\x5c\\x66\\xcd\\xda\\x3f\\x17\\x50\\xd1\\x70\\x78\\x76\\xb2\\x72\\x5a\\xfa\\x39\\x91\\x6f\\x35\\xda\\xc1\\xbd\\xe3\\x28\\xb7\\x9a\\x1e\\xa9\\x05\\x2d\\xc7\\x7c\\x5a\\xcb\\x5a\\x17\\x8b\\xd8\\x47\\x4e\\x21\\x63\\x68\\x44\\xc8\\x09\\x7a\\xff\\xc4\\xae\\x21\\x54\\x48\\xb1\\x28\\xdd\\xad\\x22\\x2b\\xea\\x9c\\xb5\\x9e\\x78\\xdb\\x51\\x26\\x09\\x9d\\x4b\\x9e\\x13\\x5a\\x1b\\x59\\x52\\xc3\\x33\\x92\\x49\\xa6\\x32\\x80\\x88\\x8b\\x9f\\x5f\\x6b\\x46\\x68\\xeb\\x89\\xcd\\x6f\\xb3\\x5a\\x1b\\x59\\x92\\x92\\x2a\\x3d\\xa3\\x45\\x71\\x1b\\x4b\\xf4\\xa0\\x1d\\xdc\\xd5\\x34\\x77\\x08\\xb3\\x72\\xeb\\x97\\xf3\\x3b\\xe6\\xe1\\xfe\\xed\\x70\\x4f\\x5b\\xe2\\x07\\x6c\\x07\\x4b\\x5c\\xa7\\x07\\xcc\\x6f\\x67\\xea\\x07\\x3c\\xc3\\xe1\\xfb\\xad\\xc4\\xca\\x6e\\xf1\\xe7\\xe5\\x8c\\x91\\xaa\\x1e\\x17\\x5c\\x83\\xcd\\x0b\\x82\\x6b\\x41\\xc6\\x6c\\xc6\\x5d\\x15\\xd6\\xfd\\x12\\xeb\\xd6\\x25\\xbe\\x6f\\x9e\\xef\\x12\\x19\\xf7\\xce\\xd0\\x1d\\x12\\xfe\\xce\\xdf\\xba\\x13\\xf0\\xa4\\xa4\\xd3\\x07\\xa8\\xf6\\xb7\\x6c\\xdf\\xf7\\x56\\xec\\x53\\xb1\\x08\\xe7\\x29\\x34\\xb1\\xd2\\x03\\x22\\x95\\xcb\\xff\\xf3\\x66\\x9b\\x72\\x5f\\x85\\x0e\\x71\\x8a\\x7c\\x74\\x33\\xea\\xea\\xee\\xdc\\x36\\x80\\x2a\\x56\\xa6\\x26\\x52\\x95\\x76\\xde\\xb9\\x22\\x93\\x5a\\x80\\xd3\\xf6\\x16\\x93\\x0e\\x32\\x8e\\xe0\\xfc\\x71\\x8e\\x3b\\x5a\\x68\\x19\\x84\\x01\\x2c\\x9b\\xf0\\x84\\x11\\xaa\\xc9\\x35\\x2b\\x8a\\x11\\x39\\x2c\\x0a\\xd7\\x71\\x2b\\x02\\xa5\\x6c\\xc0\\xcd\\x9a\\xc4\\xa7\\xf1\\x6a\\xb3\\x30\\xe7\\x53\\xa6\\x0d\\xd9\\xbb\\xf8\\xdb\\xe1\\x3e\\x28\\x44\\xe0\\x98\\x5a\\x10\\x43\\xa7\\x23\\x24\\xa9\\xed\\x98\\x03\\x75\\x2b\\xaf\\x41\\x2d\\xcb\\xa8\\xa1\\x85\\x9c\\x62\\xbe\\x8c\\x15\\x29\\xf6\\xf7\\x55\\x41\\x17\\xd0\\x21\\xbb\\xa2\\x0a\\x0a\\x5c\\x32\\x74\\xce\\x11\\x55\\x8b\\xdb\\x5a\\x3c\\x3e\\xde\\x49\\x79\\xbf\\x4c\\xba\\xab\\xa5\\xe2\\x10\\x58\\x3a\\x51\\xe6\\xdc\\xd3\\x9f\\xed\\x71\\x8f\\x60\\xc5\\xaa\\x82\\xde\\xe2\\x26\\xba\\x21\\x2f\\x1a\\x68\\x2d\\x6b\\xb7\\x80\\x4f\\x42\\x0a\\x16\\x9e\\x31\\x22\\x17\\xc8\\x4f\\x25\\x35\\x19\\x66\\x00\\xfc\\xa3\\x64\\x86\\xe6\\xd4\\xd0\\x91\\x35\\xee\\xff\\xd1\\x86\\xe0\\x90\\x45\\x6e\\x1f\\x74\\xfb\\x42\\xdf\\x42\\x33\\xaa\\xe2\\xf2\\x7e\\x19\\xf7\\xde\\x9a\\x16\\xe1\\x76\\x30\\xb8\\xfc\\xbe\\xbd\\xd3\\x2f\\xd5\\x51\\xbc\\xc1\\xeb\\x1f\\x7f\\xb2\\xb6\\xf5\\x9d\\x11\\xe7\\x16\\xad\\xcb\\x3f\\x6a\\xbb\\x8d\\x8a\\xf6\\x9b\\x38\\x6e\\x2d\\x99\\x30\\x7a\\x04\\x4b\\x13\\x7f\\x02\\xbe\\xf3\\xc3\\xd3\\xa3\\xdb\\xfd\\x97\\xf7\\xfb\\x80\\xee\\xf1\\xf9\\x3c\\x3c\\x3e\\x71\\x78\\x07\\xed\\x3e\\x3c\\xe1\\xbe\\x69\\x87\\xbc\\x7c\\x21\\x36\\xc0\\x7c\\x60\\x71\\x30\\x15\\xe1\\x54\\x82\\x9b\\xef\\x18\\x16\\xd7\\xb9\\x81\\x0a\\x68\\x8c\\xc2\\xdb\\xfd\\x64\\x0f\\x0a\\x5c\\x3e\\x24\\x5c\\x79\\x1f\\x72\\xc3\\x30\\xbc\\xc6\\xad\\x37\\x3d\\x2c\\x7a\\x79\\x2f\\xba\\xc2\\x6d\\xe8\\x09\\xb8\\x26\\x50\\xb6\\xeb\\x5d\\xe5\\x61\\x19\\x1e\\x1a\\xed\\x7d\\xa0\\x9f\\xcf\\xbf\\xea\\x1a\\x84\\xde\\x1b\\xf0\\x0a\\x5c\\xd0\\xca\\x54\\xbc\\x62\\x8b\\x5d\\x67\\xe9\\xda\\x1d\\x34\\xe3\\x15\\xe2\\x83\\xb8\\xf8\\xd7\\x7d\\xcb\\x8f\\xd7\\xf7\\xb4\\xe0\\x79\\x18\\x00\\xf7\\xd2\\x89\\x18\\x90\\x53\\x69\\xec\\x3f\\xc7\\x9f\\xb8\\x36\\xe8\\x63\\x38\\x92\\x4c\\x9f\\x4a\\x03\\x9f\\xf4\\x32\\x53\\x48\\x60\\x9f\\xf3\\xe4\\xdc\\x20\\x18\\x31\\x81\\xed\\x1e\\x39\\x4b\\xdc\\x7c\\x20\\x42\\x74\\xa3\\xef\\xd9\\xbb\\x4f\\x84\\x55\\x68\\xf0\\x95\\xef\\x19\\x22\\x80\\x0e\\x69\\x37\\x80\\xaf\\xf0\\x15\\x52\\x0c\\x21\\xd2\\xb2\\x72\\x04\\x37\\x8f\\x52\\xb5\\xa6\\x31\\x79\\x30\\x37\\x10\\x26\\x63\\xc3\\x37\\x5c\\xfb\\x73\\x29\\xa8\\x21\\xd4\\xbb\\x86\\xef\\xad\\x72\\x28\\x99\\x9a\\x42\\x1c\\x33\\xbb\\x27\\xee\\xf6\\x50\\x67\\xfa\\x83\\x5c\\xe8\\xf7\\xb2\\x09\\x9c\\x11\\xef\\x6f\\xf5\\x97\\x91\\x35\\xf8\\x23\\x7a\\x14\\x4a\\xe1\\x12\\x1d\\x69\\xff\\x63\\x85\\x2d\\x4c\\xf1\\xff\\x02\\x80\\x96\\x1e\\x91\\x43\\xa2\\xb9\\x98\\x16\\xac\\xf5\\x9d\\x0b\\xf5\\x46\\x8f\\xb9\\x63\\xa8\\xca\\x0e\\x61\\xe5\\xe6\\x9c\\x16\\x0c\\xdb\\x24\\x53\\x11\\x4a\\xef\\xe5\\xe4\\xc6\\xe1\\x37\\x70\\x40\\x59\\x56\\x40\\x05\\xb5\\x72\\xe7\\x8a\\x2d\\x76\\x06\\x77\\x26\\xd9\\xc7\\x1c\\xb6\\x73\\x22\\x76\\x1a\\x4c\\x89\\x16\\xd7\\x84\\x33\\x06\\x34\\xd5\\x1d\\xf8\\x6e\\x27\\xfd\\x1c\\xbd\\xf3\\xc4\\x78\\xb8\\xd7\\x8f\\xdc\\xcf\\x02\\xeb\\x55\\xee\\xe8\\x2b\\xbe\\x3a\\x9b\\xe5\\x21\\x4c\\xe2\\xf5\\xbd\\x3d\\xbd\\x0f\\x7e\\x2e\\xc1\\x08\\x80\\x9e\\x28\\x08\\x11\\xd8\\x4f\\x63\\x04\\x4f\\x6b\\x41\\x5c\\xf1\\xaa\\x6a\\xe0\\x55\\xeb\\x6a\\xaa\\x68\\xce\\xc8\\x54\\xd1\\xea\\x96\\x4d\\xb4\\x9e\\xb6\\x88\\x2a\\xe7\\xaa\\x21\\xef\\x30\\x93\\xb6\\xdf\\x26\\xb9\\x65\\xad\\xef\\xf0\\x02\\xdc\\xf9\\xbb\\x6b\\x36\\x9e\\x49\\x79\\x05\\xf0\\x0a\\xc0\\x77\\x8f\\xe8\\xe2\\xfa\\x01\\xc7\\x3a\\x6a\\x3e\\xf3\\xee\\x07\\x4d\\x72\\x66\\x28\\x2f\\x20\\xb3\\xec\\xe3\\xfb\\x0f\\x2e\\xf7\\xcc\\xeb\\x4e\\x9e\\xca\\xd5\\x32\\xa3\\x07\\x5b\\x8d\\xe6\\x2e\\xbd\\xf2\\x9c\\xcd\\x39\\xbb\\x76\\x9e\\xac\\xdb\\x44\\xd4\\x90\\x4c\\x99\\x80\\xbc\\xa6\\x3b\\xb2\\x13\\x87\\x44\\xf3\\x9c\\x1d\\x03\\x08\\xce\\xed\\x0f\\xea\\x10\\xb4\\xba\\x85\\xe6\\xfb\\x64\\xc5\\xdd\\x67\\xcf\\xbd\\xe7\\xce\\x03\\x54\\x93\\xe0\\xd1\\x38\\x93\\xea\\x0e\\x24\\xe1\\x87\\xc1\\xea\\x3c\\x0c\\x32\\xc7\\x55\\x01\\xbd\\x21\\xbf\\xfb\\xdd\\x57\\x77\\x9c\\x2b\\x9f\\x78\\x59\\x97\\x6f\\xc8\\x1f\\x7e\\xff\\xfb\\xaf\\x7e\\x7f\\xfb\\x6d\\x5c\\xe0\\x6d\\xaf\\x6f\\x7f\\x3f\\xb7\\xdb\\xde\\x9e\\x1f\\x6d\\xc1\\x7c\\xe7\\x21\\x4d\\xf8\\xee\\x80\\xf8\\x03\\x1e\\x35\\xa1\\xbc\\xa8\\x95\\x4b\\x50\\x7f\\xa0\\x35\\xf7\\x2e\\xfe\\x0d\\x04\\x33\\x9b\\xa2\\x3c\\xea\\x9f\\xe8\\xd3\\x53\\x5d\\xda\\xea\\x84\\x0b\\xa6\\xa1\\x51\\x7e\\x2d\\x14\\xcb\\xe4\\x54\\xf0\\x7f\\xb1\\xdc\\xf7\\xc9\\x87\\xe4\\x2b\\xe8\\x1d\\xea\\x59\\x9c\\x30\\x91\\x57\\x92\\x0b\\x03\\x47\\xec\\x8c\\x8a\\xbc\\xb8\\x2b\\xd9\\xe6\\x01\\x6f\\x1a\\xef\\xe0\\x4e\\x53\\x06\\xa7\\xd1\\x5a\\x13\\xf6\\xa1\\xf9\\xc5\\xd2\\x74\\xd9\\x77\\xf6\\xa1\\x5f\\x3c\\xe5\\x70\\xda\\x3a\\xbd\\x29\\x0a\\xc6\\x8b\\x3b\\x7c\\x20\\x2b\\x68\\x5c\\xcf\\x44\\x47\\xd7\\x03\\x7c\\xf6\\x73\\xcd\\xd4\\x02\\xaa\\xfe\\x1a\\x43\\x2a\\x4a\\x44\\xbd\\x6c\\xe0\\xba\\xfc\\x3b\\x3a\\xa5\\x92\\xde\\xea\\xa3\\x27\\x2b\\x5c\\x24\\x91\\xaa\\xd5\\x64\\x68\\x2d\\x51\\x05\\xbf\\x61\\x98\\xf1\\xe2\\xa3\\xb0\\xe4\\x90\\x88\\xba\\x28\\xee\\x18\\xe9\\x96\\x87\\x08\\x79\\x57\\x24\\x17\\xaf\\x07\\xf9\\x03\\x1e\\x66\\xa8\\x3f\\xd4\\x25\\x84\\xd7\\xe6\\x1c\\x43\\xf1\\x8b\\xf7\\x64\\xd5\\xac\\x9b\\xca\\xba\\x21\\x87\\x11\\x5e\\x29\\x6e\\x23\\xbc\\xd6\\xc8\\x7a\\x7f\\x78\\xc6\\xfb\\xc3\\x20\\x40\\x1f\\xe0\\x4e\\xc2\\x6b\\x9d\\x94\\xf8\\x07\\x02\\x77\\x3e\\xa6\\x83\\x09\\xaf\\xb5\\xf2\\xf5\\x1e\\xe6\\x6c\\x5a\\x41\\xfa\\x03\\x73\\xac\\x1f\\xd1\\xf1\\x84\\xd7\\x63\\xb8\\x9f\\xf0\\x5a\\x6b\\x1e\\x1f\\xe2\\x8a\\xc2\\x2b\\x65\\x16\\x9f\\xc0\\x2d\\xe5\\xde\\xf9\\x29\\x9d\\x53\\xf7\\x0c\\xd9\\xb3\\x8b\\x0a\\xaf\\x07\\x3b\\xaa\\x1c\\x71\\x6b\\xe5\\x7e\\xae\\x91\\xf7\\xf9\\x40\\xe6\\x7a\\x80\\x03\\x0b\\xaf\\xf5\\xb8\\xea\\x09\\x9d\\x59\\x7e\\xc0\\x27\\x73\\x69\\xe1\\xf5\\xd4\\x8e\\x2d\\xbc\\x1e\\x7c\\xa6\\xad\\xe7\\xe4\\x8a\\x1f\\x7e\\x0f\\xcb\\xa4\\x40\\xd5\\x28\\xc6\\xc5\\x5c\\x62\\x53\\xb4\\xb5\\x14\\xf9\\xf3\\x1b\\x3f\\x5c\\xd2\\xe7\\xaf\\xe1\\x28\\x73\\x0a\\x7d\\xb0\\x80\\x62\\xbb\\x66\\x26\\xe5\\x15\\xa9\\xf5\\xfd\\x51\\xa6\\x3b\\xdf\\xfb\\x9e\\xca\\xc6\\x5e\\x0c\\xd1\\x75\\x76\\xd8\\x79\\x5d\\xb0\\x1f\\xb8\\x99\\x7d\\xf4\\xcd\\x22\\xdd\\x36\\x33\\x75\\x55\\xc0\\x5c\\x44\\x5f\\x58\\xbe\\x3c\\x6f\\x0c\\x84\\x13\\x83\\x62\\x2e\\x93\\x65\\xc9\\x44\\x8e\\x19\\x88\\x25\\xbd\\xba\\x9b\\xe1\\xb5\\x35\\x31\\x31\\x49\\xbe\\x28\\xd0\\x8c\\x82\\xa1\\xd8\\xa7\\x8a\\x8a\\xc6\\x60\\x98\\xdb\\xc3\\xf2\\x2e\\x16\\x7e\\x20\\x03\\x3f\\x54\\x2f\\x7a\\x70\\x89\\xe0\\xda\\x3a\\xef\\x72\\x49\\x60\\x54\\xd3\\xd7\\x2a\\xfd\\x23\\x63\\x56\\x48\\x40\\x85\\xc1\\x42\\x00\\x2c\\x55\\x79\\x70\\x95\\xdc\\xc9\\xc4\\xff\\xca\\x69\\x2f\\xae\\x37\\x04\\x13\\xd3\\x06\\xdc\\x57\\x17\\x3c\\x63\\xe1\\xd8\\x92\\xe2\\x01\\xa5\\xe9\\xe7\\x4e\\xa3\\x7d\\x98\\x92\\xfc\\x90\\xf3\\xe7\\x81\\x67\\xcf\\x1a\\x4a\\x4d\\x4b\\x94\\x58\\xf3\\xe9\\xe1\\xb0\\x57\\x0d\\x88\\xd7\\x63\\xac\\xbc\\x7f\\x74\\xbc\\xf6\\x73\\xff\\xd9\\x43\\x56\\xdf\\xdf\\xfc\\xb2\\xfe\\x77\\x5d\\x1d\\xd6\\x3f\\x34\\xc9\\xed\\x7d\\xf9\\xdb\\x12\\xb5\\xd1\\x43\\xc3\\xda\\x2f\\x1d\\x2d\\x19\\x55\\xf6\\xb0\\x07\\x6f\\xfa\\x90\\xbc\\x3d\\x3f\\x3e\\xbc\\x3c\\x1e\\x90\\xef\\xce\\x8e\\xe0\\xdf\\xa3\\xff\\x8f\\xbd\\x37\\xef\\x8e\\xdc\\xb6\\x16\\xc4\\xff\\xfe\\xf9\\x53\\xe0\\x28\\x39\\x47\\x92\\x53\\x55\\xea\\xf6\\xcb\\x24\\x79\\x3d\\x79\\xf1\\x51\\x7a\\xf1\\xe8\\xb9\\x17\\x4d\\x4b\\xb6\\xcf\\x8c\\x9f\\xe7\\x19\\x22\\x51\\x2a\\x44\\x2c\\x80\\x21\\x40\\xa9\\x2b\\xcb\\x77\\xff\\x1d\\xdc\\x0b\\x80\\x60\\x55\\xb1\\x08\\xb2\\x16\\xa9\\x1d\\xe2\\x0f\\x5b\\x5d\\x24\\xb1\\x5c\\x00\\x77\\x5f\\x5e\\xbf\\x7d\\x6d\\xfe\\xff\\xf2\\xc3\\xfb\\xf7\\xaf\\x5f\\x5e\\x1b\\x06\\xf6\\xcb\\xd6\\x29\\x40\\xb5\\xcb\\x2c\\xc3\\xdd\\x37\\x1c\\x8a\\xac\\x23\\x73\\x2a\\x16\\x64\\x5a\\x6a\\x83\\x91\\xab\\xc9\\xd4\\x66\\x49\\x51\\x8d\\x47\\xd3\\x34\\x26\\x62\\xee\\x17\\x77\\x06\\x6b\\x7b\\xee\\x37\\x74\\x59\\x73\\x1a\\x96\\x5a\\xc6\\x02\\xa3\\x36\\x24\\xbb\\x7d\\x65\\x87\\x39\\xe4\\xd1\\x11\\x83\\x5d\\xcf\\x78\\xbf\\x60\\xc2\\x2f\\xbe\\x68\\xed\\xf8\\x8d\\x2c\\x08\\xfb\\x44\\xe7\\x79\\x16\\x11\\x36\\x76\\x9c\\xcb\\x54\\x1d\\xdb\\x88\\x4f\\xf3\\x77\\x3b\\xdc\\xe1\\x93\\xb3\\x4c\\xde\\x1e\\xfb\\x40\\x51\\x46\\x32\\x79\\x4b\\x54\\x79\\xe3\\x03\\x78\\x81\\x13\\x8c\\xea\\xed\\x4b\\xd7\\x4d\\x2d\\x2e\\x72\\xe4\\xa3\\x7c\\x83\\x5e\\xa3\\x27\\x57\\xeb\\x33\\xec\\xa0\\xcb\\xbc\\xce\\x54\\x42\\x33\\x56\\xeb\\xc9\\xfc\\xd0\\x75\\x42\\x5f\\x9e\\xad\\x5f\\xa1\\x13\\x55\\x78\\xb1\\xd4\\x63\\xfb\\x0e\\x5f\\x4c\\xc9\\x03\\xcf\\xd2\\x84\\x16\\xe9\\x0a\\xc2\\x00\\xe6\\x0f\\xef\\x13\\x9c\\x1d\\x2c\\xc7\\x24\\x80\\x75\\xac\\xc6\\xc6\\x64\\x6e\\xed\\x7a\\xa3\\x7b\\x56\\x64\\x34\\xc7\\xe8\\x38\\xa8\\x23\\x06\\xde\\xbc\\x31\\x73\\x7c\\xc5\\x72\\x06\\xa1\\xe4\\x58\\x3b\\x85\\x11\\x26\\x92\\x4c\\x42\\xba\\x3a\\x64\\x3c\\x47\\xf5\\x8d\\x41\\xe7\\x5f\\x57\\xe7\\x20\\x36\\xce\\xf8\\x17\\x4e\\x61\\x21\\xce\\x6a\\xd7\\x88\\x07\\x83\\xb7\\x1a\\x53\\x4a\\xba\\x88\\xda\\xd6\\x7e\\x50\\x27\\xe7\\x05\\x6d\\x46\\x8e\\x6c\\x1e\\x81\\xa3\\x11\\x39\\xf2\\xd9\\x03\\x53\\x2b\\x94\\x1f\\x7d\\x79\\xd4\\xda\\xa3\\xef\\x20\\x8c\\x40\\x07\\x99\\xdd\\x3a\\x1c\\x8c\\x61\\x9e\\x61\\x9a\\x0d\\x38\\xde\\xce\\x55\\x22\\x7a\\xea\\x55\\x66\\x4d\\xc3\\x55\\x5a\\x8b\\x07\\xac\\xa1\\x3e\\x50\\x7b\\x4f\\xe1\\x42\\x57\\x66\\x5d\\x25\\x69\\xd8\\x7a\\xc6\\x47\\x5f\\xd6\\xba\\xd7\\x90\\x25\\x0a\\x93\\x41\\xd8\\xcd\\x2b\\x98\\x39\\x8d\\x9b\\x3c\\xe4\\xc3\\x76\\x55\\xbb\\x7b\\xde\\xd5\\x24\\x4c\\x2d\\xca\\x0b\\x92\\xd3\\x82\\x09\\xed\\x27\\xdf\\xde\\x6d\\x50\\xaf\\xfb\\xe8\\xcb\\xa3\\xb8\\x5b\\xb9\\xf1\\x12\\x05\\xde\\x05\\x91\\xea\\x8a\\x2b\\xff\\xc5\\xcb\\x8c\\x2a\\xb5\\xc6\\xee\\x08\\x54\\xc0\\x74\\x4c\\x18\\xf6\\x4c\\xa8\\x73\\xbd\\x80\\x0a\\x72\\x33\\x7a\\xbf\\x61\\xa9\\x11\\x93\\xd6\\xb4\\xb8\\x65\\x7a\\xb3\\x5f\\x00\\x15\\x8b\\x0f\\x1b\\xd3\\x92\\x8f\\xa3\\x2b\\xf2\\x8c\\x7b\\x28\\x8d\\xb8\\xd0\\x63\\x59\\x8c\\xf1\\x93\\x17\\x44\\x17\\x65\\x93\\xea\\x41\\xf3\\x39\\x93\\xa5\\xbe\\x62\\x89\\x14\\xeb\\x63\\x69\\xed\\x7b\\x3b\\x73\\x74\\xe8\\x10\\x60\\x6c\\x7d\\x6d\\xce\\x1d\\x07\\x1e\\xd6\\x4a\\x70\\x1a\\xa9\\x8a\\x3d\\x77\\xfe\\x35\\xf5\\xac\\x8a\\x1f\\xde\\xbe\\xdb\\x66\\xb3\\x09\\xe4\\xff\\xd9\\xbc\\x93\\xdf\\x5b\\xa2\\x2c\\x6e\\xfd\\x4c\\xed\\xcc\\x37\\x7e\\xf6\\xae\\xd4\\xdd\\x3f\\x7a\\xe9\\xfd\\x36\\x36\\xbf\\x6d\\x81\\xb1\\x39\\xc3\\x5d\\xe3\\xfa\\x95\\xa6\\xba\\x5c\\x39\\x0d\\x6d\\xa4\\xc8\\xe2\\xf7\\x2b\\xcc\\x6f\\x60\\x25\\xfc\\x2b\\xe8\\x2a\\x34\\x1d\\x85\\x19\\xc0\\x50\\xa8\\xc3\\xec\\x81\\xf0\\x9e\\x0b\\xb4\\x98\\x10\\xfb\\xa1\\xb9\\xb2\\xba\\xa0\\x1c\\x35\\x62\\x34\\xd1\\x25\\x5d\\xb5\\x7c\\x9b\\x8f\\x6d\\x90\\xc6\\xfa\\x94\\x99\\x1b\\x74\\x62\\x9b\\xf4\\x60\\x09\\x2b\\xb4\\x7a\\x4b\\x95\\xfe\\x2e\\x4f\\x69\\x43\\x68\\xfd\\x52\\xf0\\x85\\xd2\\x70\\xa7\\x50\\xac\\x7d\\x10\\x2c\\x35\\x44\\xc8\\x82\\x04\\xfb\\x23\\x0f\\x06\\xbb\\x97\\xd8\\xe3\\x9a\\x0e\\x5b\\x4e\\xa5\\xbb\\x63\\xe6\\xf3\\xb1\\x19\\x6a\\xfd\\xac\\x3f\\x4a\\x03\\x93\\xf3\\xb5\\x38\\xaa\\x1e\\xe3\\xd2\\x36\\x5b\\x43\\xd1\\x0a\\xe8\\x8d\\x08\\xf6\\x69\\x1d\\x5b\\xb9\\xfd\\x8c\\x33\\x46\\xc5\\xfa\\x18\\xc4\\xda\\x5c\\x5f\\xe2\\x7b\\xdd\\xcf\\x94\\x1d\\x80\\x3c\\xcc\\xb8\\x91\\xb8\\x30\\x05\\x81\\x22\\x8e\\x89\\x4d\\x59\\xc6\\x1a\\x32\\x11\\x6c\\x19\\x16\\x63\\x47\\x78\\x65\\x07\\xd8\\xd6\\x83\\xf9\\xb2\\xde\\x9d\\x37\\x3c\\x5b\\xf1\\xd2\\x06\\xab\\x56\\x72\\x9a\\xe5\\x7d\\xbc\\xba\\x62\\x79\\xc1\\xc0\\xbc\\xdd\\x64\\x32\\xb9\\xc3\\x84\\xc6\\x90\\xd7\\x8a\\xff\\x8d\\x15\\x1b\\x98\\x0c\\x30\\xe6\\x71\\x91\\xf2\\xc4\\x7b\\x0d\\xe4\\x85\\xbc\\x2d\\x98\\xaa\\x81\\x1a\\x93\\x5f\\x2a\\xec\\xdd\\x8c\\x69\\x60\\xee\\xc7\\x95\\x45\\x65\\xde\\x29\\x85\\xcd\\x06\\x71\\x98\\xc8\\x1d\\x27\\x9a\\x43\\x58\\x63\\xcd\\xa4\\xbd\\x2a\\xa5\\x63\\x76\\x40\\x48\\x6d\\x6f\\x75\\x34\\x74\\x6e\\x63\\x8f\\xcf\\xbe\\x6d\\x8e\\xc8\\xdd\\x69\\x58\\xcd\\xa6\\xb8\\x60\\x7c\\x03\\xc0\\x27\\x92\\x8d\\x79\\x29\\x37\\x46\\x10\\xc7\\x5a\\x03\\x5a\\x22\\x85\\x49\\xbc\\xe8\\xe4\\xa7\\x1c\\xd3\\xdb\\x4e\\x43\\x0d\\x76\\xee\\xad\\xd2\\x18\\x05\\x59\\xb5\\x2e\\x3e\\x28\\xb1\\xf5\\x4c\\x3a\\xb9\\x36\\x88\\x2e\\xb5\\x0f\\x6a\\xb7\\xa5\\x12\\xa6\\x6c\\x4a\\x11\\x74\\x53\\x9b\\xca\\xa2\\x51\\x6c\\xdb\\xdd\\xe4\\x37\\xc7\\x95\\xb7\\x76\\x64\\x78\\xda\\x66\\x7f\\xf0\\x3a\\xe1\\x76\\x18\\xd4\\x7f\\x32\\x22\\x94\\xcc\\xb8\\xd2\\xb2\\xb0\\x8e\\x1a\\x86\\x00\\xea\\x82\\x0a\\x85\\xcf\\x1b\\x69\\xc5\\xb6\\x1e\\xe6\\x2f\\xfd\\x14\\x08\\xcd\\x73\\x46\\x7d\\x3d\\x77\\x4b\\xce\\xa0\\xb0\\x7a\\xc1\\x12\\x59\\xa4\\x6b\\x27\\xe6\\x54\\x32\\x6b\\xd9\\xb1\\xb5\\xc3\\xef\\x20\\xa5\\x46\\x46\\x95\\xbe\\xf6\\x73\\x30\\x3c\\x45\\x24\\x36\\xae\\x73\\x4c\\x76\\x89\\xd5\\x6a\\x5c\\x1a\\x43\\x29\\xaa\\x87\\x92\\x50\\x61\\x35\\x55\\x4d\\x43\\x44\\x9d\\xaf\\x76\\xbe\\xa4\\x5a\\x1b\\x32\\x80\\xbd\\xd6\\xf5\\xe0\\x99\\xbd\\x60\\x89\\x87\\x99\\xf9\\x9c\\x29\\xb5\\x31\\xce\\x7a\\x29\\xc1\\x0b\\x94\\x8d\\x21\\xbe\\x6c\\x8c\\xfd\\xdc\\x11\\x7b\\x64\\x1c\\x30\\xc4\\xc1\\xe5\\xd5\\x5d\\x34\\x1f\\x35\\x02\\x6c\\x02\\xaa\\x41\\xfc\\xb5\\xda\\x6a\\xcb\\xf2\\x19\\x55\\xb1\\x8b\\xf1\\xb7\\xc8\\x87\\xd2\\x44\\x5f\\x87\\xc8\\xd9\\x14\\x8c\\xaa\\x4d\\x29\\x2b\\xba\\xf8\\x22\\xdf\\x14\\x9c\\x4d\\xc9\\x4b\\x3a\\x67\\xd9\\x4b\\xaa\\x76\\x09\\x79\\x40\\x0f\\x9b\\x54\\x35\\x6c\\x72\\x3b\\x21\\xc7\\x1f\\x03\\x4f\\x99\\xf7\\x52\\xbf\\x63\\xfa\\xb8\\x1f\\x6c\\xe2\\x10\\xc1\\x5e\\x51\\xc0\\xd6\\xe2\\x48\\xfb\\x85\\xdf\\xf2\\xaa\\x6f\\x3d\\xc3\\x0d\\x17\\xfb\\x49\\x5c\\xe9\\xcd\\xe9\\x5a\\x9a\\xae\\x71\\xfd\\x02\\x97\\x05\\xa8\\x27\\x93\\xbe\\x17\\xb9\\x25\\x05\\x44\\xd3\\xe5\\x8d\\xb9\\xb6\\x8f\\x74\\x61\\xbb\\x5c\\xd5\\x96\\xd5\\xfb\\x2e\\xae\\xd6\\xaa\\x7a\\x56\\x00\\x71\\x5d\\x13\\xa7\\xc1\\x58\\x14\\xba\\xa8\\x43\\x41\\x26\\x33\\xfb\\x97\\x57\\xdf\\xef\\x92\\x31\\x7a\\xdc\\xb4\\x4a\\x76\\x53\\x1b\\x9f\\x6f\\xe0\\xfc\\xc7\\x9b\\xe9\\xfc\\xb6\\x29\\x9b\\x52\\xb0\\xbf\\x99\\x13\\x70\\x48\\x8f\\xb9\\x57\\x6e\\x54\\xab\\x80\\xf1\\x85\\x3f\\xe0\\x5f\\x68\\xe0\\xf7\\x33\\xab\\x9d\\x8f\\x13\\x2d\\x49\\x5e\\xb0\\x7b\\x08\\x67\\x10\\x10\\xa6\\xc9\\x88\\x60\\xca\\x5c\\x94\\xd3\\x0d\\xc3\\x47\\x8a\\x6c\\x71\\xe2\\x5a\\xbb\\x28\\xdd\\x2a\\x26\\x93\\xf6\\xad\\x75\\x2f\\x6d\\xda\\x60\\x6c\\xb1\\x52\\x61\\x84\\xd4\\xdd\\x41\\x1c\\x6c\\x97\\xa9\\x3a\\x74\\xd6\\xca\\x60\\x76\\xec\\x6f\\xbd\\xe2\\x79\\xb9\\x2d\\x15\\x1a\\x31\\x9f\\x7c\\x04\\x7c\\x8e\\xce\\x16\\x89\\xc1\\xca\\x09\\x94\\x9f\\x41\\x34\\x6f\\xd1\\x53\\x5d\\xc9\\xfc\\x71\\x19\\x07\\x82\\xeb\\x7b\\xfd\\x84\\xef\\x6a\\x59\\x65\\xc9\\x77\\x07\\xf3\\xd6\\x5c\\x69\\xd1\\xfd\\x3d\\x81\\xc4\\x6f\\xad\\x07\\x68\\xbf\\x99\\xa0\\xb0\\xb5\\x9d\\xba\\xc7\\x3f\\x6f\\x31\\x49\\x40\\x37\\x9e\\xb1\\x3d\\xe5\\xe0\\x53\\xac\\xb8\\x67\\x69\\xcd\\xc2\\x68\\xcb\\x40\\xd5\\x7f\\x0b\\xec\\xd1\\x55\\xff\\x16\\xec\\xe4\\xef\\xff\\xfc\\xe2\\x8b\\xf1\\x78\\xfc\\x45\\xe5\\x71\\xfa\\x82\\xd0\\x9c\\xb3\\x4f\\x9a\\xa1\\xdf\\xf3\\xe4\\xee\\x0f\\x50\\xeb\\xf6\\xfe\\xf9\\x17\\x70\\xe0\\xc8\\x4b\\xd0\\x73\\x3b\\x45\\xee\\x2b\\x1f\\xf7\\xff\\x85\\xcb\\xa5\\x60\\x06\\xa1\\x42\\x48\\x1d\\x7a\\x30\\x26\\x52\\xe8\\x42\\x66\\x19\\x2b\\xc6\\xb7\\x4c\\x4c\\xee\\xca\\x1b\\x76\\x53\\xf2\\x2c\\x65\\x05\\x74\\xee\\x86\\xbe\\x7f\\x36\\x79\\xfe\\xdb\\xc9\\xb3\\x2f\\xec\\xc1\\x72\\xa9\\x8a\\xf3\\x8c\\x0a\\x35\\xf1\\x41\\x4a\\x93\\x44\\x16\\x4c\\x9a\\xff\\xcd\\xbf\\x50\\x39\\x4b\\xcc\\x10\\x78\\x9f\\xc8\\xda\\x77\\xac\\x0e\\xce\\xce\\xc4\\x66\\xe0\\xad\\xa0\\x31\\x26\\x32\\x9b\\xc3\\xdf\\xb8\\x42\\x9b\\x5b\\xf9\\x32\\xb3\\x89\\x9a\\x33\\xae\\xf4\\xb7\\xcb\\x4f\\xde\\x72\\x85\\x54\\x31\\xcf\\xca\\x82\\x66\\xf5\\xa9\\xc2\\x03\\x35\\x93\\x85\\xae\\xd5\\x20\\x18\\x13\\x8e\\x14\\x50\\x71\\x71\\x5b\\x66\\xb4\\xa8\\x7d\\xf5\\x85\\xf3\\x4a\\xa9\\xf4\\x7e\\x86\\x18\\xde\\xd7\\x1c\\x81\\xc7\\xb5\\xd0\\x07\\x2e\\x34\\x2b\\x5e\\xca\\xac\\x9c\\x87\\x6a\\xb6\\xf1\\x2a\\xfb\\x38\\xe5\\x85\\xd2\\x36\\xf9\\x73\\xdd\\x6a\\xb1\\x8e\\x25\\x7e\\xbf\\x54\\xa4\\xf8\\x2f\\x4a\\x0a\\xb0\\x66\\x92\\x89\\x01\\xf7\\xa4\\xf9\\xa3\\x1f\\x9f\\xfd\\x14\\x7c\\x87\\x7b\\x58\\x67\\x4b\\xd7\\x5e\\x86\\x35\\x33\\xa6\\x79\\x5e\\xc8\\x7b\\x8a\\xa9\\xab\\x37\\xcc\\xc5\\xbd\\xb7\\x32\\xec\\xf9\\xea\\x83\\x86\\xb1\\xd7\\x77\\x59\\xb3\\x0f\\x86\\x5d\\xd6\\x1e\\x60\\x97\\xf5\\xb4\\xde\\xf8\\xf2\\xfd\\x73\\x9a\\xe5\\x33\\xea\\x92\\x00\\xa8\\x64\\xc6\\xe6\\xb4\\xda\\x24\\x99\\x33\\x71\\x7e\\x79\\xf1\\xfd\\xbf\\x5d\\x2d\\x3d\\x58\\x9f\\xe8\\xdb\\x1c\\x39\\x1f\\xf7\\x1e\\xd4\\xe2\\xa2\\x4e\\x3a\\xf3\\xc1\\x7f\\xd5\\x0d\\x58\\x99\\xe6\\x0a\\x2f\\xb7\\x9e\\x77\\x33\\xcc\\x37\\x5e\\xe5\\xa5\\x9f\\x0d\\x74\\x82\\x9f\\x9a\\x78\\xa8\\x00\\x97\\x2c\\xe1\\xb3\\x36\\xf9\\xae\\x72\\x4e\\xaf\\xad\\xd5\\x5e\\x01\\x96\\x5a\\x28\\x56\\xee\\x54\\xce\\x82\\x54\\x81\\x41\\xd8\\x55\\xae\\x4a\\x71\\xe6\\xb8\\xb2\\xc2\\xe7\\xa0\\xc4\\x2c\\x0c\\x9a\\x04\\xe9\\x03\\xb0\\x77\\xe5\\x72\\x56\\x43\\x64\\xae\\x06\\xc7\\x8b\\x42\\xd0\\x0c\\x1d\\xb2\\x46\\x6b\\x03\\xcd\\xe7\\x74\\x41\\x0a\\x66\\xc6\\xad\\x27\\x24\\x68\\x8a\\xc4\\x5c\\x53\\x5a\\xfc\\x96\\x6b\\x87\\x6b\\x13\\x39\\x9f\\x97\\x82\\xeb\\xc5\\x19\\xa0\\x4d\\x7e\\x53\\x9a\\xfd\\x3c\\x4b\\xd9\\x3d\\xcb\\xce\\x14\\xbf\\x1d\\xd3\\x22\\x99\\x71\\xcd\\x12\\x5d\\x16\\xec\\x8c\\xe6\\x7c\\x0c\\x8b\\x11\\xe8\\xa1\\x34\\x4f\\x7f\\xd5\\x64\\x0e\\x68\\xa4\\x44\\xeb\\x78\\x89\\xb6\\xcd\\x82\\x5c\\xc2\\x18\\x1f\\x1d\\x04\\x52\\xd6\\x73\\xfc\\x43\\x95\\x89\\xd7\\x57\\xd7\\x95\\x59\\x14\\x93\\x38\\xc2\\x16\\x05\\x06\\xc0\\xe6\\xdd\\x32\\x90\\x85\\x22\\x99\\xb6\\x18\\x8f\\x4b\\xed\\xe0\\x13\\x3a\\x40\\x79\\xa7\\x8c\\x1b\\xe9\\x46\\x95\\x37\\x73\\xae\\x95\\x73\\x74\\x5e\\x1f\\xf0\\xfb\\x12\\x68\\x13\\x24\\x68\\x47\\x75\\xd1\\xea\\x2b\\x17\\xa2\\xd2\\x2e\\x1c\\x7c\\xef\\xc0\\x8f\\x6a\\x6c\\x36\\x24\\x7a\\xf7\\x42\\xca\\xbb\\xfa\\xc1\\x1a\\x09\\xce\\x11\\xcd\\xc6\\xed\\x0e\\xb0\\xce\\x55\\xce\\x12\\x7f\\x1b\\x3d\\x96\\x39\\xc7\\x32\\x48\\xb6\\xd4\\x97\\x77\\xac\\x86\\x22\\xa6\\x16\\x35\\xad\\x38\\x58\\x6c\\x10\\x28\\x9b\\x85\\xc8\\x31\\x59\\x83\\xe1\\xeb\\x8f\\xd6\\x78\\x72\\x8c\\xe3\\x08\\x1b\\x69\\x91\\x04\\xdd\\xd0\\xbd\\x75\\x55\\x8e\\x88\\x59\\x69\\x1d\\xaa\\x5f\\x79\\xca\\x66\\x03\\xfa\\x40\\x76\\x17\\x21\\xc8\\xd7\\x6b\\xa0\\x2e\\x74\\x18\\x9f\\x60\\x36\\xe1\\xe8\\xdc\\x25\\xd7\\xc6\\xaa\\x4f\\xef\\xa8\\x28\\x69\\xb6\\xd6\\x39\\x70\\x23\\x0f\\xea\\xc0\\xd8\\x9c\\xb9\\xa9\\xa9\\x6e\\x45\\x33\\x94\\x77\\x9a\\x05\\x6a\\xe3\\xec\\x6d\\x26\\x96\\x8d\\xc9\\xab\\x9a\\x9c\\xe7\\xf0\\xe0\\x76\\x4e\\x7a\\x15\\x54\\x87\\x6a\\x32\\xec\\xee\\xd8\\xbf\\x2b\\xbc\\x90\\x2b\\x1e\\x38\\xc8\\x0f\\x6c\\xf4\\xc2\\x59\\x5d\\x82\\x66\\xb9\\xaa\\x12\\x64\\x69\\x49\\x12\\x39\\xcf\\x33\\xa6\\xeb\\xac\\xc5\\x3a\\x87\\xf4\\x0d\\xde\\x61\\x5b\\x79\\x83\\x6d\\x42\\x02\\x36\\x7b\\xda\\x55\\x83\\x95\\x7b\\x8c\\x8a\\xed\\x2e\\x57\\x5b\\x6b\\x26\\x4a\\x83\\xff\\xaf\\x6a\\x35\\x81\\x3e\\xb2\\xb5\\xbe\\xa3\\x51\\xb7\\xbd\\xb9\\xcb\\x30\\x07\\x36\\xa6\\xa6\\xa8\\xd7\\x59\\x75\\x0e\\x3b\\xa5\\x6a\\x28\\x50\\xa3\\x25\\x49\\xad\\x3f\\x72\\x1a\\x04\\x67\\x37\\xfb\\xee\\x6c\\xe9\\x3b\\xd5\\xcc\\xc3\\xad\\x85\\x48\\x10\\x42\\xe8\\x4c\\x05\\x76\\xc5\\x8d\\xe1\\x46\\xad\\x52\\x31\\x04\\xad\\x6f\\x72\\xa2\\x8c\\x35\\xf2\\x5d\\x58\\xf0\\x03\\x93\\x02\\x79\\x32\\x72\\xce\\x30\\x92\\xc6\\xb3\\x8b\\x00\\x4a\\x46\\x53\\xfb\\xa3\\xa1\\xc7\\x05\\xf3\\xf1\\x14\\xd6\\x38\\xb0\\x51\\x3d\\x54\\xb1\\x95\\x50\\x2c\\x95\\x62\\xbc\\x08\\xf9\\xcf\\xab\\x0f\\xef\\xcf\\xbe\\x91\\x36\\x04\\xdf\\x56\\x3b\\x84\\x5b\\x32\\x87\\xc8\\x12\\x57\\x84\\x2f\\x65\\xca\\x9c\\xfd\\x2b\\xb0\\x40\\xcc\\xa9\\xe0\\x53\\xa6\\xf4\\xc4\\xa7\\x42\\x53\\x3f\\x7e\\xf5\\x53\\xb3\\x25\\x31\\x08\\x4c\\x1a\\xb9\\xba\\x4a\\x9e\\xc7\\xb2\\x07\\x0f\\x68\\x90\\x59\\x7c\\x95\\x30\\xfe\\x81\\xeb\\x19\\x4c\\x35\\x97\\xae\\xd8\\xe1\\x03\\x2c\\x42\\xd3\\x3b\\x43\\x64\\x70\\x11\\xa5\\x91\\x16\\xef\\x36\\x68\\x79\\x8e\\x50\\x28\\xf4\\x53\\xfd\\xbb\\x11\\x80\\xfe\\x79\\x44\\x4e\\x1e\\xc0\\x97\\xfe\\xc8\\xfc\\xf3\\x08\\x27\\xe2\\x79\\xeb\\xb0\\x04\\x69\\x35\\x21\\xf4\\xc0\\x2f\\xf8\\xed\\x2d\\x2b\\x1a\\x2b\\x35\\xd9\\xd2\\xa0\\x86\\x67\\x82\\xf2\\x86\\x7c\\x4a\\x84\\x0c\\x3a\\x11\\xb6\\x2e\\x76\\x95\\x61\\x7e\\x79\\x82\\x3f\\x7e\\xf5\\xd3\\x11\\x39\\xa9\\xc3\\xa1\\x71\\x30\\x2e\\x52\\xf6\\x89\\x7c\\xe5\\x6d\\x44\\xb9\\x4c\\x4f\\x6d\\x56\\x0d\\xb5\\x10\\x9a\\x7e\\x32\\x63\\x25\\x33\\xa9\\x98\\xc0\\xd8\\x04\\x2d\\xb1\\xb2\\xa5\\x92\\x60\\x95\\xcc\\xb2\\x31\\x72\\x4f\\x29\\x79\\x80\\xbc\\x23\\x8d\\x23\\xb9\\xad\\xc2\\xbc\\x1c\\x90\\x11\\x72\\xb3\\x44\\xe3\\xda\\xf5\\x87\\x57\\x1f\\x5e\\xe0\\xec\\xcc\\x31\\xba\\x05\\xdd\\x98\\x61\\x72\\xb1\\x54\\x26\\x86\\x43\\x85\\xc9\\x29\\x55\\x89\\x87\\xc3\\x60\\xfd\\x19\\x15\\x60\\x3b\\xb3\\x15\\x36\\x0d\\x5b\\xda\\xfb\\xca\\x6e\\x52\\x49\\xc6\\xde\\x56\\x10\\x2b\\x22\\x71\\xc8\\x23\\x32\\xe3\\xd1\\x30\\xd9\\xa4\\x21\\x8d\\x85\\xc9\\xfb\\xe0\\xb6\\xf4\\x82\\x49\\x15\\x9f\\x60\\xc0\\x92\\xca\\x44\\x19\\x88\\x24\\x2c\\xd7\\xea\\x4c\\xde\\x1b\\x62\\xc4\\x1e\\xce\\x1e\\x64\\x71\\xc7\\xc5\\xed\\xd8\\x5c\\x87\\xb1\\x75\\x5f\\x3d\\x03\\xcd\\xd9\\xd9\\xaf\\xc4\\x1a\\xce\\xb9\\x13\\x08\\x36\\x7a\\xc0\\x75\\x81\\x03\\x3a\\xc4\\x3d\\x22\\x30\\xcc\\xf8\\xea\\xac\\x2f\\x2c\\x9c\\xb0\\xd4\\x85\\xba\\x6e\\x80\\xc8\\x15\\x22\\xb9\\x64\\xb9\\x5f\\x73\\xb5\\xd1\\x81\\xd6\\x2a\\x4a\\x02\\x2a\\x30\\xa7\\x29\\x92\\x09\\x2a\\x36\\x64\\x06\\xdc\\xf3\\xcd\\x32\\x10\\x07\\x2f\\x83\\x64\\x31\\xb6\\xca\\xe1\\x31\\x15\\xa9\\xf9\\x5b\\x71\\xa5\\xcd\\xef\\x7d\\x41\\xbc\\x41\\x19\\x1f\\x0b\\xd6\\xef\\x2e\\x5e\\x3d\\xee\\x7d\\x2b\\x79\\x5f\\x8c\\xd3\\x2d\\x83\\xcd\\x4d\\x29\\xd2\\x8c\\xbd\\x95\\xf2\\xae\\x21\\xcb\\x48\\x0d\\x62\\x7f\\x0e\\xdf\\xf6\\x26\\x68\\xd4\\x08\\x70\\x31\\xf6\\xae\\xe8\\x81\\x02\\x86\\xe4\\x65\\x86\\x24\\xa8\\x14\\x39\\x4d\\xee\\xe8\\x2d\\xb3\\x83\\x02\\xc9\\xb6\\xa9\\x8c\\x50\\x89\\x03\\xb2\\xe4\\x4e\\x53\\x1e\\x37\\xce\\x1e\\x15\\x57\\x76\\x9e\\x0d\\xd3\\x74\\xbc\\x89\\x4d\\xb0\\x44\\xdd\\xbc\\xdb\\xe7\\xbb\\x13\\xe7\\x89\\x9a\\xc8\\xf3\\x91\\x35\\xf1\\x0d\\xe3\\xaa\\x82\\x57\\x53\\x70\\xd8\\x78\\x53\\x85\\xec\\xb1\\x2f\\xa7\\xb2\\xf6\\x85\\x76\\x43\\xf9\\xf2\\x3c\\x63\\x9d\\x04\\x97\\x3e\\x73\\x3b\\xe2\\x10\\x95\\x85\\x72\\xed\\x35\\xf8\\xc5\\xee\\x82\\x59\\x12\\x79\\xa0\\x0a\\x30\\x5f\\x76\\x6f\\x3d\\xd5\\x0e\\x92\\x5c\\xb3\\x5d\\x38\\x5a\\xb3\\xde\\x1e\\x22\\x52\\x38\\xf1\\x56\\xe3\\x74\\xab\\xb8\\xb4\\x66\\x4e\\xad\\x31\\xcd\\x87\\x11\\x9d\\xb0\\x3d\\xa6\\x00\\x85\\xed\\x71\\xc5\\x28\\x6c\\x07\\x17\\xa6\\xb0\\x1d\\x54\\xa4\\xc2\\x76\\x38\\xc1\\x0a\\x5b\\x6f\\xf1\\x0a\\xdb\\xa1\\x84\\x2c\\xbb\\x1f\\xbb\\x0a\\xd2\\xe8\\x76\\xdf\\xbb\\x09\\x5f\\xd8\\x1e\\x5d\\x04\\xeb\\x04\\xb1\\xf6\\x10\\x9f\\x6e\\x10\\xeb\\x26\\x9a\\x35\\x42\\x6c\\xaf\\x02\\x5a\\x67\\x00\\x45\\x84\\x2b\\x75\\x87\\x52\\x47\\xc1\\x6d\\x5f\\xa0\\xda\\x28\\xbe\\x75\\x82\\x54\\xa4\\x28\\xd7\\x07\\x5e\\xfb\\x13\\xeb\\x1a\\xc1\\xfa\\x34\\x84\\xbb\\x4e\\x1b\\xd0\\xea\\xd9\\xd7\\x0d\\xe8\\x9d\\x84\\xbe\\x46\\x38\\xee\\x53\\xf4\\xeb\\x00\\x9d\\x3e\\x89\\x4c\\x37\\xc7\\xec\\x61\\x6b\\x0a\\x97\\x5b\\x32\\x47\\x99\\x95\\x42\\x62\\xa7\\xca\\x1e\\x14\\x8a\\x5f\\x6d\\x6c\\xfa\\x4e\\x8a\\x5e\\xec\\xcc\\x75\\x39\\xca\\xe7\\x58\\x37\\x55\\x62\\xc1\\x16\\xeb\\x70\\xdc\\x25\\x98\\x0f\\xdb\\x86\\x78\\x9e\\x2a\\x7e\\x63\\xeb\\xa8\\x3e\\x6c\\x1d\\x02\\x5f\\x63\\xe3\\xe4\\xaa\\x65\\xc7\\xc4\\xf9\\x75\\x58\\xb2\\x91\\x0d\\xf3\\x42\\xde\\xc4\\xe6\\xb0\\xda\\xc3\\xaa\\x22\\x5d\\xb4\\xb7\\x0c\\x1b\\x82\\x94\\x2c\\x7e\\x7f\\x77\\xb6\\xd8\\xb6\\x18\\xbb\\x35\\x73\\xc7\\xbc\\xcf\\x35\\x37\\x5c\\xbf\\x1f\\xc7\\x0a\\x36\\x79\\x1f\\x33\\xed\\xed\\xb9\\x1e\\x08\\x4d\\x38\\xc9\\x91\\x73\\xad\\xb8\\x2e\\x4a\\x36\\x22\\x6f\\x68\\xa6\\xd8\\x88\\x7c\\x27\\xee\\x84\\x7c\\xd8\\xdd\\x7c\\x37\\xa7\\xe1\\x59\\x33\\xdb\\x6b\\x9b\\x70\\x27\\x22\\x94\\x33\\x7a\\x2a\\x95\\xd6\\x28\\x12\\xd9\\x5f\\xf8\\x0f\\x9c\\xe6\\xcf\\x6a\\x7e\\xc6\\xa5\\xe0\\x7f\\x2d\\xeb\\x62\\xa8\\x37\\x51\\x9f\\x2c\\x0b\\xa8\\x2f\\xaf\\xbe\\x87\\xc3\\x81\\x6a\\x1c\\x55\\xab\\xa9\\x61\\x1e\\xaa\\xe6\\x98\\x94\\x98\\x30\\xd5\\x8d\\x0a\\x90\\x78\\x7e\\xe0\\x92\\xea\\xd9\\x92\\x94\\x9d\\xd9\\x4c\\xdd\\xcb\\xba\\xc0\\xbc\\x6c\\xce\\x9e\\x41\\xc0\\x6f\\xe7\\x58\\x99\\xa9\\xf3\\x84\\x66\\xd9\\xc2\\x08\\x9c\\x4b\\x65\\xb1\\xb7\\x8b\\xcb\\x8d\\xa0\\x2b\\x2b\\x77\\x14\\xb3\\x73\\xf1\\x7b\\x16\\x7c\\xee\\xf6\\x07\\xf5\\x9f\\x2c\\xb5\\x2b\\xdc\\x2e\\xaf\\xf8\\x86\\x62\\xcf\\x6b\\xa6\\xf6\\xd1\\xbe\\xee\\xce\\x57\\x78\\x6c\\x2a\\x78\\xdb\\x4e\\x31\\x75\\x22\\x9c\\x35\\xc1\\xc8\\x54\\x96\\x22\\x25\\x54\\xc3\\xc6\\xf5\\x9c\\x73\\xdd\\xc7\\xe4\\x70\\x0e\\x4c\\x9b\\xd9\\xae\\xdd\\xe8\\xbe\\x1b\\x0f\\x7b\\xe0\\x58\\x54\\x85\\x6d\\x6f\\x60\\xe6\\x2a\\xa4\\xc9\\x3e\\xb1\\xa4\\xb4\\x17\\xa2\\xa1\\xf3\\x18\\xb7\\xb6\\x03\\x27\\x40\\x78\\x94\\xec\\x04\\x87\\x4d\\x2c\\xb0\\xeb\\xf8\\x79\\x7f\\x2e\\xe2\\x03\\x6f\\xe2\\x18\\x92\\x1d\\x84\\x07\\xc5\\xe4\\x0c\\x8c\\x4f\\x7a\\xb7\\xee\\x32\\x00\\xed\\xc5\\xb7\\x6e\\x98\\x0a\\x56\\x88\\xca\\xc3\\xd0\\x3f\\x9f\\x6a\\x03\\x18\\x56\\x00\\x29\\xb3\\xe5\\xe6\\x20\\x05\\xe2\\x4c\\xf6\\x46\\xa4\\xb1\\xd1\\xe6\\x0d\\x17\\xfc\\x9d\\x63\\x1e\\xcd\\x3c\\x80\\xb1\\x1c\\xaf\\x30\\x96\\x96\\xf8\\x56\\x8c\\x65\\x83\\xb6\\x38\\x74\\x31\\x04\\xaa\\x3d\\xa7\\x0b\\xf0\\xf7\\x9d\\xe7\\xb2\\xd0\\x14\\x2d\\x79\\xa5\\x48\\x59\\xa1\\x34\\xc5\\x5c\\x57\\x36\\xf2\\x7a\\xfd\\xbd\\x36\\x20\\x9b\\x51\\x45\\xb8\\x56\\x24\\xb1\\x11\\xe7\\xb8\\xdf\\x7b\\x0a\\x6b\\x0f\\xf6\\xea\\xd2\\x7c\\xe0\\xf9\\x98\\xda\\xe0\\x48\\xdf\\x6b\\xfb\\xba\\x71\\x13\\x37\\x4f\\x2c\\xa3\\x1b\\xdc\\x52\\xb7\\xc5\\xea\\x57\\x9a\\xe5\\xcb\\xc8\\x3a\\x58\\x84\\x00\\x99\\xe1\\x9e\\xa7\\xe8\\x99\\xc9\\x72\\xc2\\xc5\\x6e\\x70\\x72\\xbb\\xf5\\x12\\xad\\x72\\xcd\\xb7\\x72\\xec\\x55\\x5b\\x8d\\x2f\\x6c\\x10\\xbb\\xdb\\x69\\x82\\xcc\\x31\\x48\\xaa\\x0d\\x75\\x34\\x79\\x36\\x63\\xf3\\xab\\xd8\\x12\\xdb\\x36\\xfb\\x19\\x63\\x8b\\x67\\x4c\\xcd\\x96\\xbb\\xe0\\xbb\\x0d\\x5b\\x1f\\x04\\x5c\\x80\\x4f\\xbe\\x2e\\x2c\\x53\\x67\\x18\\xd0\\x4d\\xcc\\x6a\\xdb\\xd1\\x20\\x87\\x4e\\xb0\\xd6\\x12\\x13\\xde\\x9a\\x03\\x6c\\x1c\\x78\\x6b\\x47\\xbe\\x06\\x3a\\xe2\\x8d\\xef\\xb6\\x05\\x98\\x1f\\x3a\\xa5\\xdb\\x96\\xc9\\xba\\xaa\\xe6\\x0c\\xa7\\x3b\\xe9\\xac\\xdd\\xd6\\x12\\xd9\\x51\\xb5\\x35\\x3b\\xee\\x2e\\xc2\\xd0\\x11\\xd9\\x67\\x54\\x64\\xf8\\xae\\xe3\\xa1\\x5b\\x31\\x45\\x3d\\x59\\xc4\\x3a\\x3a\\x97\\xd3\\x42\\xf3\\xa4\\xcc\\x68\\x51\\xa1\\x0c\\x20\\x1c\\x71\\x48\\xa2\\x1f\\x5a\\x54\\x9a\\x16\\x3a\\x2a\\xbf\\x4f\\xc3\\x0a\\xaf\\x5c\\x07\\x3e\\x25\\x31\\xa4\\x00\\x9a\\x31\\xe1\\x8d\\xe0\\x18\\x6d\\x4c\\x6e\\xd8\\xad\\xa1\\xe0\\x79\\x9e\\x2d\\x9a\\x80\\x5e\\x2f\\x79\\x93\\x71\\xa5\\xab\\xaa\\xf2\\xc0\\xa4\\xc4\\x3a\\x28\\x75\\x4e\\x2a\\xf4\\xaf\\x10\\xc2\\x2d\\xb3\\x79\\x22\\xc5\\x94\\xdf\\x1e\\x2e\\x80\\xfb\\xc3\\xdb\\x77\\x2f\\x61\\x48\\xf8\\xad\\x0a\\xdf\\xf6\\xbf\\xaf\\x04\\x6f\\x57\\x93\\x84\\x9f\\xab\\xf8\\x6c\\xff\\xa0\\x8a\\xce\\xb6\\x59\\x84\\xd6\\x84\\x66\\xbb\\xc0\\x5f\\xb7\\x6d\\x3d\\x43\\x7e\\xfd\\x34\\x9d\\x4b\\x94\\xa7\\xf6\\x2a\\x97\\x42\\x71\\xc3\\xbb\\x43\\x0e\\x48\\x78\\x09\\xeb\\x38\\x7e\\x78\\xfb\\x6e\\xb7\\xf1\\xbe\\x43\\x70\\xaf\\x6f\\x43\\x70\\xef\\x10\\xdc\\xfb\\x4b\\x0a\\xee\\xf5\\xf8\\x05\\x42\\x7b\\x9d\\x17\\xaf\\xf9\\xdb\\x86\\xa2\\x56\\x08\\xa8\\xa9\\x3e\\x45\\xcf\\x9c\\xee\\x53\\x46\\x0d\\x64\\xda\\x1d\\x8d\\xdf\\xd8\\x17\\xab\\x02\\xa3\\xb5\\xa4\\x15\\x16\\xf1\\x81\\x16\\xe3\\xc3\\xdb\\x77\\xbe\\xdf\\x3d\\x04\\xc2\\xa5\\x5c\\x99\\x61\\x5e\\xca\\x9c\\xb3\\xf4\\xe5\\xd5\\xf7\\x1b\\xd2\\x82\\xc5\\x31\\x66\\xaf\\x96\\x3b\\x74\\x71\\x7f\\x10\\xe3\\x87\\x0f\\xcd\\xa2\\x8e\\x15\\x39\\xc2\\x97\\xc8\\xcb\\xab\\xef\\x8f\\xdc\\x1a\\x37\\xa9\\x0f\\x83\\x32\\xce\\x3e\\x06\\x9b\\x50\\x1d\\x32\\x2f\\x48\\xc4\\x46\\x04\\xbd\\x09\\xa9\\xfb\\xb9\\xb1\\xd7\\x95\\x88\\x43\\x05\\xea\\x76\\x50\\xff\\xcc\\xa8\\x22\\x37\\x8c\\x89\\x60\\x30\\xd0\\x2f\\x34\\x76\\xf6\\xc1\\xf6\\x02\\x39\\xbc\\xad\\x7f\\x22\\x14\\xf4\\xc0\\x02\\x4e\\x95\\x7b\\x4e\\xb3\\xe8\\xf9\\x83\\x61\\xf1\\x0a\\xc6\\x84\\x01\\x53\\x3a\\x82\\xdd\\xc7\\x2c\\xf9\\x2c\\x29\\x18\\x28\\x1e\\x67\\x2c\\x04\\x9c\\x3a\\x02\\xc8\\x30\\x9a\\x34\\xfb\\x23\\xd6\\x60\\x53\\x2d\\x76\\x73\\x18\\xd4\\x26\\xc5\\x81\\xf5\\x20\\x47\\x34\\x77\\xb5\\x10\\xc9\\x85\\x21\\x33\\x0d\\x81\\xe4\\xa4\\x4b\\x0e\\xfa\\xa6\\x8e\\x6b\\x87\\x08\\xa8\\x2b\\xde\\xea\\x85\\x48\\x90\\xc6\\x99\\x77\\xa6\\x1b\\x0a\\xb6\\xdb\\x29\\x17\\xc0\\x92\\x16\\x58\\xca\\xcb\\x0d\\x17\\xfc\\x46\\x72\\x56\\x70\\x99\\x5a\\x5b\\x56\\x32\\x63\\xc9\\xdd\\xc6\\x6a\\xc2\\x95\\xa8\\x51\\x73\\xe4\\x56\\xff\\xd3\\x3a\\x06\\xd7\\x4a\\xc8\\x60\\xdf\\xa4\\x84\\x5a\\x56\\x69\\x89\\x41\\xdd\\x9b\\x0e\\xfc\\x9c\\x6a\\x72\\x02\\x99\\x19\\x8f\\x7e\\xf7\\x6c\\x7e\\x74\\x3a\\x01\\x17\\x5e\\xf4\\x26\\xa5\\x05\\x9d\\x33\\xcd\\x8a\\x11\\x3a\\x8f\\xce\\x64\\x59\\x28\\x72\\x72\\x34\\x3b\\x3a\\x1d\\x91\\x39\\x17\\xa5\\xde\\xe0\\x2e\\x77\\x72\\x34\\x37\\xaf\\x51\\x91\\x12\\x85\\xd5\\x59\\xc8\\xc9\\x91\\x3a\\x3a\\x75\\x1a\\x4f\\xef\\x07\\x3b\\xc1\\x03\\x09\\xd5\\xd4\\xdc\\x6f\\x9b\\xcb\\x2b\\xdb\\x35\\xa6\\x58\\xce\\xc7\\xb3\\x23\\x48\\x5e\\x2b\\xff\\x5a\\xeb\\x53\\x0c\\x50\\x09\\x37\\xa1\\x77\\x68\\x1e\\x98\\x46\\x0d\\xaf\\xf3\\x82\\xfc\\xbf\\x93\\x1f\\x9f\\x8d\\xff\\xfd\\xa7\\xdf\\x9c\\xfc\\xd7\\x04\\xff\\x38\\xfd\\xfa\\x44\\xfd\\x63\\xfe\\x8f\\xd9\\xe9\\xe9\\x6f\\x7e\\xfd\\xc5\\xea\\xee\\x45\\x12\\x93\\xc6\\xbc\\x84\\x7b\\x24\\x28\\x8f\\x6a\\x3a\\xab\\xec\\x65\\x9e\\x4a\\x39\\xc7\\x0c\\x40\\xc6\\x82\\x11\\x6a\\x76\\x54\\x7b\\x37\\x83\\x40\\xfe\\xae\\x6a\\x82\\x9d\\x5f\\x5e\\xf8\\xba\\x08\\x4d\\xdb\\x6b\\xe4\\xbb\\xf5\\x4f\\xae\\xad\\x7f\\x7d\\x99\\x68\\xcc\\x64\\xaa\\xb1\\xea\\xb1\\x99\\x41\\xca\\x0b\\x60\\x5a\\x15\\x03\\x15\\xb6\\x2b\\x7d\\x6f\\x29\\x02\\x3a\\x2a\\x43\\x18\\xc5\\xc4\\xaa\\xdd\\x2b\\x70\\x4e\\xea\\xde\\xf0\\x8d\\x65\\xe9\\xfe\\x3f\\x03\\x63\\xf2\\x46\\x4a\\xbb\\xfd\\x38\\x93\\xbf\\x37\\xbd\\x6d\\xfe\\x73\\x76\\x46\\x3e\\x2e\\xd9\\x17\\x6f\\xcc\\xe1\\xb6\\xe5\\x3d\\x41\\x2b\\x31\\x95\\xf2\\xb8\\x6e\\x14\\x68\\x04\\x8d\\xeb\\xf3\\x5b\\x21\\x1f\\xc4\\xba\\x95\\xc0\\x0c\\x69\\xc1\\x5e\\x90\\xa3\\xf3\\x7b\\xca\\x33\\x43\\x39\\x8e\\x46\\xe4\\xe8\\xd2\\x46\\x2b\\x71\\x71\\xeb\\x2a\\xa9\\xbd\\x62\\xb7\\x05\\x4d\\x59\\xda\\x54\\x50\\xcd\\x8d\\xf5\\x1b\\x28\\x80\\xff\\x8e\\x15\\xb7\\xec\\x5b\\xb6\\xf8\\x8f\\x0d\\xae\\x5f\\xf5\\x2f\\xae\\xb0\\xd6\\xfe\\xe2\\x3f\\xa0\\x8c\\x7e\\xdb\\x27\\x86\\xdd\\xb9\\x5e\\xe4\\xec\\x3f\\xe6\\xb4\\x49\\x45\\x5a\\x7b\\xf7\\x1d\\xcd\\x63\\x66\\x13\\x38\\xed\\xfd\\xf8\\x93\\xe1\\x2e\\xef\\x9f\\x4f\\xaa\\xa3\\xfc\\xf3\\x5f\\x94\\x14\\x2f\\x8e\\x82\\x5c\\xfc\\x72\\x6e\\x6e\\x4a\\xae\\x17\\x47\\xa4\\xb6\\x88\\x17\\x47\\xb0\\x0a\\xfb\\xab\\x03\\xc6\\x8b\\x23\\x33\\xfe\\x91\\xb9\\xb5\\x5a\\xde\\x94\\xd3\\x17\\x47\\x37\\x0b\\xcd\\xd4\\xe8\\xf9\\xa8\\x60\\xf9\\xc8\\x90\\xf8\\xff\\xa8\\xfa\\x3e\\xfa\\xb9\\xf9\\x60\\xd9\\x95\\x81\\x5b\\x1a\\x9e\\xd5\\x26\\x7c\\xfd\\xff\\xfd\\x73\\xbd\\x5a\\x67\\x7b\\x23\\xc6\\xaa\\x61\\xb9\\xf1\\xd5\\xb6\\x7c\\xb5\\x68\\x24\\x6d\\x7c\\xdc\\x92\\xb1\\xb6\\x71\\x4f\\xf7\\x58\\x1d\\x60\\xa3\\x72\\x71\\xb5\\x57\\x5f\\x0f\\x67\\x7f\\x1e\\x88\\x88\\xeb\\x50\\xc2\\xbf\\x09\\xd4\\x7d\\x60\\x73\\x04\\xfd\\x5e\\x30\\x1e\\xc6\\x5c\\xa4\\x13\\x08\\x62\\x72\\xf9\\x35\\x0c\\xa1\\x06\\x5f\\x2e\\x20\\xd2\\xc2\\xb2\\x1a\\xab\\x0a\\x44\\x83\\x93\\x11\\x3f\\xda\\x6e\\x40\\x16\\x4e\\x12\\x96\\x6b\\x83\\x3e\\x0e\\x54\\xfc\\xa0\\x5b\\x09\\x81\\x8d\\xfb\\x35\\x5f\\xb1\\x03\\xef\\xc5\\xc1\\x10\\x76\\xc8\\x32\\x49\\x54\\xd8\\x7a\\x25\\x08\\x8d\\x2d\\x61\\x36\\xa7\\x9f\\xde\\x42\\xc5\\xe6\\x17\\xe4\\xdf\\xbe\\xfa\\xfd\\xef\\xfe\\xd0\\xf0\\x22\\x92\\x12\\x96\\x7e\\xb3\\x31\\x29\\x50\\x57\\xe8\\xad\\xf6\\xba\\x6c\\x7a\\x9b\\x38\\x31\\x7d\\x52\\xa5\\x23\\xf2\\x05\\x25\\x97\\x9c\\x52\\x15\\xd3\\xe4\\x06\\x3c\\x27\\xca\\x7c\\x33\\x38\\xdf\\xb8\\x1c\\x2f\\x22\\x41\\xd7\\xfe\\xb5\\xc3\\x70\\x4f\\x29\\xb3\\x05\\x79\\xfe\\x15\\x16\\xf8\\x85\\x49\\xad\\x10\\xc3\\x1f\\x3f\\xfd\\x34\\x59\\xb3\\x18\\xae\\xc8\\xbf\\x8f\\x96\\x66\\x6a\\x24\\xbd\\x12\\x58\\x17\\x73\\x4c\\x37\\x4c\\x12\\xfc\\xb0\\x0a\\x86\\x9c\\x8e\\x53\\x95\\xaf\\x72\\x3a\\xcc\\xaf\\xa4\\xed\\x24\\x74\\xa8\\x74\\xf8\\xbb\\xdf\\x36\\x1f\\x18\\x2e\\xf8\\xbc\\x9c\\xbf\\x20\\xcf\\x1a\\x5e\\xd9\\x5d\\x0d\\x09\\xeb\\x00\\xe3\\xb9\\x40\\x8a\\x45\\xb9\\xe8\\x1c\\x72\\x73\\x05\\x9e\\x96\\xe1\\x15\\xd3\\x3b\\xf3\\x95\\xbd\\x2c\\x64\\x5a\\x26\\xac\\xc0\\xea\\x9b\\x2e\\x72\\x24\\xc0\\xbc\\x50\\x99\\xd3\\xdc\\x4a\\x2b\\x19\\xb2\\x4f\\x66\\xaf\\x58\\x55\\x62\\x56\\xa4\\x50\\x02\\x95\\x8b\\x5b\\x55\\xa5\\x93\\x07\\xfc\\x37\\xda\\x30\\xae\\xf9\\xec\\x61\\xc6\\x80\\x40\\x7b\\x19\\xc6\\x16\\x7b\\x95\\x42\\xf1\\x94\\x15\\x2c\\x25\\x94\\xdc\\x96\\xb4\\xa0\\x42\\x33\\xac\\x70\\xb7\\x19\\x7d\\x78\\x49\\xc8\\x63\\x79\\x1a\\x64\\xfa\\x6f\\xc3\\x24\\x16\\x01\\x21\\xe6\\x36\\x0b\\xb6\\xca\\x40\\xc0\\x43\\xbb\\x43\\x40\\xcf\\x9f\\x7d\\xb5\\xf1\\xdc\\xf9\\xf7\\x36\\x48\\xdb\\x4e\\x16\\xfb\\xf1\\x7c\\xfc\\x7f\\xe9\\xf8\\x6f\\x3f\\x9d\\xd8\\x3f\\x9e\\x8d\\xff\\xfd\\xbf\\x47\\x2f\\x7e\\xfa\\x32\\xf8\\xe7\\x4f\\xa7\\x5f\\xff\\xba\\xa1\\xa7\\x4e\\xd6\\x42\\xb5\\x53\\x9f\\xe7\\x28\\xa0\\xb5\\x17\\xf0\\x3c\\x32\\xa3\\x6e\\x2a\\x60\\x3c\\x26\\x47\\x30\\xa5\\xcd\\xef\\xd8\\xe9\\x6e\\x92\\x8e\\x77\\x70\\xd1\\xf5\\xb2\\x1f\\x36\\xe1\\x81\\x36\\x19\\x22\\x67\\xcd\\x6d\\x96\\x13\\x2b\\x37\\x4d\\x12\\x39\\x3f\\xdb\\xa0\\x6d\\x0e\\x56\\xd0\\x28\\xe0\\x99\\xf6\\x8e\\x8a\\x05\\xa9\\xd0\\x38\\x8a\\x34\\xcb\\xd7\\x4d\\x41\\xa2\\x02\\x9a\\x14\\x52\\xa9\\x9a\\x3d\\xf3\\x8e\\x11\\x2f\\xf8\\x20\\x71\\xb8\\x61\\x09\\x05\\xa9\\xb0\\xb8\\xe1\\xba\\xa0\\xc5\\x22\\x10\\xa4\\x6d\\xad\\xb1\\x0d\\xb3\\x29\\x15\\x9b\\x96\\x19\\x39\\x51\\x8c\\x91\\x89\\x90\\x29\\x5b\\xa5\\x33\\xa7\\x48\\x4d\\xe8\\x0d\\xcf\\xb8\\x5e\\xa0\\x52\\x2a\\x91\\x62\\x9a\\x71\\x2b\\xa6\\x3a\\x97\\xb1\\x36\\x6c\\x50\\xb0\\x5b\\xf6\\x89\\x70\\x8d\\x95\\x94\\xd1\\x35\\xf8\\x24\\x15\\xea\\xf9\\xf3\\xaf\\xfe\\xed\\xaa\\xbc\\x49\\xe5\\x9c\\x72\\xf1\\x66\\xae\\xcf\\x4e\\xbf\\x3e\\xf9\\x6b\\x49\\x33\\xd0\\x9e\\xbc\\xa7\\x73\\xf6\\x66\\xae\\xb7\\x72\\x24\\xaf\\x73\\x1c\\xcf\\x7f\\x17\\x71\\x95\\x4f\\x7e\\xc4\\x0b\\xfb\\xd3\\xc9\\x8f\\x63\\xfb\\xd7\\x97\\xee\\xa7\\xd3\\xaf\\x4f\\xfe\\x6b\\xb2\\xf1\\xf9\\xe9\\x97\\x66\\x0d\\x01\\x1a\\xf8\\xe9\\xc7\\x71\\x85\\x03\\x26\\x3f\\x7d\\x79\\xfa\\x75\\xf0\\xec\\xd4\\x61\\x84\\x7f\\x09\\x13\\xb2\\x55\\xc8\\x06\\x42\\xfd\\xc1\\x4c\\xc9\\xb6\\x0f\\x2f\\x20\\xc3\\xb3\\xc0\\xa4\\xbc\\xfc\\x7c\\xd5\\xb4\\xbc\\x32\\x79\\x78\\xbc\\x2e\\x3b\\x78\\x52\\x1b\\x24\\x30\\x42\\x2f\\x77\\x11\\x99\\x2a\\x7c\\x57\\xf6\\xe8\\xe5\\x35\\xa2\\x14\\x81\\x47\\xc0\\xab\\xae\\x80\\xae\\x18\\xbc\\xf4\\xf3\\xca\\xfb\\x3f\\xdb\\x98\\xd5\\x40\\x47\\x0d\\x76\\xb1\\x45\\xdd\\xa5\\x54\\x82\\x36\\xbf\\x9e\\xbc\\xd2\\xa7\\x9a\\x58\\xa3\\x93\\x1f\\x8c\\xdc\\x83\\x91\\xdb\\xb7\\xc1\\xc8\\x1d\\xb6\\xc1\\xc8\\xbd\\x82\\x84\\xc0\\xd8\\x4d\\xb3\\x4c\\x3e\\xa8\\xca\\xee\\x09\\x25\\xec\\x45\\x03\\x42\\xda\\x8c\\x89\\x2c\\xbe\\x1a\\x91\\x5c\\x1a\\xc6\\x8b\\x83\\x41\\x4c\\xde\\xb3\\xa2\\xe0\\xe0\\xfa\\x8e\\xdf\\x14\\xac\\x2a\\x87\\x1f\\xc6\\xc5\\xed\\xc8\\xfe\\x91\\xb2\\x3c\\x93\\x8b\\x79\\x53\\x31\\xaa\\xfd\\xc4\\x2b\\xd9\\x45\\xee\\x38\\x44\\x6a\\xb0\\xb9\\x0c\\x36\\x97\\x4d\\x63\\x0d\\x36\\x97\\x7f\\x0d\\x9b\\xcb\\x60\\x48\\x19\\x0c\\x29\\x83\\x21\\x65\\x30\\xa4\\x0c\\x86\\x94\\xc1\\x90\\x32\\x18\\x52\\x06\\x43\\xca\\x60\\x48\\x21\\x83\\x21\\x65\\x30\\xa4\\x0c\\x86\\x94\\x3d\\x1b\\x52\\xaa\\xa6\\x6a\\xd5\\x7b\\x0e\\xa4\\x58\\xe9\\x57\\x16\\x6a\\x55\\xcb\\x85\\xa8\\xc9\\xe9\\xb9\\xea\\xea\\xaa\\x35\\x3a\\x2e\\xae\\x95\\x4b\\xd8\\x01\\xea\\xac\\x49\\x58\\x6d\\x7e\\x5d\\x85\\xa7\\x55\\x68\\x6d\\x51\\xf1\\x69\\x70\\xed\\x1d\\xd4\\x4c\\x83\\x9a\\x29\\xe2\\xdd\\x41\\xcd\\x54\\x6b\\x83\\x6b\\x2f\\xb4\\x41\\x23\\x35\\x68\\xa4\\x06\\x8d\\xd4\\x76\\xd0\\x1b\\x34\\x52\\x83\\x46\\x6a\\xd0\\x48\\x2d\\xb7\\x41\\x23\\xb5\\xf6\\xbd\\x41\\x23\\x55\\xb5\\x41\\x23\\x35\\x68\\xa4\\x06\\x8d\\xd4\\x63\\xb9\\xf6\\x4e\\xcd\\xbd\\x71\\x3f\\xb6\\xf9\\xf6\\x92\\xd0\\x1b\\xf4\\x2b\\xf7\\xd5\\xe0\\x0d\\x3a\\x78\\x83\\x0e\\xde\\xa0\\x55\\x1b\\xbc\\x41\\x7f\\xb9\\xde\\xa0\\x51\\xaa\\xf3\\xd0\\x41\\xb4\\xae\\x38\\x47\\x2f\\xce\\x9a\\xa2\\x1c\\x58\\xe4\\xbc\\x90\\xf7\\x3c\\x5d\\x93\\x48\\xa4\\xee\\x5e\\xea\\x33\\xd5\\x07\\x44\\x73\\x4e\\x45\\x19\\xba\\x8c\\xb2\\xc3\\x38\\x8c\\x0e\\x5a\\xf5\\x41\\xab\\x4e\\x06\\xad\\xfa\\xa0\\x55\\x5f\\xd3\\x06\\xad\\x3a\\xb4\\x41\\xab\\x3e\\x68\\xd5\\x07\\xad\\xfa\\x76\\xd0\\x1b\\xb4\\xea\\x83\\x56\\x7d\\xd0\\xaa\\x2f\\xb7\\x41\\xab\\xbe\\xf6\\xbd\\x41\\xab\\x5e\\xb5\\x41\\xab\\x3e\\x68\\xd5\\x07\\xad\\xfa\\x61\\xfc\\x3c\\x87\\xe0\\xd9\\x41\\xff\\x32\\xe8\\x5f\\x36\\x7e\\x31\\xe8\\x5f\\x3e\\x2f\\xfd\\xcb\\xa0\\x54\\x19\\x94\\x2a\\x83\\x52\\x65\\x50\\xaa\\x0c\\x4a\\x95\\x41\\xa9\\x32\\x28\\x55\\x06\\xa5\\xca\\xa0\\x54\\x21\\x83\\x52\\x65\\x50\\xaa\\x0c\\x4a\\x95\\x7f\\xf9\\xe0\\xd9\\x96\\x48\\xd9\\x0f\\x6f\\xdf\\x05\\x8e\\x88\\xe8\\xa0\\x18\\x9c\\xc6\\x19\\xbd\\x67\\x58\\xeb\\xca\\xf1\\x2d\\x83\\x3f\\xce\\xa0\\x0f\\x1a\\xf4\\x41\\x9b\\x3f\\x19\\xf4\\x41\\x8f\\xad\\x0f\\x1a\\xfc\\x71\\x9a\\xda\\xa0\\x3a\\x5a\\xdf\\x06\\xd5\\xd1\\xa0\\x3a\\x1a\\x54\\x47\\x83\\xea\\x68\\x50\\x1d\\x0d\\xaa\\xa3\\x41\\x75\\x34\\xa8\\x8e\\x06\\xd5\\xd1\\xa0\\x3a\\x1a\\x0a\\xd8\\xec\\xa8\\x80\\x0d\\x14\\xa6\\x39\\x7c\\xf1\\x1a\\xa8\\xb7\\x0e\\xbf\\xaf\\x16\\xae\\x81\\x67\\x8d\\x45\\x6b\\x70\\xc2\\xf0\\x68\\x5d\\xc1\\x1a\\x89\\x87\\x6f\\xb5\\x52\\xcd\\xad\\x1d\\xf1\\x80\\x55\\x6a\\x96\\xf0\\x5e\\xbd\\xd6\\xbc\\x15\\xed\\x4a\\xc1\\x81\\x21\\x9c\\x97\\x99\\xe6\\x9a\\x09\\x2a\\x92\\x05\\xf0\\x0b\\x1f\\xde\\xbe\\x23\\x73\\x2a\\xe8\\x6d\\x50\\xfe\\x7d\\x29\\x88\\xf3\\x42\\x03\\x96\\xd2\\x05\\x70\\x48\\x9e\\x1d\\xcc\\x32\\x1f\\xab\\x1b\\x56\\xdf\\x87\\xc4\\x7a\\xbe\\xa0\\x3d\\x88\\x87\\x41\\x75\\x6f\\xc3\\x40\\x1b\\x2a\\x06\\xc5\\xef\\x1b\\xea\\xde\\x0f\\xf1\\xcc\\x43\\x3c\\xb3\\x6f\\x43\\x3c\\x73\\xd8\\x86\\x78\\xe6\\x1a\\x76\\x83\\xc0\\x65\\x57\\x77\\xdf\\xfc\\xed\\xaa\\xee\\xd7\\x50\\x60\\x8f\\xca\\xfb\\x29\\x9b\\xd2\\x32\\xd3\\xab\\x8c\\x67\\x99\\x83\\x9a\\xd9\\x2b\\x52\\xc9\\x2b\\x7c\\xb3\\x83\\xe1\\x43\\xb1\\x8c\\x25\\x5a\\x16\\xeb\\xb8\\xda\\xda\\x52\\xaf\\xec\\x8b\\xf6\\x0b\\x5c\\x66\\x6d\\x69\\xc7\\x6a\\x33\\x26\\x8d\\x58\\x69\\xdb\\x6c\\x09\\xe0\\x10\\x9d\\xcc\\x5e\\x7f\\xca\\x41\\xe5\\xde\\x60\\xb0\\x59\\x99\\xfd\\xf2\\x47\\x78\\x21\\x0d\\x19\\x36\\xd8\\x30\\xa3\\x37\\x2c\\xf3\\xa0\\x70\\xb8\\x1d\\x3c\\x92\\x27\\x96\\x7b\\xac\\x7e\\x01\\x46\\xf9\\xfc\\xfd\\xab\\x75\\x37\\x22\\x5c\\x60\\x93\\xb9\\x88\\x6c\\x36\\x19\\xad\\x4c\\x7d\\xa3\\x20\\x71\\xbe\\x61\\xee\\x16\\xe9\\xb8\\x27\\xa0\\x44\\xf2\\xaa\\x05\\xc4\\xb8\\x23\\x42\\xc9\\x1d\\x5b\\xa0\\xd5\\xa2\\x16\\x6c\\x3f\\xa3\\xeb\\x75\\xdd\\xd8\\x0a\\x06\\x48\\x1f\\xce\\xc0\\x1d\\x5b\\xc0\\xe7\\x4d\\x38\\xbc\\x0e\\x95\\x0d\\x6a\\x74\\x12\\xa1\\x4a\\x27\\x40\\x64\\xef\\x58\\x13\\x60\\xf1\\xb9\\x5b\\x46\\x33\\xaf\\xdd\\xaa\\xed\\x36\\xed\\x8e\\x2d\\x36\\x3d\\x5e\\xda\\x27\\x03\\x07\\xaf\\xba\\x36\\x7b\\x62\\x7e\\xf0\\x9a\\x3b\\xbf\\x0d\\x34\\xcf\\x33\\xce\\xd6\\xe3\\xdc\\xb0\\x45\\x89\\x16\\xc4\\x2f\\xb5\\xc3\\x44\\x37\\x1e\\xa8\\xb0\\xcf\\x50\\x37\\x09\\xe7\\xe4\\x58\\xe1\\xce\\x9b\\x1b\\x34\\xe3\\xb9\\x65\\xa7\\x90\\x89\\x6a\\xdb\\x7e\\x6c\\xdf\\xd3\\x8c\\x07\\xac\\x1d\\xdc\\xa5\\x0b\\x31\\x22\\xef\\xa5\\x36\\xff\\x7b\\xfd\\x89\\x1b\\x7a\\x64\\x8e\\xd3\\x2b\\xc9\\xd4\\x7b\\xa9\\xe1\\x97\\x9d\\x40\\x0a\\x27\\xb8\\x4b\\x38\\x59\\xc1\\x99\\x07\\x26\\x51\\x39\\xad\\x51\\x79\\x35\\x41\\xa3\\x41\\x95\\x3f\\xc2\\xbc\\x7d\\x21\\x8c\\x84\\x8f\\x4b\\x6e\\x19\\xa2\\xa6\\x0e\\x33\\x03\\xcc\\x4b\\x05\\x44\\x59\\x48\\x31\\x46\\x6d\\xd4\\xba\\x11\\x2c\\x1c\\x65\\x51\\x03\\x63\\xef\\xc1\\xec\\x40\\xa0\\x13\\xc3\\x27\\xc8\\x54\\x66\\x46\\x94\\x20\\x69\\x09\\x0b\\x06\\xfe\\xc6\\xd0\\x21\\x9e\\xb4\\x8c\\x03\\xe6\\x3e\\xb4\\xf6\\xc5\\xec\\xec\\x26\\x44\\x8a\\xad\\x05\\x9d\\x86\\x9d\\x6d\\x38\\x26\\x40\\x23\\xde\\x9a\\xab\\x1b\\x47\\x53\\x36\\x9c\\x8f\\xa0\\x2b\\xc4\\xc2\\x73\\x9a\\x9b\\xb3\\xf1\\x77\\x83\\x6c\\x01\\xc4\\xff\\x24\\x39\\xe5\\x85\\x9a\\x90\\x73\\x10\\xdb\\x32\\x56\\x7b\\xc6\\xd1\\x7a\\x14\\x74\\xb3\\x61\\x28\\x10\\xab\\x0c\\xde\\xbc\\xa7\\x99\\x41\\xfb\\x60\\x03\\x23\\x2c\\x43\\x22\\x60\\xc4\\xac\\x25\\xe2\\x37\\x22\\x0f\\x33\\xa9\\x10\\x73\\xa3\\x8a\\x93\\x2b\\x72\\x74\\xc7\\x16\\x47\\xa0\\x6d\\x69\\x1c\\x2a\\x3c\\x61\\x47\\x17\\xc2\\x1a\\xbb\\x57\\x4e\\x8d\\xa7\\x31\\x52\\x64\\x0b\\x72\\x04\\xcf\\x8e\\xfa\\xd3\\xd1\\x8d\\x14\\x83\\xa6\\xa8\\x28\\xa2\\xd9\\x65\\x04\\x4a\\x6f\\x39\\x02\\x9f\\xc6\\x77\\xe5\\x0d\\x2b\\x04\\xd3\\x4c\\x8d\\xe7\\x34\\x1f\\xdb\\xf3\\xa7\\xe5\\x7c\\xcd\\x99\\xae\\x7b\\xd8\\x18\\xd1\\xba\\x95\\x87\\x6a\\x38\\x31\\x57\\x2b\\x3d\\x39\\x42\\x82\\x79\\x6b\\x42\\x81\\x15\\xde\\x24\\x14\\x5f\\xb5\\x0e\\x32\\x0f\\x3c\\xcb\\x9a\\x34\\x6d\\x2e\\xb5\\x17\\x06\\x59\\xf9\\x2d\\x3c\\x51\\xa7\\x78\\xc8\\x8c\\x94\\xe1\\xb6\\x15\\xb4\\x05\\xcd\\x1c\\x5b\\x03\\xdc\\x94\\x91\\x2a\\x93\\x4b\\x4c\\xc1\\x93\\x9e\\x5f\\x5e\\xac\\xdd\\x80\\x3a\\x2f\\x09\\x9f\\x10\\xcd\\xb2\\x0c\\x5d\\x7e\\x8c\\xa4\\xa1\\xa5\\x95\\x34\\xd6\\x72\\x96\\x79\\xd0\\x7f\\xa0\\x0f\\x6a\\x9c\\xec\\x8d\\x94\\x19\\xa3\\xab\\xcf\\x91\\x43\\xf5\\x8a\\x90\\xf6\\xb9\\x36\\xec\\xd9\\xf5\\x52\\x3f\\x96\\x0a\\xb0\\x4f\\x79\\xc6\\x13\\xae\\x1d\\x55\\xac\\x38\\x61\\x90\\x96\\xe1\\xa3\\xf5\\xc7\\xfd\\x62\\x4a\\x38\\xb0\\x6c\\x8a\\xe9\\x51\\xc5\\x6d\\x73\\x45\\xf8\\xad\\x90\\xc5\\xfa\\x5b\\xb2\\x9f\\xd8\\xb8\\xa5\\x9b\\x60\\xb8\\x64\\x7b\\x15\\x14\\x5b\\xbd\\x88\\xcb\\x42\\x48\\x4f\\x80\\x7e\\x57\\xef\\xa6\\xa6\\xd8\\xb0\\x43\\x38\\x02\\x83\\xba\\xa2\\x9a\\x9a\\xc7\\xbc\\xe5\\x61\\xbd\\x1e\\xc0\\xd7\\x33\\x56\\x30\\xd4\\x72\\x7b\\x23\\xa7\\x7e\\x90\\x44\\x95\\xb9\\x4d\\xf5\\xb4\\x34\\x0c\\xa0\\x92\\xf5\\x6e\\x25\\x56\\xce\\x7a\\x01\\x87\\x17\\xae\\x1f\\xe0\\x3a\\x70\\x62\\x73\\x49\\xa7\\xec\\xad\\xb6\\x8a\\x1a\\xd8\\xff\\xb9\\xbc\\x67\\x4e\\x6b\\x82\\xe4\\xb3\\x89\\x16\\xe5\\x33\\xaa\\x58\\x25\\xc5\\xab\\x32\\x49\\x18\\x4b\\x59\\x8a\\x0f\\x2c\\x29\\x66\\xd3\\x29\\x4b\\x34\\xbf\\x67\\xd9\\x02\\xcc\\x6e\\x0a\\xd9\\x4d\\x3f\\x27\\x21\\xd7\\xa3\\x4d\\x9c\\x66\\x05\\xbf\\xa5\\x99\\x09\\xf6\\x49\\x3b\\x5d\\x12\\xe1\\xa0\\x2b\\xaa\\xab\\xd8\\x0a\\x07\\xa9\\xb5\\xbd\\xcf\\xa8\\x22\\x53\\xca\\x33\\x73\\x62\\xd7\\x43\\xef\\x9a\\x25\\xb3\\xcb\\x82\\xdd\\x73\\xf6\\xf0\\x9d\\x50\\x74\\xca\\xde\\x50\\x9e\\xbd\\x91\\xc5\\x03\\x2d\\xd2\\x00\\xa4\\x1d\\xa0\\xb9\\x76\\x18\\x0f\\xe1\\x16\\x68\\x9a\\x05\\xf9\\x67\\x38\\x73\\x0b\\xe6\\xb5\\xdd\\x9e\\x7b\\x92\\x93\\x2d\\x46\\xd5\\x6c\\xad\\x1d\\xdd\\x80\\xef\\xc1\\xc1\\xeb\\x32\\x33\\x9b\\x02\\xce\\x20\\x94\\xa8\\xf2\\xc6\\xdf\\x02\\x52\\xb0\\x29\\x2b\\x98\\x58\\x55\\x3d\\xd9\\x1d\\x72\\xf3\\x08\\x3a\\xf2\\xc4\\x36\\xa1\\x9a\\x66\\xf2\\x16\\x00\\x0d\\xbe\\x90\\x56\\x41\\x83\\x06\\x74\\x0a\\x13\\x70\\x47\\x79\\xda\\x20\\x04\\x81\\x6a\\xc8\\xf0\\x84\\x50\\x22\\x17\\x71\\x55\\xa0\\x70\\x5d\\xbf\\x6f\\x3f\\x9c\\x7f\\x7c\\x7f\\xf1\\xfe\\x9b\\x17\\x40\\xca\\x37\\x6d\\xe2\\xea\\x85\\xe5\\x8a\\x94\\xf0\\x16\\xda\\x88\\x41\\x0d\\xa8\\x56\\x35\\x15\\xd8\\xb8\\x20\\xa5\\xf0\\xb6\\xe5\\x1b\\x36\\xa3\\xf7\\xdc\\x5c\\xf8\\xc2\\x2a\\x0d\\xef\\x59\\x01\\xfe\\x26\\x29\\xd5\\x94\\x64\\x52\\x99\\xbe\\x33\\xa6\\x14\\x59\\xc8\\x12\\x5d\\x44\\x53\\xc6\\xd6\\x7b\\xba\\x81\\x87\\x8f\\xd2\\x54\\x40\\x6d\\x60\\x6b\\xc1\\x5c\\x5e\\x3f\\xb9\\x61\\xe6\\xa9\\x53\\x44\\xc7\\xa0\\x97\\x16\\x7c\\xea\\x34\\x38\\x0d\\x0a\\x1a\\xb2\\xd1\\xc2\\x39\\xde\\xf0\\x95\\x79\\xba\\x69\\x27\\xea\\xea\\xac\\x78\\xf7\\x5c\\x54\\x68\\xa1\\x9d\\xd7\\xa9\\xb4\\xf0\\x5f\\xeb\\x94\\x5a\\x4d\\x5e\\xa7\\x1b\\x18\\xb8\\x66\\x41\\x1f\\xbd\\xe5\\xbe\\xc3\\x33\\xdd\\x41\\x93\\xb5\\xd9\\x85\\xb7\\xb6\\xca\\xc0\\x73\\x71\\x49\\x78\\x5b\\xc7\\x7a\\x04\\x2e\\xa0\\xbb\\x24\\xc1\\x83\\x6f\\xf0\\xe0\\x1b\\xbc\\x69\\xac\\xc1\\x37\\x78\\xf0\\x0d\\x5e\\x7a\\x75\\xf0\\x0d\\x1e\\x7c\\x83\\x07\\xdf\\xe0\\xc1\\x37\\x78\\xf0\\x0d\\x1e\\x7c\\x83\\x07\\xdf\\xe0\\xc1\\x37\\x78\\xf0\\x0d\\x26\\x83\\x6f\\xf0\\xe0\\x1b\\x3c\\xf8\\x06\\x1f\\x2c\\xac\\x3c\\x50\\xcd\\xb4\\x6a\\x59\\xde\\x56\\xef\\x22\\x4b\\x68\\xb8\\x50\\xa5\\xe9\\x3c\\x77\\xe8\\xa1\\xce\\xc6\\x2f\\xeb\\x5d\\x2c\\x2a\\x31\\xdc\\xcc\\x77\\x4d\\x2e\\x68\\xad\\x60\\x6e\\x67\\x83\\x45\\xbc\\x2d\\xa8\\x6e\\xee\\x09\\x54\\x87\\x2b\\x7e\\x4f\\x9e\\xdc\\xd6\\x16\\xf5\\x54\\x4d\\x38\\x75\\x53\\xe6\\x47\\x36\\x8d\\xf0\\x06\\x5b\\xfa\\x22\\xd0\\x68\\x5b\\xc0\\xd4\\x2d\\x95\\xd6\\x95\\xd1\\x9b\\x32\\xf7\\xe0\\x18\\xd6\\xec\\x4f\\xbb\\x76\\x09\\x46\\xfc\\x72\\x56\\x0e\\x7b\\x1e\\xed\\x1a\\x1a\\x11\\x46\\xeb\\x95\\x06\\xa6\\xe0\\x92\\xea\\xd9\\xb6\\x0e\\x04\\x17\\x16\\xa0\\xe0\\x59\\x01\\x6e\\x36\\x39\\x67\\x09\\xab\\xb9\\xee\\x02\\xaf\\xcb\\x68\\x6a\\x7f\\x34\\xfc\\x5f\\xc1\\xec\\xb3\\x11\\xb2\\x57\\x2d\\xd8\\xa7\\x72\\xf1\\x35\\x3c\\x25\\xa1\\x06\\xdd\\xf3\\x94\\xfc\\xe7\\xd5\\x87\\xf7\\x67\\xdf\\x48\\xcb\\xe2\\x18\\x89\\x54\\xd9\\xea\\xe4\\x73\\x26\\xf4\\x88\\xa8\\x32\\x99\\x11\\xaa\\xcc\\x62\\x78\\xc1\\xd2\\x2b\\xd0\\x9c\\xcd\\xa9\\xe0\\x53\\xa6\\xf4\\xc4\\xf6\\xc6\\x0a\\xf5\\xe3\\x57\\x3f\\x35\\xa3\\xde\\x50\\xf3\\x67\\xa4\\x0e\\xd4\\xd1\\x59\\x7f\\x57\\x7b\\x94\\xe0\\x96\\x99\\xc5\\xfb\\x3e\\x41\\x10\\x80\\xa9\\xe6\\x32\\xb5\\x8b\\x7c\\x80\\x45\\x68\\x7a\\xc7\\x88\\xb4\\x8b\\x28\\x19\\x90\\xa4\\x66\\x72\\x7c\\x64\\x0e\\x62\\x30\\xd5\\xbf\\x9b\\xab\\xfb\\xcf\\x23\\x72\\xf2\\x00\\x56\\xc2\\x23\\xf3\\xcf\\x23\\x9c\\x88\\xf7\\x73\\x36\\xbf\\x05\\x8c\\x8d\\x9d\\x10\\xca\\x5f\\x05\\xbf\\xbd\\x35\\x9c\\x68\\x33\\x35\\x98\\x31\\xc2\\xee\\x99\\xd0\\xa7\\x40\\xc1\\xa7\\x44\\xc8\\xa0\\x13\\x61\\x6d\\xfe\\x95\\xa5\\x7f\\x79\\x82\\x3f\\x7e\\xf5\\xd3\\x11\\x39\\xa9\\xc3\\xa1\\x71\\x30\\x2e\\x52\\xf6\\x89\\x7c\\xe5\\x2d\\xfc\\xb9\\x4c\\x4f\\xad\\xcd\\x50\\x2d\\x84\\xa6\\x9f\\x40\\x9c\\x9b\\x49\\xc5\\x04\\x1a\\x2e\\xb5\\x44\\xbb\\x89\\x92\\x73\\x46\\x1e\\x58\\x96\\x8d\\x91\\x8b\\x4f\\xc9\\x03\\xe8\\xc5\\x1b\\x47\\x72\\x5b\\x85\\x0e\\x40\\x39\\x2d\\x74\\x8b\\x77\\xb9\\x6b\\xd7\\x1f\\x5e\\x7d\\x78\\x81\\xb3\\x33\\xc7\\xe8\\x56\\x38\\xcd\\xc9\\x94\\x0b\\x9a\\x59\\x5b\\x97\\x67\\xb3\\xcd\\xc4\\x4b\\x3c\\x1c\\x5a\\x5a\\x75\\x89\\xb3\\xcb\\x4c\\x4b\\x5d\\x16\\x8d\\x7c\\x4f\\xeb\\x95\\x5d\\xe7\\xd2\\xed\\x5a\\xec\\x6d\\x05\\x17\\xef\\x48\\x1c\\xf2\\x88\\x8e\\xd1\\xd1\\x30\\x11\\x0d\\xce\\x2c\\x5d\\x60\\xf2\\x3e\\xb8\\x2d\\xbd\\x60\\x52\\x91\\x2f\\x03\\x96\\x54\\x26\\xca\\x40\\x24\\x61\\xb9\\x56\\x67\\xf2\\xde\\x90\\x17\\xf6\\x70\\xf6\\x20\\x8b\\x3b\\x2e\\x6e\\xc7\\xe6\\x3a\\x8c\\xf1\\xcc\\xa9\\x33\\x20\\xc3\\x67\\xbf\\x82\\xff\\x6d\\x03\\x02\\x20\\xe5\\xbb\\x80\\x03\\x06\\x9f\\x3c\\x22\\x30\\x80\\x27\\x39\\xeb\\x0b\\x0b\\xc7\\xe7\\x77\\xa1\\xae\\x1b\\x20\\x72\\xe5\\xb4\\x07\\x4b\\xfd\\x9a\\xab\\x8d\\x0e\\x4d\\x36\\x68\\x25\\xa0\\x02\\x73\\x9a\\x22\\x99\\xa0\\x62\\x83\\x8c\\xbd\\xe7\\x9b\\x65\\x20\\x0e\\x3a\\xa7\\x64\\x31\\xb6\\x11\\x68\\x63\\x2a\\xd2\\xb1\\x97\\x8c\\x92\\x26\\x37\\xc5\\x56\\x10\\x97\\x7c\\x6b\\x24\\xf4\\xdd\\xc5\\xab\\xc7\\xbd\\x6f\\x25\\xef\\x8b\\x71\\x62\\x1c\\xef\\x76\\x15\\x9f\\x48\\x6a\\xc1\\x6e\\x34\\xcb\\x67\\x74\\xdb\\x52\\x9c\\x43\\xc8\\xdb\\x10\\xf2\\x36\\x84\\xbc\\x05\\x6d\\x08\\x79\\x1b\\x42\\xde\\xb6\\x0b\\x79\\x1b\\x42\\xd6\\x86\\x90\\xb5\\x21\\x64\\x2d\\x6c\\x43\\xc8\\xda\\xa6\\x36\\x84\\xac\\x0d\\x21\\x6b\\x43\\xc8\\xda\\xba\\x36\\x84\\xac\\x0d\\x21\\x6b\\xae\\x0d\\x21\\x6b\\x16\\x0e\\x43\\xc8\\xda\\x2f\\x28\\x64\\xed\\x97\\x1d\\xd6\\x30\\x58\\xdc\\x3f\\x0f\\x8b\\xfb\\x60\\x43\\x1f\\x6c\\xe8\\x83\\x0d\\x7d\\xb0\\xa1\\x0f\\x36\\xf4\\x7a\\x1b\\x6c\\xe8\\xfd\\x61\\x32\\xd8\\xd0\\x2b\\x38\\x0c\\x36\\xf4\\xb0\\x0d\\x36\\xf4\\xd5\\x36\\xd8\\xd0\\xb7\\xb1\\xa1\\x4f\\x69\\xa6\\x7e\\x51\\x49\\x7e\\x0f\\x9f\\xdf\\x17\\x7e\\x5a\\x4d\\xed\\xdb\\x98\\xd5\\xd7\\x26\\xf4\\x5d\\xc9\\xda\\x5b\\x25\\xec\\x7d\\x89\\xc9\\x2f\\xf6\\x97\\xad\\xf7\\xc3\\x5a\\xbd\\xb9\\xcd\\xb9\\xe1\\x27\\x14\\xe1\\x1c\\x30\\x58\\xfc\\x7d\\x1b\\x2c\\xfe\\x83\\xc5\\xff\\x97\\x68\\xf1\\x07\\x63\\x7f\\x78\\x15\\xad\\xec\\x5a\\x05\\x60\\x7e\\x58\\x6f\\xc4\\x6c\\x1e\\x3a\\x5e\\x73\\x67\\x95\\x76\\xe1\\xf0\\x2e\\xc6\\xb4\\x1a\\x3f\\x50\\xe0\\x81\\xf4\\x63\\xf6\\x3f\\x91\\xf3\\x5c\\x0a\\x73\\xae\\xe2\\xb5\\x78\\x9b\\xd3\\x8c\\xb8\\xfe\\x22\\xd2\\x8c\\xb8\\x57\\xed\\xef\\x37\\x2c\\x0c\\x9a\\xb2\\xd6\\xed\\x79\\x2e\\x15\\xab\\x99\\xc3\\x7a\\xe8\\x75\\x36\\x1b\\xa1\\xc7\\x68\\xde\\x75\\x1a\\xda\\x1e\\x7a\\xa1\\xda\\xf7\\x51\\x5c\\xd6\\xdb\\xf0\\x0b\\xeb\\xbb\\x00\\x36\\xe6\\xbf\\x96\\xac\\x58\\x10\\xc3\\x0d\\x55\\x96\\xd8\\x0a\\x28\\x4e\\xf9\\x8f\\xc6\\xe7\\x1a\\x58\\x8e\\x37\\x6c\\x66\\x24\\x98\\x62\\x96\\x4a\\x3a\\x38\\x6c\\xac\\xac\\xfa\\xa0\\x4e\\x1b\\x24\\xda\\xde\\x18\\x61\\x6d\\xec\\x66\\x47\\x7e\\x24\\x27\\x0e\\xd2\\xd3\\x91\\x83\\xc4\\x3a\\x73\\x90\\x48\\x87\\x0e\\x12\\xe1\\xd4\\x41\\xe2\\x1c\\x3b\\x48\\xb4\\x73\\x07\\x89\\x71\\xf0\\x20\\x7b\\x76\\xf2\\x20\\xf1\\xee\\x0b\\x24\\xda\\xd9\\x63\\x65\\xd2\\xad\\x07\\x90\\xec\\xd7\\xe9\\x83\\xec\\xc9\\xf1\\x83\\x74\\x83\\x5e\\x8c\\x03\\x08\\xe9\\x05\\xbb\\x03\\x38\\x82\\x90\\x43\\x3b\\x83\\x6c\\x1c\\x70\\xc7\\x0e\\x21\\xa4\\x8b\\x53\\x08\\xe9\\xe0\\x18\\x42\\x62\\x9d\\x43\\x48\\x7c\\x8c\\x71\\xab\\x93\\x08\\xe9\\x78\\x86\\x0e\\xe8\\x2c\\x42\\x0e\\xeb\\x30\\x42\\x1e\\xc1\\x69\\x84\\xc4\\x53\\xa7\\x6e\\xce\\x23\\x24\\xee\\x88\\x74\\x73\\x22\\x21\\x68\\xb2\\x88\\x73\\x38\\xfa\\xc8\\xa6\\x08\\x80\\x80\\xd5\\xab\\x6c\\x9c\\xb2\\x91\\xbf\\xab\\x38\\xc2\\x91\\x25\\x51\\x2e\\xbf\\x65\\x8d\\xaf\\x3c\\x8c\\x3b\\xeb\\x47\\x9e\\xcc\\x3e\\x86\\x9a\\x54\\x1a\\x28\\x56\\x81\\xb6\\xb8\\xd9\\x8e\\x08\\x13\\x05\\x4f\\x66\\x6e\\xb2\\x46\\x00\\xb1\\x46\\xf5\\xcd\\x59\\x04\\xc3\\x69\\xb7\\x1c\\x82\\x38\\x5e\\xa1\\xdd\\x90\\xbb\\x66\\xa1\\x3d\\xcc\\xb9\\xe1\\xc4\\x5b\\x49\\xda\\xe6\\x14\\x8d\\x0d\\x93\\x0a\\x52\\xc9\\x2d\\xe5\\x43\\xb2\\x3a\\x99\\x5a\\xfe\\x1f\\x7f\\x82\\x0e\\xe8\\xa6\\xb7\\x7e\\xba\\xd5\\x6c\\xc3\\xc9\\x52\\x97\\x24\\x63\\x35\\x21\\xa1\\xa8\\x26\\x6f\\x7d\\x31\\x36\\x66\\xf3\\x20\\x5d\\x78\\xda\\x78\\xae\\xb6\\x35\\x51\\x5c\\xf8\\xe2\\x86\\x34\\x80\\xae\\xc5\\xb3\\xb6\\xdd\\xd2\\xc8\\x55\\x6d\\xc5\\x05\\x66\\x4f\\x99\\xe1\\x5c\\xeb\\xc0\\xbf\\x91\\x0e\\x89\\xd8\\xea\\x60\\x40\\xff\\x9b\\x9d\\x82\\xe0\\x81\\x82\\x4f\\xda\\xcd\\x06\\x0b\\xfb\\x01\\x17\\xd9\\x9a\\x77\\xae\\x61\\x75\\xe7\\x7b\\xcc\\x2c\\xd7\\x6b\\xf1\\x6d\\x29\\xbe\\x1a\\xd6\\x71\\xbd\\xb3\\xd4\\x5c\\xbd\\x66\\xdd\\x96\\xd4\\xa9\\x61\\xd6\\x57\\x3b\\x4d\\xef\\xd4\\x73\\xee\\x9b\\x33\\x2d\\x35\\xcc\\xfc\\x7a\\x39\\xad\\xd2\\x0e\\xa7\\xd5\\xea\\xb2\\xb4\\x66\\x3e\\xad\\x52\\xda\\x61\\xdc\\x97\\xb0\\x3d\\xa6\\x13\\x13\\xb6\\xc7\\x75\\x65\\xc2\\x76\\x70\\x87\\x26\\x6c\\x07\\x75\\x6b\\xc2\\x76\\x38\\xe7\\x26\\x6c\\xbd\\x5d\\x9c\\xb0\\x1d\\xca\\xd1\\xc9\\xee\\x47\\xdc\\xa5\\xdf\\xe4\\xf4\\x84\\xad\\xdb\\x7d\\xef\\xe6\\x00\\x85\\xed\\xd1\\xdd\\xa0\\x3a\\x41\\x6c\\x93\\x4b\\x54\\x1f\\x88\\x75\\x73\\x8f\\x6a\\x84\\xd8\\x5e\\x9d\\xa4\\x3a\\x03\\x68\\xa3\\xc3\\x54\\x5f\\x28\\x75\\x74\\x9e\\xda\\x17\\xa8\\x36\\xba\\x50\\x75\\x82\\x54\\xa4\\x3b\\x55\\x1f\\x78\\xed\\xcf\\xb5\\xaa\\x11\\xac\\x4f\\xc3\\xc1\\xaa\\xd3\\x06\\x6c\\x70\\xb6\\xea\\x03\\xf4\\x4e\\x8e\\x57\\x8d\\x70\\xdc\\xa7\\xfb\\x55\\x07\\xe8\\x1c\\x32\\x9d\\xc9\\x53\\xf6\\xc4\\x0a\\x2b\\xde\\x1c\\xce\\x1b\\xeb\\x2a\\x18\\x15\\x7e\\xae\\x3c\\xb2\\xc2\\x47\\x2b\\x5e\\x59\\xb5\\xd9\\xc2\\x93\\x75\\xa5\\xd6\\x55\\x79\\x13\\xfe\\xbd\\xec\\xc2\\xa5\\xea\\x83\\xc7\\xd4\\x5d\\x0f\\x55\\xba\\xe0\\x5e\\xf4\\x52\\x66\\xe5\\x3c\\x54\\x91\\x8d\\x57\\x25\\xc7\\x9c\\x26\\x77\\x46\\xe8\\xb5\\xe3\\xdd\\x80\\xd1\\x3c\\x38\\x90\\x7f\\x51\\x52\\x80\\x40\\x42\\x26\\xc0\\x2d\\x1a\\x08\\x06\\x8f\\x71\\x7f\\x2e\\xb1\\x93\\x2f\\x5a\\x8e\\xf7\\x9a\\xe1\\x5d\\x09\\x22\\xeb\\xc7\\xe3\\x04\\xd8\\x8a\\x47\\xcd\\x57\\xba\\x5e\\x9e\\x11\\x7e\\xba\\x32\\xa7\\xab\\xe5\\x9f\\xa3\\xa7\\x34\\xa3\\x42\\xb0\\xcc\\x60\\x11\\xf4\\xe5\\x01\\x16\\xdd\\xc3\\x67\\x33\\x78\\xec\\xc7\\x2b\\xb3\\x79\\xb9\\xf2\\xfb\\x9a\\xe9\\xd4\\x72\\x09\\x6d\\xeb\\x90\\x17\\x1e\\x51\\x72\\xc7\\x58\\xae\\x02\\x0b\\x64\\x09\\xa6\\x4c\\x08\\x38\\xbc\\x59\\x10\\x5d\\xd0\\xe4\\x0e\\xea\\x11\\x00\\x8b\\x0b\\xeb\\x7d\\x89\\x1b\\xb3\\xe3\\x74\\x3e\\x70\\xd8\\x73\\x16\\xda\\x02\\x06\\x7f\\x3f\\xdf\\x06\\x7f\\xbf\\xc1\\xdf\\xef\\x97\\xe4\\xef\\x17\\xa2\\xa0\\x9a\\xcf\\x1f\\x15\\xe4\\x3c\\xcf\\x33\\xd0\\xb2\\xba\\xca\\x13\\x98\\xc8\\xdb\\x25\\x24\\x5b\\xd1\\x75\\xf4\\x0c\\x95\\x5d\\x22\\x57\\xee\\xe7\\x15\\x9a\\x51\\x7f\\xe0\\xc9\\xec\\xd2\\x1b\\x1b\\xdd\\xf9\\x10\\xc3\\xaf\\xe3\\x65\\x37\\xf2\\x7a\\x89\\x14\\x53\\x7e\\xdb\\x1e\\xe3\\x19\\xc0\\xf2\\x25\\x7c\\x52\\x99\\x8d\\xb1\\x8b\\xd2\\x96\\xc7\\xa8\\x68\\x27\\x84\\x22\\xd7\\x38\\x89\\x7d\\x04\\x7a\\x4e\\x81\\xf5\\x6b\\x74\\x26\\xea\\x10\\x64\\xe9\\x67\\x3e\\x02\\xaf\\xbe\\x82\\xa7\\x16\\x75\\xe7\\x32\\x3d\\x56\\x80\\x58\\xd3\\x32\\xb3\\x85\\x73\\x30\\x8b\\xdd\\xba\\x4b\\xef\\x9a\\xe0\\x99\\x59\\xfc\\x98\\x6a\\xbc\\x41\\x4c\\x61\\xb6\\x80\\x2f\\x85\\xd4\\x5f\\xfa\\x11\\x50\\x41\\x58\\xf0\\x5b\\xee\\xb1\\xb3\\x2f\\x04\\x9a\\xcb\\x74\\xe2\\xb3\\x51\\x69\\x70\\x03\\xa8\\x77\\xd8\\x3c\\xf8\\x77\\xca\\x7a\\x8a\\x38\\x34\\x75\\xf2\\xf7\\x7f\\x9e\\x1a\\x9a\\xc0\\x0a\\x4c\\xbe\\x6f\\x07\\xac\\xf5\\xd7\\xe2\\x53\\xb4\\x23\\x9f\\x44\\x21\\x53\\x76\\xde\\xb2\\x6b\\x64\\x79\\xe7\\x5e\\x79\\xbf\\x53\\xf3\\xb9\\xdf\\xf5\\x70\\x53\\x8a\\x32\\x0b\\xa2\\xa7\\x0d\\xec\\x36\\x74\\x1e\\x69\\x70\\x8c\\x35\\xfa\\xe5\\xa8\\xe1\\x66\\xe9\\x2b\\xf0\\xbf\\xb9\\xf2\\xb3\\xba\\xc0\\x04\\x02\\xf8\\xf3\\xeb\\x4f\\x2c\\x29\\x75\\xab\\x98\\xdf\\xdd\\x0d\\xca\\xf0\\x8d\\x16\\x12\\xa0\\x37\\xcd\\x32\\x3b\\x23\\x60\\x1d\\xed\\x03\\x03\\x12\\x60\\x0b\\x0c\\x04\\xad\\xd7\\xae\\xa2\\x9a\\xab\\x69\\xbb\\x23\\x0f\\x24\\xc4\\x70\\x30\\x67\\x81\\x5b\\x68\\x75\\xdb\\x0d\\x23\\x57\\x55\\x42\\x81\\xca\\x09\\x50\\x89\\x60\\x41\\x92\\x99\\x94\\xaa\\xdd\\x90\\x46\\x71\\x6b\\x61\\x5e\\xf7\\x5c\\xa2\\x73\\x24\\x98\\x63\\x0a\\x32\\x37\\xe4\\xca\\xca\\xd5\\xc1\\xf0\\xe8\\xa4\\x52\\x7d\\xc6\\xdb\\x6d\\xbd\\x73\\xa9\\x74\\xb5\\x5d\\xce\\xa1\\xd0\\x0c\\x03\\x8e\\x0e\\xe6\\x1f\\xb7\\x05\\xb3\\x06\\xf9\\x72\\x6e\\x06\\x7d\\x60\\xfc\\x76\\xa6\\xd5\\x88\\xf0\\x49\\xab\\x21\\x1b\\x2c\\x88\\x84\\xd1\\x64\\x16\\x4c\\x6b\\xce\\x98\\x56\\x84\\x66\\x99\\x2f\\xd4\\x19\\x9c\\xda\\xd0\\xc3\\xe6\\xc4\\x71\\x18\\xad\\xa3\\x58\\xee\\x60\\xe4\\xa9\\xcf\\xf2\\xc1\\x5b\\xbb\\x5d\\x23\\xc2\\x74\\x32\\x39\\x6d\\xf7\\x3f\\x4b\\xe4\\x3c\\x37\\x08\\x81\\x02\\x0c\\x6e\\x16\\x84\\x6b\\x28\\x7f\\x04\\xdc\\x50\\x21\\xcb\\x5b\\x84\\x94\\xf5\\x5b\\x52\\x9e\\x97\\xb5\\x06\\x16\\x91\\x82\\x34\\x18\\x61\\x02\\x3b\\x42\\xe0\\x1e\\x39\\x76\\xd5\\x0c\\x67\\xad\\x26\\x00\\x3f\\x57\\xc9\\x02\\xcd\\x12\\x45\\xc1\\x54\\x2e\\xb1\\xe6\\xe9\\xb2\\xa3\\xd4\\xff\\x6c\\x75\\x87\\x22\\x16\\xf9\\x9c\\xa8\\xd3\\x6a\\xb3\\x67\\xfc\\x76\\xe6\\xf6\\x9a\\x16\\x88\\x8e\\xeb\\x67\\x24\\xce\\x77\\x21\\xc6\\x21\\x2e\\xd2\\x1d\\xae\\xbb\\x13\\xe4\\xb9\\xab\\x1e\\x56\\x1d\\xec\\xe0\\x88\\x69\\x56\\xcc\\x3d\\x20\\xe1\\x14\\xa2\\xb2\\xc8\\xba\\xf6\\xcc\\x6d\\xda\\x14\\xdc\\x89\\xc6\\x0a\\x50\\x61\\x3b\\x31\\x37\\x81\\x70\\x7d\\xac\\xe0\\xd6\\x8e\\x65\\x7e\\x3a\\x21\\xe7\\x44\\x94\\x1e\\xf1\\x6c\\x9a\\x82\\x90\\x7e\\x06\\xb6\\x23\\x33\\x2d\\x25\\xab\\xbe\\xda\\xf1\\x51\\xbc\\xbf\\x48\\x17\\x8f\\x11\\xc3\\x82\\xe5\\x5e\\x21\\x1a\\xf5\\x3a\\x42\\xad\\xf5\\xd5\\x2e\\xde\\x23\\x24\\x98\\x43\\xcc\\xdb\\x2b\\x8e\\x05\\x70\\x73\\x2a\\xbf\\x75\\x56\\xcc\\x47\\x84\\x2a\\x25\\x13\\x5e\\x95\\x57\\x5e\\xbd\\x50\\xb8\\x92\\x18\\x6b\\x72\\x47\\xf8\\x93\\xce\\xeb\\x27\\x1d\\x43\\x17\\xea\\x6d\\x09\\x1a\\x2e\\x68\\xa1\\x0e\\x95\\x1a\\xde\\xbd\\x59\\xc0\\x53\\x70\\x57\\xb8\\x61\\x59\\x94\\x57\\x35\\xb6\\x2e\\xde\\xb0\\xae\\x45\\x7b\\xc5\\xae\\x5d\\x50\\x14\\x42\\xa8\\xda\\xf2\\x69\\xd8\\x4d\\x7c\\x43\\xa7\\x29\\x40\\xc7\\x7d\\xa3\\x1d\\x96\\xba\\xea\\x7a\\xee\\xb0\\x75\\xc1\\x00\\x55\\x8b\\x89\\x8b\\x58\\xfe\\xa2\\x07\\x80\\xba\\x5f\\x0d\\x6c\\x51\\x11\\x14\\xf5\\xb6\\xa2\\x6c\\xdc\\x55\\x20\\x45\\xbd\\x75\\xf4\\xb9\\xaa\\x5a\\x7c\\x90\\xc5\\x86\\x75\\x75\\xbc\\x20\\xa6\\x7d\\xdc\\x4b\\xdc\\x45\\xbd\\x45\\x45\\x61\\x8c\\xea\\x21\\x18\\xe4\\x1b\\x8d\\x57\\xef\\x6d\\x24\\x5e\\xae\\x5a\\xef\\x3d\\x88\\x0d\\xd5\\xa8\\xb7\\x6d\\x77\\xe0\\x7c\\x9f\\xc1\\x1b\\xf5\\x76\\xf0\\x50\\x8e\\xc8\\xe1\\x9b\\x87\\xfe\\x46\\x9b\\x61\\xdf\\xea\\x51\\xf0\\x71\\xe7\\x71\\x83\\xc1\\xc0\\x03\\x86\\xba\\x78\\x06\\xcb\\xc4\\x8f\\xea\\x19\\x0d\\x51\\x63\\x9c\\x17\\xcc\\x70\\x0c\\x58\\x10\\xdd\\x96\\x1a\\xed\\x7e\\xf4\\xa3\\x63\\x55\\xba\\x45\\xa2\\xd4\\x5b\\x1f\\x4a\\x8c\\xad\\x33\\x3d\\x0e\\x07\\xec\\x74\\xc3\\x80\\xa7\\x79\\x03\\xe5\\xb9\\x0f\\xc3\\xce\\x60\\x29\\xf0\\x81\\x9d\\x19\\xd8\\x99\\x81\\x9d\\x19\\xd8\\x99\\x81\\x9d\\x89\\x6d\\x03\\x3b\\xb3\\xf5\\xf0\\x03\\x3b\\xf3\\x0b\\x67\\x67\\xba\\x47\\x5b\\xd6\\x1b\\xea\\x9b\\x7a\\x28\\xb8\\x7e\\x40\\x45\\xe5\\xb2\\x46\\x0b\\x98\\x2b\\x67\\xaf\\xaf\\xab\\xb6\\x0c\\xcf\\xe0\\x42\\x2d\\xaf\\x41\\x1d\\x66\\x2d\\x6c\\x05\\xf8\\x54\\x3f\\x1f\\x3f\\x7f\\xf6\\xac\\x8b\\xe2\\xab\\xad\\xe8\\x7e\\xd8\\x82\\x02\\xfc\\xff\\xf6\\xd5\\xc6\\x2f\\x9a\\x54\\xf9\\x87\\xb1\\x21\\xd9\\x8b\\xea\\xcd\\x06\\x35\\x8e\\xb2\\xc1\\xcc\\x03\\x58\\x5f\\x48\\x4d\\xe6\\x4c\\x93\\xd6\\x84\\x17\\xa4\\xa6\\x11\\xe6\\x73\\x36\\x72\\x96\\x3a\\xbc\\xa5\\xd6\\xa3\\xc1\\xd9\\xab\\x52\\x22\\x85\\x0b\\x4e\\x90\\x69\\x84\\xe5\\xa5\\xd7\\x0a\\x12\\x46\\x15\\x04\\xbf\\xde\\x30\\xb3\\x8a\\x76\\x2b\\x95\\xc6\\xd8\\x01\\xf4\\xdb\\xb0\\x77\\xde\\x2c\\x81\\xb9\\x8d\\x21\\x27\\x6c\\x72\\x3b\\x21\\x69\\xc9\\x6c\\x74\\x37\\xba\\x68\\xd8\\x2a\\xdf\\x6a\\xa1\\x34\\x9b\\xb7\\x9b\\xa9\\x0c\\xed\\x28\\x7c\\x59\\x7e\\x5d\\x40\\xe8\\x02\\x44\\x57\\x94\\x34\\xcb\\x16\\x84\\xdd\\x73\\x9b\\x56\\xc6\\x0c\\x0e\\x1e\\x25\\x50\\x2f\\x2d\\x02\\x52\\x7b\\x0a\\xb6\\x5c\\xbe\\x64\\x6d\\x38\\xbd\\x0b\\xa3\\xb8\\xd2\\x77\\xe7\\xb0\\xa9\\x8f\\x76\\x25\\x93\\x46\\x11\\x4a\\x9b\\x7e\\xd1\\xa2\\x08\\x7f\\xc2\\xe1\\xfe\\xf0\\xb1\\xdd\\x00\\x44\\x3a\\xa3\\xeb\\x0e\\x28\\xba\\x1f\\x27\\x62\\x6d\\x31\\xb2\\xb0\\x76\\xa1\\xd5\\x95\\xae\\xb1\\xc6\\xac\\x09\\xf9\\x6f\\x0d\\x88\\x71\\x4d\\xcf\\xd8\\x3c\\x2e\\x41\\x40\\xd8\\xcc\\x78\\xd7\\x32\\x97\\x99\\xbc\\x5d\\x84\\xdb\\x0b\\xe0\\x04\\xcb\\x94\\x4b\\x3d\\x00\\x6e\\x24\\x36\\x63\\xfa\\x8c\\x91\\xf7\\x4b\\xe7\\x61\\xb0\\x5a\\x0c\\x56\\x8b\\x41\\xcc\\x87\\x36\\x88\\xf9\\x83\\x98\\x3f\\x88\\xf9\\x71\\x6d\\x10\\xf3\\xb7\\x1e\\x7e\\x10\\xf3\\x7f\\xe1\\x62\\xfe\\x60\\xb5\\x58\\xb3\\xa0\\x81\\x9d\\x19\\xd8\\x19\\x68\\x03\\x3b\\xb3\\x7e\\x5d\\x03\\x3b\\x43\\x06\\x76\\x66\\x43\\x1b\\xd8\\x99\\x81\\x9d\\xa9\\xb5\\xcf\\xc1\\x6a\\xd1\\xef\\xdb\\x5c\\xa6\\x5b\\x84\\xbb\\xe4\\x32\\xdd\\x10\\xed\\x82\\xaa\\xe6\\x44\\x8e\\x33\\x99\\x60\\xf9\\x4e\\x4c\\x82\\xe3\\xec\\x1b\\x8a\\xce\\x51\\x7b\\x3e\\x22\\x7f\\x93\\x82\\xa1\\xff\\xbf\\x39\\x49\\xa0\\xc3\\x86\\x4c\\x71\\xe6\\xf5\\x13\\x75\\xba\\xd1\\xe9\\x7a\\x88\\x96\\x19\\xa2\\x65\\x86\\x68\\x99\\xc6\\xf6\\x64\\xa2\\x65\\x66\\x54\\xe1\\xb9\\x45\\x2a\\xd2\\x1c\\x3c\\x13\\xe0\\xa4\\x6b\\x56\\xcc\\x7f\\xa1\\xb1\\x33\\xe6\\xb8\\xdb\\xe3\\x08\\x61\\xf5\\xd5\\x91\\x42\\xc8\\xa4\\xd6\\x94\\xcc\\xd2\\xcb\\x3a\\x3c\\xac\\x04\\x8a\\x09\\x7f\\xd3\\x94\\xa5\\x24\\x67\\xc5\\x18\\x8f\\xa8\\x24\\x53\\x6e\\xb3\\x28\\x2f\\xdd\\x0e\\x0b\\x9f\\x76\\xf4\\xb0\\xc7\\xe0\\x95\\xfa\\x3a\\xa2\\xbe\\xd9\\x4f\\x04\\x4b\\x7d\\x22\\x3d\\x6c\\x5d\\xa1\\xc1\\xae\\x46\\x04\\x9f\\x44\\x3c\\x4b\\x57\\x61\\x76\\x4c\\xb4\\xb5\\x73\\x7d\\x1b\\x29\\xce\\x76\\x97\\x48\\xa3\\x6a\\x9b\\xac\\xb6\\xfe\\x52\\xc3\\x79\\x4c\\x25\\x94\\x91\\x4f\\xce\\x97\\x50\\x85\\x64\\xb5\\x0b\\x57\\x09\\xb5\\xb9\\x8f\\x15\\xd8\\x33\\x6d\\x62\\xc4\\xe5\\xcb\\xea\\xd0\\x1c\\x9c\\x03\\x21\\xcd\\xf3\\xce\\xca\\xa3\\x8e\\xda\\x8c\\x7e\\xea\\x82\\xfe\\xc6\\x41\\xf2\\xe8\\xf5\\x59\\x56\\x5b\\x5f\\x5e\\xbf\\x17\\xa7\\xbf\\xb5\\x68\\xfb\\x78\\x75\\x5e\\x56\\xdb\\x6e\\xd4\\x70\\xa4\\xbf\\x2a\\x8e\\xf4\\x56\\xc7\\x91\\x5e\\x2a\\x39\\xd2\\x57\\x2d\\x47\\xb6\\x50\\xcd\\x91\\x7e\\xea\\x39\\x72\\x80\\xba\\x33\\xab\\xad\\xb7\\xa6\\x88\\x6c\\xa1\\xb1\\x23\\x3b\\xb8\\x58\\x64\\xff\\xf5\\x6b\\x56\\xdb\\xbe\\x2a\\xda\\xac\\xb6\\xad\\xf6\\xa5\\x9f\\x16\\x8f\\xec\\x68\\x57\\x0e\\x54\\x19\\x67\\xb5\\x3d\\xb2\\x6e\\x6f\\xe3\\x14\\xf6\\x50\\x3d\\x67\\xb5\\x6d\\xa1\\x40\\x23\\x5b\\x29\\xd1\\x48\\x7f\\x45\\x1a\\xe9\\x7f\\xd8\\x23\\xeb\\xf2\\xac\\xb6\\xed\\x4e\\xf9\\x81\\x6b\\xf7\\xac\\x9b\\xc0\\x41\\xab\\xf9\\xac\\xb6\\xc7\\xa8\\xef\\xb3\\xda\\x7a\\xf3\\x20\\xdd\\x6b\\x00\\x35\\x0d\\xde\\xf1\\xc8\\x6e\\xeb\\xb9\\x4e\\x6a\\xa7\\xef\\x5b\\xb6\\xe8\\x6b\\x17\\xef\\x74\\xe6\\xdf\\xd5\\x46\\x74\\x4c\\x2b\\x1c\\x33\\x23\\x1f\\x7b\\xde\\x44\\x05\\x65\\x27\\x51\\x0f\\x84\\x2a\\x21\\x9e\\x65\\x1d\\x46\\xbb\\x61\\x90\\x7a\\x1e\\x0c\\x0e\\x90\\xc6\\x5d\\xf1\\x94\\x61\\x8a\\x2f\\x3c\\x3a\\x30\\x92\\x39\\x32\\xae\\xd2\\x65\\x26\\xe5\\x5d\\x99\\xbb\\xa3\\xe7\\x72\\xdc\\x75\\x18\\x92\\x8b\\x44\\xce\\x9d\\x3b\\x35\\xba\\x34\\x8e\\x6c\\xda\\xab\\x3b\\xb6\\x18\\xdb\\xfc\\xf7\\x78\\xe1\\xcd\\xc0\\x80\\x66\\xad\\xf8\\xff\\x73\\xad\\x9c\\xd2\\xcf\\x84\\x2a\\xf2\\x33\\x30\\x6e\\x82\\x9c\\xc0\\x87\\xa7\\x3f\\x77\\xb1\\x70\\xd7\\xea\\x76\\x42\\x4e\\x57\\x03\\x66\\x66\\x08\\x92\\x9d\\xa0\\x5a\\x86\\xed\\x26\\x88\\x75\\x18\\xda\\xe5\\xaf\\x0a\\x81\\x71\\x8c\\x3a\\xfd\\x13\\x2a\\x34\\x3f\\xf5\\x8a\\x90\\x09\\x81\\x73\\x00\\x9c\\x68\\x2a\\xc5\\xb1\\xc6\\xf9\\x39\\xbc\\xe6\\x3a\\xe8\\x62\\x04\\xf7\\x70\\xaf\\x0c\\x50\\xa8\\x91\\xc7\\x2d\\x4f\\xd9\\x94\\x96\\x99\\xb6\\x39\\x12\\x0d\\xea\\x03\\x6a\\xda\\x61\\x84\\x6b\\x67\\x93\\xb0\\x4c\\xf5\\x54\\x16\\x37\\x3c\\x4d\\x19\\x24\\xa5\\xf6\\xd3\\xbf\\x91\\x7a\\xb6\\x7c\\xdc\\xc1\\x00\\x1b\\x53\\x32\\x6b\\x5d\\x3b\\xcf\\x94\\x1c\\x2d\\xf7\\x98\\xf8\\x1c\\x8a\\xe6\\x16\\x3d\\xcc\\x98\\x58\\xa9\\xf5\\x6a\\x80\\xaa\\x58\\x27\\xc6\\x11\\x38\\x0b\\xcb\\x73\\x65\\xf9\\x8c\\x06\\x4a\\x5e\\x8b\\x6c\\x15\\x61\\x82\\xde\\x80\\xd6\\xb9\\x3e\\xa3\\x0b\\x11\\x68\\x36\\xc8\\x94\\x51\\x5d\\x16\\x8c\\xdc\\x46\\x94\\x4f\\xaa\\xda\\x41\\x5c\\x61\\xb6\\x47\\xba\\x19\\x57\\xba\\x17\\xd6\\xe5\\xea\\x11\\x10\\xef\\xf2\\xa0\\x03\\xee\\x8d\\xc2\\xbd\\x42\\xea\\x01\\xfd\\x7e\\xb6\\xe8\\x77\\xe5\\xd0\\xef\\x02\\x03\\xaf\\x74\\x3a\\x20\\x61\\xdb\\x3e\\x23\\x24\\xec\\x4b\\x60\\x3c\\xb2\\xad\\x01\\xd5\\x6f\\xe8\\x56\\xea\\xab\\x72\\x54\\x9a\\x39\\x88\\x72\\xea\\xa7\\x95\\x73\\x31\\x60\\x70\\x86\\xa0\\x87\\xd4\\x99\\x5c\\x4b\\x11\\x14\\x95\\x0c\\x86\\xf5\\xc5\\x3d\\x6b\\x96\\xfd\\x0e\\x63\\x3a\\xd1\\x4d\\x0a\\xa6\\x40\\x91\\xcf\\xbc\\x17\\x47\\x30\\x0c\\xf4\\xda\\x65\\x29\\x10\\x07\\x56\\x29\\x29\\x45\\xba\\x1c\\x19\\x56\\xf5\\x0d\\xd6\\x83\\x39\\xa3\\x42\\x91\\x23\\xe7\\x48\\x72\\xac\\xaa\\x37\\x8e\\x3a\\x5d\\x78\\x97\\x92\\xd0\\x8f\\x0d\\x19\\x68\\xc3\\x34\\x84\\xd5\\xd0\\x83\\xb5\\x66\\xb0\\xd6\\x84\\x6d\\xb0\\xd6\\xac\\x4e\\x62\\xb0\\xd6\\x34\\xb5\\xc1\\x5a\\xd3\\x6b\\xfc\\xc1\\x5a\\x53\\x6f\\x83\\xb5\\x66\\xb0\\xd6\\x0c\\xd6\\x9a\\xe6\\x36\\x58\\x6b\\x06\\x6b\\xcd\\xe7\\x6a\\xad\\xa9\\x44\\x8d\\x43\\xc8\\xaa\\xa1\\x58\\x68\\x3d\\xbe\\xb1\\xc2\\x10\\xd5\\x3c\\xa9\\x42\\x21\\x7d\\x3d\\x4b\\xf8\\xeb\\xb1\\x04\\xd7\\x50\\xd4\\xdc\\x56\\x6c\\x0d\\x85\\xe0\\x15\\x2d\\x41\\x67\\xa9\\xb5\\x51\\x46\\xf5\\x52\\xec\\xca\\x18\\x3b\\x12\\x5f\\x9f\\xaa\\x02\\x27\\xf0\\x21\\x3d\\xc4\\x39\\xbe\\x76\\xd1\\x24\\xb6\\xda\\xd8\\x0d\\xab\\x42\\x4d\\x52\\x72\\xe2\\x34\\xa1\\x50\\xee\\x59\\x48\\x5d\\x7f\\x28\\x34\\x1f\\x57\\x6f\\x78\\x1f\\x5d\\x50\\xd8\\xba\\x54\\x5d\\x5d\\xa0\\xe5\\x18\\xfa\\x4a\\x33\\x28\\x96\\x6a\\xf5\\x55\\xc7\\xc4\\x20\\x6e\\x56\\xd4\\x66\\x0b\\x25\\x97\\xb1\\xd2\\x33\\x55\\xa4\\x28\\x85\\x30\\xbc\\x03\\x14\\xd6\\x16\\x32\\xed\\x82\\xcb\\x91\\x26\\xa0\\x12\\xd6\\x5e\\x27\\x94\\x34\\x60\\x8d\\x20\\x6e\\x54\\xdb\\x14\\xf8\\xe0\\x53\\x5b\\x2b\\xda\\x66\\xe3\\x91\\xc2\\xaa\\xb0\\xcd\\x2f\\xd8\\x4f\\x87\\x49\\xf8\\x9b\\x06\\xf0\\xe4\\x7e\\x45\\x5d\\x2e\\xd9\\x6b\\xb8\\x5c\\xe1\\x64\\x6d\\x35\\x6a\\x9a\\x65\\xf2\\xa1\\x0b\\x61\\xe9\\x78\\x94\\x7b\\x67\\x7e\\x8b\\x3e\\xbd\\x0f\\x9d\\x53\\xc4\\x2d\\x39\\xac\\xc7\\x32\\xb2\\x43\\x1e\\xb9\\xe5\\x36\\xe4\\x91\\xdb\\x4f\\x1e\\xb9\\xc0\\xd0\\x18\\x26\\x94\\x6b\\x87\\x15\\x24\\x9c\\xdb\\x6b\\x42\\x39\\x42\\x7e\\x98\\x31\\xb8\\x08\\x05\\x43\\xeb\\x60\\x99\\x69\\x9e\\x57\\x61\\xad\\x0a\\x77\\x28\\x43\\x91\\x71\\x6a\\x63\\xea\\xea\\x17\\xd0\\xcc\\x86\\x26\\x6d\\x05\\xff\\x57\\x22\\x4b\\x60\\x3c\\x08\\x93\\x55\\x80\\x10\\x31\\xee\\x0c\\xf4\\xcb\\x98\\xc5\\xcd\\xc9\\x92\\x18\\xbc\\xc7\\x1f\\x3b\\x26\\x29\\x0a\\x85\\xbd\\x72\\x85\\x0a\\x03\\x23\\xb3\\x22\\x27\\x86\\xc0\\x65\\x0b\\x6b\\x96\\xad\\xe1\\xb2\\x1a\\x65\\x8c\\x18\\x00\\xf5\\x3c\\xf7\\xcc\\x31\\x87\\xb7\\xfc\\x9e\\x89\\x8a\\x80\\x9e\\xa8\\xd3\\x53\\xc7\\x8f\\x2e\\xb3\\x00\\x11\\xbd\\x6f\\xc3\\x24\\xc4\\x20\\xde\\xae\\xc4\\x7d\\x89\\x64\\x47\\x8c\\xb0\\x86\\xa8\\xff\\x31\\x20\\x94\\x7f\\x6a\\x27\\xeb\\x11\\x83\\xe0\\x95\\x76\\x41\\x8e\\xc1\\x46\\x57\\xe4\\xbc\\xb5\\x97\\x3d\\xc6\\x92\\x75\\x09\\x58\\xea\\xa6\\xf5\\xed\\x11\\xa8\\xd4\\x37\\x0d\\xe2\\x7e\\x03\\x94\\xf6\\x1a\\x9c\\xf4\\xf9\\x64\\x2b\\x7c\\x64\\xf3\\xd6\\x67\\x90\\xfe\\xe7\\x89\\x98\\xb3\\x86\\xfc\\x3f\\x4d\\xed\\xb1\\xf2\\xff\\xec\\xdd\\x5c\\xf5\\xd9\\xa5\\x01\\x3a\\xa8\\x79\\xea\\x30\\xa6\\xa9\\xcf\\x2c\\x0d\\xd0\\xa3\\x98\\xa2\\x9e\\x78\\x42\\xa0\\xfd\\x99\\xa0\\x7e\\xd1\\xd9\\x76\\x7a\\x9a\\x9b\\xfa\\x9f\\xe0\\x47\\x35\\x33\\x3d\\xaa\\x89\\xe9\\xf1\\xcd\\x4b\\xbd\\xf8\\x82\\x6d\\xcd\\x4a\\x07\\x2f\\x5b\\xd1\\xc7\\xff\\xbc\\xdf\\x79\\x3e\\x5c\\xc0\\xcf\\x81\\x1d\\xce\\x9f\\x46\\xa0\\xcf\\x23\\x79\\x99\\x3f\\x96\\x87\\xf9\\x7e\\xbd\\xcb\\x1f\\x21\\xb0\\xe7\\x40\\x41\\x3d\\x8f\\xe8\\x4b\\xde\\x95\\xbe\\x77\\xa2\\xea\\xdb\\x21\\xce\\x3e\\xbe\\xe3\\x3d\\x83\\x77\\x7a\\x22\\xcf\\x43\\x06\\xed\\xfc\\x02\\xf0\\x67\\xaf\\x60\\x9d\\x01\\x85\\x3e\\x12\\x0a\\xdd\\x5d\\x70\\xce\\xe1\\x02\\x73\\x06\\x44\\x6a\\xdb\\xd6\\x88\\xb4\\x67\\x00\\xce\\xce\\x74\\xe8\\xfb\\x09\\xbc\\x39\\x74\\xd0\\xcd\\x1e\\x02\\x6e\\x1e\\x23\\xd8\\x66\\x0f\\x81\\x36\\x83\\xe5\\x21\\xb2\\x0d\\x96\\x87\\xd8\\x36\\x58\\x1e\\x9a\\xda\\x60\\x79\\x58\\x6e\\x83\\xe5\\x61\\xb0\\x3c\\x0c\\x96\\x87\\xc1\\xf2\\xb0\\x3a\\xe0\\x60\\x79\\x68\\x1c\\x7c\\xb0\\x3c\\xfc\\xe2\\x2d\\x0f\\x5d\\x83\\x58\\xfa\\x9d\\xe5\\xc7\\x09\\x5e\\x39\\x6c\\xe0\\xca\\xee\\x83\\x56\\x1e\\x31\\x60\\xe5\\x29\\x29\\x37\\x3a\\x07\\xa8\\xf4\\x3b\\xa3\\x4f\\x25\\x30\\xe5\\x69\\x04\\xa5\\x3c\\x7a\\x40\\xca\\xb6\\xc1\\x28\\xbb\\x09\\x44\\x89\\x3a\\xaa\\xb9\\x4c\\xcf\\x85\\xe6\\xdb\\x16\\xe4\\x09\\xcf\\x50\\x53\\x55\\x1e\\x7a\\x2f\\x79\\x4a\\xf2\\x52\\xdb\\x42\\x20\\x43\\x65\\x9e\\xd6\\x6d\\x3c\\x4c\\x65\\x9e\\xda\\xe6\\x0d\\xe5\\x79\\x36\\xb5\\x27\\x53\\x9e\\xa7\\x69\\xcf\\x86\\x1a\\x3d\\xf5\\x36\\xd4\\xe8\\x19\\x6a\\xf4\\x0c\\x35\\x7a\\xb0\\x0d\\x35\\x7a\\x86\\x1a\\x3d\\x43\\xd6\\xb7\\x21\\xeb\\xdb\\x90\\xf5\\x2d\\xfe\\xab\\x21\\xeb\\x5b\\x73\\x1b\\xb2\\xbe\\x75\\x69\\x43\\xd6\\xb7\\xe8\\xd1\\x87\\xac\\x6f\\x43\\xd6\\xb7\\x6e\\x03\\x0f\\x59\\xdf\\xa2\\x27\\x30\\x64\\x7d\\xfb\\x97\\xcd\\xfa\\x36\\xd4\\xe8\\xf9\\x2c\\xea\\x44\\x0c\\x45\\x22\\xba\\xb8\\x8b\\x3d\\xa9\\x22\\x11\\x43\\x8d\\x9e\\xa1\\x3c\\xc4\\x72\\x1b\\x6a\\xf4\\x7c\\x46\\xb8\\x77\\xa8\\xd1\\xf3\\x39\\xa3\\xdf\\xa1\\x46\\xcf\\x80\\x84\\xd7\\xb7\\xa1\\x46\\xcf\\x50\\xa3\\xa7\\xb5\\x0d\\x35\\x7a\\x06\\x6b\\xcd\\x60\\xad\\xa9\\xb7\\xc1\\x5a\\xb3\\xb9\\x0d\\xd6\\x9a\\xb6\\x36\\x58\\x6b\\x36\\xb6\\xc1\\x5a\\xd3\\xbd\\x0d\\xd6\\x9a\\xc1\\x5a\\x13\\xd5\\x06\\x6b\\xcd\\x60\\xad\\xf9\\x5c\\xad\\x35\\x43\\x8d\\x9e\\xa1\\x46\\xcf\\x50\\xa3\\x67\\xa8\\xd1\\x33\\xd4\\xe8\\x09\\xda\\x50\\xa3\\x67\\xa8\\xd1\\xb3\\xbf\\x1a\\x3d\\xb5\\xa8\\x9a\\xcf\\xb7\\x50\\x4f\\xf7\\x65\\x0c\\xd5\\x7a\\x86\\x6a\\x3d\\x0d\\x6d\\xa8\\xd6\\x33\\x54\\xeb\\x59\\xd7\\x86\\x6a\\x3d\\x43\\xb5\\x9e\\x0d\\x6d\\xc8\\x99\\x17\\xd9\\x86\\x9c\\x79\\xb1\\x6d\\xc8\\x99\\xd7\\xd4\\x86\\x9c\\x79\\xcb\\x6d\\xc8\\x99\\x37\\xe4\\xcc\\x1b\\x72\\xe6\\x0d\\x39\\xf3\\x56\\x07\\x1c\\x72\\xe6\\x35\\x0e\\x3e\\xe4\\xcc\\xfb\\xc5\\xe7\\xcc\\x1b\\xaa\\xf5\\x3c\\xc9\\x6a\\x13\\x43\\xa9\\x89\\x96\\xf6\\x74\\x4a\\x4d\\x0c\\xd5\\x7a\\xfe\\x35\\x8b\\x4c\\x0c\\xd5\\x7a\\x9e\\x30\\xfe\\x1c\\xaa\\xf5\\xb4\\xb7\\xa7\\x83\\x42\\x87\\x6a\\x3d\\xff\\xca\\x88\\x74\\xa8\\xd6\\x33\\x54\\xeb\\xf1\\x6d\\xa8\\xd6\\x33\\x58\\x1e\\x1a\\xdb\\x60\\x79\\x20\\x83\\xe5\\xc1\\xb7\\xc1\\xf2\\x10\\x35\\xee\\x60\\x79\\x18\\x2c\\x0f\\x83\\xe5\\x61\\xf3\\xa4\\x07\\xcb\\xc3\\x86\\xe1\\x06\\xcb\\xc3\\x60\\x79\\x58\\xd3\\x86\\x6a\\x3d\\xcd\\x6d\\xa8\\xd6\\x33\\x54\\xeb\\x19\\xaa\\xf5\\x0c\\xd5\\x7a\\xf6\\x59\\xad\\x07\\x34\\x9a\\xc8\\xc5\\x37\\x1d\\xce\\xd8\\xe3\\x78\\x5e\\x75\\x65\\xb9\\xd5\\x52\\x28\\x5d\\x94\\x89\\x2e\\x0b\\x96\\x02\\xcc\\x71\\x3f\\x0c\\x61\\x56\\x5a\\x16\\x4e\\xfd\\x0e\\xa5\\x4f\\x5e\\xb1\\x3c\\x93\\x0b\\x43\\xed\\x46\\xe4\\x52\\xa6\\x23\\x72\\x7e\\x79\\x71\\xc5\\x8a\\x7b\\x9e\\x30\\x77\\x80\\x3e\\x58\\x9a\\xda\\xbc\\xf4\\xeb\\x45\\xce\\x13\\x9a\\x65\\x20\\x9d\\x57\\xb3\\x99\\xd3\\x85\\x53\\xda\\xde\\x2c\\x08\\xfb\\xa4\\x59\\x21\\x68\\x46\\xb4\\x94\\x19\\xda\\x39\\xcc\\x64\\xac\\xd2\\x55\\x17\\x9c\\xdd\\x33\\x42\\x8b\\x1b\\xae\\x0b\\x5a\\x2c\\xc8\\x9c\\x69\\x9a\\x52\\x4d\\x9b\\x47\\xfd\\x4e\\xb1\\x30\\xea\\x41\\x4b\\x92\\x17\\x6c\\x8c\\x87\\xb8\\x36\\x0f\\x38\\x5e\\x1f\\xde\\xbe\\x73\\x57\\x94\\xa6\\xa9\\x73\\xf1\\x77\\x87\\xf4\\xaa\\xbc\\xf1\\xd0\\x3e\\x6e\\xe6\\x76\\x52\\x0f\\x2d\\x35\\x82\\x13\\x66\\xd5\\x11\\x39\\x57\\x08\\xb3\\x46\\xe9\\x2b\\x82\\x2d\\xe8\\xc6\\x04\\xb4\\x1e\\x31\\x26\\xee\\xb7\\x3d\\x5a\\xaf\\xc5\\x7d\\x5d\\x8b\\xc5\\xc4\\x3d\\x2f\\xa4\\x00\\x3e\\xee\\x9e\\x16\\x9c\\xde\\x64\\xcc\\x9a\\xac\\xbc\\x21\\xc3\\xf2\\x56\\x6c\\xc3\\x79\\x79\\xe9\\x15\\xfa\\x18\\x3e\\xd2\\x78\\xab\\xda\\xe9\\x49\\x0b\\x05\\xa9\\xad\\xf4\\xb5\\xb8\\xff\\x9e\\xd6\\x45\\x6a\\xb1\\x76\\x49\\xc4\\xbe\\x60\\x96\\x44\\xc9\\xcb\\xf6\\x05\\x45\\x31\\x7d\\x31\\xaa\\x9f\\x31\\x20\\xe9\\xc6\\x17\\xe2\\x14\\x34\\xa6\\x8b\\xcd\\x24\\xaf\\x06\\x96\\xf7\\x74\\x5e\\x55\\x6c\\x5a\\x03\\x8d\\x09\\x79\\x67\\xc5\\x40\\x4a\\x5e\\xfe\\xf7\\xc5\\xab\\xd7\\xef\\xaf\\x2f\\xde\\x5c\\xbc\\xfe\\xb8\\x19\\x15\\x46\\x52\\x6b\\x40\\x4d\\x1d\\x26\\xdb\\x4a\\x97\\xbf\\x77\\x7b\\x08\\x55\\x71\\x98\\x30\\x8c\\xcf\\xaf\\x4f\\xbe\\x3f\\xff\\xf8\\xdf\\xef\\xcf\\xdf\\xbd\\x3e\\x05\\x96\\x9e\\x7d\\xca\\xa9\\x48\\x59\\x1b\\x8b\\x56\\x2a\\x17\\xd3\\x92\\x17\\xec\\x9e\\xcb\\x52\\x65\\x0b\\x4f\\x24\\xd7\\x5f\\x85\\xe5\\x3b\\x60\\xd0\\x43\\xcb\\x28\\x86\\xc4\\x59\\xec\\xb1\\xbe\\x53\\x10\\xf9\\x69\\x75\\x38\\x2b\\x73\\x58\\xc1\\x94\\xcc\\xee\\x59\\xda\\x26\\xe9\\x43\\x80\\xa0\\x03\\x47\\x65\\x70\\xcc\\x4b\\xed\\x14\\x1a\\xce\\x86\\x58\\x8a\\x64\\x46\\xc5\\x2d\\x4b\\x27\\xe4\\x95\\x2c\\xcd\\x68\\xbf\\xfe\\x35\\x80\\xac\\x60\\x69\\x99\\xb4\\x42\\x0c\\xb5\\x51\\x28\\x50\\xfe\\x7a\\xe4\\x68\\xb8\\xa1\\x9c\\x0a\\xab\\x6d\\xa9\\x84\\xe6\\x0e\\xa8\\xe1\\xae\\xa8\\x85\\xd0\\xf4\\xd3\\x8b\\x98\\xba\\x5d\\x47\\xbf\\x0e\\x3e\\x3c\\x72\\x75\\xd4\\xa4\\x99\\x1e\\xf2\\x3b\\xb8\\xa2\\x0c\\x4a\\x60\\x65\\xe4\\x28\\x7c\\xbb\\xad\\xef\\xd7\\x66\\x7e\\x2c\\x0d\\xcf\\x0e\\xc6\\xf2\\xb1\\x7b\\x56\\x80\\x22\\xc4\\x9e\\x9c\\x11\\x29\\xd8\\x2d\\x2d\\xd2\\x8c\\x29\\x88\\x22\\x7b\\x98\\x31\\x28\\x6a\\x87\\x92\\x26\\x6e\\x54\\xcb\\x58\\xcc\\x2b\\x6d\\x84\\x6c\\x55\\xa6\\xbd\\x42\\x73\\x2e\\xe0\\xda\\xa3\\x96\\x65\\x74\\xb9\\x79\\x6f\\x0a\\xd9\\x52\\x1a\\xa9\\x76\\xfb\\xae\\x20\\x4c\\xc5\\x1b\\xbd\\xd7\\x1d\\xd7\\x63\\xab\\xb0\\x9f\\x84\\x58\\x5e\\x19\\x06\\x73\\x5a\\x19\\xa3\\xcd\\xef\\x11\\x06\\xe9\\x68\\x59\\x3a\\x5e\\x71\\x9d\\x48\\x31\\xe5\\xb7\\xef\\x68\\xfe\\x2d\\x5b\\x7c\\x64\\xd3\\x8e\\x11\\x73\\xc8\\x5b\\x5b\\x55\\x2c\\x70\\xac\\x86\\x3a\\x60\\x87\\xed\\x9c\\xe1\\x1e\\x03\\xa4\\x62\\xcc\\x03\\xdd\\xb4\\xfb\\xd1\\x3a\\xfd\\x95\\x82\\x67\\xc8\\xe5\\x5b\\x4e\\x7c\\x87\\xd5\\x2d\\xab\\xd6\\x4e\\xe0\\xd6\\x4e\\x2e\\x5a\\xa6\\x0b\\x29\\xa2\\x45\\x05\\xd1\\xea\\xee\\x77\\x12\\x82\\x40\\xa7\\xf2\\x05\\x99\\x69\\x9d\\xab\\x17\\x67\\x67\\x95\\xaa\\x65\\xc2\\xe5\\x59\\x2a\\x13\\x75\\x96\\x48\\x91\\xb0\\x5c\\xab\\x33\\x79\\x6f\\x50\\x3f\\x7b\\x38\\x7b\\x90\\xc5\\x1d\\x17\\xb7\\x63\\xc3\\x9a\\x8f\\xf1\\x8c\\xa8\\x33\\x90\\xd8\\xce\\x7e\\x05\\xff\\x8b\\x95\\x47\\x3f\\xbc\\xfa\\xf0\\x82\\x9c\\xa7\\xa9\\x2d\\xb3\\x59\\x2a\\x36\\x2d\\x33\\x5b\\x4f\\x6e\\x62\\x58\\xd5\\xef\\x59\\xa1\\xb8\\x14\\x23\\x72\\xc7\\x45\\x3a\\x22\\x25\\x4f\\xbf\\xde\\xc7\\x26\\xc9\\x1c\\x99\\xd9\\x1e\\x1b\\x75\\x05\\x22\\xeb\\xa2\\x86\\x55\\xfd\\x3d\\x33\\x18\\x93\\x6b\\x05\\xc7\\xcc\\xe9\\xa7\\x2d\\x51\\xee\\xb0\\x8c\\x1b\\x29\\x33\\x46\\xdb\\xbd\\x7c\\xb6\\x51\\x94\\x01\\xcc\\xbb\\x23\\x99\\xa8\\x63\\x5a\\x61\\x22\\x94\\x7e\\xec\\x69\\xcd\\x65\\xfa\\x82\\xa8\\x32\\xcf\\x65\\xa1\\x55\\x25\\x43\\x99\\x03\\x34\\xaa\\xff\\x13\\x14\\x01\\x23\\xf2\\xb3\\xff\\x11\\xbd\\x89\\x7e\\x3c\\xfe\\xe3\\xb7\\xaf\\xff\\xcf\\x9f\\x8e\\x7f\\xfa\\x39\\x7c\\x16\\x48\\x53\\xc1\\x0b\\x11\\xd3\\x54\\x39\\x4b\\x26\\x46\\xa4\\x7f\\x0f\\x33\\x80\\x7f\\x5a\\x66\\xe7\\x3c\\x49\\x64\\x29\\xb4\\x7d\\xa0\\xa9\\x2e\\xd5\\x64\\x26\\x95\\xbe\\xb8\\xf4\\xff\\xcc\\x65\\xba\\xfc\\xaf\\x08\\xf3\\xd6\\x1e\\xd1\\x2c\\xc0\\xfa\\x92\\xea\\x88\\xd0\\xf0\\x4e\\xc8\\xb6\\xba\\x95\\x3d\\x6e\\x8b\\xfd\\x32\\xac\\x58\\x3a\\xa7\\xf0\\xe7\\x1b\\x37\\x5d\\x43\\x73\\x1f\\x0a\\xae\\x35\\xb8\\xba\\xd9\\x68\\x74\\x39\\x1d\\x39\\x37\\x31\\xe4\\x2b\\xee\\x9f\\x77\\x52\\xf3\\x45\\x63\\x02\\x0f\\xb5\\x1e\\x8b\\x83\\xd9\\xdb\\x95\\x79\\x39\\xdf\\x3a\\xfa\\xad\\x28\\xb8\\xce\\x2f\\x2f\\xc8\\x3d\\x42\\x63\\x0f\\x0b\\xd9\\x06\\x15\\xb8\\x08\\xdf\\x37\\x07\\x41\\x09\\x6e\\x34\\x07\\x38\\x2f\\x8e\\xbc\\x40\\x83\\x87\\x8f\\x37\\x26\\x19\\x9f\\x73\\x6b\\xdb\\xb5\\x75\\x6a\\x63\\xe8\\xcc\\x09\\x7e\\x36\\x49\\xf2\\x72\\x64\\xbb\\x98\\xcc\\xd9\\x5c\\x16\\x0b\\xff\\x4f\\x96\\xcf\\xd8\\xdc\\x30\\xe0\\x63\\xa5\\x65\\x41\\x6f\\xd9\\xc8\\x0f\\x80\\x9f\\xf9\\x7f\\xe1\\x87\\xb5\\x29\\xac\\x7e\\x8d\\x72\\x5b\\x52\\x16\\x86\\x14\\x67\\x0b\\x87\\xe2\\x62\\xf4\\x71\\x7b\\x44\\x07\\xd1\\x35\\x80\\xbb\\x61\\x03\\xbf\\x5d\\xef\\xfb\\xf1\\x39\\xc7\\x5e\\x63\\x81\\x9c\\x92\\x5f\\x15\\x30\\xee\\xf7\\x32\\x2b\\xe7\\x4c\\x8d\\x3c\\x81\\x46\\xc9\\x4c\\xdc\\x1b\\x16\\x5e\\x1d\\xef\\x03\\x01\\xa4\\xfc\\x9e\\xab\\x5e\\xae\\x81\\x57\\xde\\xec\\x03\\x36\\x92\\x52\\x1b\\x99\\x15\\x13\\xd1\\x04\\x45\\xa6\\xa5\\x02\\x99\\xcd\\x07\\xd1\\xd7\\xb0\\xda\\xf3\\xa3\\xa8\\x61\\x73\\xaa\\x35\\x2b\\xc4\\x0b\\xf2\\xff\\x4e\\xfe\\xeb\\x37\\xff\\x18\\x9f\\x7e\\x7d\\x72\\xf2\\xe3\\xb3\\xf1\\xbf\\xff\\xf4\\x9b\\x93\\xff\\x9a\\xc0\\x1f\\x5f\\x9e\\x7e\\x7d\\xfa\\x0f\\xf7\\x8f\\xdf\\x9c\\x9e\\x9e\\x9c\\xfc\\xf8\\xed\\xbb\\x6f\\xae\\x2f\\x5f\\xff\\xc4\\x4f\\xff\\xf1\\xa3\\x28\\xe7\\x77\\xf8\\xaf\\x7f\\x9c\\xfc\\xc8\\x5e\\xff\\x14\\xd9\\xc9\\xe9\\xe9\\xd7\\xbf\\x8e\\x9a\\x1e\\x15\\x8b\\x0f\\x11\\x58\\x03\\xdb\\xb8\\x47\\x76\\x9f\\xea\\xab\\xbe\\x66\\x44\\x2e\\xf4\\x58\\x16\\x63\\xfc\\xfc\\x05\\xd1\\x45\\x19\\xa3\\xb4\\x77\\xdb\\xd6\\xe7\\x9c\\xbb\\x0a\\xbd\\x2f\\x2a\\x8c\\xe7\\xa9\\xc3\\x1e\\x0e\\xf2\\x36\\x04\\x40\\xb1\\xa4\\x60\\x7a\\x57\\x42\\x27\\xf6\\xe6\\x08\\xe0\\x92\\xad\\x6e\\x90\\x43\\x2b\\x39\\xd4\\x67\\x34\\x01\\x78\\x55\\xac\\xc3\\xb4\\x90\\xf3\\x09\\x09\\x14\\x9b\\xf7\\xe0\\x03\\x65\\xdf\\xbb\\x63\\x91\\x9e\\xf2\\x83\\xdc\\x3a\\xc8\\xad\\x2d\\x72\\xeb\\x15\\x1e\\xa9\\x27\\x2e\\xb4\\x32\\x71\\xbf\\x49\\x15\\xd8\\xc1\\x60\\xf4\\x06\\xb2\\x75\\x85\\x46\\x23\\xc7\\x6b\\x6a\\x49\\x72\\x99\\x97\\x19\\xd5\\x0d\\x8a\\xee\\x0e\\x16\\x24\\x1f\\xc8\\xe4\\xd4\\xf1\\xe6\\xf8\\x81\\xb5\\xc6\\xd2\\x81\\xf9\\x7a\\x93\\x05\\x39\\xcf\\x32\\xc2\\x05\\xde\\x76\\xd3\\x41\\xe3\\x08\\x4e\\x23\\x5e\\x30\\x64\\x34\\x09\\x45\\x73\\xd1\\xbd\\x99\\xf2\\x83\\xcd\\x31\\x16\\x28\\xfa\\xb9\\x32\\x72\\x6a\\xa1\\xb9\\xb8\\x9d\\x60\\x0e\\x32\\xc4\\xd7\\x56\\xcd\\xcb\\x85\\xcf\\x44\\xd6\\x38\\xa4\\xe7\\x5f\\xbc\\xbf\\xd2\\xda\\x22\\xf3\\x19\\x55\\xda\\x2d\\x13\\x66\\xa9\\xe9\\x1d\\x98\\x28\\x12\\x96\\x32\\x91\\x6c\\x50\\xa0\\x7f\\x8f\\x3e\\x50\\x0e\\x66\\x37\\x86\\xeb\\x06\\x23\\x1f\\xf4\\x4d\\x49\\x5a\\xe6\\x19\\x4f\\xcc\\xfe\\x98\\x99\\x77\\xeb\\xfb\\x62\\x3e\\x2f\\x35\\x98\\x8b\\x0e\\x65\\xcb\\x33\\x27\\xcd\\x2a\\xa4\\x03\\x93\\x1e\\xa0\\x7b\\x2f\\xfd\\x78\\xdf\\x58\\xaf\\x3e\\x6a\\xde\\xf1\\x28\\xb2\\x18\\x47\\xbc\\xbc\\x96\\xb9\\x95\\xda\\xaf\\x50\\xad\\x4a\\xcf\\x55\\xa7\\x56\\x87\\x56\\x94\\xc7\\xd1\\xaa\\xee\\x74\\xaa\\x2f\\x8d\\x7a\\x4c\\xfa\\xb4\\x1f\\xda\\xd4\\x81\\x2e\\xc5\\xd3\\xa4\\x0e\\x7a\\xd4\\xae\\x74\\x28\\x9e\\x06\\xf5\\x65\\x94\\xf3\\x82\\x4d\\xf9\\xa7\\x0e\\x17\\xe6\\x5c\\x54\\x52\\x2c\\x4f\\x99\\xd0\\x46\\x56\\x2c\\xac\\x2b\\x48\\xce\\x44\\xe5\\xe7\\x61\\xe3\\xf2\\x6b\\x10\\xd8\\xab\\x61\\x1b\\x59\\xc9\\xee\\xf7\\xff\\x6a\\x1d\\xab\\x3a\\x5c\\xfe\\xe1\\xf2\\xef\\xe2\\xf2\\xdb\\xc3\\xf5\\x94\\x6e\\xbe\\x90\\x69\\x6b\\xec\\x68\\xec\\x41\\x7b\\x1f\\xf4\\xb5\\x14\\x52\\x86\\xae\\x08\\x6e\\xe1\\xba\\x28\\x2b\\x2b\\x76\\x2e\\x01\\x4d\\x4c\\xb9\\xae\\xdc\\x1d\\x9b\\x0f\\xe5\\xd5\\x9a\\x1e\\xc1\\x8f\\xd1\\x7e\\x79\\xac\\x5c\\x5c\\xf6\\x52\\xff\\x4b\\xb9\\x80\\xd1\\x2b\\x6d\\xf3\\x58\\x1d\\x8f\\x3d\\x72\\x1d\\x25\\xc6\\xaf\\x9f\\x51\\xa5\\xf8\\xad\\x18\\xe7\\x32\\x1d\\x9b\\x51\\xce\\x36\\xb2\\x65\\x87\\x74\\x4c\\xf3\\x8a\\xba\\x6d\\xb7\\xfb\\xa3\\x57\\x63\\x07\\xfc\\x5f\\x22\\xe7\\x79\\xa9\\x59\\xa0\\xe3\\xf6\\xda\\x4f\\x17\\x99\\x1b\\x21\\x5f\\xb4\\x72\\xb3\\x5b\\x6e\\xce\\x9c\\x0a\\x7a\\xcb\\xc6\\x76\\xb2\\x63\\x3f\\xd9\\xb1\\x9f\\xdb\\x16\\xfb\\x15\\x83\\xe7\\x93\\x8c\\xf2\\xcd\\xae\\xd7\\x5d\\xb0\\xfb\\x4b\\xe8\\xcd\\x26\\x55\\xf6\\xbe\\xf1\\x4b\\xa9\\x4d\\x9d\\xd8\\xc1\\x05\\xda\\x01\\xdd\\x23\\xfc\\x78\\xb3\\x35\\x11\\x2e\\x8b\\x4f\\x5a\\xb1\\x66\\x23\\xbf\\xd8\\xf8\\x79\\xa7\\x78\\xff\\x36\\x67\\xe3\\x57\\x0b\\x41\\xe7\\x3c\\x71\\xa7\\xef\\x3c\\x03\\x17\\x6a\\x2e\\xc5\\x52\\x36\\x80\\x88\\x29\\xf9\\x60\\x17\\xee\\xcf\\x1b\\xb9\\xd0\\x24\\xa1\\x02\\x0d\\x35\\xd6\\x7b\\xd6\\x60\\x12\\xbf\\xd6\\x8d\\x16\\xd0\\x38\\x07\\xfc\\x08\\xb7\\xfb\\xda\\xee\\x7f\\x0c\\x77\\x2a\\x74\\x8e\\x92\\xc2\\x88\\xf2\\xba\\x00\\xde\\xea\\x52\\xa6\\x86\\xe6\\x4c\\x6a\\x6f\\xb7\\xd8\\x6b\\xa3\\x79\\x97\\x58\\x35\\x64\\x8b\\x03\\x25\\x79\\x3a\\x6c\\x50\\x40\\x39\\xdc\\x8d\\x31\\x17\\xa6\\x06\\xd2\\x5c\\xa6\\x93\\x35\\x77\\x25\\x3e\\x71\\xf4\\xa5\\x4c\\xad\\xab\\xbf\\xae\\x9d\\x37\\x73\\x8d\\xe0\\xa8\\xcd\\xe9\\x9d\\x73\\xc0\\xf7\\x3a\\x74\\x7a\\x4f\\x79\\x16\\xe1\\xc1\\x46\\x20\\xff\\x8b\\xe2\\xa9\\x61\\xa0\\x23\\x90\\xaa\\x9f\\x58\\x1c\\xef\\xb3\\x9a\\x9b\\xc2\\x30\\x14\\x77\\xad\\xc9\\x7a\\x5a\\x8f\\x40\\x53\\xd2\\x8b\\x39\\xcd\\x1b\\xbf\\x42\\xb3\\xe6\\xae\\xf0\\xe5\\x5b\\x34\\xbb\\xe2\\x27\\x37\\xd6\\xba\\x35\\xa7\\x9f\\xf8\\xbc\\x9c\\x13\\x3a\\x97\\x25\\xc6\\xc9\\xad\\xd2\\xb2\\xa8\\x28\\x84\\x5d\\x50\\xa6\\x35\\x14\\x49\\x35\\x91\\x24\\x12\\x7f\\x91\\xbb\\x07\\xba\\x3d\\x51\\xbb\\x5c\\x94\\x3d\\xae\\x9b\\x1d\\xae\\x83\\xfd\\xad\\xb7\\xdd\\xcd\\x59\\xd8\\x77\\x75\\x90\\x3f\\xda\\xfe\\x96\\x8f\\x32\\x17\\xad\\x47\\xd9\\x61\\xf4\\xcd\\x67\\xf9\\x62\\x5a\\x8d\\xc1\\x15\\x91\\x73\\xae\\xb5\\x35\\x64\\x07\\x38\\x67\\x44\\xb8\\xae\\x59\\x7d\\xed\\x05\\xe3\\x53\\x44\\x6d\\x5c\\x11\\xf6\\x29\\xcf\\x78\\xc2\\xc1\\x79\\xc0\\x39\\x8c\\x6c\\xe6\\x39\\x40\\xdc\\x7b\\xe0\\x58\\x4a\\x83\\x0a\\xc2\\xe7\\x39\\x86\\xb0\\xc2\\x45\\x19\\x3b\\x76\\xc6\\x7a\\xbb\\xfa\\x59\\x5a\\xf7\\x6c\\xf6\\x29\\x61\\x2c\\xb5\\x13\\x19\\xee\\xeb\\x70\\x5f\\x3b\\xdf\\x57\\xb5\\x23\\xa9\\x38\\x94\\x88\\xab\\x80\\x3c\\x2f\\x19\\x9b\\xab\\x04\\xc1\\x72\\x28\\xa3\\xba\\xd3\\xb5\\xe9\\x62\\xbe\\x76\\x49\\xd5\\x3e\\x32\\x30\\x18\\x5c\\x31\\xad\\x6c\\xe8\\x1f\\xf4\\x44\\x8b\\x0d\\x46\\x8e\\xe5\\x3c\\x49\\x3e\\x11\\x9b\\x0b\\x82\\xa5\\xd3\\x69\\xfd\\x8d\\x2a\\xea\\x6a\\x83\\xc0\\xa6\\x97\\x19\\x2a\\x10\\xbb\\xd9\\x3c\\xcf\\xa8\\xae\\x84\\xf2\\x2d\\xc2\\xb3\\x62\\xd8\\xc6\\x2e\\xa9\\x84\\x1e\\x37\\x79\\xd0\\x7e\\x04\\x85\\x56\\xee\\xf7\\x11\\x93\\x00\\xf5\\x4d\\xfb\\xb3\\x07\\x11\\xa5\\xdd\\x4b\\x22\\x32\\x7d\\x4f\\xbc\\x28\\x13\\xe5\\x46\\xb1\\xef\\xa4\\x3c\\x9d\\x94\\x9e\\xb1\\x89\\x77\\xba\\x8b\\x5f\\x7b\\x4e\\xae\\xb3\\xaf\\x74\\x3a\\x1d\\xa0\\x17\\x9b\\x32\\xa7\\x3b\\xec\\x0e\\x94\\x16\\xe7\\xe0\\x89\\x70\\x0e\\x99\\xfa\\xa6\\x53\\xb2\\x9b\\x2e\\x29\\x15\\xa2\\xd3\\x29\\x44\\x1d\\xa5\\xc8\\xa4\\x35\\x5d\\xce\\xd0\\x81\\x13\\xd3\\x1c\\x38\\x15\\xcd\\x63\\x24\\x9f\\xd9\\x1b\\x1f\\x1f\\x71\\x44\\xba\\x1b\\x7b\\xb4\\xcc\\x6c\\x7a\\xdd\\x38\\xe5\\xff\\x75\\xf5\\x3e\\x80\\xa3\\xf2\\x76\\x0c\\x7a\\x3a\\x8c\\xc3\\xc9\\xc6\\x93\\x7d\\xed\\xf8\\x4d\\x83\\x25\\xaa\\x49\\xc3\\x19\\xd7\\x9a\\x26\\x33\\x9b\\x42\\x06\\x9f\\x98\\x93\\x20\\x16\\xc4\\x1c\\x02\\x8d\\x14\\xd5\\x26\\xc2\\xd8\\xb4\\xcf\\x33\\x46\\x74\\x01\\x85\\x0c\\xff\\xe8\\x2f\\xc4\\x88\\x01\\xab\\xfc\\xa7\\x20\\x52\\xd9\\x97\\xe2\\xf3\\x87\\xf1\\x8f\\xee\\xaf\\x3f\\x6d\\x19\\xbf\\x1e\\xc7\\x6c\\xe0\\x94\\x76\\xc9\\x33\\xbe\\x86\\x1e\\x09\\x17\\x29\\xf8\\x26\\x21\\x4b\\x82\\xc0\\xc3\\xc1\\x0c\\x68\\x61\\xdd\\x13\\x9b\\xbe\\x03\\x13\\xd9\\x58\\xab\\x1c\\x38\\x31\\x55\\x2f\\xb7\\x92\\x70\\xf0\\xdd\\xaa\\x54\\x04\\x4e\\xe5\\x56\\xdd\\x61\\x46\\xde\\x4b\\x5b\\xd3\\x94\\x8d\\xc8\\x25\\xa8\\xc3\\xab\\x5f\\xe0\\xce\\xbf\\x97\\x58\\xdd\\xb4\\x25\\x98\\x39\\x92\\xa2\\xb7\\xf2\\x6e\\xdd\\xe0\\xf9\\x6d\\xc5\\xd8\\x21\\x60\\x6a\\x8c\\x5d\\x75\\xb1\\x42\\xd6\\x6e\\x23\\x60\\xef\\xd8\\xa2\\x15\\xaa\\x96\\x58\\x5b\\xa6\\x12\\x88\\xea\\xa8\\x3a\\xa3\\x8e\\xd8\\x22\\xfd\\xfe\\x9f\\xce\\xba\\x33\\xbf\\xe1\\x02\\xa7\\x82\\x03\\xbb\\x7d\\x86\\xb1\\xdd\\x7e\\x18\\x49\\x20\\xcb\\x22\\x26\\x11\\x09\\xed\\x38\\xce\\xb3\\x1b\\xc8\\x3f\\x74\\xe0\\x38\\x3d\\xbd\\x68\\x03\\xe9\\x3a\\x3e\\x33\\x60\\x2e\\x5f\\xff\\xb5\\xa4\\xd9\\xa4\\x16\\x39\\x8e\\x3f\\xb5\\x5d\\x37\\xeb\\xb0\\xb8\\x4c\\x37\\x1f\\x78\\x96\\x26\\xb4\\xb0\\x41\\x24\\x80\\x7e\\x88\\x92\\xd6\\x32\\x07\\xd8\\x2f\\x69\\x75\\x4d\\x75\\x08\\xb0\\x3a\\x3c\\x0a\\xbd\\xf4\\x72\\x5a\\x68\\x9e\\x94\\x19\\x2d\\x88\\xb9\\xe3\\xb7\\xb2\\x88\\x0a\\x0d\\x6f\\xdd\\xcc\\xea\\x34\\x5f\\xb1\\x44\\x8a\\x74\\xa7\\xc2\\xec\\xf5\\x72\\xe7\\xcb\\x7e\\x88\\x39\\x2b\\xb8\\x2d\\xab\\xc9\\xe7\\x6c\\xf9\\x7a\\x9d\\xd4\\x7c\\x12\\xda\\xe4\\xa1\\xa9\\x43\\x76\\x1e\\xb7\\x8c\\x42\\x0d\\x65\\xdd\\x9a\\x88\\x99\\xe0\\x4f\\x03\\x82\\xe3\\x6f\\xfb\\x84\\xfc\\x79\\xe1\\x54\\xa5\\x6d\\x8c\\x31\\xd7\\x2e\\x58\\x5f\\x31\\xed\\xd2\\x39\\xb8\\xab\\x68\\x77\\xb2\\x42\\x23\\x53\\x59\\x40\\x9a\\x84\\x93\\x54\\x62\\x80\\xff\\x3d\\x4f\\xf4\\xe9\\x84\\xfc\\x5f\\x56\\xc8\\x88\\x3c\\x18\\x82\\xdd\\x62\\x1d\\x58\\x7b\\xb1\\xbd\\x5e\\xa8\\x60\\xd4\\xfa\\xdf\\x3e\\x23\\x27\\x58\\x1a\\x98\\xcf\\xe7\\x2c\\xe5\\x54\\xb3\\x6c\\x71\\x8a\\x6a\\x22\\x66\\x8b\\x0b\\xc7\\x9c\\x9a\\x18\\xf5\\x5e\\x50\\xec\\xfa\\x77\\xbf\\xdd\\xf0\\xe6\\x1e\\xf2\\x97\\xd8\\x1c\\x09\\x15\\x60\\xd1\\x15\\x78\\xe9\\xf4\\xf8\\xdc\\x59\\xad\\x72\\x77\\xa3\\x9c\\x14\\x3a\\x1a\\x57\\xd9\\xcb\\x1c\\x6e\\xf6\\x67\\xeb\\x2f\\xe6\\x80\\x52\\x52\\xb0\\x5b\\xb8\\x9f\\x78\\xe7\\xb6\\xbc\\x9d\\x18\\x84\\xf6\\x4e\\x96\\xa2\\xd9\\x16\\x51\\x83\\xdb\\x5b\\xab\\x0a\\xfb\\x3e\\xf8\\xb0\\x6b\\xe2\\xa1\\xdd\\x32\\x84\\xc1\\x4c\\x02\\xeb\\x07\\x25\\x60\\xf2\\x00\\x0e\\xcc\\x20\\x36\\x7c\\xab\\x72\\x4f\\x8f\\x30\\x93\\xee\\x30\\x99\\x10\\xcc\\xa5\\x25\\x5e\\x79\\x27\\x29\\x87\\xfc\\x40\\xbb\\xbc\\x0a\\x10\\xfb\\x6b\\x21\\xb7\\x94\\x55\\xc7\\x55\\x47\\x81\\x03\\x8c\\x20\\xae\\x4e\\x30\\x4c\\x86\\xa5\\x36\\xbe\\xa7\\x0d\\xed\\x48\\xaf\\x65\\x24\\xc7\\x2f\\x8e\\x77\\x42\\x75\\x10\\x1a\\x85\\xcc\\xe9\\x2d\\x6d\\xaf\\x70\\xdf\\x0d\\x28\\xcb\\x7d\\x93\\x94\\x69\\x56\\xcc\\xa1\\x46\\xf7\\x4c\\x3e\\xe0\\x73\\x64\\x06\\x72\\xfb\\x16\\x4b\\x7d\\x55\\x17\\x32\\x93\\xad\\x10\\xc1\\x4a\\x28\\x55\\xfe\\x22\\xc4\\x1e\\xe0\\x43\\xf8\\x40\\x17\\x84\\x16\\xb2\\x14\\xad\\x71\\xb7\\xc0\\x45\\x7b\\xca\\xf1\\x6e\\x69\\xd2\\xef\\xa5\\x60\\xde\\x0d\\xa1\\x8d\\xca\\xd6\\x48\\xdb\\x0d\\xd3\\xd4\\x5c\\xf8\\xe7\\x93\\xe7\\xcf\\x76\\xb2\\x57\\x1d\\x93\\x65\\xc1\\x6c\\x96\\x2c\\x0d\\xce\\xab\\xd5\\xdd\\xf6\\x9d\\xcc\\xab\\x60\\x34\\xfd\\x20\\xb2\\x9d\\x72\\xfe\\xef\\xf0\\x62\\x40\\xdf\\x63\\xd0\\x3e\\xf0\\x29\\xd8\\x9f\\x46\\xf8\\xd3\\x43\\xc1\\x35\\x0b\\x30\\xff\\xc9\\x94\\x66\\x8a\\x11\\x59\\x90\\x52\\x78\\x89\\xe8\\xb4\\x4b\\xae\\x22\\xe8\\x20\\x06\\x1e\\xed\\xce\\xa5\\xaa\\xbc\\xd9\\x37\\x82\\xb1\\x98\\x04\\x2e\\x4b\\x85\\x5f\\xfc\\x65\\x38\\x56\\xcd\\xb8\\xa6\\x03\\x4c\\x8e\\x8e\\xc8\\x09\\xf6\\x63\\xb8\\x7f\\x29\\x75\\x0b\\x44\\x63\\x1d\\xce\\x11\\x3e\\xaf\\x3f\\xe5\\x3b\\x15\\x5d\\x5e\\xdb\\x8c\\x57\\x24\\x3f\\x18\\xb0\\xfe\\xcc\\x66\\xf4\\x9e\\x29\\xa2\\xf8\\x9c\\x67\\xb4\\xc8\\x20\\x9d\\xd0\\x15\\x2e\\x8f\\xdc\\x94\\x7a\\x7d\\xce\\xbe\\x88\\x7c\\x6f\\x81\\x9e\\x24\\x9c\\x67\\xd0\\xdd\\x3e\\xf7\\x91\\xb8\\x35\\x98\\x2d\\x02\\xc4\\xea\\xd6\\x04\\x85\\xb1\\x4a\\x5d\\xd2\\x2c\\x5b\\x10\\xf6\\x29\\xc9\\x4a\\xc5\\xef\\xb7\\x45\\x23\\x36\\xce\\xbf\\x07\\x77\\xb5\\xcc\\x58\\xe5\\xd6\\xb1\\xef\\x80\\x6c\\x55\\x5d\\x50\\x36\\x38\\x3a\\x75\\xc7\\x09\\xd8\\x28\\x54\\xb6\\x81\\xe6\\x0c\\xbc\\x24\\x69\\x92\\x30\\xa5\\x5c\\x4c\\xdb\\x22\\x8c\\xcb\\xf3\\x6b\\xf8\\x5c\\xd2\\x37\\xd2\\x07\\xf5\\x3a\\xa3\\x4a\\xf3\\xe4\\xcf\\x99\\x4c\\xee\\xae\\xb4\\x2c\\x76\\x2a\\x61\\xac\\xeb\\x7f\\x29\\x29\\xe6\\xf9\\x0f\\x57\\xe4\\x15\\x57\\x77\\x41\\x5c\\xbd\\x75\\xa3\\x09\\xd5\\x99\\xb4\\xcd\\xe6\\x58\\xde\\xb0\\x8c\\xe9\\x63\\x05\\x5c\\x07\\x99\\xd3\\x64\\x86\\xa9\\x59\\x81\\xa5\\x10\\x3e\\x73\\x83\\x55\\x7a\\x6c\\xdc\\x22\\x6c\\x1d\\x3d\\x65\\x6c\\xf2\\x90\\x33\\x7b\\x15\\x7e\\x45\\x1f\\x14\\xc3\\x95\\xdf\\x98\\x95\\x43\\xfe\\xd9\\x43\\xdb\\x7e\\x71\\x2e\\x17\\xaf\\x76\\x64\\xd7\\x9d\\xaa\\x6b\\x33\\xc7\\x3d\\x58\\xfa\\xb0\\x67\\x27\\x89\\x4e\\x79\\xc6\\x50\\xc2\\x06\\xa0\\xb8\\x20\\x1e\\x7b\\x27\\xe1\\x74\\x2c\\x64\\x49\\x1e\\x28\\x2a\\x8b\\x00\\xd3\\xc7\\x18\\x4b\\xaf\\x79\\xfe\\x82\\xbc\\x16\\xaa\\x2c\\x58\\xa5\\x83\\x5c\\x1e\\x8c\\xab\\x2a\\xe1\\x8b\\x13\\xf7\\xe1\\x48\\xa1\\x4c\\x6b\\x70\\x7a\\x8c\\xf4\\x8f\\xed\\xf5\\x27\\x3a\\xcf\\x33\\xa6\\x5e\\x90\\x23\\xf6\\x49\\xff\\xf6\\x68\\x44\\x8e\\x3e\\x4d\\x95\\xf9\\x9f\\xd0\\x53\\x75\\x34\\x21\\x17\\x73\\xef\\x29\\xc6\\xc5\\x94\\x15\\x05\\x73\\xf1\\x1b\\xf8\\x81\\x61\\x9a\\x02\\x7e\\x68\\x0f\\xf1\\x4b\\x5b\\x9f\\x5b\\x0b\\x5b\\x88\\x5c\\x32\\x42\\x41\\x2a\\xc9\\x03\\x66\\x31\\x35\\x24\\x93\\x15\\x85\\x2c\\x7c\\xb4\\x75\\x00\\x6c\\xa0\\xe5\\x89\\x9c\\xe7\\x85\\x9c\\xf3\\xc0\\xa4\\x00\\xf7\\x76\\x97\\xf6\\x69\\x50\\xf7\\xb5\\x4b\\x46\\xa4\\xd7\\xc1\\xf5\\x9d\\xbb\\xb3\\x1b\\xfc\\x20\\x76\\x73\\x6a\\x2f\\xa6\\xce\\x13\\x11\\x75\\x28\\xae\\xda\\x22\\x57\\xbe\\x1b\\x73\\x4e\\xed\\x38\\x86\\x26\\x74\\x3b\\x99\\x6f\\x7c\\x9e\\x1e\\x72\\x96\\xb2\\xfb\\x33\\x95\\xd2\\xe7\\x23\\x98\\xaa\\xb2\\x51\\x5d\\xf5\\x75\\x51\\x45\\x8e\\xe2\\x92\\x77\\x5d\\x39\\x9e\\x6a\\x14\\x42\\xa2\\xea\\x69\\x2a\\x0b\\x3f\\x24\\xd8\\x31\\x9f\\x1d\\x91\\x13\\x59\\xc0\\xd8\\x09\\x15\\x24\\x63\\xf4\\xde\\xda\\xe1\\x10\\x47\\x2d\\x50\\x61\\xd4\\xca\\xfb\\x74\\x51\\xbe\\x91\\xba\\x02\\xee\\xdf\\xbe\\x6a\\x79\\x3b\\x4e\\x56\\x22\\xbd\\x4e\\x93\\xeb\\xdb\\x69\\xe1\\x8a\\xd2\\x46\\xdd\\x4f\\x65\\x61\\x33\\xce\\xfa\\x57\\x14\\xd3\\x80\\x8c\\xb8\\xa8\\xe9\\xa9\\x9e\\x2a\\x86\\xe8\\x92\\x54\\xc2\\x91\\xad\\xbd\\xf8\\x94\\xd8\\xbe\\x41\\x23\\x20\\xf8\\x5f\\x4b\\x46\\x2e\\x5e\\xf9\\x8c\\x86\\xac\\x50\\x5c\\x69\\x83\\xb7\\xd2\\x1a\\x47\\xc2\\x91\\x4d\\x39\\x39\\x9f\\xd3\\xbf\\x49\\x41\\x5e\\xff\\xf9\\xca\\x76\\x14\\x71\\x14\\x1f\\x13\\xde\\xad\\x08\\x92\\xfe\\xad\\x2c\\x98\\xe1\\xbe\\x3a\\x30\\x7d\\xfe\\x9b\\x65\\x46\\xce\\xfc\\x4e\\x5e\\x51\\x4d\\x91\\x9f\\xb3\\xfe\\xd8\\xa2\\x22\\xa1\\x86\\x1b\\xbb\\xe1\\x22\\xb5\\x8f\\x62\\x79\\xb1\\x3d\\x70\\x46\\x66\\x7b\\xdf\\xb7\\x05\\xef\\xb8\\x17\\xbf\\xfb\\x78\\xb1\\x23\\x0e\\x2a\\x01\\xf2\\x76\\xfb\\x4e\\xa6\\x5d\\xd9\\xa8\\xe3\\xe0\\x53\\x47\\x6b\\xfe\\x97\\x81\\xe9\\x4b\\xfc\\x9d\\xcc\\x4d\\x9f\\xe4\\xbd\\x14\\x6c\\x44\\x3e\\x32\\x9a\\x12\\x83\\x25\\xec\\x9f\\x3f\\x14\\x5c\\xb3\\x49\\x7b\\x96\\xaa\\x0e\\x54\\xd5\\x01\\xb0\\xe3\\x32\\xdc\\x67\\x6e\\x09\\x61\\x90\\x76\\x6a\\x4e\\x0e\\xdc\\x3b\\x4b\\x3a\\x6f\\x32\\x79\\x43\\xec\\x6d\\xd8\\xf5\\xdc\\xbf\\xfb\\x78\\xd1\\x63\\xea\\xdf\\x7d\\xbc\\x70\\x33\\x37\\x7f\\xca\\xe9\\xe1\\x26\\x7d\\x08\\xe6\\xfb\\xcd\\x12\\x2f\\xdc\\x85\\x4d\\xa9\\xd2\\x1b\\x2c\\x73\\xd4\\xbb\\x64\\xa7\\x27\\x07\\x63\\xa4\\x3b\\x6c\\xcd\\x1d\\x17\\x11\\x29\\xcb\\xea\\xd7\\xd9\\x7c\\x63\\x84\\x52\\xf4\\x3e\\x0f\\xfc\\x3d\\xae\\x66\\x14\\xb2\\xcc\\xb9\\x0c\\x3e\\x78\\xa0\\xcc\\x09\\x53\\x86\\x3e\\xb9\\xa3\\x45\\x28\\xa6\\xb4\\x25\\xe4\\x15\\x43\\x5f\\x95\\xf4\\x85\\xf3\\x62\\xf3\\x5f\\xac\\xff\\xe0\\x1d\\x44\\x71\\xa4\\x16\\x91\\x13\\x0c\\xea\\x48\\x83\\x93\\x7c\\x82\\xea\\x5a\\xe1\\x1f\\xd9\\x20\\x3d\\x9e\\x71\\xa8\\xb7\\xab\\x4f\\x27\\xb5\\x00\\x18\\x05\\x53\\xde\\x29\\x7a\\x39\\x08\\x97\\xb5\\xa2\\x3c\\x26\\x27\\xe6\\xd9\\x19\\xa8\\xa6\\x4f\\x27\\x80\\x3b\\xe1\\x45\\x08\\x6a\\xac\\x18\\xb1\\x88\\x31\\xcc\\x31\\xff\\xb8\\x35\\xab\\x16\\xcb\\x34\\xc1\\x46\\x9a\\xcb\\xdb\\x95\\x8a\\x9b\\x6f\\xd6\\x52\\x71\\x78\\xe0\\x6a\\xf3\\x3c\\x65\\x42\\x8e\\xa9\\x4f\\xa2\\x48\\x39\\x1c\\xd3\\xd6\\x37\\xe3\\x89\\xf9\\x41\\xce\\x68\\xfa\\x4b\\x39\\xa3\\xc4\\xe7\\xa9\\xe9\\xc1\\x36\\x54\\x1f\\x3a\\xf2\\xeb\\x63\\x98\\x5d\\xba\\xc5\\x5a\\x04\\x07\\x1e\\xe2\\x2b\\x8b\\xf9\\x6c\\xf6\\x6f\\x64\\x36\\xcc\\xd1\\xfd\\x36\\x22\\x73\\x64\\x07\\x64\\xe5\\x0f\\x56\\xd7\\x55\\xb9\\xef\\xdc\\xa2\\x10\\x21\\xc3\\xcf\\x24\\xe2\\x48\\x47\\x4f\\x32\\x61\\xf9\\x6c\\xda\\xc5\\x1d\\xc9\\x7c\\xf0\\xe6\\xaa\\xae\\x18\\x7f\\xc9\\xf2\\x19\\x79\\x73\\xb5\\x06\\x1b\\x00\\xec\\x61\\xd6\\x0a\\xd5\\xe5\\xc7\\x8a\\x64\\x7c\\xca\\x34\\x6f\\x59\\xc2\\x1e\\xf0\\xc1\\x5c\\x0a\\xae\\x65\\xb1\\xd9\\x57\\x3b\\xfe\\x8e\\xbb\\xee\\xf6\\x71\\xc7\\x5d\\xdf\\x66\\xf7\\xab\\xec\\xb2\\xef\\x82\\x5f\\x29\\x49\\x64\\x96\\xb1\\x44\\xdb\\x94\\xeb\\xb0\\x05\\x51\\x2b\\xc4\\xb6\\x46\\xf0\\x64\\x56\\xef\\x33\\xb9\\xfb\\x03\\x88\\x9e\\x56\\xc8\\x3c\\xc3\\x23\\x72\\xf6\\xf1\\xf5\\xf9\\xab\\x77\\xaf\\x27\\xf3\\xf4\\x57\\x33\\xf9\\x30\\xd6\\x72\\x5c\\x2a\\x36\\xe6\\xed\\x99\\x5b\\x1f\\x2f\\x72\\x00\\x5b\\x1e\\x95\\xf1\\xbd\\xce\\x82\\xe5\\x36\\x59\\xfd\\x07\\x97\\xf3\\x88\\x7c\\xa7\\xd0\\xf7\\x0b\\x34\\x91\\xce\\x7e\\x2d\\xa5\\x1e\\x91\\x82\\xda\\xbc\\x46\\xd4\\x2a\\x32\\xcb\\x2c\\xc3\\xed\\xd0\\x05\\x63\\xa3\\x50\\x29\\x77\\xf6\\xf9\\x31\\x42\\x35\\x20\\x3c\\x79\\xae\\xe8\\xf0\\xe7\\xba\\x0b\\x75\\x6b\\x67\\xc3\\x48\\xaf\\xcd\\xaa\\x7a\\xaf\\x6f\\xd7\\x55\\xed\\x77\\x54\\xd5\\xea\\x99\\xd9\\xbc\\x3b\\xb6\\x20\\x10\\x31\\x34\\x95\\x85\\x39\\xda\\x45\\xfd\\x98\\x32\\x9d\\x00\\x74\\xce\\x4a\\xc5\\x8a\\x09\\x76\\xff\\x04\\x61\\x1f\\x47\\x81\\xe3\\x12\\xe0\\x91\\x2d\\x20\\xff\\x91\\x4d\\xd7\\x01\\xde\\xfe\\x5c\\x55\\x3c\\xb3\\xbc\\x30\\x2d\\xf5\\x8c\\x09\\xcd\\x6d\\xb6\\x1e\\xcb\\xa5\\xac\\xdd\\x89\\x88\\xe2\\x54\\xd8\\x0e\\x0d\\xfa\\xc8\\xac\\xdd\\xdd\\x72\\x6c\\x0f\\x79\\xa9\\x9b\\xdb\\x13\\xc9\\x4b\\xbd\\x4d\\xee\\x79\\x83\\x4c\\xf6\\x71\\x09\\x4d\\xbf\\x90\\x94\\x23\\x24\\xd6\\x3e\\xcd\\x40\\x41\\x53\\xa9\\xf0\\x1d\\x2c\\x3f\\x14\\x5c\\x2f\\x9a\\xce\\x79\\x7b\\x1a\\xeb\\x27\\x88\\xd8\\x12\\x2e\\xd2\\x36\\x60\\x76\\x03\\x24\\xf6\\x58\\x67\\xeb\\xed\\x6f\\xd6\\x38\\xe7\\x5d\\x2e\\xa8\\x13\\xee\\x31\\x81\\xa0\\x75\\xaf\\xa8\\x7b\\x57\\xf4\\xf0\\xa0\\x58\\x86\\xe8\\x7c\\xa1\\xfe\\x9a\\x8d\\x71\\x0e\\xe3\\x3c\\xad\\x40\\x3a\\xb8\\x4a\\x6c\\xec\\xb9\\xc9\\x55\\xe2\\xe9\\x69\\x6c\\x9f\\x84\\x03\\xc4\\x6e\\x8e\\x1d\\x79\\x82\\xac\\xfb\\x93\\xd7\\x0f\\x1d\\x64\\x3f\\xba\\x30\\xe8\\x87\\xe0\\x12\\x2b\\x2a\\x95\\x4b\\x6e\\xa3\\x47\\x7c\\x25\\x15\\xc4\\x5b\\x4e\\x59\\x65\\x80\\x9a\\xd3\\x82\\xce\\x99\\x66\\x05\\x7a\\xa9\\x5b\\xaf\\x78\\x11\\xc3\\x7c\\x81\\x0b\\xfd\\x87\\x9c\\x89\\x2b\\x4d\\x93\\xbb\\x1d\\x57\\xa8\\x1a\\x38\\xbb\\x81\\xb3\\xf3\\xed\\x20\\x5e\\x19\\xee\\xf8\\xdb\\x04\\xeb\\x8b\\xd0\\x71\\x88\\x0b\\xcb\\xac\\x3c\\x11\\xa4\\xd3\\xce\\xc0\\xb9\\xe4\\xef\\x5d\\x34\\xaf\\x3e\\x65\\x7e\\x9d\\x4b\\xab\\x2a\\x35\\xa0\\xb2\\x15\\xdc\\xdc\\x7d\\x89\\x13\\x08\\xc9\\x44\\x30\\xed\\x86\\x71\\x8a\\xbf\\xf9\\x96\\x00\\xf5\\x70\\x69\\x88\\x3a\\x19\\x41\\xf7\\x75\\xc4\\x3a\\x37\\xbf\\xdc\\x70\\x5d\\xa1\\x4c\\xc5\\x34\\xc9\\x59\\x31\\xe7\\x36\\xad\\x95\\x14\\x24\\xb1\\xf1\\x9c\\xc0\\xe0\\x18\\x66\\xc6\\x76\\xd7\\x89\\x3d\\x12\\x44\\x26\\x9a\\xda\\x20\\x70\\x72\\xc3\\xf4\\x03\\x63\\x82\\x3c\\x7b\\xf6\\xec\\x19\\x70\\xc9\\xcf\\x7e\\xff\\xfb\\xdf\\x13\\x48\\x11\\x98\\xb2\\x84\\xcf\\x57\\x5f\\x84\\xb7\\xfe\\xc7\\xf3\\xe7\\x31\\x83\\xfe\\x9f\\xf3\\x77\\x6f\\xc1\\xc1\\x3c\\xd7\\x8a\\xdc\\x48\\x3d\\xb3\\x63\\x9b\\x2e\\x6a\\xdd\\xab\\x11\\xf9\\xcf\\xab\\x0f\\xef\\xab\\x94\\xc2\\xf5\\xa7\\xa0\\x69\\xf0\\x20\\x8a\\x19\\x39\\x54\\xfb\\x3d\\xfb\\xdd\\x6f\\x7f\\x1b\\xf5\\x0d\\x2f\\x20\\x31\\x13\\x87\\x10\\x5a\\x1f\\xad\\x91\\xbb\\x38\\x03\\x21\\xf5\\x6a\\x86\\x35\\xcb\\x49\\x44\\x39\\xec\\x42\\x00\\x14\\xbf\\x9d\\xc1\\x46\\x98\\xfb\\x2f\\xc5\\x34\\xe3\\x89\\xc6\\x22\\x32\\x88\\x4a\\xf1\\x48\\xd8\\xbc\\xb2\\xd4\\x26\\x69\\xb0\\xac\\x71\\x94\\x16\\x3e\\x65\\x23\\x92\\xf1\\x3b\\x46\\xa6\\xea\\x9b\\x42\\x96\\x79\\x95\\x4a\\xa5\\x60\\xca\\x08\\x91\\x09\\x15\\x66\\x7c\\x1c\\xae\\x3a\\x77\\x8a\\x45\\x27\\x52\\xda\\x87\\x23\\x62\\xa4\\x1a\\xbd\\xfb\\x95\\x83\\x8e\\x97\\xf8\\xee\\x91\\xaf\\x6c\\x31\\xc6\\xd3\\x9d\\x53\\xee\\xe3\\x1d\\xc0\\xe5\\xab\\x56\\x1a\\xd8\\xab\\xc3\\x62\\x2a\\x4e\\x55\\x55\\x42\\x5c\\x18\\x76\\x5e\\xc8\\xbf\\xe0\\xa1\\xe1\\xc2\\x65\\x29\\xb0\\xf2\\xa9\\xb2\\xe2\\x8a\\x4d\\x9d\\x23\\x2a\\xeb\\x59\\xc4\\x48\\x2e\\x15\\x9b\\x61\\xbd\\x6c\\x12\\xb8\\x2a\\x03\\x02\\xb9\\x98\\x86\\xa9\\x38\\x20\\x17\\x19\\x57\\x66\\x12\\x50\\xfc\\xc9\\xce\\x2d\\x62\\x94\\x35\\xb3\\xaf\\xca\\xc6\\x9a\\xbb\\xa1\\xf0\\x84\\x95\\x62\\xa5\\x7f\\xac\\x61\\x1f\\x35\\x06\\x90\\x06\\x98\\x34\\x75\\x99\\x2e\\xaa\\x51\\x30\\x46\\xca\\xc6\\xd3\\xdb\\x77\\x57\\x4a\\x92\\x44\\xa7\\xaa\\xb2\\xa1\\x55\\x4c\\x97\\x76\\x8b\\xc0\\xa9\\xdb\\xcc\\x9f\\x29\\x65\\x03\\xf7\\xe7\\xb4\\xb8\\x63\\xa9\\xc7\\xcf\\x13\\x88\\x77\\x53\\x91\\x09\\x07\\x88\\x4b\\x99\\xc7\\xef\\xd1\\x40\\x3b\\xa7\\x8b\\x5a\\xb0\\xac\\x99\\xc6\\xf1\\x64\\x72\\x8c\\xa8\\x45\\x16\\x58\\xfe\\x0a\\xb1\\x80\\xf9\\xfd\\x91\\x52\\x5b\\xd5\\xee\\xd6\\x3b\\x9a\\x2b\\x4c\\xce\\x65\\x58\\x7a\\x5b\\x98\\x9e\\xd6\\x42\\xd9\\xa8\\x85\\x65\\x0c\\xee\\xeb\\xc4\\xa8\\x77\\x2b\\x9d\\x18\\x5b\\x3c\\x11\\xdf\\xcc\\x63\\x4a\\x50\\x77\\x95\\x15\\x3a\\xd4\\x5a\\x6c\\x4e\\x15\\x68\\x61\\x6c\\xef\\x5b\\xac\\x28\\xd0\\xb9\\xf0\\xe8\\x3c\\x8a\\xb5\\x59\\x33\\xd5\\x68\\xc9\\x06\\xc7\\xa8\\x9b\\x17\\xa2\\xf8\\x1b\\x9b\\x8a\\x63\\x53\\xe9\\x88\\xe5\\xf6\\x28\\x6c\\x0d\\xb6\\xc7\\x63\\x6e\\xb0\\x5d\\x4c\\x31\\x4a\\xbc\\x8e\\xe4\\x2d\\x7a\\x0b\\x19\\x4d\\x47\\x87\\x62\\x42\\xc6\\xab\\x76\\x08\\x6e\\x05\\xdb\\x9e\\x79\\x16\\x6c\\x7d\\xca\\xfa\\x76\\xe1\\x5f\\xb0\\xc5\\x19\\xee\\xb1\\xf5\\xbd\\x5c\\xce\\xd0\\x8f\\xe0\\xb1\\x64\\x26\\xaf\\x15\\x7b\\xcf\\x50\\x75\\x0a\\xf2\\x95\\x43\\x2c\\x1d\\xee\\x94\\x25\\x57\\x78\\xad\\xe8\\x8d\\x92\\x59\\xa9\\x71\\x88\\xee\\x9d\\x84\\x34\\x0f\\x26\\xe9\\x32\\x08\\xc6\\x11\\xba\\xe5\\xee\\x02\\x4a\\x09\\x9c\\x08\\x92\\xa7\\x2e\\x7d\\x75\\x40\\x98\\x43\\x2d\\xaf\\xaa\\x7d\\xae\\xb5\\xbc\\x7c\\x91\\x3b\\xb5\\xb1\\xa2\\x5f\\x55\\x64\\x56\\x3d\\xa9\\x1a\\x5f\\xd8\\x12\\xc5\\xbb\\x28\\x5d\\x14\\x27\\x27\\x55\\x21\\x7b\\xe7\\x37\\x78\\x21\\x34\\x2b\\xa6\\x34\\x61\\xa7\\xa1\\x32\\x86\\xe5\\x33\\x36\\x67\\x85\\x01\\x90\\x7d\\xcf\\xc5\\x2b\\xcf\\xa8\\x48\\x33\\x94\\x74\\x13\\x56\\xc0\\x25\\x66\\x9f\\x34\\x2b\\x0c\\x30\\x5f\\x5e\\x5d\\x90\\xb4\\xe0\\xf7\\xac\\x50\\xe4\\xe4\\xcf\\xcc\\x08\\x4c\\x58\\xc0\\x27\\x2a\\x21\\xc3\\x6e\\x63\\x5f\\x60\\x1a\\xbb\\x52\\xff\\x40\\x67\\x7b\\xd1\\xfc\\x40\\xcf\\x0e\\x6f\\x8b\\x00\\x03\\x54\\xb0\\x44\\xd0\\x23\\xdc\\x55\\xa8\\x05\\x8b\\x41\\x0e\\x2f\\xa5\\x00\\x52\\x09\\xb8\\x71\\x21\\xcb\\x02\\x4d\\xc5\\xbe\\x96\\x5a\\x22\\x8b\\xc2\\x90\\x67\\x18\\x9a\\x2a\\x52\\xb0\\x5b\\x23\\xaf\\x15\\x58\\x56\\x0a\\xde\\xc8\\x4a\\xf3\\xc3\\x4e\\x83\\x09\\xf6\\x6e\\x39\\xf4\\x26\\xc2\\x0d\\xe1\\x14\\x11\\xbd\\x59\\x66\\x2a\\x2f\\xe4\\x3d\\x4f\\x1d\\x2f\\x05\\xae\\x2c\\x96\\x51\\xe4\\x8a\\xe4\\x54\\x05\\x31\\xf7\\x41\\x7d\\xe1\\x6a\\x07\\x23\\x46\\x42\\x61\\x16\\x78\\x32\\x9f\\x7f\\xa8\\x16\\x09\\x1b\\x9a\\x2f\\x25\\x64\\x92\\x8c\\x70\\xa7\\xe9\\x42\\xd5\\x64\\xca\\x2e\\xcb\\x9b\\x8c\\xab\\xd9\\xd5\\x3e\\x4d\\x48\\xeb\\xc6\\x41\\x37\\xd0\\x15\\xf7\\xa2\\x26\\x53\\x52\\x94\\xa1\\x4a\\x28\\x0e\\x2c\\x90\\x21\\x8c\\x86\\x5f\\xe3\\x46\\x92\\x90\\xb0\\x5b\\xae\\xff\\xf0\\x8a\\x49\\x08\\xd3\\xce\\x98\\x4d\\xc0\\xf7\\xf2\\x6a\\x73\\x34\\x1c\\xb6\\xf7\\xd5\\x5a\\x6c\\x96\\x0d\\xcc\\x55\\x9a\\xb2\\xef\\x44\\x5e\\xfb\\x3d\\xa1\\x59\\x73\\xad\\x84\\xb0\\xd5\\x93\\x33\\x39\\x32\\x85\\x9c\\xaf\\xcb\\xcd\\x81\\x07\\x90\\x9b\\xb3\\xe9\\x60\\xc4\\x83\\xf2\\x2f\\x36\\x3f\\x5d\\xb4\\x39\\x6f\\x09\\xc0\\x8a\\xcc\\x25\\xe6\\x0e\\x10\\x50\\x3b\\x0b\\x5f\\x82\\xb4\\xad\\xee\\x83\\x20\\x33\\x0c\\xa4\\xc5\\x82\\x1b\\x30\\x98\\xe5\\x1a\\xda\\x60\\x96\\x83\\xb6\\x8d\\x59\\xee\\x20\\x5e\\x06\\x4e\\x64\\x46\\x5c\\xe4\\x12\\x7a\\xd5\\x8a\\x03\\x79\\xb2\\x19\\x4f\\x80\\x5b\\x3c\\x8d\\x77\\x6a\\xfb\\xc7\\x59\\x9d\\x6b\\x5d\\xf0\\x9b\\x52\\xef\\xa9\\x5e\\xc1\\xd2\\x18\\xc0\\x20\\x32\\x65\\x11\\xe9\\xd8\\x02\\x31\\x09\\xee\\x6f\\x55\\x6b\\xb2\\x4e\\x2a\\xe3\\x70\\x2c\\xf6\\x3b\\xf1\\x8c\\x0c\\xf0\\x30\\xf8\\xe3\\xb1\\x22\\xa9\\x4c\\x4a\\x5f\\x41\\x0a\\x76\\xa7\\x72\\xeb\\x89\\x2d\\x30\\xd1\\x09\\x2d\\x75\\xcf\\xfb\\x1e\\x0e\\xd2\\x7a\\x55\\x52\\xf9\\x20\\x1e\\x68\\x91\\x9e\\x5f\\xb6\\x44\\xee\\xd6\\xa3\\x76\\xab\\xaf\\x42\\x26\\xde\\xfd\\x4c\\xcc\\xef\\xf4\\x46\\x96\\xba\\xaa\\xe3\\xf3\\xaf\\x65\\x60\\x5d\\xa7\\x71\\xd4\\xd2\\x60\\xc2\\x8d\\x06\\xd4\\x4a\\x8f\\xd8\\x73\\x8c\\xc1\\x6a\\x3b\\x58\\x6d\\x07\\xab\\x6d\\x53\\xab\\xdd\\xe3\\x0b\\x34\\xc8\\x86\\x55\\xba\\x6a\\xf8\\xcb\\x65\\x47\\x8c\\x01\\xdd\\xfe\\xed\\x60\\xaf\\x2a\\x8c\\x8b\\x1c\\xfe\\x72\\x90\\xf1\\x92\\xd8\\x81\\xb7\\xbd\\xd2\\xc3\\x06\\x7e\\x71\\x0e\\x25\\x03\\x3f\\xf6\\xf8\\x36\\xb3\\x3d\\x59\\xc2\\x60\\x75\\x51\\x22\\x25\\xb6\\x7a\\x14\\x5b\\x15\\x39\\x88\\xb5\\xf7\\xd0\\x40\\x1e\\xd8\\xe2\\x73\\x99\\xbe\\xc0\\xf2\\x2f\\x50\\x2c\\x12\\xf3\\xff\\x8f\\x6c\\x8d\\xba\\x91\\xd5\\x6e\\x88\\x14\\xcb\\x68\\xe7\\x34\\x61\\x80\\x04\\x3c\\xaf\\x10\\x91\\x36\\x04\\x5b\\x47\\xe0\\x93\\xce\\x1b\\x40\\x60\\x13\\x60\\x6d\\x2d\\x69\\xa6\\xc3\\xd6\\x75\\x37\\x4c\\xab\\xf8\\xfe\\xf8\\x6f\\x96\\x53\\x4b\\xe2\\xf7\\x6e\\x13\\x54\\x32\\x63\\x73\\x0a\\x7f\\xbe\\x71\\x0b\\x30\\x37\\xda\\xb0\\xba\\x9a\\x61\\xb2\\x30\\x56\\x40\\xb5\\xe5\\x51\\xcd\\xa7\\xf7\\xe8\\x3e\\x2e\\xd7\\x96\\x6b\\x9d\\xad\\x9b\\xc4\\x9d\\xc0\\xf6\\x84\\xb7\\x1b\\x96\\x7b\\x59\\xb3\\xa6\\x98\\xd3\\x07\\xa4\\x3d\\xc3\\x62\\x2a\\x4b\\x3e\\x10\\x80\\xb3\\x10\\x3e\\x7b\\x5e\\xda\\x36\\x82\\x15\\xb6\\x43\\x18\\x7f\\xfb\\x1a\\x7d\\x47\\x5e\\xf1\\x5e\\xe7\\x76\\xa2\\x07\\x1e\\x8c\\xbe\\x83\\xd1\\xb7\\xde\\x9e\\xb8\\xd1\\x37\\xa0\\x76\\x0e\\x83\\xae\\xb1\\xea\\x86\\xb6\\x02\\x67\\xda\\xbd\\x61\\x4e\\xac\\xb0\\xa2\\x8b\\xb3\\xd7\\x3a\\x63\\xad\\x2c\\xea\\xde\\x46\\xc7\\x93\\xc9\\x31\\xfa\\x1b\\x55\\xb2\\x4e\\xa9\\xa7\\xe3\\x3f\\x10\\x26\\x12\\x99\\x9a\\x7e\\xae\\xa1\\xff\\x42\\x69\\xe0\\x94\\x2a\\x1d\\x58\\x38\\x97\\xb9\\x1b\\x2b\\xf4\\x58\\x82\\xbe\\xbb\\xd1\\xd5\\x0e\\x68\\xcf\\x65\\xad\\x7b\\xb3\\x0d\\x5f\\xd1\\x01\\x7d\\x55\\x7c\\x87\\xcf\\x97\\x67\\x41\\xe1\\x33\\x23\\x5b\\x06\\xa4\\x2a\\xc8\\x8d\\x25\\xee\\xe1\\xfc\\xba\\x32\\xe1\\xd1\\xe3\\x9d\\xe0\\xc7\\x93\\x24\\x2f\\x47\\xb6\\xa3\\xc9\\x9c\\xcd\\x65\\xb1\\x18\\xf9\\xce\\xcc\\xc3\\x5a\\xef\\xf6\\x0d\\xcc\\xd1\\x9d\\x94\\x45\\xc1\\x04\\x94\\xe7\\xf6\\x6c\\xce\\xd3\\xe2\\x72\\x1c\\xa4\\xf6\\xc8\\xe4\\xf8\\xcd\\x89\\xcb\\x5c\\x52\\xb5\\xfa\\x8d\\xac\\xcc\\xa6\\xa0\\x68\\xf6\\xab\\xc5\\xd2\\x4d\\x18\\x30\\x39\\xaa\\x8c\\xca\\xe6\\x57\\x26\\xee\\xc9\\x3d\\x2d\\x54\\xec\\x0d\\x20\\x7d\\xf9\\x9a\\x94\\xdf\\x73\\x15\\x53\\xd7\\xb5\\x61\\x71\\x57\\x5e\\xed\\x09\\x65\\x29\\x4a\\x9d\\x97\\xda\\xa2\\x3b\\x77\\xc4\\x5d\\x5e\\x69\\x7f\\xb4\\x97\\xd8\\xb7\\xe7\\x47\\x1d\\x06\\x7f\\xa2\\xf5\\xcc\\xeb\\x2d\\xaa\\xba\\x79\\xbd\\x75\\xab\\x75\\xbe\\xfe\\xdb\\x8e\\x5b\\xdf\\xb3\\x0e\\xfa\\xba\\xe6\\xb6\\xb6\\xff\\x1d\\xa9\\xa8\\x56\\x95\\xe3\\xdc\\xb1\\xc7\\x7b\\xbe\\x04\\x7d\\x39\\x60\\x30\\xa4\\xbd\\xe2\\x3b\\x0d\\x3f\\x76\\x7d\\xd6\\x43\\x5b\\x34\\x9b\\xe7\\xb2\\xa0\\xc5\\x82\\xa4\\x56\\x31\\xb5\\xd8\\x98\\x51\\x68\\xcf\\x79\\xdb\\x61\\x92\\x29\\xdf\\x7c\\x48\\xf7\\xa0\\xe6\\x9d\\xb3\\x94\\x97\\xf3\\xbd\\xe4\\x19\\x82\\x9e\\x43\\xa0\\x3f\\x40\\xf2\\x73\\x9b\\x5a\\xdd\\x79\\xb1\\xd8\\xd7\\x5c\\x05\\x0d\\x9a\\xdc\\xd9\\x8a\\xf8\\x6e\\x57\\xe2\\x74\\x7f\\xb5\\x04\\xd5\\x47\\x47\\x4b\\x85\\xdc\\x40\\xaf\\x0c\\xfe\\x1c\\x32\\x65\\xc7\\xca\\xbf\\x8b\\x83\\x77\\x54\\xf0\\xa2\\xb1\\xd7\\x7a\\xb4\\x9d\\xd8\\xae\\x4e\\x0d\\x27\\xf7\\x0e\\x88\\xfd\\x01\\x72\\xf3\\x46\\x9d\\x16\\xd2\\x31\\x99\\x09\\xff\\x1b\\x7b\\x6b\\xd8\\x9a\\xbd\\x84\\xa9\\xba\\xce\\x7d\\xd9\\x37\\x09\\xd2\\x98\\xcd\\xea\\x35\\x25\\x99\\x4c\\x02\\xd7\\xa6\\x1a\\x35\\x87\\xe3\\xf0\\xda\\x5d\\xe2\\x78\\x3b\\x9f\\x39\\x14\\x66\\x5c\\x64\\xd6\\x40\\x91\\x99\\x29\\x74\\xd4\\xe0\\x09\\xd4\\x53\\x01\\xd9\\x0e\\xf6\\xac\\xc3\\x49\\xb8\\x86\\x7c\\xf1\\x9f\\xf8\\xbc\\x9c\\x93\\x52\\x99\\xd9\\x42\\xf1\\xce\\xa0\\x97\\x6a\\xb2\\x0f\\xae\\x2c\\x0c\\xa4\\x76\\xe2\\x02\\x3e\\xaa\\xc9\\xb6\\x31\\xea\\xc5\\x19\\x23\\x57\\x1e\\x7e\\x95\\x3e\\x03\\x42\\xab\\x9d\\x28\\xa6\\x4a\\x90\\x04\\xec\\x3c\\x2c\\x9f\\x2b\\xa7\\xe0\\x23\\xe0\\x59\\x2e\\xe5\\x2b\\x8b\\xf4\\xb8\\x54\\x82\\x67\\xf5\\x5b\\xe5\\x4a\\x19\\x78\\xf0\\x96\\xc2\\x7a\\xe2\\x3d\\xa5\\x1b\\xf0\\x84\\x99\\x9b\\x68\\x96\\xa6\\x3b\\x23\\xd3\\x91\\x7d\\xd9\\x82\\x69\\xf1\\x7e\\x89\\x3b\\x25\\xd9\\xde\\xd9\\xb1\\x46\\xb3\\xc3\\xa2\\x06\\x75\\xc7\\x47\\xea\\x9c\\xe2\\x3c\\x0a\\xb1\\x56\\xea\\x96\\x81\\xae\\xbd\\x52\\xc6\\x92\\xfa\\x64\\x91\\xd8\\x94\\x56\\xbc\\x56\\xb6\\x05\\x07\\xc5\\xf3\\x0d\\xc1\\x47\\x63\\xf3\\x1f\\xa7\\xbc\\x71\\xa6\\xc3\\x1b\\x36\\x95\\x55\\x0d\\x6f\\x14\\xbe\\x55\\x5b\\xc0\\x13\\xaa\\xa4\\x32\\xa6\\x21\\x82\\x8a\\xf9\\x62\\x3e\\xe8\\x42\\x34\\x97\\xf7\\xe6\\x42\\x7d\\xd1\\xd2\\xc9\\x77\\xae\\x42\\x2a\\x6f\\x3d\\x51\\xf4\\xb4\\x16\\xde\\x6c\\x8b\\xb4\\x0b\\xc6\\x52\\x0c\\xe1\\xca\\xaa\\x05\\x14\\xa5\\x68\\x9d\\xfe\\xcd\\xa9\\xf3\\x29\\x05\\x84\\x23\\x8c\\x9c\\x92\\x39\\x11\\x0c\\x15\\x47\\x05\\x33\\xbb\\x02\\x39\\xc1\\x0a\\x39\\x27\\x4a\\xd0\\x5c\\xcd\\xa4\\x06\\xe5\\x07\\xcd\\x69\\xc2\\x75\\x44\\x54\\x90\\x2e\\x68\\x72\\x67\\xfa\\x00\\x63\\x21\\xcc\\xb6\\x6d\\x6a\\xc9\\xa9\\x75\\x3e\\x0f\\x8f\\x44\\x3d\\x64\\x4d\\xcf\\x0a\\x59\\xde\\xce\\x20\\x82\\x0a\\xdf\\x4a\\x32\\xaa\\x30\\x54\\xae\\xcd\\x42\\xbe\\xb6\\x77\\x2b\\xda\\x2b\\x92\\x2e\\x04\\x9d\\xf3\\xc4\\xd7\\x9f\\x28\\xe4\\x3d\\x57\\x5c\\x5a\\x0b\\x13\\x8c\\xda\\xbe\\x68\\x4a\\x2e\\x7d\\x71\\x00\\x34\\x6b\\xbd\\xcc\\x28\\x9f\\x93\\x13\\xc5\\x18\\x79\\xed\\x6e\\x09\\x3e\\xb9\\x42\\x16\\x1f\\x15\\x96\\x31\\xd5\\x53\\x42\\x8b\\x98\\xf4\\xf5\\x27\\x85\\x4d\\xfc\\xe8\\x94\\xaf\\x81\\x0f\\x02\\x20\\x95\\x88\\x49\\x8b\\x74\\xfd\\xb4\\x4f\\xe3\\xce\\xf1\\xfa\\x25\\xcb\\x02\\x9c\\xdf\\x5c\\x55\\x1e\\x26\\x52\\x59\\x39\\xb7\\xb4\\xf4\\x7a\\x7e\\x79\\xa1\\x42\\xcd\\x00\\xde\\x66\\x5b\\x77\\x01\\x1e\\x64\\x52\\xdc\\x86\\x99\\x16\\x3d\\x2e\\x68\\xe9\\xd9\\x90\\x58\\x01\\x85\\xdb\\xef\\x79\\x5a\\xd2\\x0c\\x89\\x6b\\xcc\\x2a\\x5f\\x5e\\x5d\\xe0\\xc8\\xfc\\x76\\xa6\\xc7\\x0f\\x0c\\x94\\xb9\\xc8\\x06\\x55\\xe8\\xcf\\xcd\\x97\\xaf\\xb8\\x20\\x73\\x05\\x74\\x58\\x13\\x2d\\xdb\\x2e\\x28\\xb3\\x6a\\x7d\\xb3\\xe6\\x07\\xba\\x80\\xf4\\xc5\\xd6\\x95\\xb5\\xe6\\xac\\xe3\\x12\\xe2\\xe3\\x00\\x53\\xd9\\x46\\x68\\xe6\\x8e\\x84\\xdb\\x43\\xd4\\xbe\\xee\\x73\\x57\\x44\\x1b\\x18\\x72\\x50\\xcb\\x9b\\x23\\x05\\x88\\x63\\x75\\xd1\\xed\\x57\\x30\\xa8\\x9c\\xe1\\x3f\\x42\\xa6\\x44\\x51\\x73\\x5c\\x5b\\xe5\\xb6\\x3d\\x48\\x54\\xf7\\xd5\\x99\\xbd\\x66\\xf3\\x3c\\xa3\\x7a\\x2f\\x0e\\x34\\x3f\\x04\\x76\\x83\\xc0\\x9e\\x6d\\xf0\\x18\\x15\\xe9\\x98\\x66\\xe6\\xb2\\x5c\\x7e\\xff\\xd2\\x86\\x2a\\x22\\xee\\xe9\\xe8\\x29\\x77\\xed\\x08\\x91\\xf0\\xe5\\x0f\\x0d\\x2b\\xbe\\x16\\xed\\x40\\x46\\xc1\\x1b\\x96\\x02\\x11\\x71\\x75\\xad\\xa3\\x7c\\x5e\\xe5\\x83\\x60\\x85\\x3b\\x7c\\x97\\xdf\\xbf\\x1c\\x11\\x3e\\x61\\x13\\xf7\\x2f\\xdf\\x99\\x23\\x91\\x5a\\xde\\x62\\x60\\x88\\x0b\\x2e\\x8a\\xb1\\x8d\\xcb\\x74\\x82\\xcb\\x09\\x95\\xf4\\x61\\xef\\x3f\\xff\\xd1\\x2c\\xd4\\x3c\\xfd\\xd3\\xf8\\x8f\\x41\\x51\\xa3\\x3f\\xfd\\x6c\\x68\\x72\\x54\\x2d\\xaa\\x9f\\x97\\xbe\\x0b\\x43\\x08\\x7c\\x71\\xda\\x9f\\x2f\\x6d\\xa5\\x41\\x5b\\x87\\xf0\\xe7\\x48\\xa7\\x08\\x42\\x98\\xd0\\xc5\\x62\\x42\\x2e\\x25\\xf8\\xd1\\xf1\\x14\\xef\\x2c\\xcc\\xbf\\x60\\x7f\\x71\\xb6\\x1d\\xd8\\x2e\\xaf\\x06\\x4f\\xa8\\x66\\x02\\x38\\x93\\x8d\\x45\\xfb\\xaa\\x66\\x63\\xb7\\x61\\x00\\xc0\\x4e\\x14\\xa0\\x74\\x02\\xfa\\x53\\x4c\\x64\\x32\\x22\\x5a\\x4a\\xc0\\x97\\x11\\xe8\\xdc\\xb4\\x73\\x41\\xd8\\x27\\xae\\x20\\x8f\\x13\\x82\\x1c\\xf6\\x8d\\xda\\x10\\x07\\xc7\\xcd\\x99\\x71\\xcd\\x51\\xf0\\xd9\\xbf\\x72\\x19\\xe3\\x7c\\x01\\x00\\xf8\\x52\\x48\\xfd\\xa5\\xbf\\x0d\\xce\\x25\\x14\\xd8\\x36\\x49\\xe8\\xbd\\xe4\\xae\\x2e\\xa6\\xc1\\x3c\\x02\\x4c\\x25\\x51\\x39\\x02\\xec\\x86\\xde\\x2c\\xc8\\x9c\\x2b\\x4d\\xef\\xd8\\x84\\x5c\\x19\\x9e\\x2e\\xf4\\x12\\xc1\\x6d\\x16\\x04\\xaa\\xe4\\xb0\\x94\\x94\\x42\\xf3\\x2c\\x52\\xac\\xf3\\x73\\x01\\xc0\\x04\\xfc\\x1e\\x64\\x05\\x28\\x13\\xc3\\x97\\xe4\\x05\\x1b\\x3b\\xfe\\x12\\xdf\\x8a\\x52\\xbe\\xd8\\x7a\\x5f\\x0e\\x26\\x15\\x4c\\x47\\xfe\\xec\\xcf\\x28\\xea\\x46\\xf2\\x14\\x3a\\x87\\x7d\\x69\\xf5\\x68\\x25\\xfe\\xc6\\xae\\x44\\x07\\x18\\x68\\x48\\x91\\x54\\xec\\x23\\x6c\\xbb\\x9a\\x90\\xf7\\xc0\\x13\\x66\\x31\\xa7\\x1c\\xbd\\xbe\\x50\\x19\\x64\\x6d\\x65\\x82\\x25\\x4c\\x29\\x5a\\x2c\\x46\\x50\\x19\\x95\\xfb\\x8a\\x98\\xd6\\x6d\\xda\\xf0\\xcc\\x31\\x20\\xa1\\x02\\xab\\x8f\\x16\\x2c\\x91\\x42\\xe9\\xa2\\x4c\\x60\\x1f\\x29\\xb9\\x29\\xe4\\x1d\\x13\\x55\\x58\\x4d\\xcc\\xa1\\xae\\x47\\x05\\x54\\xce\\xc9\\xe0\\xd2\\x22\\x49\\x32\\xa3\\xe2\\x36\\xa8\\xf0\\x3f\\xa7\\x29\\x1c\\xa3\\x6f\\xbd\\x98\\x15\\x03\\x0b\\xe9\\xb7\\x8a\\x4e\\x8d\\x6c\\xc3\\x35\\xec\\xd9\\x8d\\x61\\xcb\\x9c\\x59\\x31\\x6a\\xb6\\x4e\\x13\\x3c\\xaa\\x0c\\x83\\x06\\xb0\\x3c\\xdb\\xb1\\x2f\\x6e\\x17\\x9b\\xd3\\x18\\xb8\\xf0\\x76\\xf9\\xbd\\x93\\x8d\\x69\\xce\\x34\\x4d\\xa9\\xa6\\xfb\\x8c\\x3c\\x78\\x47\\x7d\\xf1\\x55\\xeb\\xce\\x04\\xbb\\x1e\\xb8\\x39\\x59\\x56\\xcb\\x09\\x87\\x32\\xe7\\x61\\x56\\x8e\\xcb\\xef\\x5f\\x46\\x8e\\x04\\xd2\\x20\\x6c\\x34\\xe4\\xc0\\xd3\\xe6\\x26\\x59\\x33\\x3b\\xc6\\x0a\\x80\\x2c\\x44\\xb3\\x4c\\x3e\\xd8\\xdc\\x99\\x6e\\x4c\\xa4\\x08\\x2c\\x25\\x69\\xd9\\x41\\x6b\\x5f\\xd1\\x95\\x38\\xbb\\x64\\x47\\xab\\xa4\\xd9\\xef\\x7d\\x6e\\xcc\\x75\\xe5\\xee\\x93\\xd4\\x83\\x03\\xd6\\x4a\\x14\\x68\\x49\\x67\\x42\\xf3\\x82\\x05\\xb9\\x59\\x22\\x07\\xb3\\xbb\\x5a\\x0a\\xbc\\xea\\xf5\\xfd\\xc5\\x03\\x70\\xcb\\xb4\\xaa\\xbc\\x8a\\x91\\x03\\x88\\xee\\x5f\\x5b\\xde\\x11\\x67\\x09\\xec\\xac\\xdb\\x73\\xab\\xc6\\x5b\\xbb\\xa8\\xc8\\xde\\xf1\\xdc\\x28\\x69\\x29\\xbd\\xe1\\x70\\xf6\\xb2\\xe5\\x7d\\x6c\\xc4\\x58\\xe8\\xf8\\x9d\\x4c\\xbb\\x98\\x95\\xfb\\x7a\\x11\\xd4\\x86\\xab\\x02\\xae\\x30\\xce\\x4f\\x81\\x0e\\x1a\\x5f\\x00\\xc7\\x16\\x55\\xcb\\x4c\\x83\\x54\\x6a\\x46\\xdb\\xea\\x58\\xd7\\x5b\\x4f\\xc5\\x67\\x25\\xea\\x8c\\x7d\\x85\\x3e\\x98\\xd8\\x18\\x26\\x36\\x7e\\x1e\\x3d\\x85\\x2e\\xbe\\xb8\\xae\\x45\\xfb\\xe4\\xd6\\x07\\xe9\\x64\\x33\\x34\\x78\\xfb\\xaa\\xa3\\xc9\\xb3\\xff\\xb6\\x57\\xa3\\x59\\x32\\x6e\\xbd\\x98\\xbc\\x07\\x9c\\x0d\\x43\\x67\\xdc\\xe0\\xdb\\x2e\\x4b\\xff\\xb2\\xc6\\xf1\\x5a\\x21\\xc9\\xab\\xbc\\x30\\xb2\\xef\\xc4\\xe9\\xc0\\x26\\x76\\x7f\\x5d\\x76\\xc0\\xfa\\xeb\\xa7\\xbd\\x87\\x05\\xae\\x7d\\xbd\\x12\\xa6\\x43\\x9f\\x17\\xd6\\x97\\xd7\\xc9\\x8f\\x46\\x4e\\x2b\\xc0\\x06\\xe6\\x02\\xcc\\xcd\\x8d\\x29\\x64\\x96\\xb1\\x02\\x00\\x68\\xb5\\x5f\\x4b\\x9e\\x97\\x50\\xe3\\x0b\\x2d\\xd0\\x31\\xd9\\x9f\\x5c\\x73\\x0a\\x56\\x2f\\xda\\x0a\\xf6\\xe0\\x59\\x72\\xaa\\x30\\x45\\xb4\\x73\\xf8\\x01\\x15\\xb1\\x73\\x7b\\x5d\\x37\\x72\\x97\\x3b\\xfa\\x83\\x53\\xc3\\x9e\\x8b\\x05\\x82\\xee\\x55\\x70\\x5c\\x50\\xdb\\x49\\x6e\\xcd\\xa4\\x8c\\xd8\\x2b\\xe8\\x4d\\x66\\x78\\xab\\xe0\\x48\\xf9\\x19\\x2d\\x31\\x01\\x5a\\x06\\x6f\\x7d\\x64\\xd3\\x2e\\xe0\\x00\\x3d\\x71\\xf8\\x71\\xdc\\x28\\xc8\\x45\\xd4\\x3e\\x9c\\x54\\x4e\\xd7\\x56\\xf0\\xea\\x94\\xe9\\xd8\\x35\\x7b\\x3a\\x6a\\x9d\\xd5\\x1d\\x1e\\x97\\xc6\\x0d\\xb3\\x8d\\xad\\x9d\\x6b\\xfc\\xe8\\x3d\\x1c\\xa2\\xfa\\xb8\\x44\\x41\\xce\\x2a\\xde\\xaa\\x87\\xaa\\x7f\\x10\\x29\\x6b\\x63\\xeb\\xe3\\x43\\x05\\xae\\xe2\\xe0\\x8b\\xd9\\xcd\\x21\\xa6\\x3f\\xb6\\x24\\xa8\\x44\\x85\\x31\\x9d\\x62\\xe3\\x16\\xfe\\xe1\\x58\\x2c\\xef\\x62\\x72\\xc3\\x0c\\xfe\\xa9\\x52\\xf1\\x75\\x39\\x51\\x04\\x4f\\x55\\x38\\xd2\\x1a\\x2f\\xda\\xea\\x7a\\x7f\\x0b\\xc5\\xe0\\xac\\x69\\xde\\x65\\x47\\x30\\xf4\\xf5\\xfc\\xf2\\x02\\xe7\\xd7\\x75\\xf4\\x37\\x80\\xdf\\x16\\x96\\xcb\\xd6\\x33\\x5e\\xa4\\xe3\\x9c\\x16\\x7a\\x81\\x8a\\xca\\x51\\x6d\\x6e\\x3e\\xc0\\xbb\\xd3\\x20\\x3d\\x1d\\x8b\\xe2\\xca\\x3d\\x86\\xad\\xb6\\xdd\\x00\\x2a\\x67\\x7c\\xb7\\x3e\\x18\\x8d\\x7b\\x76\\x88\\xf5\\xc4\\x07\\x88\\xaf\\x5d\\x4f\\x58\\xc0\\xcc\\x29\\xf5\\x1e\\x71\\x3d\\xdb\\xbb\\xfc\\x93\\x3a\\xae\\x3c\\x2c\\x0f\\x64\\x90\\xb3\\xaa\\xbb\\x1d\\x22\\xa3\\x02\\x62\\x8b\\x55\\xfe\\xca\\x30\\x30\\xd5\\xb3\\xc1\\xa0\\x36\\x32\\x3d\\x8d\\x08\\x9f\\x1a\\x22\\x2d\\xc5\\x18\\xac\\xf3\\x1d\\x26\\x52\\xd9\\x22\\x2d\\xd3\\x3d\\xb1\\x1e\\xee\\xa8\\xe8\\x81\\x0b\\x19\\xcc\\x27\\x18\\xa4\\xba\\xe9\\xe4\\x44\\xc8\\x18\\x3d\\x90\\x6b\\x80\\x27\\xb0\\xd7\\x53\\x0c\\x3e\\x68\\xb0\\x3b\\xdd\\x74\\x49\\xf3\\x47\\x2a\\xee\\x21\\x54\\x10\\x05\\x18\\xcc\\x31\\x30\\x5c\\xa4\\xe6\\x90\\x02\\x49\\x04\\xd5\\x91\\x2a\\x93\\x84\\x31\\xaf\\xbe\\xb5\\x97\\xb4\\x0b\\xcf\\x5d\\xc3\\x8d\\x16\\x60\\x73\\xaa\\x93\\x19\\x53\\x44\\x49\\xc8\\x65\\xad\\x34\\xcd\\x32\\x96\\x7a\\xab\\x24\\x6e\\xa8\\x04\\xbe\\xce\\x5a\\x2c\\x3b\\x8c\\x18\\x30\\x86\\x5d\\x00\\x14\\x28\\xcf\\xac\\xfe\\x3a\\xcf\\xa8\\xd5\\x1b\\x4e\\x4b\\x91\\xa0\\xd3\\x2e\\xd7\\x8b\\xb0\\x46\\x73\\x8d\\x59\\x07\\x85\\x8b\\x02\\x15\\x69\\x17\\x86\\x72\\x8a\\x36\\xa7\\x40\\x79\\xe2\\x0f\\x12\\x90\\x96\\x05\\x12\\x13\\x23\\xd2\\x55\\x56\\x24\\x9b\\xa7\\xd5\\x50\\x86\\x1b\\x9a\\xdc\\x3d\\xd0\\x22\\x8d\\xf7\\x1a\\x27\\x90\\xc5\\x84\\x6a\\x8e\\x65\\x6c\\x47\\xc8\\x8d\\x85\\x2c\\x93\\x38\\x0e\\x9d\\x7a\\xb8\\xe8\\xcf\\x20\\x86\\x6b\\x3b\\x09\\x40\\xb6\\xc2\\x38\\x9e\\x7a\\x86\\x51\\x31\\x5f\\x46\\x55\\x75\\xe1\\x5a\\x88\\xf5\\x62\\xa2\\xa5\\x96\\x73\\xaa\\x79\\x02\\x9a\\x55\\x3e\\x0d\\x4c\\xb4\\x73\\x5f\\x64\\xca\\x3b\\x29\\x21\\x51\\x05\\xa2\\x6e\\xa1\\xde\\xf9\\x5a\\xad\\x67\\x36\\xb7\\x02\\x5b\\x00\\x29\\xbb\\x1b\\x75\\xa0\\xb8\\xa5\\x06\\xac\\x46\\xe7\\xb9\\x5f\\xa3\\xb3\\x16\\xf8\\x86\\x14\\x8c\\x11\\x3e\\x37\\x62\\x12\\x85\\x8a\\xff\\x53\\x9f\\xba\\xc5\\x99\\xdc\\x37\\xed\\x5d\\x37\\x49\\xf4\\x07\\x70\\xe7\\x08\\xfa\\x43\\x25\\x75\\x96\\xc9\\x07\\x45\\xf4\\x83\\xf4\\xfa\\xb2\\xca\\x0e\\x6b\\xf3\\x9a\\x8c\\xea\\xc3\\x76\\xa2\\xa0\\xb6\\x7f\\x83\\xb6\\xcd\\x4e\\x07\\x98\\x76\\x64\\x6e\\xed\\x03\\xcb\\x32\\xf3\\xff\\x4d\\xf8\\xb6\\x43\\xa8\\xd5\\xda\\x75\\xf2\\x5b\\x81\\x49\\x30\\xb8\\x72\\xfa\\x51\\x1b\\xd0\\x75\\x92\\x16\\x32\\xcf\\xad\\x05\\x67\\x7e\\xba\\xcd\\x3a\\xc1\\x35\\xa9\\xb8\\x67\\x0a\\xdc\\xec\\x5c\\x38\\x99\\xd9\\xb2\\x5b\\x26\\x58\\x41\\x35\\x18\\xb1\\x6d\\xde\\x62\\x20\\x8e\\xcb\\xd3\\x89\\xd7\\x37\\x62\\xeb\\x25\\xa7\\xb5\\x1c\\x03\\xf4\\x39\\x58\\xbf\\xed\\xee\\x1d\\xfb\\xb4\\xd3\\x5c\\xb9\\xc0\\x13\\xe0\\x6e\\x6c\\xa7\\x2d\\x85\\x64\\x75\\xa7\\xe4\\x3b\\x85\\x1b\\xe5\\xe9\\x85\\x0f\\xd3\\x8b\\x92\\xce\\xd1\\x00\\x66\\x05\\xf4\\x4e\\xc3\\x9f\\x67\\xf9\\x2c\\x18\\x3f\\x94\\x72\\x7d\\x98\\x73\\x1d\\x52\\xb5\\x99\\xbd\\x2c\\xa4\\x52\\xef\\xdd\\x27\\x7b\\x99\\xe4\\x20\\x01\\x0f\\x12\\xf0\\x20\\x01\\x6f\\x6e\\x83\\x04\\x7c\\xe8\\xf5\\x00\\xbe\\x3b\\xe4\\x9d\\x7c\\x1f\\x32\\x84\\x75\\x44\\xbd\\x33\\x78\\x10\\xf2\\x5e\\x6a\\xeb\\xa9\\x02\\xfc\\x3b\\x6d\\x54\\x7a\\x52\\xc0\\xe9\\x0f\\x74\\x31\\x11\\x4c\\xdb\\x7c\\x71\\x4e\\xb7\\xff\\xd1\\x8d\\xfe\\x4d\\x61\\x38\\x3f\\x2b\\xa0\\x05\\xb7\\xc8\\x5d\\x60\\x97\\xcf\\x2e\\x18\\x45\\x4b\\x24\\xc5\\x95\\xe3\\x0c\\xfc\\x7e\\xac\\xac\\x33\\x86\\x79\\x0e\\xd1\\xee\\xa4\\x56\\x08\\x63\\x42\\xae\\xac\\xab\\xdf\\xd2\\xe0\\xab\\x69\\xba\\x52\\xa6\\x29\\x8f\\x4b\\x89\\x18\\x36\\x47\\x29\\xaf\\x1b\\x68\\xf4\\x01\\x28\\x21\\xe9\\x77\\x64\\x7d\\xec\\xe4\\x21\\x54\\x2d\\x55\\x0c\\x72\\xe0\\xd1\\x1e\\x46\\x85\\x54\\x2f\\x6c\\x6f\\x62\\xbc\\x98\\x92\\x8f\\x2c\\x91\\xf7\\xac\\x40\\x78\\xbf\\xfe\\x94\\x53\\x61\\xc4\\xf4\\x37\\x94\\x67\\x06\\xda\\x0e\\xea\\x95\\xf5\\x02\\xaa\\x98\\xd6\\xfd\\x09\\x02\\x23\\x98\\xbf\\x46\\x76\\x6b\\xcd\\xc9\\xe9\\xc2\\x0c\\xfa\\x7c\\x73\\xa6\\x67\\xeb\\x65\\x9b\\x17\\xec\\x9e\\xcb\\x52\\xb9\\x78\\x98\\x52\\x23\\x1d\\x53\\xda\\xca\\xa6\\x33\\x7e\\xeb\\x8b\\x9f\\x3b\\x37\\x71\\x70\\xde\\x29\\x52\\x7f\\x55\\x3a\\xcc\\x41\\x69\\xaa\\x4b\\x55\\x4f\\x52\\x93\\x80\\x1f\\xc0\\xa3\\x18\\x6f\\xfd\\x7e\\xef\\x97\\xe1\\xeb\\xc7\\x5c\\x61\\xfc\\xd0\\x21\\xd1\\xf8\\x5b\\x8c\\x58\\xc2\\x4e\\x6e\\xec\\x2d\\x70\\x61\\x56\\x55\\x98\\x58\\x22\\xe7\\x79\\xa9\\x59\\x70\\x5b\\xec\\x69\\xed\\x8a\\xb6\\x3a\\x6e\\x64\\x2d\\xe7\\xe4\\xd9\\x9c\\x0a\\x7a\\xcb\\xc6\\x7e\\x12\\xe3\\x2a\\xc2\\xea\\xac\\x07\\xd6\\xea\\xb8\\xa5\\x64\\x8b\\xa4\\x87\\x61\\x7b\\xc2\\x91\\x51\\x4b\\x8b\\xed\\x1e\\xfa\\x4d\\xb6\\x0c\\xff\\x26\\xdb\\x84\\x80\\x93\\x5d\\x86\\x81\\x13\\x9f\\x4b\\xe2\\x90\\xd7\\xf1\\xa3\\x1d\\x73\\xf9\\x42\\x5a\\x62\\xb5\\xe9\\x42\\xf6\\x13\\x09\\x2c\\xd1\\xb2\\xa3\\x72\\x45\\xe4\\x9c\\x6b\\xcd\\x9c\\x13\\xb2\\xbf\\x60\\x23\\xc2\\x75\\x2d\\xd5\\x81\\x45\\x1c\\xa0\\x34\\x47\\x47\\x62\\xf6\\xc9\\xd7\\xf6\\xad\\x18\\xb3\\x8e\\x93\\x01\\xe1\\xe7\\x81\\x2b\\x64\\xbc\\x04\\xe1\\xf3\\x1c\\xcb\\x61\\x00\\x02\\x18\\xdb\\x38\\x47\\xa7\\x1a\\xf6\\xf3\\x4e\\xc0\\x09\\x90\\xb0\\x4f\\xa0\\xc8\\xc7\\xa9\\x0d\\x98\\x69\\xc0\\x4c\\x4b\\xed\\x97\\x80\\x99\\x30\\x8d\\x44\\x97\\x2c\\x27\\x35\\x8c\\xe4\\x3e\\xb7\\xf9\\x25\\xe9\\x0d\\xcb\\xc8\\x5f\\x4b\\x56\\x2c\\x88\\x61\\x5b\\xab\\x38\\x2d\\x28\\x49\\xac\\x78\\x8a\\x01\\x49\\xce\\x6a\\xb6\\x67\\x2d\\x59\\x3f\\xa6\\x09\\x2c\\x6d\\xaf\\x3f\\x19\\xee\\x1e\\x92\\xa6\\x6d\\x81\\xaf\\x97\\xbb\\xaa\\x67\\xe1\\x44\\x68\\x79\\x08\\x86\\x3c\\x39\\x7a\\x8b\\x86\\xbf\\x00\\xdb\\x7d\\xfe\\xfe\\x55\\x3f\\x81\\xaa\\x9b\\x97\\x20\\xe9\\xe3\\x29\\xb8\\xb2\\xf8\\xce\\xc4\\x8a\\x90\\xf3\\x0d\\x30\\x41\\xd8\\xf9\\x27\\x40\\x25\\xbc\\x9f\\xa7\\xd7\\xd9\\x93\\x3b\\xb6\\x18\\x59\\x3f\\x6e\\x5b\\x72\\xde\\xbe\\xdc\\x79\\x32\\x18\\xd2\\x51\\xd5\\x8a\\x33\\x9d\\xc6\\x66\\xbe\\xae\\xb7\\xde\\x48\\xb8\\x9f\\xa2\\x17\\x5b\\x7c\\x91\\xbe\\xfa\\x57\\x0e\\x68\\x5d\\x71\\x7d\\x6f\\x2a\\xd1\\xa9\\x98\\x5f\\xd8\\x9a\\x0a\\xfb\\xe1\\x19\\x82\\x2a\\x5c\\x2e\\xb7\\x81\\x3f\\x36\\x90\\x35\\x02\\x10\\x52\\xd7\\x4d\\x24\\xfd\\x15\\x6a\\xd8\\x1c\\x60\\xb7\\x5e\\x6a\\x8f\\x8b\\x15\\x8e\\x5f\\x8f\\xc5\\xbf\\x63\\x8b\\x63\\x65\\xb3\\xce\\x49\\xa1\\x66\\x3c\\x77\\xd5\\xe6\\x01\\x47\\xf5\\x3b\\xf0\\xd8\\xbe\\x07\\x9f\\x74\\x37\\x2c\\x62\\xb0\\x0b\\x31\\x22\\xef\\xa5\\x36\\xff\\x7b\\x0d\\x51\\x45\\x70\\xad\\x5e\\x49\\xa6\\xde\\x4b\\x0d\\xbf\\x1c\\x7c\\x5f\\x70\\x89\\x8f\\xb5\\x2b\\xd6\\x9a\\xc9\\xc1\\xc2\\x08\\x68\\x1a\\xb3\\xea\\x40\\x98\\xbd\\x85\\xbe\\xf3\\xd0\\xf4\\x3b\\xc8\\x15\\xb9\\x10\\x44\\x16\\x16\\x94\\xbd\\x06\\xd6\\xae\\x74\\xad\\xb2\\xc3\\x3a\\xeb\\x43\\x65\\xd4\\x5f\\x37\\xae\\xdd\\x35\\x59\\xd4\\x36\\x6d\\xc7\\x53\\xb0\\xc3\\x83\\x2e\\x12\\x9f\\x80\\x76\\x15\\xbc\\x4b\\x5c\\x2c\\x0c\\x16\\x4b\\xa5\\x9a\\xdd\\x76\\x72\\x75\\xa9\\xda\\x9c\\x15\\xb7\\x90\\x66\\x31\\xe9\\x50\\x66\\x2f\\x98\\x7c\\x4f\\xc2\\x8a\\xad\\x17\\x79\\x0d\\x07\\xee\\x7c\\xd8\\x81\\x17\\x79\\x0b\\x71\\x4e\\x87\\x94\\x40\\x83\\x61\\x91\\x82\\xcf\\x69\\x6e\\x4e\\xf8\\xdf\\x0d\\xa1\\x86\\xcd\\xff\\x27\\x54\\x83\\x56\\x13\\x72\\x4e\\x14\\x17\\xb7\\x19\\xab\\x3d\\xb3\\xaa\\xf4\\xa0\\x9b\\xce\\x13\\x00\\x0b\\x97\\xa1\\xa3\\xf7\\x34\\x63\\x18\\x4e\\x49\\x85\\xaf\\x8b\\x28\\xa7\\x2b\\x6c\\xda\\xc8\\x96\\x87\\x36\\x24\\xc4\\xbb\\x7e\\x1d\\xdd\\xb1\\xc5\\xd1\\xa8\\xa3\\xb2\\x92\\x84\\x78\\xd7\\x74\\x72\\x21\\x8e\\xaa\\xbc\\xab\\xb5\\xb3\\xef\\x79\\x19\\xb0\\xe9\\x1f\\xc1\\xb3\\xa3\\x5d\\xf3\\x81\\x8f\\x24\\x08\\x3e\\x9a\\x2b\\xa6\\x55\\xdc\\xbe\\xcc\\x28\\x1a\\x2f\\x0e\\x61\\x22\\x58\\x1e\\x73\\x5d\\x0d\\xba\\xab\\xe0\\x9d\\xca\\x6c\\x64\\x83\\x7b\\x1f\\x51\\x9b\\x0d\\x49\\x53\\x3a\\xc7\\x20\\x75\\xda\\xd8\\xe5\\x32\\x37\\x07\\xdd\\x9b\\xc6\\xc1\\x83\\x58\\x64\\x9f\\x38\\xdb\\xec\\xc5\\xf7\\xeb\\x3e\\x08\\x42\\xb1\\xb9\\xea\\xbe\\x5d\\xab\\x95\\xe2\\x83\\x7c\\x20\\x61\\xa4\\x8c\\x2c\\x6c\\x50\\xf7\\x8a\\x9f\\x2e\\x14\\xc4\\xab\\x2a\\x05\\xc5\\x56\\xce\\xac\\x5a\\xe5\\x62\\x50\\x30\\x95\\x4b\\xf4\\x61\\x5d\\xbb\\x58\\x4b\\x86\\x67\\x50\\x3b\\xdf\\x79\\xb9\\x69\\x92\\x97\\x45\\x2e\\x95\\xad\\x66\\xb6\\x7c\\xe4\\x3b\\x46\\x07\\xd9\\x90\\x2d\\x17\\x81\\x89\\x41\\xd2\\xfe\\x26\\x98\\xfb\\xe3\\x93\\x2f\\x9f\\x2f\\xe5\\xed\\x43\\xa3\\x53\\x90\\xc9\\x4c\\xc8\\xf5\\xcb\\xe8\\x30\\x23\\xe7\\x54\\x89\\xb2\\x82\\xcf\\x1e\\x85\\x93\\xc1\\xd0\\xf5\\x63\\x74\\xe7\\x08\\x4c\\x6c\\x86\\xa3\\xd6\\xa1\\x87\\x93\\x96\\xf5\\x99\\x42\\x44\\x3d\\x26\\x58\\xeb\\x90\\x51\\x9b\\xe0\\x79\\x29\\x45\\xe5\\x2a\\xe2\\xa8\\xc7\\x7a\\xb7\\x3b\\xc8\\xdf\\x76\\x23\\x4b\\x61\\x8f\\x96\\xcb\\xfc\\xb6\\x2b\\xa0\\x98\\x55\\xba\\x24\\x04\\x7e\\x02\\xf6\\x68\\x06\\x41\\x64\\x7c\\x6a\\xd6\\x6a\\x13\\x07\\x74\\x5b\\x6b\\xcd\\x07\\x07\\x2c\\xe0\\x05\\x82\\xf8\\x66\\xb1\\xfe\\xfe\\x92\\x54\\x32\\xdc\\x0f\\x18\\x6f\\x84\\xbb\\xb0\\x1e\\x3c\\x76\\x19\\x5d\\xd0\\x39\\x7a\\x91\\x52\\x72\\xc9\\xf0\\x96\\x28\\x4d\\x35\\x1b\\x61\\x49\\xcf\\x69\\x16\\xd4\\xb9\\x61\\x64\\x2e\\x53\\x3e\\xb5\\xbe\\x6c\\x57\\x81\\x9d\\x72\\x84\\xd9\\x24\\x6c\\x2a\\x88\\x30\\xd7\\x75\\x87\\x89\\x74\\x07\\xe6\\xee\\xe8\\x02\\xfe\\xbf\\xc2\\x38\\x49\\xc7\\xd3\\xb3\\xec\\x87\\xb7\\xde\\xc7\\x60\\x3d\\xb2\\xdd\\x9d\\x93\\x5d\\x0f\\x3a\\x15\\x57\\x37\\xcb\\xb5\\x6d\\x09\\x13\\x54\\x12\\x70\\xc9\\xe9\\x6a\\x69\\x56\\xab\\xc8\\x8a\\xad\\xb9\\x85\\xef\\x01\\x65\\xca\\x29\\x79\\x53\\x15\\x3e\\xe5\\x0a\\x4c\\x23\\xdc\\xa5\\xae\\x33\\x97\\x89\\x8b\\x24\\x2b\\xad\\x89\\x1e\\x71\\x9f\\xc1\\x41\\x07\\x80\\xf9\\x16\\xcc\\x40\\xd5\\x81\\xe3\\xba\\x5c\\x7c\\xc6\\x4a\\x96\\x93\\x65\\xfc\\x00\\x41\\x01\\xfe\\x74\\x76\\x84\\x6a\\xe4\\x5a\\xa7\\x2d\\x79\\x13\\x6a\\x6b\\x99\\x26\\x75\\x4d\\xcd\\x1b\\x7e\\x53\\x30\\xf2\\x72\\x46\\x85\\x60\\x59\\x90\\x0a\\xda\\x9a\\xcb\\xa8\\xd6\\x34\\x99\\x21\\xa6\\xa4\\xc4\\xdc\\xf3\\x8c\\x19\\x3a\\x35\\x93\\x4a\\x93\\x39\\x4d\\x66\\x5c\\xf8\\x34\\xa3\\xc2\\x27\\x1e\\xaf\\x52\\xbe\\x1c\\x3c\\xc1\\xd6\\xde\\x4b\\x15\\xdb\\x13\\x10\\xd6\\xf7\\xad\\x55\\x30\\x8e\\xe8\\xc9\\xa7\\x0b\\x5e\\xe9\\xa5\\xaa\\x86\\x68\\xef\\x21\\xc0\\x19\\x65\\x3d\\xa0\\x12\\xf0\\x6e\\xcc\\x18\\xcd\\x75\\x94\\xc9\\xc5\\xdc\\x9b\\x40\\xb9\\x08\\x08\\x21\\xb3\\x1f\\x18\\x32\\x1b\\xb0\\x06\\x51\\xb9\\xc0\\xa0\\x66\\xe9\\x4c\\x3e\\x90\\x54\\x92\\x07\\x06\\xee\\x3b\\x86\\x9f\\x03\\xe7\\x76\\xe5\\xf8\\xc2\\x60\\xb5\\x10\\xa9\\x95\\xc8\\x79\\x5e\\xc8\\x39\\xf7\\x6e\\xd4\\xf6\\x40\\xb5\\x0e\\xd8\\x01\\x09\\x64\\x65\\x44\\xbd\\xa4\\x7a\\x66\\xf4\\xac\\x14\\x66\\x97\\xab\\x0a\\x38\\x6f\\x5e\\x12\\x4d\\x8b\\x5b\\xa6\\x4d\\x6f\\x44\\x94\\xf3\\x1b\\x56\\xb4\\xa7\\x48\\xdf\\x5f\\xbd\\xb6\\x83\\x94\\x57\\xad\\x41\\xa0\\xa5\\x2a\\x2a\\xf9\\xe8\\xbe\\x82\\x48\\x16\\x60\\x87\\xa6\\x32\\x8e\\x11\\x41\\xf7\\x43\\x57\\xd3\\x15\\x2b\\xfa\\x99\\x03\\xf3\\xbd\\xa5\\x5d\\xa5\\x88\\x61\\x4f\\xba\\x94\\x5d\\xc5\\xbd\\xfc\\xe1\\x87\\xf7\\x5d\\x6b\\xde\\x1d\\x57\\x5f\\x36\\x1d\\x90\\x07\\x59\\x64\\xe9\\x03\\x4f\\xad\\xa7\\x29\\x39\\x31\\x2f\\x9f\\xc6\\x1e\\x96\\x1d\\x97\\xc0\\xeb\\x70\\x4d\\x1e\\x1e\\x78\\xba\\x97\\xfa\\xb3\\xd0\\x71\\x1d\\x54\\x4e\\xe4\\x34\\xa0\\x22\\x00\\x2b\\x9e\\x32\\xa1\\x0d\\xb2\\x29\\x14\\x39\\x81\\x2f\\x62\\xf2\\x50\\xbc\\xe6\\x98\\xe9\\x0f\\x46\\x80\\x52\\x39\\xf3\\x1b\\x2e\\xaa\\x6c\\x95\\xd5\\x66\\x19\\x02\\x65\\xae\\xae\\xd3\\x04\\x2b\\xa6\\x31\\x5d\\x18\\x64\\x1b\\x90\\x7a\\x46\\x14\\x9f\\x97\\x99\\xa6\\x82\\xc9\\x52\\xc5\\x57\\x6a\\x7f\\x9c\\xfd\\x9a\\x66\\xec\\x13\\xde\\x8e\\x5d\\x66\\x55\\xae\\x7a\\xad\\x33\\x08\\x10\\xac\\x54\\x65\\xaa\\x5d\\xe6\\x10\\x5a\\x7a\\xad\\x62\\x40\\xd3\\x33\\xcf\\x4b\\xf8\\x6c\\x7b\\xec\\x13\\x4b\\x6c\\xb2\\x8e\\x3c\\x2b\\x6f\\x79\\x4b\\x66\\xa9\\x68\\x76\\x21\\xd6\\xbe\\x39\\x8e\\x29\\xf8\\xdf\\xa1\\x2a\\x2e\\x74\\xd6\\xf1\\x16\\x55\\x19\\x5b\\x97\\xd5\\x79\\x55\\xad\\xfb\\x52\\xb1\\x2a\\xd9\\x7d\\x6c\\x86\\xce\\x0e\\xb7\\x7f\\x60\\x9a\\xb0\\x6d\\x60\\x9a\\xc2\\x7c\\xf7\\xc1\\x04\\x52\\x96\\x33\\x91\\x42\\x09\\xbc\\x37\\xd5\\x05\\x42\\x28\\xed\\x74\\x8b\\x6c\\xb9\\xb6\\xae\\x14\\xcb\\x55\\x79\\xab\\x91\\xab\\x40\\x52\\x9e\\xc9\\x2c\\x55\\x84\\x7d\\xd2\\x05\\x35\\xf8\\x73\\x6e\\x30\\xa5\\xff\\x66\\x4a\\xa8\\x58\\x44\\xd4\\xda\\x7c\\x4a\\x15\\xb9\\xc9\\xa3\\xf0\\x47\\xe9\\x2f\\x89\\x3f\\x52\\x2c\\x29\\x98\\x8e\\x8a\\x26\\xee\\x51\\xeb\\xc3\\x75\\x5e\\x07\\x60\\xed\\xe7\\x15\\xa9\\x1a\\x9f\\xba\\x98\\x98\\xaa\\x18\\x6f\\xd4\\x78\\x42\\x71\\x28\\x7d\\xb7\\x54\\xe2\\x37\\xa7\\x4a\\x79\\x41\\x15\\x88\\x8f\\xbd\\xb6\\xaa\\x96\\x5e\\x22\\x62\\x08\\x54\\xc8\\xf2\\x29\\x11\\x72\\x69\\xa6\\x61\\xf4\\x8f\\xb7\\x7b\\xd7\\x5e\\x89\\xe8\\xde\\x9b\\xf0\\xe6\\x58\\x3d\\x80\\x0a\\x88\\xa3\\xc7\\x6e\\x46\\x10\\x5c\\x8c\\x7f\\xab\\x35\\x45\\xfb\\x71\\x65\\x31\\x70\\xb2\\x6b\\xdf\\xed\\x65\\xef\\xe6\\xbf\\x13\\x1f\\xf2\\xd6\\x4f\\x25\\xf6\\x3e\\x20\\xae\\x2e\\x8a\\x2a\\x56\\x1b\\xd3\\x51\\xeb\\x29\\xef\\x59\\x71\\xcf\\xd9\\xc3\\x99\\x8d\\xf2\\x1a\\x3f\\x70\\x3d\\x1b\\xdb\\x40\\xe9\\x33\\x90\\x0d\\xce\\x7e\\x05\\xff\\x8b\\x1c\\x1f\\x25\\xec\\xf3\\x34\\xb5\\xa1\\x97\\x36\\xbd\\x2d\\x26\\x74\\x98\\x04\\xd5\\x81\\x47\\x10\\x09\\x39\\x22\\x25\\x4f\\xbf\\x8e\\xea\\xbb\\x7f\\x2d\\x90\\x0e\\xe6\\xd3\\x29\\xe4\\x3f\\xee\\x52\\xb9\\xcb\\x7e\\xb1\\xa4\\xad\\xb2\\x3f\\x5a\\x66\\x34\\x46\\x3b\\x65\\x6f\\x73\\x40\\xa8\\xcd\\xf6\\xbb\\x8e\\xac\\x71\\x81\\x28\\xb3\\x5d\\x55\\x24\\x60\\x29\\x5a\\xd1\\xcb\\x1e\\x74\\x57\\x29\\xd5\\x54\\x31\\x1d\\xa7\\xa9\\xec\\x7e\\x05\\x82\\xee\\x0d\\x66\\x0a\\x6f\\x83\\x7d\\x04\\x26\\x37\\x06\\xc9\\x53\\x5c\\xae\\x5c\\x32\\xfe\\x93\\x65\\x4a\\x45\\xed\\x4d\\xc3\\x8e\\x5a\\x20\\xc6\\x60\\x97\\x99\\xab\\x75\\xe4\\x1c\\x76\\x71\\x94\\xd4\\x6c\\x6e\\x12\\x95\\x6f\\xbb\\xc3\\x31\\xb5\\x73\\xfc\\xee\\xbb\\x8b\\x57\\x5d\\x99\\xf1\\xea\\x4b\\xc7\\xb3\\xc2\\xdf\\x75\\x30\\xd9\\x23\\x05\\x46\\x31\\xfe\\xd7\\x32\\x94\\x5f\\xa1\\xe4\\x83\\x3f\\x5d\\xf6\\xfd\\x5d\\xad\\xed\\x36\\x61\\x95\\x7e\\xf9\\x15\\x57\\x77\\xbb\\x94\\xff\\x56\\x3a\\xaf\\xdf\\xbc\\x6f\\x5e\\xbe\\x26\\xf6\\xd7\\x4d\\x2a\\xe2\\x96\\x41\\x76\\xad\\x40\\xde\\xba\\x52\\xd4\\x6d\\xc2\\x2a\\xc3\\x54\\xca\\xd5\\xdd\\xa1\\x05\\xd0\\x3c\\x7d\\xdf\\x96\\x0e\\xe1\\x69\\x29\\xbf\\x97\\xa5\\x2f\\x57\\x72\\x25\\xa8\\xbe\\xb4\\x90\\x25\\x79\\xb0\\x29\\xe6\\xa3\\xe5\\xbb\\x6b\\x9e\\xbf\\x20\\xaf\\x85\\x2a\\x0b\\x56\\x79\\xd8\\x2e\\x0f\\x66\\x18\\xaa\\x1d\\x4a\\x7b\\x50\\xb2\\x40\\xbd\\x38\\xa0\\xa2\\xfc\\xa0\\xc7\\xd5\\x02\\xf6\\xc9\\xea\\xe6\\x73\\x5a\\x68\\x90\\x05\\xf7\\x71\\x62\\x7d\\xe7\\x0e\\x91\\x07\\x3f\\x88\\xdd\\x1c\\xd9\\x8b\\xa9\\x0b\\x44\\xab\\x7b\\x45\\x70\\xe5\\xbb\\xa9\\xdc\\x0b\\x80\\x8a\\x76\\x3b\\x96\\x6f\\x7c\\x4d\\x22\\x72\\x96\\xb2\\xfb\\x33\\x95\\xd2\\xe7\\x23\\x98\\xaa\\x0b\\xbd\\xae\\xaf\\x8b\\x2a\\x72\\xf4\\xfc\\x28\\x66\\x8c\\x2b\\x3e\\xe7\\x19\\x2d\\xb2\\x45\\xad\\xf2\\x7c\\xd5\\x93\\xa1\\xee\\x6e\\x48\\xf0\\x30\\x7c\\x76\\x44\\x4e\\x64\\x01\\x63\\x27\\x54\\x90\\x8c\\xb9\\x24\\x68\\x16\\x39\\x2d\\x50\\x0a\\x3a\\x7d\\x92\\x77\\x60\\x7f\\x96\\x18\\xc4\\xde\\x7b\\x39\\xbe\\xa9\\xe3\\xd3\\x2c\\x8f\\x51\\xab\\x4d\\xf3\\xaa\\x22\\xc3\\x5c\\x18\\xda\\x3c\\x21\\xdf\\x59\\xba\\x69\\x79\\x11\\x3c\\x1b\\x06\\x3c\\xee\\x8d\\xa7\\xbb\\x33\\x4f\\x47\\xa9\\xb3\\xa4\\x9e\\xd9\\x91\\xf2\\x85\\xac\\xda\\xcf\\x9e\\xf0\\x6e\\xb4\\x2b\\x89\\x6e\\xb9\\xfe\\xc8\\x72\\xb9\\x53\\xee\\x13\\xbb\\x5c\\x32\\x3d\\x70\\x6d\\x7e\\x90\\x8a\\x43\\x01\\x66\\xaa\\x09\\x45\\x1c\\x95\\x94\\x19\\x35\\x92\\x21\\x9a\\x16\\xda\\x60\\xf9\\xea\\xf5\\xe5\\xc7\\xd7\\x2f\\xcf\\xaf\\x5f\\xbf\\x7a\\x41\\xbe\\xb1\\xe3\\xf0\\x50\\xf6\\x98\\x90\\xeb\\xb0\\x0c\\x56\\x10\\x50\\x6c\\xcb\\xde\\xf8\\x99\\x8c\\x2c\\x56\\x6f\\xd5\\xa1\\xf9\\x22\\xaf\\x50\\xf8\\x81\\x0a\\x72\\x21\\xb8\\xae\\xca\\xd2\\x63\\x9c\\x59\\x26\\x85\\xf5\\x51\\x32\\x7d\\x5b\\xb3\\xc8\\x2d\\xd7\\x36\\x3b\\x36\\x0e\\x65\\x1e\\xbb\\xde\\x5a\\x06\\xad\\x8a\\x4c\\x40\\x71\\x6a\\xbf\\x8a\\x83\\x5b\\x55\\xaa\\x4d\\xdb\\x95\\x64\\xec\\xea\\x3d\\xef\\x45\\x2e\\xf6\\x25\\xbe\\x5d\\xfe\\x27\\xb4\\xe5\\x56\\xbf\\xc7\\x92\\xee\\x77\\xae\\x7e\\x8e\\xab\\x00\\x23\\x0b\\x2c\\xf3\\x89\\xe7\\xe8\\x78\\x32\\x39\\x9e\\x00\\xdb\\x70\\x3c\\x39\\x76\\xbc\\x6c\\xe6\\xfd\\x75\\x2d\\x15\\xae\\x86\\xed\\x56\\x29\\xad\\x7e\\x5b\\x26\\x84\\x7c\\x70\\x61\\xea\\x90\\x7b\\x77\\xc9\\x39\\xd8\\xfb\\xfd\\x56\\x25\\x80\\x31\\x6b\\x59\\xfd\\xce\\x45\\xe9\\x0e\\x41\\xab\\x59\\xde\\x84\\x13\\xb7\\xde\\xc4\\xb7\\xfc\\xde\\xa6\\xe5\\xdc\\xa9\\x31\\xa4\\x9a\\x60\\xc7\\xf3\\x10\\xae\\xcc\\x8a\\xf7\\x1f\\xdf\\xee\\x76\\x66\\x88\\x44\\x3a\\xcf\\xcb\\xe2\\x1e\\x3b\\xab\\x44\\xce\\xe7\\x58\\xcf\\x69\\xe6\\x33\\xc8\\x55\\xbe\\xba\\xb1\\x88\\x2f\\x5e\\xb1\\x80\\xc5\\xad\\xa6\\x2d\\xf7\\xb0\\x23\\x4a\\x77\\x9d\\x2e\\x29\\x12\\xfc\\xcf\\x36\\x4d\\x84\\xa8\\xa4\\xb8\\x1d\\x97\\xd8\\xb7\\x35\\xe9\\x94\\x4b\\xb1\\x65\\x29\\xe3\\x99\\x9f\\xd9\\xd9\\xc7\\xd7\\xe7\\xaf\\xde\\xbd\\x9e\\xcc\\x37\\xab\\x9f\\xf6\\x80\\x21\\x99\\x48\\x73\\xc9\\xdb\\xf3\\x24\\x8d\\x49\\x4e\\xf5\\xe6\\x2c\\xc6\\xf1\\x58\\xd4\\x0f\\xba\\x0f\\x2c\\xea\\x3b\\x77\\x67\\xd8\\xfd\\x10\\x14\\xf2\\xb3\\x59\\xc4\\x82\\x33\\xa0\\x65\\x2e\\x33\\x79\\xdb\\xb7\\x2c\\x7e\\x87\\x1d\\xfe\\x15\\x7a\\xfb\\x8f\\xe9\\x38\\xa6\\x74\\x60\\x27\\x29\\x56\\xcf\\xf6\\x23\\xc0\\xea\\x99\\x83\\x65\\x05\\x30\\x2f\\xaa\\xe9\\xa8\\xf8\\xc2\\x27\\x0a\\xb3\\x47\\x63\\xe6\\x57\\x00\\x89\\xfa\\x1c\\x40\\x45\\xae\\xca\\x61\\x55\\xaf\\x2f\\x67\\xc5\\x9c\\x63\\xf4\\xde\\x21\\xb9\\xfc\\x3d\\xef\\x50\\x3b\\x83\\x6f\\x90\\xf1\\x65\\xeb\\xb1\\xee\\xb6\\x35\\xae\\xcf\\x3a\\x35\\xc8\\x0b\\x36\\xf6\\x65\\x89\\xa6\\x3c\\x83\\xf0\\xa4\\x8a\\x91\\x08\\x88\\x43\\x4b\\xf7\\x4e\\x95\\xec\\xb4\\xd2\\xd8\\x47\\xb6\\x58\\x56\\x29\\x57\\x4c\\xb1\\x57\\xe2\\x63\\x3a\\xe6\\xf6\\x0a\\x94\\xbe\\x7c\\xa8\\xd5\\x93\\xd1\\x5b\\x2c\\x2b\\x54\\x58\\x93\\x5c\\x5e\\xf0\\x7b\\x9e\\xb1\\x5b\\xa8\\xa6\\xcc\\xc5\\xad\\xaa\\x32\\xdb\\xd9\\x90\\x9e\\x96\\x01\\x20\\x42\\x8c\\x55\\xe4\\xd0\\x5b\\xb0\\xde\\x99\\x7f\\x55\\xc9\\x7a\\xf0\\x50\\xbf\\xff\\x70\\x0d\\x95\\xce\\xc1\\x9d\\x63\\xcf\\x6a\\x72\\x33\\x9d\\x56\\x42\\x44\\xc8\\x78\\xdc\\x76\\x0a\\xae\\x3f\\xbc\\xfa\\x70\\xf2\\x17\\x23\\xf7\\xa4\\xd9\\x29\\xf9\\x81\\xd9\\x15\\x40\\xa4\\x93\\x2e\\x78\\xa2\\xc9\\xc3\\x4c\\xfa\\x1a\\xd0\\x00\\x85\\xea\\x34\\xc0\\x2d\\x45\\x6f\\x3e\\xfb\\xd6\\x99\\x79\\x53\\xc8\\xd6\\xc3\\x01\\x9c\\x46\\xad\\x37\\xce\\x14\\x06\\xdb\\x38\\x2f\\x8d\\x83\\x0b\\x49\\x3b\\x24\\xec\\x7b\\x25\\x41\\xce\\xf6\\xb5\\xee\\x52\\x46\\x6a\\x49\\x51\\x4d\\x89\\xe4\\x8c\\x12\\xb5\\x98\\x67\\x5c\\xdc\\x8d\\x7c\\x09\\xaf\\xa9\\xb4\\xc9\\x4b\\x19\\x31\\x0f\\xdc\\x55\\x2d\\x18\\xcd\\xb6\\x21\\x74\\x7b\\x38\\xe0\\x9d\\x88\\x9c\\xde\\x93\\x2d\\x06\\x2c\\x21\\x06\\x0f\\xfd\\x2f\\x87\\x52\\x51\\x1d\\xd5\\x91\\x42\\x1d\\x1d\\x7d\\x7e\\x60\\xe5\\x2a\\x51\\x7c\\x97\\x54\\x09\\x3a\\xac\\x91\\x24\\x41\\x2e\\xae\\x5e\\x5e\\x5d\\x7c\\x2e\\xc6\\xce\\x26\\x5e\\x01\\x16\\xf6\\x78\\xf2\\x0d\\xff\\x6b\\x9b\\xe2\\x60\\x4c\\xb2\\xb2\\xfd\\x1d\\x54\\xc5\\x5c\\xca\\x42\\xd3\\xcd\\x65\\xb3\\xe3\\x91\\x65\\x32\\xa3\\xf9\\x79\\xa9\\x67\\xaf\\xb8\\x82\\x2c\\xb8\\x5d\\x99\\xd0\\x95\\xef\\x83\\xd8\\x3a\\xac\\x3d\\xef\\xea\\x1c\\x72\\x77\\x90\\xec\\x7b\\x2f\\xff\\xd7\\xf9\\x25\\xa1\\xa5\\xd9\\x7c\\x6d\\x8b\\xd0\\xee\\x8c\\x65\\x0b\\x57\\x76\\x85\\x19\\x27\\x7a\\xae\\xcb\\x7e\\xdd\\xb2\\x2a\\xf7\\xd6\\xbe\\xd7\\xf4\\x58\\xae\\xc9\\x83\\x59\\xfb\\x80\\x66\\x6d\\x40\\x56\\x9f\\xb5\\x29\\x9b\\x0b\\xae\\x39\\xd5\\xb2\\xd8\\x97\\x3d\\xb0\\x36\\x80\\x57\\x13\\x96\\x4a\\xcb\\xb9\\xbd\\x91\\x17\\xee\\x0d\\xf0\\xec\\x8a\\xe4\\xcc\\x56\\xba\\xad\\xb4\\x8c\\x20\\x0b\\xc3\\xce\\x5c\\x08\\x23\\x75\\xd2\\x84\\x2d\\x85\\xc9\\x8c\\xa0\\xe6\\x2a\\x8e\\xce\\xdd\\x3b\\x11\\xe3\\xfe\\xd1\\x2a\\xd8\\xa1\\xca\\x51\\xf6\\xa7\\x17\\x7f\\x0c\\x2c\\xe4\\x7f\\xaa\\xca\\x95\\xba\\xda\\xd8\\x56\\xff\\x99\\x48\\x21\\x58\\x12\\x57\\x7f\\xbc\\xcb\\xce\\xfd\\xb5\\x2b\\xa2\\xe4\\x7f\\x15\\x4b\\x96\\x02\\x04\\xc1\\xff\\x2e\\x69\\x86\\xa0\\x8b\\xdb\\x80\\x2e\\x93\\xac\\x6d\\xc3\\x5e\\xce\\x57\\x7d\\xa3\\xed\\xfa\\xfc\\xae\\xa2\\xb7\\x20\\x20\\xb0\\x52\\x61\\xe1\\x22\\x5c\\xb4\\x2e\\xa8\\x50\\x66\\x23\\xbb\\x2a\\x48\\x8e\\xad\\xb7\\xc4\\x31\\x39\\xd1\\x49\\x1e\\xe1\\x38\\xb0\\xd7\\xa0\\xcf\\xac\\x14\\x21\\x17\\x88\\x6b\\xbb\\xc6\\xdd\\x7d\\xeb\\x83\\x3e\\x63\\x27\\xb9\\x17\\x57\\x03\\xb8\\x2c\\x7b\\x51\\xdd\\xda\\xae\\xfd\\xa6\\x87\\x8b\\x47\\xd6\\x8b\\xbc\\xe5\\x4a\\x63\\x10\\x0c\\xbe\\x0c\\xc9\\xaf\\x30\\xfe\\xce\\x70\\xcc\\x97\\x44\\x16\\x84\\xe7\\xff\\x4d\\xd3\\xb4\\x78\\x81\\x5c\\x82\\x95\\xfa\\x64\\x11\\xe3\\xe3\\xce\\x95\\xaf\\x28\\x43\\x85\\xf7\\xa3\\x39\\xd1\\x8b\\xdc\\x16\\x8f\\xbb\\x7e\\x79\\x09\\x7d\\x29\\xf2\\x87\\xdf\\x3d\\x03\\x16\\xfa\\xdf\\xbe\\xfa\\xdd\\xb3\\xe8\\x53\\xf3\\x78\\x81\\x95\\xff\\x6a\\x6e\\x0b\\x87\\x08\\x34\\xa9\\x05\\x8b\\x40\\xa6\\x23\\xc3\\x84\\x5e\\x61\\x5c\\x85\\x21\\x17\\x16\\x35\\xe1\\x09\\x36\\x87\\xc5\\x93\\xb9\\x7e\\xac\\xea\\x10\\xed\\x30\\x44\\x3b\\x74\\x4d\\x16\\x17\\x4a\\xae\\x7b\\xd1\\x02\\x05\\xfd\\x43\\xa6\\x95\\x55\\xac\\x8d\\x08\\xfb\\xf2\\x73\\x44\\xd8\\xad\\x1b\\xd4\\x7e\\x7b\\xba\\x81\\x34\\x74\\xaf\\x8b\\x8b\\xb0\\xad\\x02\\x52\\x5f\\xbd\\xbf\\xfa\\xef\\xb7\\xe7\\x7f\\x7e\\xfd\\x16\\xd6\\x69\\xfd\\xf5\\xcc\\x15\\xb0\\x02\\xc9\\xee\\xdd\\xd8\\x77\\x74\\xe1\\x62\\x61\\xbd\\x5b\\xc7\\x00\\xb1\\xe4\\x12\\x20\\xc8\\xfb\\x37\\x57\\x1d\\xbd\\x01\\xf6\\x6b\\xee\\x10\\xd3\\x18\\xb8\\x1d\\xd6\\x1a\\x60\\x5e\\x82\\x7a\\xa2\\xbb\\x8a\\x56\\xdf\\xab\\xd1\\x20\\x28\\xb7\\x51\\xd3\\x6a\\x98\\x9d\\xc6\\x55\\x1c\\x40\\xad\\xd0\\xb6\\x8d\\xe4\\x33\\x61\\xe5\\x0c\\xd0\\x10\\x90\\x4f\\xd2\\x5c\\xbd\\x9f\\x2d\\x89\\x65\\x21\\x8b\\xee\\x29\\x17\\x22\\x03\\x95\\x8b\\x20\\x2f\\x83\\x41\\x48\\x48\\x22\\x0a\\x43\\x3c\\x0d\\xd9\\x64\\x4a\\x39\\x82\\xf1\\xb9\\x9e\\xea\\x7c\\x5d\\x36\\xc3\\x5d\\xa2\\xfa\\xb5\\x03\\xd8\\x4c\\x86\\x2e\\x15\\x63\\xe0\\x0d\\x50\\x0b\\xfc\\x6e\\x33\\xaf\\x34\\x64\\xaa\\x44\\x02\\x02\\xa5\\xb9\\x7d\\x21\\xc4\\x3d\\x59\\xc7\\xd7\\xa4\\x34\\x5c\\xce\\x5e\\x09\\x19\\xdf\\x0e\\x4e\\x4c\\x60\\xd4\\x1d\\xc6\\x95\\xf9\\xfe\\xf6\\x71\\xd1\\x7c\\xe7\\xcb\\x39\\x50\\x68\\x97\\x2d\\x26\\x54\\x39\\x5e\\xcb\\x3a\\x52\\x77\\x4a\\x96\\xf2\\xc8\\x67\\x80\\x3c\\x41\\x4a\\xf4\\xc3\\xde\\xf4\\x09\\xbb\\xd6\\x25\\xe4\\x33\\xa9\\xa5\\xe8\\x1d\\x1a\\xbb\\xee\\xf3\\x3a\\x5e\\xba\\x84\\x37\\x5e\\x56\\x89\\x68\\xab\\x2d\\xc6\\x10\\x1b\\x6f\\x16\\x36\\x02\\x80\\xa3\\xce\\x52\\x38\\x13\\x70\\xdd\\x02\\x7c\\x70\\xd6\\x32\\xbd\\x78\\xb5\\x23\\x44\\x30\\x24\\x0a\\xc2\\x76\\xc8\\xec\\x8a\\x5d\\x5c\\x51\\xd3\\xce\\x11\\xef\\xe6\\x13\\x07\\xf5\\x8b\\x57\\x96\\x6f\\x77\\xe1\\xec\\xca\\x9e\\x7c\\xd2\\x7c\\xf4\\x77\\xc6\\x8a\\xc8\\x42\\x3f\\xc8\\xa2\\x7b\\x62\\xb3\\xfa\\x87\\x4b\\xde\\x85\\xf6\\xd9\\x4a\\xbe\\x88\\xa7\\x78\\x4d\\x71\\x8e\\x9f\\xc3\\x55\\xbd\\x82\\xab\\xba\\x54\\xaa\\xb8\\xe9\\xca\\x3e\\xd5\\x1b\\xfb\\xb8\\x37\\xf5\\x20\\x14\\xfc\\x17\\x95\\x95\\xca\\x5d\\x8f\\x8e\\x10\\x73\\x9f\\x59\\xb5\\x9c\\xd9\\xeb\\x0a\\xbb\\x51\\x50\\x8e\\x06\\x18\\x62\\x67\\xd8\\xac\\x90\\x7f\\x81\\x1c\\xee\\x5d\\x10\\x99\\xfb\\x06\\xed\\x50\\x58\\xdb\\x34\\xcb\\x0c\\x54\\xa5\\x08\\x6b\\xa8\\xda\\x6c\\x4f\\x23\\x82\\xd5\\x3d\\xe7\\x34\\x57\\x58\\xfd\\x25\\x95\\x0f\\xe2\\x81\\x16\\x29\\x39\\xbf\\xbc\\xd8\\x0d\\xf6\\xea\\x10\\xa1\\x87\\x67\\x2d\\x2e\\xb3\\x79\\x8f\\x18\\xbd\\xaa\\x7b\\x70\\xa8\\xb6\\x79\\xf1\\x19\\xb9\\xe1\\x5a\\xd5\\xea\\x6b\\x04\\x4a\\x10\\x83\\xda\\xbd\\x17\\x81\\xc1\\x2c\\x06\\x8b\\xd8\\x9e\\x3a\\x71\\x12\\x82\\xc8\\x44\\xd3\\xcc\\x15\\x23\\x67\\xfa\\x81\\x31\\x41\\x9e\\x3d\\x7b\\x86\\x9a\\xed\\x67\\xbf\\xff\\xfd\\xef\\x09\\x54\\xa2\\x4d\\x59\\xc2\\xe7\\xab\\x2f\\xc2\\x5b\\xff\\xe3\\xf9\\xf3\\x98\\x41\\xff\\xcf\\xf9\\xbb\\xb7\\xb6\\x5a\\xbf\\xc2\\xdc\\xa4\\x38\\x36\\x6c\\x70\\xd8\\xbd\\x1a\\x91\\xff\\xbc\\xfa\\xf0\\xbe\\x4a\\x76\\x5f\\x7f\\x0a\\xe7\\xc7\\x83\\x28\\x8a\\x3b\\x0f\\x5c\\xa3\\x43\\xed\\x35\\xd5\\x33\\x80\\x39\\xd4\\xa6\\x98\\x4e\\x83\\xda\\x04\\x58\\x75\\x42\\x47\\xd6\\xdc\\xc4\\xac\\x6a\\xfc\\x76\\x06\\x40\\xe5\\x02\\xce\\x6f\\x06\\x3e\\xdf\\xdc\\x2c\\x13\\xec\\x09\\x2e\\xf9\\x20\\xba\\xce\\xc3\\x68\\x9e\\xbc\\x44\\x8c\\x61\\x16\\x3c\\x22\\x19\\xbf\\x63\\x64\\xaa\\xbe\\x29\\x64\\x99\\x57\\x85\\x91\\x0a\\xa6\\x8c\\xf0\\x61\\xeb\\x82\\xe0\\x70\\xd5\\x19\\x8a\\x2a\\x9f\\xb1\\x3f\\xf3\\xbe\\xbd\\xdc\\x5d\\x2d\\xa1\\x16\\x25\\xb8\\x1a\\x85\\xb6\\x06\\xa8\\x0b\\x12\\x42\\x8c\\x62\\xe0\\xf9\\x38\\x76\\xf2\\xda\\x5c\\x2f\\xfd\\x6c\\x70\\x73\\x6d\\x6d\\x9c\\x0a\\xed\\xd1\\x4c\\x8a\\xdb\\xf0\\x2c\\x54\\xd4\\xdf\\xb9\\xe1\\x2d\\xf2\\x28\\x13\\x62\\xc7\\xb2\\x54\\x5d\\xab\\x4c\\x26\\x18\\x87\\x73\\x5d\\x94\\x4a\\xff\\xb9\\x14\\x69\\x16\\x5d\\x58\\xa0\\x6f\\x29\\x87\\x97\\x2b\\x23\\x62\\x48\\x89\\x35\\x8c\\x80\\xba\\x2c\\x49\\x98\\xc2\\x63\\xf0\\xf3\\x04\\x6a\\x2a\\xe8\\xea\\xed\\x9f\\xd1\\x74\\x1a\\x3d\\x9e\\x9c\\xae\\x1b\\xd2\\xda\\x97\\xcc\\xd5\\xa5\\x82\\xd0\\x52\\xcb\\x31\\x54\\x12\\x72\\xb1\\x3b\\x93\\x2f\\xbe\\x88\\x1e\\x01\\x4a\\x77\\x8c\\xa0\\xfc\\x86\\x67\\xee\\x56\\x87\\x0c\\xce\\x4c\\x58\\xb0\\xa3\\xcb\\x40\\x1b\\xd6\\x61\\x30\\x81\\xb5\\x89\\xde\\xb8\\x6a\\x9e\\x38\\x1b\\x41\\xe7\\x6c\\x64\\x50\\x3a\\xce\\x2c\\x7a\\xb0\\xa5\\x14\\xd4\\x8a\\xdf\\x0a\\x56\\xa0\\x42\\x0b\\xaa\\xc7\\x2e\\x55\\xa2\\xed\\xb2\\x8e\\x6f\\x51\\x46\\x31\\xf4\\xcd\\xe0\\x15\\x45\\xe8\\xed\\x2d\\x94\\x96\\xbb\\x37\\x98\\xb9\\x98\\xd3\\x8c\\xff\\xad\\xca\\x7d\\x3d\\x63\\xe4\\xf2\\xf5\\x3b\\x88\\x19\\x02\\x0e\\xdd\\xb0\\x7c\\x9a\\xc5\\x04\\x73\\x63\\xf3\\xa9\\x04\\xcc\\xe9\\xaa\\xb8\\xf2\\x09\\x21\\xaf\\x95\\xd4\\x90\\x10\\xda\\xf4\\x6f\\x37\\x45\\xf9\\x1a\\x34\\xe0\\x30\\x36\\xbe\\xc9\\x64\\x12\\x93\\x9a\\xc8\\x03\\xcd\\x16\\xa1\\x13\\x29\\x81\\x4f\\xc9\\x8c\\xd1\\x94\\xd9\\xe2\\x9e\\x86\\xd9\\xca\\x73\\x96\\x4e\\x08\\x79\\x69\\x6e\\xe9\\x94\\x27\\x50\\x41\\xd7\\x3c\\x4b\\x59\\x5a\\x1a\\x26\\x1e\\xb2\\x38\\x44\\x0f\\x78\\x3d\\x63\\x44\\x16\\x29\\xc3\\x0a\\x4a\\x53\\x92\\x84\\xdd\\x06\\x94\\x0f\\xe2\\xd1\\xa0\\x58\\xe4\\x0d\\xd7\\x05\\x2d\\x6c\\x0d\\x60\\xbb\\x13\\xd1\\xc3\\x19\\x44\\x87\\x55\\xa8\\xa0\\x57\\x18\\x19\\x0b\\x59\\xc7\\xc4\\x35\\xbb\\xd6\\xa3\\xd4\\x5e\\xf7\\x32\\xbf\\x51\\x76\\x48\\xd7\\xfa\\x14\\xe7\\x85\\xf3\\x7f\\xd5\\xb9\\x3a\\xf8\\x76\\xf5\\x22\\x71\\x3c\\x60\\xa6\\x57\\xb1\\x81\\x72\\xd4\\x48\\x27\\x33\\x64\\x69\\x96\\xee\\x28\\x21\\x28\\x23\\xd1\\x6e\\x35\\x22\\x19\\xf2\\x2e\\xdc\\x61\\x01\\xef\\x60\\xcb\\xf4\\xc4\\xb0\\x96\\xba\\xa4\\x59\\xb6\\x18\\xb3\\x4f\\x86\\x9a\\x98\\x4b\\x0c\\x84\\x0f\\x52\\x25\\xb8\\xe2\\x5c\\xac\\x63\\x05\\x54\\xb8\\x7c\\x79\\xc1\\x34\\x26\\x57\\x3c\\xc2\\x35\\x09\\x09\\xd1\\x88\\x47\\xd8\\x2d\\x54\\xda\\x2a\\x35\\xa6\\x6b\\x1a\\xad\\xff\\xa4\\xdb\\x3a\\xef\\x59\\xb1\\xb0\\x23\\x74\\xf8\\xb0\\x67\\xe5\\xc8\\xbe\\x05\\xa1\\xb7\\x2b\\xbf\\xfe\\xf4\\x0a\\xb0\\x6f\\x53\\x29\\xb6\\x67\\x95\\xd8\\xed\\xeb\\x12\\x3f\\xa9\\x42\\xec\\xbb\\x2c\\xc5\\xbe\\x55\\x31\\xf6\\x6d\\xca\\xb1\\xf7\\x2d\\xc8\\xbe\\x45\\x49\\xf6\\xed\\x8a\\xb2\\xf7\\x2e\\xcb\\xfe\\x18\\x85\\xd9\\xb7\\x2c\\x01\\xbe\\x5d\\x71\\xf6\\xdd\\x14\\x02\\x7f\\x84\\x02\\xed\\x87\\x2c\\xd1\\xbe\\xf5\\x0e\\xf5\\x2f\\xd3\\xbe\\xab\\xfd\\x79\\xb4\\x52\\xed\\x4f\\xa2\\x58\\xfb\\x63\\x97\\x6b\\xdf\\xba\\x60\\xfb\\xb6\\x25\\xdb\\xb7\\x2a\\xda\\xbe\\xc5\\xf1\\xef\\x5d\\xb8\\x7d\\xfb\\x73\\xff\\xe8\\xc5\\xdb\\x9f\\x40\\xf9\\xf6\\xa7\\x52\\xc0\\x7d\\x2b\\xce\\x65\\x17\\x45\\xdc\\x7b\\x1f\\xe1\\x5d\\x14\\x72\\xef\\x12\\x84\\x81\\x6d\\x17\\x62\\xa8\\x3b\\xd3\\x6b\\x34\\x53\\x37\\x0b\\x57\\x3a\\xc4\\x0a\\x82\\xab\\x72\\x62\\xa7\\x21\\x41\\xa6\\x0c\\xe4\\x4f\\x28\\x84\\x16\\x8a\\xe0\\xdd\\x45\\xb6\\x8e\\x1b\\x25\\x5d\\x89\\x97\\x03\\x01\\xd9\\xd0\\xab\\xa2\\x64\\x23\\x92\\x4a\\x71\\xac\\xad\\x3a\\x29\\x97\\x29\\xe6\\x61\\x2c\\x73\\x17\\xe7\\xe0\\x5d\\x0d\\xd3\\x35\\xfb\\x70\\x12\\x55\\x7f\\xae\\x6a\\xb4\\x60\\x66\\x30\\x7a\\x4f\\x79\\x46\\x6f\\x32\\x27\\xc1\\x83\\x1b\\x1a\\xaa\\x12\\x21\\xe1\\x83\\x73\\x6e\\x5b\\x37\\x64\\x7b\\x29\\xb5\\xa5\\x21\\x6d\\x91\\x70\\x21\\x01\\x77\\x41\\x0e\\xa5\\x70\\xd8\\x6a\\xd3\\x83\\xc1\\xeb\\xea\\xc9\\x4e\\xe3\\x6d\\x3a\\x44\\x80\\xc5\\xab\\xa2\\xe5\\xa8\\x76\\xf8\\x1b\\x2b\\x64\\xa7\\x11\\xd6\\xa8\\x66\\xba\\x9f\\xce\\x38\\x5b\\x72\\xd5\\xe2\\x9c\\xe0\\xab\\x56\\x3b\\x9a\\x1f\\x81\\x7d\\xbe\\xb7\\x26\\x32\\x88\\x35\\x0f\\x72\\x06\\x14\\x12\\xb7\\x06\\xac\\xed\\xf0\\xe0\\x06\\x56\\xb5\\xf7\\x2b\\x57\\x6d\\xd5\\x13\\x55\\xb0\\x05\\x6a\\xf1\\x6e\\xd4\\xaa\\x45\\x6b\\x76\\x6d\\xf3\\x7b\\x61\\x5a\\xae\\xa9\\x2d\\x8d\\x84\\x5a\\xfd\\x6d\\x8f\\xa2\\x0f\\x4b\\x2f\\x45\\x55\\x30\\xbf\\x9f\\xfa\\xb9\\xc7\\xb6\\xa2\\xa5\\xff\\x1d\\xcd\\x7b\\x19\\x9a\\xfc\\xd7\\xb5\\x1a\\x58\\xf4\\x46\\x96\\xda\\x45\\xd6\\xdb\\xe7\\x50\\xf1\\x45\\x4b\\x67\\x94\\xdb\\x9f\\x6a\\xba\\x8f\\x0e\\xa1\\x33\\xa3\\xbc\\xcd\\x91\\x46\\x1f\\x8c\\xba\\x07\\xd0\\x88\\x30\\x9a\\xcc\\x0c\\x07\\x38\\x46\\x03\\xbf\\xe1\\x52\\x1d\\x3b\\xfa\\xca\\x80\\x0e\\x19\\x43\\xb9\\x4c\\x62\\xba\\x1d\\x3e\\xbf\\x1b\\xee\\xc8\\x05\\x9e\\x21\\xce\\x2c\\xe3\\x1c\\xda\\x94\\x75\\x9a\\xb2\\xcc\\xa9\\xa8\\xdc\\xa8\\x3b\\x8d\\xe9\\xd4\\x5f\\xf6\\xf6\\x38\\xd5\\x0a\\xac\\x12\\x64\\xc0\\xa5\\xec\\xc1\\x19\\x57\\x66\\x3a\\x77\\x6c\\xe1\\x2f\\x46\\xa7\\xf1\\xd6\\xac\\xa8\\x4a\\x3c\\x61\\xb0\\xa9\\xf5\\x68\\x29\\xc5\\xca\\x48\\x50\\xb2\\xb5\\xeb\\x68\\xa0\\xf7\\x80\\x85\\x50\\xa7\\x3a\\x0a\\x12\\x5d\\xcc\\x78\\x02\\xa9\\xc9\\x4c\\xd7\\xf6\\x5d\\xb7\\xab\\x7e\\x33\\xba\\x89\\xb7\\xc1\\x16\\x29\\x66\\xb8\\x0e\\x98\\x3a\\xa4\\x29\\x31\\x6b\\x62\\x4a\\x11\\x0e\\x50\\x9e\\xd3\\xe2\\x8e\\xa5\\x9e\\x4b\\x9a\\x90\\x4b\\xb3\\x78\\x27\\x03\\x77\\x1a\\xb3\\x70\\xd4\\x08\\x9c\\x1b\\xe9\\xa2\\x96\\x88\\xda\\x4c\\xe8\\x78\\x32\\x39\\xb6\\x29\\xdd\\x56\\xd3\\x52\\x77\\xc6\\x5e\\x5d\\x05\\xde\\x1e\\x62\\x6e\\xed\\xfe\\xbe\\xa3\\xb9\\x42\\x71\\xdf\\xb0\\x37\\xa0\\xee\\x93\\x90\\x0f\\x5e\\xcf\\x9c\\xcd\\x8e\\x76\\x70\\xf7\\x5f\\x5e\\x4e\\x0f\\x01\\xa8\\xaf\\xda\\xb6\\x8f\\xca\\xb6\\x93\\x61\\x0e\\x5b\\x7f\\x35\\x6d\\x2f\\x15\\x6d\\x93\\x7a\\xd6\\xee\\x94\\xbd\\xf1\\x7d\\x35\\xeb\\xbd\\x14\\x7c\\xf3\\x28\\x67\\xb4\\xe5\\xb6\\xbd\\x5a\\x0f\\x9c\\x8a\\x6a\\xe5\\x2d\\xa3\\x5c\\xd5\\x6c\\x59\\xd6\\x6e\\x1c\\xa2\\x6b\\x8f\\xe2\\xab\\xb6\\xdc\\x1e\\xcf\\x77\\x6d\\xb9\\x5d\\x4c\\x01\\xfd\\xad\\x4f\\x7a\\x1f\\x3a\\x13\\x7a\\xb6\\x4e\\x75\\x57\\x9d\\x90\\x03\\x39\\xb5\\x2d\\xb7\\x3d\\x3b\\xb9\\x2d\\xb7\\x6e\\x4e\\x6f\\xcb\\xad\\x8b\\x13\\xdc\\x72\\xeb\\x2a\\x9d\\x61\\xdb\\xfe\\x02\\x87\\xa9\\xb7\\x8b\\x9a\\x90\\x67\\x59\\x3b\\x60\\xb9\\x40\\xd4\\xcd\\x03\\x24\\xd7\\xeb\\xde\\x5a\\x42\\x8d\\x57\\x97\\xde\\x28\\x99\\x95\\x3a\\x3e\\xbf\\x77\\x53\\x77\\x21\\xdd\\x87\\x89\\x3b\\xcd\\x66\\x57\\x62\\xbf\\xdc\\x71\\xc0\\x37\\x00\\xd7\\x86\\xe4\\xb8\\x5f\\xaf\\xbd\\x50\\xfb\\x21\\x35\\x76\\xdb\\xa4\\x50\\xc1\\xf6\\xd8\\x89\\x54\\xb0\\xed\\x2f\\x9d\\x0a\\xb6\\xc7\\xd1\\x0c\\xba\\x0e\\x7c\\x35\\x34\\x97\\xa9\\xb2\\xc6\\xb8\\x43\\xa2\\x13\\xad\\x50\\x82\\x70\\xb6\\x25\\xcc\\x6d\\xd9\\x45\\x2e\\xeb\\xa3\\x5e\\xda\\x5e\\x45\\xed\\x3c\\xfa\\xcf\\x2f\\x2f\\x7a\\x49\\xfe\\xc1\\xf7\\x0d\\xb2\\x7f\\xf8\\xc6\\x2f\\x58\\xfa\\xbf\\x40\\x71\\x3e\\xf4\\xd3\\x79\\x55\\xad\\xdc\\xc6\\x8e\\x75\\x24\\xc7\\x8f\\x23\\x07\\xad\\x4c\\xfb\\x8d\\xa1\\x45\\x61\\xee\\xba\\x7a\\x9d\\x73\\x0c\\x80\\xa8\\xa8\\x56\\x55\\x3d\\x3d\\xf0\\xef\\xec\\xe2\\x1b\\x4c\\x1e\\x47\\x66\\x3a\\xa0\\xfc\\x03\\xf0\\x88\\x4a\\x4b\\xb6\\xdc\\x6a\\x3b\\x75\\xfc\\xd1\\x2d\\xd6\\x2a\\x48\\x51\\x59\\x13\\x68\\x88\\x72\\x99\\xbe\\x40\\xc3\\x1e\\x15\\x42\\x6a\\xf4\\xc5\\x18\\xa1\\x72\\x5d\\x8d\\x2a\\xbf\\xe1\\x20\\xca\\xbd\\x08\\x82\\xe2\\x26\\xc7\\x9f\\x93\\x9f\\x12\\xac\\xfc\\xb2\\xeb\\x2e\\x92\\xad\\x1d\\x8e\\x2a\\xea\\xb6\\x03\\x37\\x0f\\xdb\\x93\\xdb\\x40\\x95\\xcc\\xd8\\x9c\\xc2\\x9f\\x6f\\xdc\\xf2\\x0c\\x96\\xb1\\xee\\xd6\\xa0\\x45\\x62\\xc5\\x5c\\x11\\x39\\x1d\\xd5\\xc2\\xf1\\x8e\\xee\\xe3\\x0a\\x75\\xae\\xb6\\x2d\\x1d\\x5e\\xfc\\x2e\\xec\\x00\\x18\\x97\\x35\\x8e\\xd8\\x9c\\x6b\\x10\\x6c\\xc1\\x16\\xe0\\x92\\x34\\x78\\x2d\\x9b\\x21\\x30\\xf7\\x08\\xbd\\x47\\x58\\xf8\\x6e\\xac\\xc5\\xd8\\x1e\\x4b\\xad\\xd0\\x57\\x9d\\x30\\xf2\\x6c\\x4f\\x5d\\x39\\xd0\\x63\\x0a\\x83\\x3a\\x61\\x50\\x27\\xfc\\x4b\\xab\\x13\\x02\\x9a\\xee\\x70\\xfd\\x1a\\x2d\\x41\\x98\\x4c\\xd0\\xa9\\x0a\\xaa\\x8c\\xd6\\x93\\xaa\\x4e\\xa4\\xb9\\x93\\x4e\\xe4\\x97\\x45\\x5d\\x5b\\x6f\\x64\\x6a\\xd4\\xd7\\x4f\\xbc\\x76\\xaf\\xd4\\xd3\\xf1\\x1f\\x08\\x13\\x89\\x4c\\xa1\\x6c\\x29\\xf4\\x5f\\x28\\x0d\\x5c\\x65\\x25\\xa9\\x86\\x73\\x99\\xbb\\xb1\\x42\\x8d\\x3f\\xf4\\xdd\\x97\\x7b\\xe8\\x85\\x82\\x5d\\xf8\\xf2\\x9b\\xdd\\xf0\\x56\\xbd\\x10\\x68\\xc5\\x85\\xf9\\xba\\x1e\\x16\\x64\\xbe\\xb6\\x92\\x65\\xc7\\xaa\\x60\\xeb\\x8c\\xcf\\xb9\\x75\\x56\\x35\\xd8\\x85\\xa9\\xd6\\x92\\x7d\\xeb\\xda\\x09\\x76\\x33\\x49\\xf2\\x72\\x64\\xbb\\x9c\\xcc\\xd9\\x5c\\x16\\x8b\\x91\\xef\\xd6\\x3c\\xac\\x8d\\x63\\xdf\\x38\\x05\\xa6\\x2f\\x29\\x8b\\x82\\x09\\x9d\\x2d\\x02\\xf6\\xef\\x73\\xe2\\xfe\\x1c\\x44\\x0f\\xcc\\xfc\\xf9\\x8d\\xed\\xea\\x0e\\x51\\xb5\\xfa\\xfd\\xaf\\x6a\\xf8\\x82\\x22\\xca\\x43\\x05\\x68\\x8c\\xcd\\x00\\x35\\xaa\\x54\\x13\\xe6\\x57\\x26\\xee\\xc9\\x3d\\x2d\\x54\\xf7\\xfb\\x46\\xb6\\xe7\\xf7\\x52\\x7e\\xcf\\xd5\\x4e\\x3c\\xd0\\xaf\\x2c\\xf1\\x43\\xb5\\xa8\\x2c\\x75\\x5e\\x6a\\x8b\\x8e\\xdd\\x35\\x72\\x15\\x6d\\xfc\\xf5\\x59\\x62\\x7a\\x9f\\xc7\\x94\\x1c\\x5a\\x6d\\x39\\xd5\\x9a\\x15\\xe2\\x05\\xf9\\x7f\\x27\\xff\\xf5\\x9b\\x7f\\x8c\\x4f\\xbf\\x3e\\x39\\xf9\\xf1\\xd9\\xf8\\xdf\\x7f\\xfa\\xcd\\xc9\\x7f\\x4d\\xe0\\x8f\\x2f\\x4f\\xbf\\x3e\\xfd\\x87\\xfb\\xc7\\x6f\\x4e\\x4f\\x4f\\x4e\\x7e\\xfc\\xf6\\xdd\\x37\\xd7\\x97\\xaf\\x7f\\xe2\\xa7\\xff\\xf8\\x51\\x94\\xf3\\x3b\\xfc\\xd7\\x3f\\x4e\\x7e\\x64\\xaf\\x7f\\x8a\\xec\\xe4\\xf4\\xf4\\xeb\\x5f\\xf7\\x9a\\x2e\\x15\\x8b\\x0f\\x3d\\xf0\\x1b\\xb6\\xf1\\x96\\xf4\\xb1\\xde\\x4b\\xef\\x63\\xb3\\xc4\\x31\\x73\\xa1\\xc7\\xb2\\x18\\x63\\x77\\x2f\\xc0\\xc3\\xae\\x47\\xa7\\xee\\x58\\xec\\xe2\\x1e\\x56\\x74\\xb8\\xaa\\xd1\\xe4\\x84\\x8f\\x47\\xb8\\x68\\xdb\\xcb\\x17\\x98\\xd5\\xa3\\x97\\x96\\x0f\\x3f\\x6d\\x50\\xf0\\xd9\\x87\\xbf\\x60\\xdd\\xde\\x67\\xe3\\xd9\\x63\\x33\\xd4\\x0f\\x6e\\x3d\\x8f\\xee\\xd6\\x83\\x3b\\x31\\xf8\\xf4\\x54\\x8b\\x1b\\x7c\\x7a\\xa0\\x0d\\x3e\\x3d\\x61\\x1b\\x7c\\x7a\\x6a\\xe3\\x0e\\x3e\\x3d\\x83\\x12\\x6e\\x50\\xc2\\x3d\\xbe\\x12\\x6e\\xf0\\xe9\\x19\\x7c\\x7a\\x06\\x9f\\x9e\\x5f\\xb6\\x4f\\x0f\\xca\\x5b\\xeb\\x3c\\x7b\\xac\\x14\\x55\\xb9\\xf5\\x7c\\x76\\x5e\\x3d\\xca\\x1c\\x88\\x84\\x9d\\x27\\x89\\x2c\\x85\\xbe\\x96\\x77\\x2c\\xda\\x34\\xbd\\x24\\xf7\\xaf\\xf4\\x03\\x95\\xa0\\x1a\\xf4\\x00\\xab\\x2f\\x1f\\x4c\\x29\\xf0\\x04\\x33\\x51\\xd1\\x32\\xe5\\x46\\x84\\x3f\\x14\\xde\\x71\\xe3\\x85\\xa5\\x35\\x45\\xca\\xd2\\xea\\x81\\x45\\x4a\\xda\\x6c\\xcd\\x84\\x9c\\x93\\x82\\x25\\x3c\\xe7\\x36\\x1c\\x9d\\xe2\\xef\\x9d\\x86\\x84\\x7b\\x61\\xd3\\xdd\\x2e\\xcc\\x6d\\x61\\xd9\\x14\\xd1\\x3c\\x15\\x55\\x1a\\xdc\\x22\\x90\\x99\\x2d\\x75\\x59\\x9a\\x52\\x37\\xd1\\xcb\\x4c\\x13\\x79\\x17\\x40\\x4c\\x0f\\x5c\\x31\\xa2\\x66\\xb2\\xcc\\x52\\x52\\xb0\\xbf\\x38\\x36\\xc9\\xae\\xf2\\x3a\\x1c\\x2d\\xd4\\x15\\x77\\x1d\\x36\\x58\\x8e\\x85\\x23\\xcd\\x79\\x7c\\x4d\\x16\\x3f\\xfb\\x3e\\x58\\x8f\\x7d\\xca\\x79\\x01\\xf7\\xed\\x8a\\x25\\x52\\xa4\\x07\\x53\\x65\\xad\\x0c\\x5c\\x31\\x38\\x60\\x42\\xc2\\x3c\\x19\\x3e\\x2b\\xe0\\x3d\\xcd\\x78\\xca\\xf5\\xc2\\x7b\\xaf\\x20\\x4a\\xe8\\x76\\x8c\\x11\\x7f\\xf8\\x53\\xaa\\xaa\\xdd\\x24\\x34\\xcf\\x0b\\x49\\x93\\x19\\x53\\xc1\\xcc\\x90\\x4b\\xb7\\x19\\xd6\\x63\\xd3\\x2c\\x87\\x2d\\xcf\\xca\\x5b\\x2e\\x90\\xa9\\x87\\xfe\\x0d\\xe7\\x96\\x2d\\x48\\x21\\xb5\\x73\\x6c\\xb3\\x0b\\x59\\x9e\\xdc\\x75\\x30\\xb0\\xf9\\xbc\\xd3\\xb0\\xc8\\x14\\xe9\\x62\\x01\\x9e\\x72\\x32\\x1c\\x0e\\x57\\xcb\\xa7\\xe1\\x3f\\x14\\x91\\x59\\xea\\xea\\xe1\\xfd\\xe1\\x99\\x91\\x03\\x13\\xbc\\xba\\x1d\\x95\\x93\\x0a\\xb2\\x02\\x9a\\x11\\x33\\xc3\\xa1\\x1a\\x32\\xd7\\x3c\\xd0\\x57\\xbf\\x25\\x33\\x59\\x16\\x6a\\x12\\xd6\\x72\\x7a\\x0e\\xbf\\x75\\xdb\\x55\\x91\\x56\\x4e\\x22\\x9a\\x64\\x8c\\x2a\\x4d\\x9e\\x3f\\x23\\x73\\x2e\\x4a\\xdd\\x27\\x0e\\xbb\\xbb\\x64\\x11\\xc8\\x14\\xbf\\xfb\\x6d\\xf4\\x77\\x5b\\xc5\\x6f\\x77\\xbc\\x6d\\xa1\\x04\\x01\\x7f\\x7b\\x31\\xc2\\xea\\x3a\\xb1\\x84\\x5d\\x2e\\xb9\\xd0\\xcb\\x42\\x85\\xa5\\xb0\\xfd\\xb0\\x29\\x68\\x53\\xf7\\x80\\xc5\\xfe\\x5a\\xca\\x9b\\x85\\xee\\x52\\x6c\\xc1\\x7e\\x51\\xcf\\x25\\xf5\\xbf\\xed\\x8f\\x3b\\xac\\xe0\\xb7\\x87\\xf2\\x0a\\x05\\xbb\\xe5\\x4a\\x17\\x6d\\x4a\\xba\\x71\\x0c\\x8a\\x8a\\xe7\\x37\\x6e\\x8d\\x24\\xbf\\x8f\\x84\\xe8\\xd0\\xb1\\x13\\x57\\x9d\\xd9\\xc0\\xa6\\x00\\x8e\\xc9\\xbb\\xe0\\x4a\\xf1\\x80\\x7e\\x1c\\x7b\\x6b\\xfd\\xea\\xa9\\xd5\\x37\\x58\\x57\\x2b\\xcf\\x1d\\x46\\x97\\x31\\xfa\\x71\\xeb\\xe5\\x75\\x91\\x2f\\xdc\\x01\\xdd\\x0f\\xc8\\xb0\\xef\\xfa\\xc5\\xb5\\x79\\x68\\x64\\x41\\xe6\\x65\\xa6\\x79\\x9e\\x55\\xe0\\xfb\\xe8\\x3e\\xb0\\xa4\\x35\\x46\\x36\\xad\\xd8\\x48\\x1a\\x68\\xf5\\x29\\x56\\x55\\xc1\\x22\\xb3\\x60\\x56\\x3b\\xf1\\xa3\\x31\\xa1\\x21\\xdb\\x3c\\x78\\x35\\xb3\\x9c\\x16\\xd4\\xef\\x52\\x22\\xe7\\x73\\x1a\\x95\\x86\\x05\\xed\\x3c\\x14\\x1c\\x7b\\x10\\x39\\x1b\\xc2\\x5b\\xd0\\xac\\x5a\\x75\\xe0\\x9b\\xb1\\xcb\\x43\\xae\\x99\\xa0\\x22\\xc2\\x64\\xdb\\xa3\\xb8\\x2f\\xf4\\x4c\\xe4\\x83\\xf7\\xd3\\xbf\\xe5\\xf7\\x4c\\x2c\\x9f\\x6e\\xcb\\xae\\xff\\x99\\x26\\x77\\x4c\\xc4\\xc8\\xbd\\xdf\\x29\\x07\\xdf\\x74\\x21\\xe8\\xdc\\xd6\\xea\\xcd\\x0b\\x79\\xcf\\xcd\\x35\\x60\\xe9\\xd2\\x08\\x6a\\x64\\x55\\xc9\\x98\\xb8\\xd6\\x25\\xea\\x46\\x96\\x6c\\x97\\xa0\\x2c\\xd5\\x7e\\xaa\\x38\\x9a\\x7e\\xb7\\xc7\\x92\\x0a\\xb5\\xfb\\x05\\xbf\\x4f\\x98\\xe3\\x31\\x4d\\xcf\\xbb\\x84\\xc0\\x7d\\x44\\xe1\\x23\\xb2\\xbe\\xba\\x89\\xcd\\x9d\\x8a\\xf7\\x0d\\x68\\xae\\x37\\x50\\x63\\x56\\xc1\\xec\\xff\\x67\\xef\\xea\\x7a\\xdb\\xc6\\x95\\xf6\\xfd\\xfe\\x0a\\x22\\x7b\\xd1\\x16\\x88\\xe3\\x17\\xc5\\xe2\\xc5\\x41\\xcf\\x55\\x9a\\xa4\\x5d\\x63\\xfb\\x11\\xd4\\x49\\x81\\x83\\xc5\\x5e\\xd0\\x12\\x63\\x13\\x91\\x49\\x1f\\x92\\xb2\\x1b\\x2c\\xf6\\xbf\\x1f\\x90\\x43\\x4a\\x94\\x6d\\x49\\xa4\\x2c\\xcb\\x29\\x90\\xbd\\xd9\\x46\\x16\\x25\\x72\\x38\\x1a\\xce\\x3c\\xf3\\xa5\\x65\\xde\\x53\\xd1\\x0b\\x63\\x8b\\x8b\\x6c\\xbd\\xf3\\xde\\xfa\\xdb\\x88\\x59\\x4c\\xdb\\x93\\xd6\\x6d\\x14\\xb3\\xb4\\x2a\\xb6\\xbe\\xe1\\x94\\x4b\\xf4\\xde\\x54\\x76\\xba\\x26\\x46\\xf1\\x8f\\x53\\x3d\\x3a\\xb4\\x83\\x24\\x3f\\xf0\\x72\\x95\\x11\\x79\\xf1\\xf8\\x2f\\x03\\xf1\\xd9\\xcf\\x63\\x2c\\x66\\xe9\\xf8\\xdb\\xcd\\xe5\\xf5\\xe7\\x9b\\x8b\\x65\\xf3\\x07\\x78\\x04\\x95\\x86\\x2e\\xf1\\xbc\\x4d\\x9d\\x1c\\xa1\\x25\\x67\\x54\\x71\\xd1\\x2c\\xf9\\x9e\\x45\\x5f\\xa9\\xc6\\x16\\x70\\x95\\xde\\xdc\\xb0\\xbd\\x4f\\x3c\\x47\\x1b\\x0c\\xc5\\xfb\\x82\\xdb\\xc3\\xdd\\xd1\\xd5\\x3b\\x74\\xc3\\x64\\x2e\\x48\\x59\\x30\\x76\\xfb\\x65\\x5a\\xdc\\xf5\\xd8\\x7a\\x0a\\x78\\xe7\\xdd\\x60\\x2d\\xe3\\x0e\\xee\\x31\\x2b\\x66\\x21\\xa7\\x09\\x40\\xd0\\x0b\\xbe\\x41\\x29\\x47\\x1b\\x82\\x56\\x82\\xac\\xb5\\xcd\\x6b\\x62\\x22\\x24\\xf2\\xaa\\xe8\\x5b\\xda\\x9a\\x12\\x59\\x09\\x5f\\xae\\x04\\x5f\\x52\\xe9\\x8e\\xb6\\x90\\x7e\\x6b\\x28\\x4e\\x98\\x9a\\x2f\\xe3\\x18\\x3c\\x6a\\x1e\\x5c\\xa0\\x2c\\x46\\x10\\xc1\\xa5\\xd0\\x62\\x56\\x5d\\x65\\xcb\\xaf\\x0b\\xbe\\x19\\x29\\x3e\\xca\\x25\\x19\\xd1\\x76\\xd8\\x35\\x82\\x56\\x8f\\xe4\\xc9\\x44\\xf5\\x1d\\x81\\x5a\\xf6\\xd1\\x15\\xa3\\x59\\x71\\x83\\xd9\\x9b\\xeb\\x5a\\x2f\\xfb\\xf6\\xfe\\xfa\\x5e\\x86\\x81\\x74\\x9e\\xcd\\x32\\x26\\x2a\\x19\\x27\\x64\\xb5\\x18\\xdb\\x77\\xfc\\x9c\\xb4\\x77\\xb2\\xf9\\x18\\xc4\\x77\\xcf\\x06\\xed\\x20\\xe1\\x59\\x66\\x3b\\xa9\\xf0\\x07\\x74\\x45\\x56\\x8b\\xe2\\x86\\x67\\x47\\xba\\x9e\\xbb\\x10\\xc5\\x34\\xd0\\xe4\\x3c\\xc0\\x77\\xd5\\xa1\\x27\\x3e\\xe7\\x59\\x55\\x6a\\x98\\x2b\\xa1\\x42\\xc3\\x63\\x7c\\x31\\xeb\\x2a\\xff\\x4f\\xcc\\xea\\x27\\x43\\x04\\x7a\\x6c\\x5c\\x7c\\x70\\xab\\xfc\\xe3\\xed\\x41\\x68\\xbb\\xfc\\x44\\x10\\x15\\x94\\x7e\\xd3\\xa5\\x63\\xbe\\x7d\\xb8\\x01\\x95\\x3c\\x37\\x3b\\xce\\xd5\\x82\\x30\\x45\\x13\\xf0\\x44\\xd8\\x88\\x64\\x5f\\xf8\\xa3\\xc9\\x03\\x58\\xa1\\x69\\x90\\xfb\\x96\\xaf\\x89\\x10\\x34\\x25\\x12\\x45\\x48\\x7f\\x1f\\xf1\\xa2\\xd9\\xb3\\xdb\\xc0\\x40\\x7f\\x6a\\x9c\\xab\\x33\\x3c\\xb0\\xa2\\x1b\\x30\\x7e\\x48\\x30\\xc5\\xa9\\xc3\\x28\\x8e\\x17\\x40\\x11\\xe5\\x44\\x3c\\x24\\x9c\\xe0\\xa8\\xa8\\x49\\xe5\\xb8\\x32\\x57\\x3a\\x1c\\x57\\x38\\x5d\\xd2\\xa0\\x7c\\xef\\xe7\\x75\\x60\\xc9\\x04\\x67\\x64\\xf2\\x35\\x02\\xc6\\xb0\\x23\\xaa\\x48\\xc5\\xd4\\x5e\\xf4\\x7a\\x66\\xb7\\x74\\xa2\\xfe\\xa3\\xe0\\x05\\xc4\\x78\\xda\\xe6\\x79\\x3b\\x02\\xa6\\x30\\xc7\\x8a\\x6c\\x5a\\xb5\\xaf\\x51\\x29\\xec\\xdb\\xef\\x34\\xb6\\xdf\\x4f\\x8e\\x3e\\xfc\\x3c\\x0d\\xe8\\xe3\\xbe\\x4f\\x68\\x85\\xdd\\xa7\\x9e\\x67\\x19\\x28\\x72\\x8b\\xec\\x28\\x47\\x7e\\x43\\x17\\x9c\\xa6\\x82\\x48\\xe9\\xce\\x17\\xf7\\x31\\x5d\\xde\\x4e\\xd0\\x47\\xb8\\xbd\\xdf\\xe6\\xf9\\x82\\x2b\\xb0\\x90\\xae\\xf9\\x12\\xd3\\x80\\x90\\xac\\xed\\xf6\\xcd\\x95\\xe1\\x6e\\x29\\xbe\\x22\\xe4\\x96\\x70\\x5b\\xdc\\x8b\\xec\\xcd\\x0f\\x5c\\x78\\xa5\\x98\\x73\\x41\\x52\\x64\\x31\\x99\\x9f\\xaf\\xed\\xf8\\x8e\\xb2\\xfc\\x33\\xb7\\x1d\\x1f\\x48\\x63\\xf6\\x00\\x7b\\x97\\x38\\x55\\x6a\\xc9\\x8e\\x6d\\xcc\\x21\\x5c\\x04\\x56\\x05\\x3d\\x9f\\x49\\x6a\\x22\\x14\\xbc\\x98\\x40\\xdb\\xd3\\x87\\xca\\x32\\x37\\x0a\\x14\\xef\\x73\\xf4\\x89\\xcf\\xa9\\xeb\\xab\\xa6\\x99\\x13\\xf6\\x06\\x87\\x68\\xcb\\x2f\\x4a\\xec\\x8b\\x12\\xdb\\x4d\\x89\\x95\\x32\\xbb\\x61\\x78\\x96\\x85\\x44\\x87\\x56\\x55\\xae\\x62\\x20\\xfa\\x90\\xe1\\x39\\x22\\xe6\\x8f\\x71\\x4a\\xa5\\xfe\\x3f\\x9a\\x4e\\x3f\\x19\\x2f\\x72\\xce\\x9c\\xe1\\x69\\x1c\\x9f\\xf6\\xe8\\x28\\x32\\xd3\\x41\\x44\\xf5\\x2b\\x33\\x40\\x72\\x1f\\xab\\x17\\xbe\\xf7\\x78\\x44\\x59\\xea\\xfa\\xd6\\x7a\\x21\\xd2\\xf6\\x0e\\x23\\x3c\\x70\\x91\\xb4\\x08\\x31\\x98\\x33\\x82\\xee\\x16\\x34\\x79\\xbc\\xf5\\x9c\\xbe\\x5c\\xe8\\x6b\\xcc\\xbb\\x14\\xa9\\x46\\x44\\x8f\\x8e\\xe0\\x2e\\xbb\\x98\\xdb\\x78\\x68\\xce\\x1b\\xe9\\x4e\\x63\\x27\\x4a\\xa7\\x96\\x42\\xe6\\x37\\x2c\\x25\\x4f\\x68\\x19\\x7b\\x60\\xb0\\xea\\xf2\\x88\\x4e\\xcd\\x11\\xdd\\xef\\x9a\\x8c\\xa2\\x17\\xbb\\x1c\\xd0\\x24\\xf7\\xe8\\x15\\x6e\\xbf\\xed\\x1d\\x58\\xfa\\x7a\\x04\\x65\\x6e\\xd5\\xbd\\x2e\\x01\\xb8\\x2a\\xac\\xac\\x46\\x3c\\x8f\\x97\\x4f\\xdf\\x5e\\x6f\\xc1\\xcf\\xdb\\x5e\\x6d\\x97\\xda\\x6b\\x77\\x38\\xc0\\xec\\xb0\\x6b\\x5e\\x60\\x30\\x55\\x77\\xb8\\x80\\xca\\xe2\\xdb\\x31\\x15\\x06\\x7a\\xa3\\x5f\\x48\\xae\\x7f\\x1c\\xcd\\xac\\xb6\\x50\\x0d\\xef\\x81\\x6b\\xd6\\x13\\x6e\\x3e\\xfe\\x15\\x5f\\xe5\\x19\\x84\\xb1\\x16\\x8b\\xeb\\xe0\\x0d\\x8f\\x71\\x25\\xc2\\x2c\\xfa\\x31\\x63\\xc3\\xf5\\x06\\x2f\\x1d\\xf0\\x18\\xec\\xe9\\x67\\x1b\\xc6\\x27\\x85\\x3a\\x8e\\x35\\xe6\\xa1\\x36\\x05\\xed\\xe3\\xa2\\x8c\\xcb\\x21\\x73\\x42\\xfb\\xca\\x01\\x0d\\x31\\xc3\\x2b\\x59\\xa2\\x15\\x5b\\xe2\\xff\\xfe\\xff\\xb7\\xdf\\x82\\xce\\x25\\x2a\\x4c\\x5b\\x2a\\x5a\\xed\\xe6\\x6e\\xbc\\x8f\\x58\\x10\\xa3\\xf3\\x42\\xc2\\xa6\\x33\\xc4\\x21\\xba\\x49\\x05\\x02\\xc9\\x43\\xa4\\x87\\x1e\\x39\\x1d\\x34\\x2e\\x48\\x3b\\x26\\xdd\\x33\\xd0\\x2b\\xd7\\xc1\\xf3\\x6e\\xca\\x76\\x4c\\x06\\x2b\\xdb\\x31\\x50\\xb1\\x8e\\x61\\x4a\\x74\\x0c\\x51\\x98\\x63\\x90\\x72\\x1c\\xc3\\x15\\xe1\\x38\\x72\\xe9\\x8d\\xa3\\x78\\xba\\x8f\\x59\\x5c\\x23\\x32\\xeb\\x2f\\x2e\\xe3\\x2f\\xbc\\x7c\\x46\\x70\\x5e\\x60\\x6c\\x4e\\x60\\x44\\x81\\x8c\\x7e\\xcb\\x62\\x44\\xa7\\x9c\\xc5\\x94\\xc0\\xe8\\x9a\\xef\\x32\\x5c\\xb9\\x8b\\x13\\x16\\xb9\\x38\\x75\\x69\\x8b\\x23\\x17\\xb4\\x18\\xae\\x8c\\xc5\\x20\\xc5\\x2b\\xba\\x24\\x96\\xc5\\x17\\xaa\\x88\\x49\\x28\\xeb\\xfa\\x71\\x1d\\xbd\\x14\\x45\\x2f\\x05\\x28\\x7a\\x2e\\x3b\\xd1\\x5f\\xb1\\x89\\x08\\x81\\x19\\x5e\\x8f\\xe0\\xe0\\x2a\\x04\\xf1\\xcd\\x45\\xe2\\xdd\\x10\\xc7\\x42\\x5b\\xca\\xa7\\xef\\x45\\x97\\x5c\\x79\\x41\\xd7\\xb3\\xe0\\x95\\xf4\\x3a\\x12\\x28\\xae\\xc5\\xd2\\x00\\x31\\xc9\\x01\\x40\\x02\\x8a\\x80\\x60\\xe0\\xe9\\xbc\\x45\\x3b\\xd8\\x87\\x27\\x7e\\x9d\\x6e\\x79\\xf9\\x8b\\xcb\\xa7\\x71\\xee\\xbf\\x78\\xcf\\xfb\\xf3\\x9e\\xf7\\x1f\\x8b\\xff\\xdc\\xbc\\xb3\\xe9\\x8b\\x77\\x36\\xda\\x3b\\x2b\\x2b\\xa5\\x8f\\x1d\\xae\\x6a\\x04\\x9f\\xd1\\xfd\\xf8\\xcc\\x6f\\xa9\\x53\\xca\\x83\\xcb\\xdb\\x49\\xc0\\x7b\\x12\\x41\\x4c\\xf1\\x0a\\x9c\\xc9\\x8b\\x7d\\x4a\\xa1\\x73\\x54\\x59\\x65\\xd3\\x29\\x83\\x58\\x29\\xb2\\x5c\\x05\\xd5\\x01\\x7f\\x71\\xce\\xbe\\x38\\x67\\xbb\\x39\\x67\\x87\\xf6\\xf2\\x2c\\xf2\\x25\\x66\\x23\\x2d\\x90\\x8c\\x0f\\xb7\\x12\\x3c\\xb3\\x75\\xcc\\x5e\\x20\\x2b\\x58\\x02\\xb9\\x14\\xd2\\x8c\\x4d\\xe2\\x77\\xce\\xe8\\x7f\\x73\\x52\\xa2\\x20\\x85\\x36\\x73\\x24\\x0f\\x99\\x79\\xf6\\x71\\x09\\x08\\xca\\xd8\\x96\\xa0\\x4a\\xf8\\x4e\\xe2\\x9c\\x5d\\x73\\x41\\x4c\\x27\\x71\\x42\\x89\\x68\\x5e\\x53\\x01\\xf6\\xd4\\x82\\x80\\x66\\x78\\xbb\\xa5\\x19\\x56\\xac\\x56\\x6b\\x8e\\xe2\\x2c\\xe3\\x9b\\x50\\x6c\\xd4\\xd7\\x97\\x34\\x23\\xe8\\xf5\\xd8\\x6a\\x2c\\x33\\x82\\x96\\x54\\x08\\x2e\\xac\\xb7\\xce\\x5f\\x12\\x04\\x53\\x69\\xbb\\x97\\x08\\xb0\\x17\\x21\\x9c\\x25\\x44\\x6c\\x4c\\x89\\xb2\\x5c\\x65\\xb8\\x52\\x71\\x84\\x19\\xa4\\xc7\\xea\\x7f\\xbb\\xb8\\x73\\xb3\\x5c\\x27\\x96\\x67\\x64\\x81\\xd7\\x94\\xe7\\x41\\x29\\x4c\\x53\\x38\\x38\\xce\\xec\\x60\\xa3\\x4e\\x3c\\xf1\\xbc\\xf0\\x4b\\xe4\\x26\\x2b\\xae\\xa0\\xa1\\xdc\\xdd\\xaf\\x80\\x97\\x7c\\x29\\x87\\x1b\\xb3\\x3e\\xe5\\x0e\\x74\\x1d\\x91\\x1f\\x54\\xaa\\x5d\\x8a\\xb9\\xad\\x72\\x1d\\x4a\\xfa\\xfa\\x0c\\xd6\\x72\\xa5\\xd5\\x88\\xef\\x01\\xb9\\xcd\\xd5\\xbc\\x66\\x7f\\x5c\\x55\\xdb\\x5e\\x4f\\xcd\\x4f\\x6d\\xba\\xb6\\xad\\xfb\\x03\\xc5\\x07\\x82\\x52\\x0c\\x8f\\x10\\x4c\\x0b\\x73\\x6c\\xed\\x79\\xf6\\xbc\\x14\\xf8\\x17\\xe5\\xbd\\xfc\\xaf\\x4b\\x98\\x4a\\x46\\x93\\xa7\\xc9\\x75\\xd7\\x50\\x15\\x18\\xed\\x8e\\x43\\x59\\x84\\xa9\\xe8\\xeb\\xe8\\x3d\\x96\\x24\\x45\\x9f\\x31\\xc3\\x73\\x80\\x60\\x5e\\x4f\\x6f\\xdf\\x7f\\x7e\\xa3\\x19\\xc8\\x40\\x46\\x93\\xeb\\xbd\\xb1\\x2c\\x53\\xff\\xe1\\x5f\\xfa\\x4c\\xf5\\xdf\\x59\\x78\\x07\\x4d\\x61\\x67\\x7c\\xc7\\xc5\\xf7\\x5a\\xc3\\x00\\x15\\x87\\x6b\\x58\\xaf\\xbc\\x3d\\x55\\x19\\x6e\\xb7\\xcb\\x45\\x41\\xa0\\x89\\xab\\x53\\x27\\xb7\\x25\\xd9\\x7a\\x99\\x3e\\x1e\\x36\\x7d\\xca\\xa4\\xc2\\x59\\x76\\x9b\\x61\\x76\\xb9\\x5a\\x09\\xbe\\xde\\x0f\\x7c\\x85\\x08\\x07\\x37\\xde\\x2d\\x00\\x42\\x4f\\xdd\\xc5\\x15\\xec\\x88\\x09\\x2f\\x63\\x68\\x52\\xbe\\x76\\x3f\\xfd\\x27\\xaa\\xc0\\xc6\\x38\\x33\\x0a\\xc9\\xd9\\x65\\xae\\xf8\\x12\\x2b\\x9a\\x9c\\x21\\x2e\\xd0\\xd9\\x67\\xcc\\x72\\x9c\\xed\\x0d\\x44\\x6f\\x5c\\x71\\x9d\\xf5\\xd1\\x38\\xa8\\xbe\\x09\\x49\\xc0\\xb0\\x46\\x75\\xae\\x79\\xbc\\xc2\\x42\\x8b\\xba\\xab\\xe9\\xf7\\xa8\\xb1\\x52\\x61\\x95\\xef\\x9c\\x0c\\x0d\\xa7\\x55\\xfd\\xf9\\x34\\x42\\x19\\x96\\xea\\x7e\\x95\\x6a\\xf9\\xb0\\xf5\\x6b\\xd3\\x21\\x94\\x60\\x85\\x33\\x3e\\xff\\x9d\\xe0\\x6c\\xff\\xc7\\x10\\xc2\\x52\\x57\\xfe\\x43\\x1c\\xaa\\x6c\\xa3\\xf2\\xf2\\x59\\x31\\xfe\\x95\\x44\\xda\\x08\\xd3\\x5c\\x42\\x95\\x44\\x82\\x64\\x64\\x8d\\x99\\x72\\xc3\\xa7\\xd0\\x58\\xe8\\x95\\x25\\x4b\\x2d\\xc3\\xd1\\xd2\\x4f\\x95\\x12\\x45\\xc4\\x92\\xb2\\xea\\x7b\\xa6\\x66\\xfc\\x15\\x67\\x29\\x05\\x0f\\x88\\x41\\xe2\\x61\\x44\\xf5\\x5d\\xf5\\x5c\\x59\\xe7\\xbe\\x6d\\x70\\xd8\\x56\\x5b\\x2a\\x79\\xf3\\xa9\\x92\\x07\\x6e\\x9b\\x59\\x45\\x7e\\x01\\x17\\x4d\\xf4\\x5b\\x65\\x6e\\x3b\\xd4\\x43\\x8f\\x4c\\xeb\\xd7\\xa6\\xec\\xeb\\x7e\\xda\\xb4\\xaa\\x39\\x6d\\xea\\xcd\\xc8\\xb1\\x03\\x4c\\xa1\\x3e\\x05\\x68\\x64\\xe7\\x5d\\xe7\\xd8\\x6d\\xe2\\x46\\xf8\\xaf\\x5d\\x31\\xda\\x9e\\x4a\\xbd\\xa4\\xae\\x10\\xfe\\x6a\\x6b\\x18\\xe4\\xc8\\x17\\xf1\\x21\\xe0\\x29\\xaf\\xdc\\x54\\x7f\\xb2\\x04\\xe9\\x8d\\x61\\x2a\\x5e\\x68\\xab\\xda\\xca\\x5a\\xbc\\xc6\\xaa\\x71\\x40\\x49\\xe0\\x51\\x18\\xd8\\x31\\x36\\x4e\\xe5\\x9c\\xd8\\x94\\x07\\x61\\xed\\x39\\x8c\\x56\\x94\\x40\\xc1\\x59\\xcc\\x2c\\x31\\xcd\\x79\\x46\\x70\\x6a\\x2f\\xea\\x73\\x53\\x1b\\xf0\\xe6\\xb7\\x73\\x1b\\xb5\\x15\\xa4\\xa0\\x40\\xec\\xa3\\xf3\\x63\\x61\\xa8\\x83\\x6a\\x3c\\xba\\xe3\\x8f\\xdc\\xfa\\x78\\x6c\\x55\\x28\\x2d\\x55\\x8c\\x76\\x71\\x8e\\x64\\x9e\\x2c\\x10\\x96\\x7a\\x61\\xfa\\x73\\xd0\\xf2\\x82\\x5c\\x2c\\x31\\xa3\\x0f\\x44\\xaa\\x8b\\xa2\\xb1\\x9c\\xfc\\xf3\\xed\\x5f\\x6d\\x6a\\xc7\\x07\\x2e\\x90\\xcd\\x66\\x3c\\x77\\xe5\\x3c\\xed\\x1a\\x4b\\x9e\\xa3\\x12\\x08\\x51\\x3c\\xb9\\xc4\\x27\\x56\\x3c\\xb5\\x0b\\xde\\x98\\xa5\\x28\\xfc\\xa8\\x8f\\x52\\x58\\x4a\\x4e\\x8c\\xe7\\xb5\\x4d\\x47\\x39\\xd3\\x6a\\xaf\\x37\\xed\\xbf\\xf5\\xd9\\xf9\\xcf\\x19\\x7a\\xbd\\x31\\x4a\\xc8\\x99\\xfe\\xf3\\x0c\\xa6\\x53\\xe4\\xa0\\xf8\\xf0\\x4b\\x39\\x2d\\xa8\\x9a\\x23\\xe8\\x7c\\x4e\\x44\\xab\\x9b\\xcb\\xb4\\x85\\x5b\\x13\\xa6\\xde\\xd8\\x52\\xa6\\x8c\\x7b\\x8f\\x72\\xb1\\x52\\x25\\x9a\\xb0\\x3d\\xcd\\x3f\\xdf\\xfe\\x75\\x86\\x5e\\x57\\x69\\xd2\\xf2\\x4a\\xca\\x52\\xf2\\x03\\xbd\\x05\\x87\\x15\\x95\\x9a\\x7a\\x6f\\x2e\\x00\\x7e\\x90\\x4f\\x4c\\xe1\\x1f\\xfa\\x8d\\xc9\\x82\\x4b\\xc2\\x00\\x0e\\x52\\x1c\\x2d\\xf0\\x9a\\x20\\xc9\\x97\\x04\\x6d\\x48\\x96\\x8d\\xac\\x0b\\x0f\\x6d\\xf0\\x53\\x7b\\x05\\x57\\xb7\\x85\\xa6\\xda\\x1d\\x5a\\x61\\xa1\\x2a\\x6c\\xdc\\xc6\\x1c\\x80\\x12\\x9a\\x99\\x6a\\x56\\x9b\\x33\\x17\\x24\\xf5\\x40\\x99\\x0d\\x46\\xb0\\x61\\x15\\x9a\\x4f\\x4d\\x65\\x22\\x60\\x1d\\xc5\\x51\\xb2\\xc0\\x6c\\x5e\\xd4\\x81\\x7b\\xc8\\x55\\x2e\\x5a\\x74\\xe0\\xc0\\x8f\\xfe\\x91\\xb2\\x5e\\x8b\\x78\\xfd\\x41\\xd9\\x76\\x18\\x5e\\x2b\\x61\\xf6\\xc0\\xb7\\x73\\xaa\\x5c\\x36\\xb0\\x4d\\xed\\x50\\x4f\\x63\\xcd\\x1c\\x82\\xce\\x72\\xc5\\x85\\x1c\\xa7\\x64\\x4d\\xb2\\xb1\\xa4\\xf3\\x11\\x16\\xc9\\x82\\x2a\\x92\\x68\\x9a\\x8c\\xf1\\x8a\\x8e\\x12\\xce\\x34\\x23\\x9a\\x72\\x8f\\xcb\\xf4\\x57\\x4d\\x09\\x39\\xd2\\x0b\\x6d\\xc6\\x73\\x03\\x29\\xd6\\x0e\\x84\\xc7\\x51\\xac\\x0b\\xf0\\x7d\\x1a\\xc0\\x3b\\x82\\x40\\x01\\x40\\x68\\x3c\\x95\\x00\\x6d\\x3c\\x39\\xa9\\x0c\\xe0\\x36\\xee\\x83\\x52\\xae\\xa3\\x61\\xbc\\x2e\\xd0\\x4a\\x2f\\xdb\\xc4\\x33\\xd9\\x7e\\x87\\x16\\x26\\x10\\xa1\\x69\\x64\\x4d\\xe5\\x54\\x5a\\xe2\\x14\\x8e\\x2d\\xcc\\x5a\\x33\\x6e\\x8f\\xfc\\xcd\\xea\\xfd\\x30\\x8d\\x70\\x93\\xa7\\x91\\x79\\x04\\xcf\\x46\\x98\\xa5\\xfa\\xdf\\x90\\x60\\x9f\\x34\\x47\\x11\\x06\\x6e\\x40\\x4e\\x7b\\x15\\x7e\\xf7\\x93\\xeb\\xd3\\xb3\\xe7\\xf8\\xd7\\x9c\\xf6\\x21\\xe9\\xba\\x78\\x93\\xac\\x1d\\x10\\xa8\\x9c\\x83\\x09\\x04\\x51\\x95\\x22\\x27\\x4e\\x61\\xaa\\x1a\\x3e\\x54\\xba\\xa7\\xfe\\xdb\\xba\\xb1\\x8b\\x6e\\x03\\x6d\\xaa\\x7a\\xb3\\x6b\\xd9\\xb3\\x49\\x02\\xe7\\xfb\\xa9\\x1c\\xe1\\x43\\xd5\\x26\\x5a\\x1b\\x4b\\x65\\xeb\\xb9\\xbb\\x52\\x83\\x95\\x65\\x38\\x63\\xd8\\x1c\\xe3\\xf5\\xaa\\x54\\xd0\\xc6\\xb8\\x58\\x37\\x3d\\x91\\xd1\\xde\\x0a\\xdb\\x49\\x61\\xec\\xb6\\xda\\xf0\\x9e\\x5d\\x6c\\x4c\\xa3\\x8c\\xca\\xa2\\xa6\\xb9\\x36\\x93\\xa5\\x42\\x78\\x8d\\x69\\x66\\xbc\\x74\\x7c\\x26\\x89\\x58\\x63\\xb8\\x1d\\x3a\\x8e\\xe0\\x6d\\x9b\\xde\\xf6\\xaf\\x06\\x05\\x7b\\x20\\x8b\\xda\\xad\\x61\\x77\\x57\\x9a\\x16\\x60\\xac\\xec\\xad\\xd9\\xd7\\xce\\xba\\x17\\x7b\\x1a\\xa0\\x8c\\xda\\x9f\\xf5\\x1b\\x3a\\x9a\\xc7\\x9a\\xff\\x7e\\x27\\x58\\xa8\\x19\\xc1\\xea\\x8e\\x36\\x69\\x28\\x3b\\x2c\\x5d\\x19\\xe7\\x70\\xc0\\x92\\xa1\\x37\\x04\\xcd\\xb9\\xd2\\x6a\\x6e\\x6e\\x78\\x1f\\xec\\x11\\x28\\x53\\x5c\\x30\\xda\\xb1\\x39\\xba\\x5c\\xe5\\x9d\\xc0\\x26\\xd7\\x9d\\xb3\\xc8\\x65\\x56\\x07\\xee\\xae\\xd3\\xda\\x3e\\x96\\x93\\x14\\xdc\\x0d\\x95\\x2c\\x39\\x23\\x76\\xef\\xc0\\x51\\xd8\\x9c\\x96\\xdf\\xeb\\x92\\x97\\x44\\xca\\xc6\\x12\\x97\\xd5\\x54\\x00\\xb8\\x1b\\x3e\\xe5\\x2d\\x17\\xfb\\xd2\\xfd\\x06\\x99\\xc4\\xda\\x88\\x49\\x89\\xc2\\x34\\x73\\x9f\\x32\\x90\\xa2\\xa0\\x52\\x9b\\x74\\x6d\\x5c\\xa0\\x20\\x58\\x36\\x29\\x34\\x95\\x59\\x7f\\x33\\x37\\xc3\\xa4\\x39\\x23\\xa3\\x0d\\x17\\x29\\xba\\xc2\\x4b\\x92\\x5d\\x61\\x49\\xec\\xb3\\xfc\\xca\\x19\\xb0\\x47\\xaf\\x64\\xaf\\x53\\xde\\x0f\\xbf\\xd6\\x4c\\x19\\x40\\xc5\\xd2\\x81\\x61\\xfe\\x2a\\x0d\\x68\\x98\\xe0\\xb9\\x43\\xc1\\xef\\x44\\x4e\\xce\\xd1\\x07\\x7d\\x7a\\x9d\\xa3\\x7b\\xf6\\xc8\\xf8\\xe6\\xb0\\xb9\\xaa\\x46\\xe7\\x60\\x65\\xa6\\x7e\\xb8\\x9e\\xab\\xaf\\x5b\\x01\\x12\\x8b\\xe9\\x76\\x9c\\x91\\x15\\xf8\\x35\\x68\\x77\\xf5\\xb0\\x29\\x6e\\x75\\x33\\xd2\\xff\\xdc\\x81\\x36\\xb5\\x29\\x2f\\xf8\\x5c\\x10\\x09\\xa5\\x63\\xf7\\x06\\x44\\x87\\x3a\\x48\\x3e\\x12\\x66\\xab\\x5c\\xb4\\x4e\\x6f\\xb2\\x6f\\x94\\x9b\\xa9\\x3b\\xd7\\xe6\\xe5\\x2f\\x76\\xbf\\xed\\xcb\\x56\\xd9\\x5e\\x55\\xa3\\x39\\x9a\\xdd\\x9b\\x68\\x0d\\xa8\\x59\\x37\\xc3\\xfd\\x60\\xa6\\x77\\xea\\x79\\xf7\\x82\\x52\\xd2\\x84\\xc4\\xbb\\xd5\\x5d\\x4d\\xbf\\xd7\\x13\\xbb\\xf6\\xec\\x6b\\x3b\\x9f\\xda\\xe1\\xce\\x43\\x81\\xce\\xd6\\x6f\\xa6\\x15\\xdc\\x0c\\xd5\\xf4\\x87\\x01\\x34\\x4f\\x09\\x65\\x9e\\x16\\xc4\\x1c\\x1c\\xbe\\x1c\\x14\\xb8\\x1c\\x0e\\xb2\\xec\\x0c\\x56\\x0e\\x05\\x53\\xb6\\x7e\\xb2\\x4d\\xd0\\x64\\xe8\\xd7\\x1a\\x07\\x47\\x9e\\x1c\\x88\\x6c\\xa5\\x49\\x13\\xf8\\x18\\x4a\\x93\\x38\\xc0\\x71\\x68\\xa8\\x31\\x88\\x04\\x8d\\xf0\\x62\\x0c\\x1d\\x22\\x21\\xc5\\x81\\xc1\\xc4\\x56\\x5a\\x04\\x02\\x88\\xa1\\x14\\x39\\x1e\\x68\\xf8\\x6c\\xe1\\xc2\\x56\\x12\\x37\\x40\\x84\\xa1\\x64\\x8d\\x82\\x05\\x07\\x06\\x04\\x5b\\xd6\\x1f\\x07\\x02\\x5a\\x6d\\x96\\xa4\\x21\\xc6\\xc0\\xc4\\xbb\\xd9\\x37\\x07\\xac\\x2a\\x6a\\x42\\xfb\\xec\\x1d\\x2e\\x94\\xd0\\x57\\x5a\\xbb\\xda\\x04\\x5a\\x4d\\xef\\x1a\\xd9\\x62\\xa7\\x1c\\xae\\x77\\x5b\\x63\\x81\\xa4\\x85\\xf5\\xda\\xb6\\x04\\x84\\xae\\x6f\\x6e\\xbf\\xdd\\x5c\\x5d\\xde\\xdd\\x5c\\x6f\\xeb\\xfb\\xf1\\x8a\\x79\\x33\\x24\\x35\\xf2\\x14\\xf3\\x9a\\x1b\\xf4\\x61\\x55\\xf3\\x93\\xe6\\xad\\x9a\\x9f\\xf2\\x9c\\xee\\x1b\\x75\\xb8\\x99\\x70\\x90\\xce\\x70\\xd0\\xe1\\xda\\x2e\\x27\\x7a\\x12\\x14\\x86\\xb7\\x20\\x1e\\x57\\xeb\\xaf\\x0b\\x9e\\xa5\\xd2\\xe5\\x31\\x4c\\xae\\x8b\\x34\\x75\\xca\\x92\\x2c\\x4f\\xb5\\x72\\x77\\x7f\\x3f\\xb9\\x96\\x17\\x08\\xbd\\x27\\x09\\xce\\xa5\\x56\\x12\\xeb\\x81\\x01\\xce\\x5e\\x29\\xf4\\xf5\\xcb\\xa7\\xff\\x98\\x8c\\x26\\x33\\xf2\\xbc\\x28\\x11\\x69\\x1a\\x48\\x51\\x0c\\x3d\\xb0\\xcc\\x42\\xcd\\x53\\x41\\x81\\x34\\x33\\x4a\\xf0\\x4a\\x4b\\xe0\\x7a\\xe7\\x02\\x85\\xda\\x26\\x5a\\x47\\x5c\\x90\\x6c\\xa5\\x4f\\x87\\x47\\x82\\xca\\x16\\x3c\\xfa\\x85\\xe6\\x57\\xc8\\xd3\\xb0\\xf1\\xea\\x73\\xa2\\x20\\x65\\xbd\\x29\\x24\\xbd\\x71\\x03\\x5a\\xb0\\xfc\\x03\\x50\\xfc\\x0a\\x30\\x61\\x71\\x9e\\x0d\\x96\\x16\\x0b\\xdd\\x3b\\xdb\\x16\\x56\\x69\\x47\\xfe\\xea\\xc1\\xb3\\x1a\\xd8\\x0c\\x4e\\x16\\xf3\\xd7\\xce\\x9c\\xf5\\x64\\x4b\\x84\\x0c\\xc2\\xde\\xa8\\x0a\\xc6\\xe9\\xeb\\x63\\x1c\\xf7\\xf7\\x13\\xdd\\x41\\xc9\\xc8\\x36\\x91\\x2b\\x2f\\x2e\\x72\\x7e\\xbc\\x29\\x87\\xcd\\xc5\\xb4\\x7c\\x4e\\xdf\\x19\\xcf\\x91\\xbb\\x04\\x71\\xc4\\xd5\\x6b\\xf9\\xcc\\x29\\x33\\x9e\\xd4\\xb1\\x58\\x1f\\xfa\\xfb\\x9f\\x5f\\x7e\\xf9\\x5f\\x00\\x00\\x00\\xff\\xff\\xd6\\x7d\\x4d\\xf0\\x1f\\xcd\\x10\\x00\")\n\nfunc olmManifests0280CrdsYamlBytes() ([]byte, error) {\n\treturn bindataRead(\n\t\t_olmManifests0280CrdsYaml,\n\t\t\"olm-manifests/0.28.0-crds.yaml\",\n\t)\n}\n\nfunc olmManifests0280CrdsYaml() (*asset, error) {\n\tbytes, err := olmManifests0280CrdsYamlBytes()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tinfo := bindataFileInfo{name: \"olm-manifests/0.28.0-crds.yaml\", size: 1101087, mode: os.FileMode(420), modTime: time.Unix(1730300880, 0)}\n\ta := &asset{bytes: bytes, info: info}\n\treturn a, nil\n}\n\nvar _olmManifests0280OlmYaml = []byte(\"\\x1f\\x8b\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xec\\x5a\\x6d\\x6f\\x1b\\xb9\\xf1\\x7f\\xaf\\x4f\\x31\\x10\\xfe\\x80\\xff\\x2d\\xb2\\x7a\\xb0\\x9d\\x44\\x5d\\x20\\xc0\\xb9\\x4e\\xee\\x72\\xa8\\xed\\x08\\xb6\\xd3\\x37\\x87\\xa0\\xa0\\xb8\\xa3\\x15\\x6b\\x3e\\xec\\x91\\x5c\\x29\\xba\\xa2\\xdf\\xbd\\xe0\\x72\\x9f\\x45\\xc9\\xb2\\x93\\xbb\\x14\\x45\\xf8\\x46\\x12\\x39\\xe4\\x0c\\x67\\x66\\xe7\\xe1\\xa7\\x8d\\xa2\\x68\\x40\\x32\\xf6\\x77\\xd4\\x86\\x29\\x19\\xc3\\x7a\\x3a\\x78\\x60\\x32\\x89\\xe1\\x86\\x08\\x34\\x19\\xa1\\x38\\x10\\x68\\x49\\x42\\x2c\\x89\\x07\\x00\\x92\\x08\\x8c\\x41\\x71\\x31\\x00\\xe0\\x64\\x81\\xdc\\xb8\\x59\\x80\\x4c\\x25\\x91\\x41\\x9a\\x6b\\x66\\xb7\\xa3\\x87\\x7c\\x81\\x5a\\xa2\\x45\\x33\\x62\\x6a\\x8c\\x72\\xa9\\x34\\xc5\\x18\\x34\\x1a\\xab\\x19\\xb5\\x98\\x1c\\xb9\\x25\\x5a\\x57\\x52\\x71\\x62\\xd1\\xd8\\xc7\\xb6\\x91\\x3c\\x61\\xf6\\x29\\x7c\\x8a\\x0d\\x4f\\xe5\\xb2\\x21\\x5a\\x3e\\x85\\x89\\xa3\\xdf\\xe1\\xf1\\x3c\\xb5\\x67\\xa8\\x89\\x55\\xda\\x3c\\x43\\xf9\\x0b\\x62\\x90\\x33\\x89\\xdf\\x55\\xef\\x54\\xef\\x75\\x7d\\x87\\x7a\\xcd\\x28\\x5e\\x50\\xaa\\x72\\x69\\xfb\\xf6\\x08\\xba\\x7d\\x54\\xd9\\x20\\x32\\x7e\\x33\\x29\\x37\\x7b\\x9a\\xc2\\x72\\xfe\\xf9\\xe8\\x5b\\x58\\x2f\\x08\\x1d\\x91\\xdc\\xae\\x94\\x66\\xbf\\x11\\xcb\\x94\\x1c\\x3d\\xcc\\x0a\\x29\\x6b\\xdb\\x5f\\xf2\\xdc\\x58\\xd4\\xb7\\x8a\\x87\\xac\\x6f\\xb6\\xc6\\xa2\\x88\\xa9\\x92\\x56\\x2b\\xce\\x51\\xc7\\xb5\\x2c\\x9c\\x2d\\x91\\x6e\\x29\\xc7\\x48\\x10\\x49\\x52\\xd4\\x03\\x9d\\x73\\x34\\xf1\\x20\\x02\\x92\\xb1\\x9f\\xb4\\xca\\x33\\x13\\xc3\\x2f\\xc3\\x3f\\x0f\\x3f\\x0d\\xc0\\xe9\\x4f\\xe5\\x9a\\x62\\x6b\\x6a\\x8d\\x7a\\x51\\xfc\\xdc\\x10\\x4b\\x57\\xc3\\x17\\x30\\xe4\\xcc\\x58\\xf7\\x99\\x62\\xf1\\x41\\x35\\x12\\x8b\\xee\\x5b\\x9e\\x25\\xe5\\xb7\\xac\\xa2\\x4d\\x90\\xa3\\x9f\\xf2\\xdf\\xa8\\x13\\x8f\\xba\\x2b\\xba\\x39\\x34\\x94\\xf0\\x72\\xcb\\x82\\xc9\\x64\\xf8\\x69\\x10\\x81\\x54\\xf2\\xb6\\x14\\xe3\\xe3\\xed\\x55\\x48\\x12\\xf7\\xf3\\xcb\\x74\\xf8\\x57\\x26\\x13\\x26\\xd3\\xc7\\x0c\\xb9\\xf0\\x64\\x91\\x33\\x9a\\x56\\x1c\\x6f\\x71\\xe9\\x28\\x2b\\xc5\\x1d\\xe0\\x3a\\x00\\xd8\\x35\\xdc\\xb3\\xcc\\x65\\xf2\\xc5\\x3f\\x91\\xda\\xc2\\x62\\x41\\xdf\\xfc\\x2a\\x2e\\x58\\xc7\\x8f\\x11\\x55\\x1a\\x95\\xfb\\x10\\x8d\\xe6\\x3e\\x5c\\x5d\\x5f\\x2a\\xb9\\x64\\x21\\x85\\x51\\x7f\\xc1\\x9d\\x13\\x49\\x96\\x99\\xe6\\x84\\xb7\\x98\\x71\\xb5\\x15\\x28\\xed\\x23\\x3a\\xdf\\x15\\xb5\\x1b\\xd0\\x48\\x96\\xf5\\x36\\x98\\x0c\\xa9\\x5b\\x33\\x56\\x13\\x8b\\xe9\\xd6\\xd3\\xd9\\x6d\\x86\\x31\\xdc\\xa2\\xf7\\xce\\xc2\\xb5\\x33\\xce\\x28\\x31\\x31\\x4c\\x1d\\x31\\x3a\\x37\\x54\\xda\\x13\\x0b\\xe7\\xae\\x57\\x2d\\x2e\\x21\\x3e\\x00\\x16\\x45\\xe6\\xdc\\xb5\\xdc\\xd4\\xba\\x87\\x1b\\xbc\\xb3\\x3f\\x7c\\x02\\x40\\x25\\x6d\\xf1\\xbd\\x0c\\x4d\\x97\\x4a\\x5a\\xfc\\x6c\\x9b\\xad\\x3a\\x97\\x17\\xe6\\x46\\xc9\\x5b\\xa5\\x6c\\x0c\\x56\\xe7\\x58\\x2f\\x19\\xa4\\x54\\x89\\x6c\\xae\\xd5\\x92\\x71\\x6c\\xb6\\xd4\\x37\\xce\\xa5\\x65\\x02\\xdf\\xe2\\x92\\xe4\\xdc\\xd6\\x8c\\xda\\x1e\\x73\\x73\\x84\\xbb\\xb8\\xe1\\xfc\\x93\\x30\\x89\\xba\\x75\\xa9\\x28\\x6c\\xb2\\x96\\x74\\xe1\\x1b\\x15\\x0a\\xe1\\x5c\\x6d\\xe6\\x9a\\xad\\x19\\xc7\\x14\\xdf\\xf9\\x67\\xbf\\xf0\\x95\\x25\\xe1\\x06\\x3b\\xb4\\x94\\x64\\x64\\xc1\\x38\\xb3\\x0c\\x4d\\xf7\\x14\\x80\\x44\\xab\\x2c\\x86\\x5f\\x60\\x78\\x71\\x75\\x35\\x84\\x4f\\xad\\x55\\xaa\\x84\\x20\\x32\\x69\\x6f\\x88\\x60\\xbc\\x60\\x72\\xec\\x1d\\xa9\\x96\\x44\\xa7\\xa6\\x4b\\x14\\x45\\xb5\\xd7\\x75\\xe6\\xff\\xef\\xff\\x3f\\xcc\\xdf\\xdd\\x5e\\xdc\\x7f\\xb8\\xfd\\xc7\\xcd\\xc5\\xf5\\xbb\\xbb\\xf9\\xc5\\xe5\\xbb\\x3f\\xf5\\x76\\x6e\\x34\\xb3\\x78\\x67\\x89\\xcd\\x8d\\x53\\x6d\\x67\\x75\\x38\\x6c\\xfd\\x64\\x82\\xa4\\x18\\xc3\\xaf\\x39\\xd9\\xba\\xc0\\x54\\x6b\\x7f\\xa9\\x89\\xc0\\x8d\\xd2\\x0f\\x4e\\xcc\\x1f\\xcc\\x8a\\x9c\\xbe\\x7c\\x15\\x9f\\x4f\\x92\\xc9\\xd9\\xab\\xb3\\xe5\\x39\\x21\\xaf\\x66\\xe7\\x67\\xd3\\xbf\\xd0\\xe4\\xf5\\xe9\\x94\\x9e\\x2e\\xe9\\xf2\\xec\\xec\\x74\\xfa\\x7a\\xf6\\xf2\\x6c\\x36\\x59\\x26\\xf4\\xf5\\x79\\x82\\x33\\x5c\\xce\\x4e\\xa7\\x67\\xd3\\xd7\\x34\\x39\\x7d\\x49\\xa6\\x93\\xd7\\xb3\\x53\\xd2\\xe7\\x3b\\xcf\\x39\\x9f\\x2b\\xce\\xe8\\x36\\x86\\x9f\\x97\\x37\\xca\\xce\\x35\\x1a\\xac\\x8d\\x0d\\x45\\xba\\xd4\\xb6\\xa7\\xed\\xa8\\xf1\\x82\\xb9\\xd2\\x36\\x86\\xd9\\x64\\x36\\xe9\\xd9\\xc3\\x7b\\x84\\x40\\x97\\x79\\x4d\\x6b\\x8d\\xb3\\x35\\x4a\\x34\\x66\\xae\\xd5\\x02\\xbb\\xc7\\xae\\xac\\xcd\\x7e\\x42\\xdb\\xb7\\x6c\\x46\\xec\\x2a\\x86\\xf1\\x0a\\x09\\xb7\\xab\\xdf\\xfa\\x8b\\xfb\\xf8\\x1b\\xba\\x42\\x27\\xc1\\xfb\\xfb\\xfb\\x79\\x6b\\x49\\x23\\x49\\xd8\\x37\\xe4\\x6f\\x51\\x0b\\x26\\x0b\\x0f\\xbf\\x46\\x63\\x9c\\x09\\x4a\\xf5\\xff\\x48\\x38\\x5f\\x10\\xfa\\x70\\xaf\\xae\\x54\\x6a\\x3e\\xc8\\x77\\x5a\\x77\\x9e\\x22\\x94\\xeb\\xae\\x77\\x7a\\x0d\\xef\\x7a\\x62\\x47\\x90\\x35\\xe1\\x39\\xfe\\xa8\\x95\\xe8\\xdf\\x6a\\xc9\\x90\\x27\\x65\\xea\\x0a\\xac\\xcc\\x8b\\x4b\\x57\\xd1\\x6c\\x14\\x7e\\x0e\\x02\\x12\\xec\\x32\\xdf\\x1b\\x16\\x9a\\xb2\\xa2\\xb3\\x49\\xe3\\xaf\\x39\\x9a\\xbe\\xcb\\x01\\xd0\\x2c\\x8f\\x61\\x3a\\x11\\xbd\\x69\\x81\\x42\\xe9\\x6d\\x0c\\xd3\\x57\\x93\\x6b\\x56\\xae\\x49\\x95\\xe0\\x5d\\x27\\x96\\xbb\\xd1\\x2d\\xf5\\x94\\x89\\x81\\x33\\x99\\x7f\\xfe\\x92\\x1c\\x45\\x89\\x25\\x5c\\xa5\\x4f\\xcb\\x53\\x3b\\x9b\\x7e\\xc7\\x5c\\x15\\x10\\xf0\\x19\\xf9\\x2a\\x70\\xca\\xff\\x4c\\xce\\x0a\\xde\\xed\\x91\\x5b\\xc1\\x37\\xce\\x5b\\xa5\\xcc\\x07\\x73\\xd7\\x49\\x2b\\x79\\x9d\\x74\\x56\\xba\\x59\\xcf\\xe5\\x2a\\x5a\\x94\\x71\\x82\\x64\\xae\\x88\\x44\\xfd\\xb3\\xcb\\x0c\\x6f\\x0e\\x24\\xa4\\x9a\\xbe\\xd1\\xbb\\xc6\\x94\\x19\\xab\\xb7\\x71\\xab\\x31\\x6b\\x18\\xe4\\x96\\xf1\\xa8\\x48\\x38\\x9d\\x85\\x3f\\x3e\\xe9\\x39\\x61\\x0c\\xda\\xc8\\xb1\\xe0\\x8a\\x24\\x51\\x6e\\x50\\x47\\x2c\\x79\\xd3\\x71\\xcd\\xef\\x49\\xb9\\x19\\xdf\\x93\\xf2\\xa1\\xa4\\xfc\\x75\\x73\\xd8\\xec\\x4b\\x52\\xd8\\x6e\\x67\\x79\\x74\\x27\\xbc\\x9b\\xd8\\x48\\x9a\\x6a\\x4c\\x89\\x45\\xd7\\xe5\\x46\\x98\\x30\\xdb\\xcb\\x64\\xfb\\xcf\\x6b\\xb6\\x5a\\x15\\x91\\x44\\x30\\x19\\xc3\\xd0\\x3d\\x5e\\xc3\\xa7\\x6c\\xc4\\x02\\x1e\\x2a\\xf7\\x85\\xc1\\x89\\x50\\x77\\xba\\x8b\\x57\\x98\\x7c\\x61\\xa8\\x66\\x99\\xe3\\x64\\xba\\x88\\xc1\\x31\\x18\\xc5\\xa7\\xe7\\x71\\x2d\\xfb\\xdf\\x32\\x1b\\x95\\x88\\x92\\x29\\x80\\x11\\x1f\\xbb\\x4b\\x5a\\x37\\xc3\\xa4\\xb1\\x84\\xf3\\x8c\\x13\\x4f\\x71\\x40\\xe2\\x46\\xa8\\xdf\\xd7\\xe0\\x6b\\x86\\x9b\\x6f\\x69\\xf0\\x27\\xec\\x73\\xa2\\x7e\\x15\\x47\\xf9\\x7a\\x26\\x7b\\x01\\x35\\xcb\\xb4\\x10\\xa2\\x6b\\xc4\\x12\\x21\\xab\\x00\\x33\\x8f\\xa0\\xed\\xf8\\x59\\x46\\xe8\\x03\\x49\\xd1\\x8c\\x8e\\x93\\xbe\\x24\\x17\\x44\\xb2\\xa5\\x8b\\x3c\\xde\\x97\\xbb\\x73\\x63\\x46\\x95\\x3c\\x4e\\x96\\xa7\\x01\\x41\\xe5\\x6a\\x21\\x7c\\xc0\\xb7\\x52\\xae\\x16\\x84\\x47\\x6d\\x34\\xba\\x5d\\x25\\xd7\\xd3\\x5f\\x97\\x6b\\xbb\\x2c\\xec\\xb3\\xe4\\xa2\\x2e\\xba\\x2d\\xd1\\x29\\xda\\x1a\\x45\\x2f\\xbd\\x3d\\x7a\\x0a\\x1e\\x46\\x78\\xb6\\x22\\x3d\\x3c\\xb1\\x84\\xe3\\xca\\xad\\x01\\xf1\\x2a\\xfb\\x16\\x15\\xd7\\x63\\x7d\\x83\\xe2\\x62\\x54\\xc3\\xd2\\xeb\\xc9\\xe8\\x74\\x36\\x9a\\xd4\\x37\\x48\\x98\\xc9\\x38\\xd9\\xfa\\x62\\x78\\xee\\x8f\\x85\\xbb\\xea\\xdc\\x04\\x6b\\xcf\\x74\\xdd\\x44\\xe6\\x4b\\x09\\x03\\x44\\xd6\\x1a\\xac\\x64\\x01\\xbb\\x22\\x16\\x98\\x01\\xb2\\x26\\x8c\\x93\\x05\\x47\\x58\\x6a\\x25\\x80\\x40\\xea\\xea\\x03\\xb8\\xf4\\xcf\\xc1\\x5d\\xe1\\x75\\xb0\\x59\\x31\\xba\\x82\\x0d\\xe3\\xbc\\xf0\\x44\\xbe\\x46\\xb0\\x0a\\x48\\x58\\x01\\xa3\\x01\\x80\\x60\\xf2\\x6f\\xf9\\x02\\x6b\\x6d\\x4e\\x47\\xd3\\xe9\\xc8\\x65\\xe8\\x07\\xdc\\x6e\\x94\\x4e\\x9c\\x43\\x9e\\xf4\\x7d\\xf6\\xe4\\x05\\x9c\\x28\\x2e\\xdc\\x47\\xa5\\xb1\\x13\\xe7\\xc1\\x82\\xb0\\x76\\x4d\\x5f\\x55\\xf3\\xb7\\x98\\xc0\\x7b\\xe2\\x2b\\x25\\x14\\x84\\xf1\\xc2\\x68\\xd2\\xac\\xd8\\xd2\\x36\\xde\\xf0\\x83\\xc6\\x64\\x45\\xac\\x33\\xdf\\x00\\x20\\xd3\\x6a\\xcd\\x12\\x2c\\xd3\\x6c\\xff\\x1c\\xce\\xe4\\x43\\x87\\xc5\\x8e\\x86\\x01\\x72\\xcd\\xe3\\xa2\\x50\\x31\\xf1\\x78\\x9c\\x32\\xbb\\xca\\x17\\x85\\x6b\\x84\\xca\\xc6\\xbd\\x98\\xee\\xd8\\x6a\\xc4\\xb1\\x20\\x4e\\x79\\xe3\\xec\\x21\\x1d\\x97\\xf7\\x8d\\x6a\\x17\\x29\\xa3\\xce\\xb5\\x4a\\xb0\\x94\\xc8\\x77\\x4a\\x1f\\x36\\xf2\\xa6\\xd3\\x9f\\x9b\\x3c\\x73\\x25\\x10\\x26\\x75\\xcb\\x55\\x91\\xde\\x31\\x99\\x72\\x3c\\x96\\xfa\\x3a\\xe7\\x96\\x1d\\x4b\\x7c\\xc1\\x79\\xf3\\x14\\xed\\xa1\\x2d\\x6f\\xe0\\x35\\x5d\\xb7\\xbb\\x90\\x34\\x3d\\x36\\xf4\\x3a\\xcb\\x32\\x2a\\xcf\\x5d\\x85\\x66\\x8a\\x88\\x5c\\xad\\x44\\xcf\\x6c\\x06\\x5d\\x53\\xca\\xb1\\xd3\\x09\\x36\\x81\\xb7\\x57\\x51\\xef\\x01\\xf1\\x1f\\xa9\\xfe\\x22\\x28\\xe1\\x79\\x42\\x29\\x1a\\xa3\\xd1\\xe5\\xa8\\x76\\xb9\\xed\\xc3\\x6f\\xbf\\x7a\\xaf\\xfa\\xfc\\xf6\\x64\\x8a\\xf6\\x31\\x39\\x7b\\x70\\x62\\x50\\xa6\\xa2\\x37\\xf0\\x2d\\xdb\\x41\\x39\\xba\\x0c\\xdd\\x6f\\x97\\x19\\x3a\\x13\\x45\\x8a\\x38\\x42\\xa6\\x60\\xda\\x3a\\x42\\xce\\x4e\\xae\\xfd\\x83\\x64\\x3d\\x9c\\x6b\\x1f\\x17\\xba\\x1f\\xb4\\x9e\\x2d\\x76\\xf3\\x20\\xb4\\xdc\\x3c\\x9c\\x2f\\xfc\\x68\\x3f\\x2a\\x00\\x7d\\x08\\xa9\\x1a\\x25\\xa0\\xa2\\x38\\x67\\x32\\xfd\\x58\\xd4\\xba\\xdd\\x76\\xa5\\xbd\\xd2\\xef\\x59\\x04\\xf9\\xfc\\x51\\xd6\\x19\\xc1\\x83\\x4f\\xbd\\xf5\\xbb\\x5c\\xa7\\xbd\\x95\\x06\\xac\\x3a\\xed\\x20\\x2a\\xfd\\x8e\\x06\\xc2\\xe0\\x55\\x35\\x0a\\xf8\\x29\\x7c\\xf5\\x3e\\x92\\x55\\x9f\\xd6\\x43\\xb4\\xaa\\xd1\\x47\\xb6\\x8e\\x62\\xb1\\xab\\x61\\x78\\x0c\\x18\\x82\\xc3\\xb0\\x57\\xeb\\x8c\\x3d\\xf0\\x57\\x7d\\xbd\\xfd\\x30\\x58\\x73\\xc8\\xf3\\x22\\xa0\\x1f\\xe1\\x1e\\xb3\\x1a\\xfb\\x7a\\xcd\\x2e\\x55\\x08\\x5a\\xf3\\xe3\\xb0\\xe3\\x1e\\xad\\xca\\xa7\\x21\\x6d\\xa5\\x50\\x07\\xf0\\x36\\x3f\\xf6\\xa3\\x6e\\xd5\\xb5\\x76\\xb0\\xb7\\xea\\x56\\x05\\x02\\xb7\\x93\\x9b\\xfb\\x54\\xd1\\xfa\\xcd\\x79\\x68\\xda\\xbf\\x79\\x80\\x91\\x4b\\x8c\\x81\\xf5\\xe1\\xcb\\xf3\\xf3\\xb3\\x61\\x70\\x63\\x59\\x45\\x87\\x90\\xf8\\x8a\\xa8\\x8b\\xec\\xf9\\xf1\\xad\\x90\\xac\\x16\\xf7\\x36\\x9e\\x75\\xc1\\x37\\x64\\x6b\\x76\\xe8\\x02\\x78\\x16\\x84\\x30\\x2d\\xa7\\x9e\\x80\\x41\\x33\\xad\\xac\\xa2\\x8a\\xc7\\x70\\x7f\\x39\\xdf\\x59\\x3f\\x80\\x6e\\xf9\\xb1\\x07\\x63\\xf2\\xa3\\x8d\\x19\\xdd\\x05\\x29\\x0e\\x62\\x51\\xcd\\xfd\\xf6\\x48\\x7f\\x08\\xfc\\xfa\\x2f\\x10\\xef\\xf9\\xd8\\x58\\x75\\xbd\\x60\\x8d\\x54\\x2d\\x86\\x71\\x32\\x3f\\xf6\\xa0\\x65\\x7e\\x54\\x98\\xd9\\xcb\\x06\\x33\\x6b\\xc6\\x5a\\xf1\\x5c\\xe0\\xb5\\x8b\\x79\\x41\\xaf\\xf2\\x91\\xc9\\x8a\\x6c\\xb9\\xeb\\x8a\\x00\\xc2\\xed\\xf3\\x7f\\x80\\x8d\\xad\\xc8\\x06\\xa1\\xb3\\xf7\\x86\\xbb\\xf0\\xa1\\x28\\x32\\xbb\\x7d\\xcb\\x74\\x0c\\xff\\xfa\\x77\\xd1\\xbd\\xd8\\x22\\xea\\xc5\\x50\\xf4\\x8e\\xbe\\x23\\xef\\x76\\x77\\xc5\\x0b\\x25\\x65\\xf8\\x4e\\x70\\xc9\\x24\\xb3\\x4d\\xf5\\xab\\x36\\x12\\x93\\xaa\\x53\\x4d\\xfd\\x5b\\x27\\x07\\x8b\\x98\\x52\\xa0\\x75\\xeb\\x75\\x25\\x3f\\xe3\\x9b\\xd6\\xb2\\xa7\\xb9\\x2e\\x0b\\x98\\x0a\\x83\\x6c\\xc7\\xef\\x7e\\x71\\x13\\xea\\x3a\\x7b\\xfb\\x3b\\xad\\xe7\\x45\\x9f\\xa8\\x68\\x34\\x6b\\xf7\\x80\\x14\\xa5\\x13\\x1b\\x13\\xdf\\x73\\xe2\\x67\\x66\\x2c\\x93\\x69\\xb7\\xe9\\x74\\x6d\\x6b\\x02\\x76\\x85\\x4c\\x83\\x7f\\xf7\\xe4\\xba\\xa9\\x68\\x9b\\xe2\\xe9\\x66\\x6f\\xe2\\x09\\x85\\x93\\x67\\x75\\xf9\\x6d\\xa9\\x0e\\xbc\\x79\\xb7\\xca\\x17\\x4c\\x45\\xcd\\xff\\x35\\x7b\\x40\\x08\\xaf\\x83\\xfb\\x22\\xe1\\xa7\\x3a\\xa3\\x83\\xbd\\x71\\xbb\\x38\\xb0\\xfa\\x03\\xa8\\xf9\\xb3\\xa5\\x63\\x8d\\x4b\\x25\\x44\\x2e\\x99\\xdd\\xd6\\x1d\\xbe\\x53\\x51\\x96\\x2f\\x38\\x33\\x2b\\xd4\\x0d\\x74\\xf2\\x3e\\x5f\\xf8\\x86\\xc6\\xf1\\x9c\\xab\\xc4\\xab\\xb4\\xec\\xce\\xba\\x89\\xb9\\x5c\\xea\\xbe\\x4b\\xe7\\x61\\xd3\\xbb\\x4e\\xcd\\x59\\xfd\\x11\\x34\\x57\\x55\\x9f\\xe7\\xda\\x3e\\x8b\\x7a\\x4d\\x78\\x0c\\xaf\\x26\\x62\\xf0\\x9f\\x00\\x00\\x00\\xff\\xff\\x80\\xce\\x61\\xa0\\x42\\x2a\\x00\\x00\")\n\nfunc olmManifests0280OlmYamlBytes() ([]byte, error) {\n\treturn bindataRead(\n\t\t_olmManifests0280OlmYaml,\n\t\t\"olm-manifests/0.28.0-olm.yaml\",\n\t)\n}\n\nfunc olmManifests0280OlmYaml() (*asset, error) {\n\tbytes, err := olmManifests0280OlmYamlBytes()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tinfo := bindataFileInfo{name: \"olm-manifests/0.28.0-olm.yaml\", size: 10818, mode: os.FileMode(420), modTime: time.Unix(1730300879, 0)}\n\ta := &asset{bytes: bytes, info: info}\n\treturn a, nil\n}\n\n// Asset loads and returns the asset for the given name.\n// It returns an error if the asset could not be found or\n// could not be loaded.\nfunc Asset(name string) ([]byte, error) {\n\tcannonicalName := strings.Replace(name, \"\\\\\", \"/\", -1)\n\tif f, ok := _bindata[cannonicalName]; ok {\n\t\ta, err := f()\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"Asset %s can't read by error: %v\", name, err)\n\t\t}\n\t\treturn a.bytes, nil\n\t}\n\treturn nil, fmt.Errorf(\"Asset %s not found\", name)\n}\n\n// MustAsset is like Asset but panics when Asset would return an error.\n// It simplifies safe initialization of global variables.\nfunc MustAsset(name string) []byte {\n\ta, err := Asset(name)\n\tif err != nil {\n\t\tpanic(\"asset: Asset(\" + name + \"): \" + err.Error())\n\t}\n\n\treturn a\n}\n\n// AssetInfo loads and returns the asset info for the given name.\n// It returns an error if the asset could not be found or\n// could not be loaded.\nfunc AssetInfo(name string) (os.FileInfo, error) {\n\tcannonicalName := strings.Replace(name, \"\\\\\", \"/\", -1)\n\tif f, ok := _bindata[cannonicalName]; ok {\n\t\ta, err := f()\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"AssetInfo %s can't read by error: %v\", name, err)\n\t\t}\n\t\treturn a.info, nil\n\t}\n\treturn nil, fmt.Errorf(\"AssetInfo %s not found\", name)\n}\n\n// AssetNames returns the names of the assets.\nfunc AssetNames() []string {\n\tnames := make([]string, 0, len(_bindata))\n\tfor name := range _bindata {\n\t\tnames = append(names, name)\n\t}\n\treturn names\n}\n\n// _bindata is a table, holding each asset generator, mapped to its name.\nvar _bindata = map[string]func() (*asset, error){\n\t\"olm-manifests/0.26.0-crds.yaml\": olmManifests0260CrdsYaml,\n\t\"olm-manifests/0.26.0-olm.yaml\":  olmManifests0260OlmYaml,\n\t\"olm-manifests/0.27.0-crds.yaml\": olmManifests0270CrdsYaml,\n\t\"olm-manifests/0.27.0-olm.yaml\":  olmManifests0270OlmYaml,\n\t\"olm-manifests/0.28.0-crds.yaml\": olmManifests0280CrdsYaml,\n\t\"olm-manifests/0.28.0-olm.yaml\":  olmManifests0280OlmYaml,\n}\n\n// AssetDir returns the file names below a certain\n// directory embedded in the file by go-bindata.\n// For example if you run go-bindata on data/... and data contains the\n// following hierarchy:\n//\n//\tdata/\n//\t  foo.txt\n//\t  img/\n//\t    a.png\n//\t    b.png\n//\n// then AssetDir(\"data\") would return []string{\"foo.txt\", \"img\"}\n// AssetDir(\"data/img\") would return []string{\"a.png\", \"b.png\"}\n// AssetDir(\"foo.txt\") and AssetDir(\"notexist\") would return an error\n// AssetDir(\"\") will return []string{\"data\"}.\nfunc AssetDir(name string) ([]string, error) {\n\tnode := _bintree\n\tif len(name) != 0 {\n\t\tcannonicalName := strings.Replace(name, \"\\\\\", \"/\", -1)\n\t\tpathList := strings.SplitSeq(cannonicalName, \"/\")\n\t\tfor p := range pathList {\n\t\t\tnode = node.Children[p]\n\t\t\tif node == nil {\n\t\t\t\treturn nil, fmt.Errorf(\"Asset %s not found\", name)\n\t\t\t}\n\t\t}\n\t}\n\tif node.Func != nil {\n\t\treturn nil, fmt.Errorf(\"Asset %s not found\", name)\n\t}\n\trv := make([]string, 0, len(node.Children))\n\tfor childName := range node.Children {\n\t\trv = append(rv, childName)\n\t}\n\treturn rv, nil\n}\n\ntype bintree struct {\n\tFunc     func() (*asset, error)\n\tChildren map[string]*bintree\n}\n\nvar _bintree = &bintree{nil, map[string]*bintree{\n\t\"olm-manifests\": &bintree{nil, map[string]*bintree{\n\t\t\"0.26.0-crds.yaml\": &bintree{olmManifests0260CrdsYaml, map[string]*bintree{}},\n\t\t\"0.26.0-olm.yaml\":  &bintree{olmManifests0260OlmYaml, map[string]*bintree{}},\n\t\t\"0.27.0-crds.yaml\": &bintree{olmManifests0270CrdsYaml, map[string]*bintree{}},\n\t\t\"0.27.0-olm.yaml\":  &bintree{olmManifests0270OlmYaml, map[string]*bintree{}},\n\t\t\"0.28.0-crds.yaml\": &bintree{olmManifests0280CrdsYaml, map[string]*bintree{}},\n\t\t\"0.28.0-olm.yaml\":  &bintree{olmManifests0280OlmYaml, map[string]*bintree{}},\n\t}},\n}}\n\n// RestoreAsset restores an asset under the given directory\nfunc RestoreAsset(dir, name string) error {\n\tdata, err := Asset(name)\n\tif err != nil {\n\t\treturn err\n\t}\n\tinfo, err := AssetInfo(name)\n\tif err != nil {\n\t\treturn err\n\t}\n\terr = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755))\n\tif err != nil {\n\t\treturn err\n\t}\n\terr = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())\n\tif err != nil {\n\t\treturn err\n\t}\n\terr = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// RestoreAssets restores an asset under the given directory recursively\nfunc RestoreAssets(dir, name string) error {\n\tchildren, err := AssetDir(name)\n\t// File\n\tif err != nil {\n\t\treturn RestoreAsset(dir, name)\n\t}\n\t// Dir\n\tfor _, child := range children {\n\t\terr = RestoreAssets(dir, filepath.Join(name, child))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc _filePath(dir, name string) string {\n\tcannonicalName := strings.Replace(name, \"\\\\\", \"/\", -1)\n\treturn filepath.Join(append([]string{dir}, strings.Split(cannonicalName, \"/\")...)...)\n}\n"
  },
  {
    "path": "internal/bindata/olm/versions.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage olm\n\nvar availableVersions = map[string]struct{}{\n\t\"0.25.0\": {},\n\t\"0.26.0\": {},\n\t\"0.27.0\": {},\n}\n\n// HasVersion returns whether version maps to released OLM manifests as bindata.\nfunc HasVersion(version string) bool {\n\t_, ok := availableVersions[version]\n\treturn ok\n}\n"
  },
  {
    "path": "internal/cmd/helm-operator/run/cmd.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage run\n\nimport (\n\t\"errors\"\n\t\"flag\"\n\t\"fmt\"\n\t\"os\"\n\t\"runtime\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/go-logr/logr\"\n\t\"github.com/spf13/cobra\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\tapimachruntime \"k8s.io/apimachinery/pkg/runtime\"\n\t\"sigs.k8s.io/controller-runtime/pkg/cache\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client/config\"\n\t\"sigs.k8s.io/controller-runtime/pkg/healthz\"\n\tlogf \"sigs.k8s.io/controller-runtime/pkg/log\"\n\tzapf \"sigs.k8s.io/controller-runtime/pkg/log/zap\"\n\t\"sigs.k8s.io/controller-runtime/pkg/manager\"\n\t\"sigs.k8s.io/controller-runtime/pkg/manager/signals\"\n\tcrmetrics \"sigs.k8s.io/controller-runtime/pkg/metrics\"\n\n\thelmClient \"github.com/operator-framework/operator-sdk/internal/helm/client\"\n\t\"github.com/operator-framework/operator-sdk/internal/helm/controller\"\n\t\"github.com/operator-framework/operator-sdk/internal/helm/flags\"\n\t\"github.com/operator-framework/operator-sdk/internal/helm/metrics\"\n\t\"github.com/operator-framework/operator-sdk/internal/helm/release\"\n\t\"github.com/operator-framework/operator-sdk/internal/helm/watches\"\n\t\"github.com/operator-framework/operator-sdk/internal/util/k8sutil\"\n\tsdkVersion \"github.com/operator-framework/operator-sdk/internal/version\"\n\t\"helm.sh/helm/v3/pkg/chart/loader\"\n\t\"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured\"\n\t\"k8s.io/apimachinery/pkg/labels\"\n\t\"k8s.io/apimachinery/pkg/selection\"\n)\n\nvar log = logf.Log.WithName(\"cmd\")\n\nfunc printVersion() {\n\tversion := sdkVersion.GitVersion\n\tif version == \"unknown\" {\n\t\tversion = sdkVersion.Version\n\t}\n\tlog.Info(\"Version\",\n\t\t\"Go Version\", runtime.Version(),\n\t\t\"GOOS\", runtime.GOOS,\n\t\t\"GOARCH\", runtime.GOARCH,\n\t\t\"helm-operator\", version,\n\t\t\"commit\", sdkVersion.GitCommit)\n}\n\nfunc NewCmd() *cobra.Command {\n\tf := &flags.Flags{}\n\tzapfs := flag.NewFlagSet(\"zap\", flag.ExitOnError)\n\topts := &zapf.Options{}\n\topts.BindFlags(zapfs)\n\n\tcmd := &cobra.Command{\n\t\tUse:   \"run\",\n\t\tShort: \"Run the operator\",\n\t\tArgs: func(cmd *cobra.Command, _ []string) error {\n\t\t\tif cmd.Flag(\"metrics-require-rbac\").Value.String() == \"true\" && cmd.Flag(\"metrics-secure\").Value.String() == \"false\" {\n\t\t\t\treturn errors.New(\"--metrics-secure flag is required when --metrics-require-rbac is present\")\n\t\t\t}\n\t\t\treturn nil\n\t\t},\n\t\tRun: func(cmd *cobra.Command, _ []string) {\n\t\t\tlogf.SetLogger(zapf.New(zapf.UseFlagOptions(opts)))\n\t\t\trun(cmd, f)\n\t\t},\n\t}\n\n\tf.AddTo(cmd.Flags())\n\tcmd.Flags().AddGoFlagSet(zapfs)\n\treturn cmd\n}\n\nfunc run(cmd *cobra.Command, f *flags.Flags) {\n\tprintVersion()\n\tmetrics.RegisterBuildInfo(crmetrics.Registry)\n\n\t// Load config options from the config at f.ManagerConfigPath.\n\t// These options will not override those set by flags.\n\tvar (\n\t\toptions manager.Options\n\t\terr     error\n\t)\n\n\texitIfUnsupported(options)\n\n\tcfg, err := config.GetConfig()\n\tif err != nil {\n\t\tlog.Error(err, \"Failed to get config.\")\n\t\tos.Exit(1)\n\t}\n\n\t// TODO(2.0.0): remove\n\t// Deprecated: OPERATOR_NAME environment variable is an artifact of the\n\t// legacy operator-sdk project scaffolding. Flag `--leader-election-id`\n\t// should be used instead.\n\tif operatorName, found := os.LookupEnv(\"OPERATOR_NAME\"); found {\n\t\tlog.Info(\"Environment variable OPERATOR_NAME has been deprecated, use --leader-election-id instead.\")\n\t\tif cmd.Flags().Changed(\"leader-election-id\") {\n\t\t\tlog.Info(\"Ignoring OPERATOR_NAME environment variable since --leader-election-id is set\")\n\t\t} else if options.LeaderElectionID == \"\" {\n\t\t\t// Only set leader election ID using OPERATOR_NAME if unset everywhere else,\n\t\t\t// since this env var is deprecated.\n\t\t\toptions.LeaderElectionID = operatorName\n\t\t}\n\t}\n\n\t//TODO(2.0.0): remove the following checks. they are required just because of the flags deprecation\n\tif cmd.Flags().Changed(\"leader-elect\") && cmd.Flags().Changed(\"enable-leader-election\") {\n\t\tlog.Error(errors.New(\"only one of --leader-elect and --enable-leader-election may be set\"), \"invalid flags usage\")\n\t\tos.Exit(1)\n\t}\n\n\tif cmd.Flags().Changed(\"metrics-addr\") && cmd.Flags().Changed(\"metrics-bind-address\") {\n\t\tlog.Error(errors.New(\"only one of --metrics-addr and --metrics-bind-address may be set\"), \"invalid flags usage\")\n\t\tos.Exit(1)\n\t}\n\n\t// Set default manager options\n\toptions = f.ToManagerOptions(options)\n\n\tif options.Scheme == nil {\n\t\toptions.Scheme = apimachruntime.NewScheme()\n\t}\n\n\tws, err := watches.Load(f.WatchesFile)\n\tif err != nil {\n\t\tlog.Error(err, \"Failed to load watches file.\")\n\t\tos.Exit(1)\n\t}\n\n\tconfigureWatchNamespaces(&options, log)\n\terr = configureSelectors(&options, ws, options.Scheme)\n\tif err != nil {\n\t\tlog.Error(err, \"Failed to configure default selectors for caching\")\n\t\tos.Exit(1)\n\t}\n\tif options.NewClient == nil {\n\t\toptions.NewClient = client.New\n\t}\n\n\tmgr, err := manager.New(cfg, options)\n\tif err != nil {\n\t\tlog.Error(err, \"Failed to create a new manager.\")\n\t\tos.Exit(1)\n\t}\n\n\tif err := mgr.AddHealthzCheck(\"healthz\", healthz.Ping); err != nil {\n\t\tlog.Error(err, \"Unable to set up health check\")\n\t\tos.Exit(1)\n\t}\n\tif err := mgr.AddReadyzCheck(\"readyz\", healthz.Ping); err != nil {\n\t\tlog.Error(err, \"Unable to set up ready check\")\n\t\tos.Exit(1)\n\t}\n\n\tacg, err := helmClient.NewActionConfigGetter(mgr.GetConfig(), mgr.GetRESTMapper(), mgr.GetLogger())\n\tif err != nil {\n\t\tlog.Error(err, \"Failed to create Helm action config getter\")\n\t\tos.Exit(1)\n\t}\n\tfor _, w := range ws {\n\t\t// Register the controller with the factory.\n\t\treconcilePeriod := f.ReconcilePeriod\n\t\tif w.ReconcilePeriod.Duration != time.Duration(0) {\n\t\t\treconcilePeriod = w.ReconcilePeriod.Duration\n\t\t}\n\n\t\terr := controller.Add(mgr, controller.WatchOptions{\n\t\t\tGVK:                     w.GroupVersionKind,\n\t\t\tManagerFactory:          release.NewManagerFactory(mgr, acg, w.ChartDir),\n\t\t\tReconcilePeriod:         reconcilePeriod,\n\t\t\tWatchDependentResources: *w.WatchDependentResources,\n\t\t\tOverrideValues:          w.OverrideValues,\n\t\t\tSuppressOverrideValues:  f.SuppressOverrideValues,\n\t\t\tMaxConcurrentReconciles: f.MaxConcurrentReconciles,\n\t\t\tSelector:                w.Selector,\n\t\t\tDryRunOption:            w.DryRunOption,\n\t\t})\n\t\tif err != nil {\n\t\t\tlog.Error(err, \"Failed to add manager factory to controller.\")\n\t\t\tos.Exit(1)\n\t\t}\n\t}\n\n\t// Start the Cmd\n\tif err = mgr.Start(signals.SetupSignalHandler()); err != nil {\n\t\tlog.Error(err, \"Manager exited non-zero.\")\n\t\tos.Exit(1)\n\t}\n}\n\n// exitIfUnsupported prints an error containing unsupported field names and exits\n// if any of those fields are not their default values.\nfunc exitIfUnsupported(options manager.Options) {\n\t// The below options are webhook-specific, which is not supported by helm.\n\tif options.WebhookServer != nil {\n\t\tlog.Error(errors.New(\"webhook configurations set in manager options\"), \"unsupported configuration\")\n\t\tos.Exit(1)\n\t}\n}\n\nfunc configureWatchNamespaces(options *manager.Options, log logr.Logger) {\n\tnamespaces := splitNamespaces(os.Getenv(k8sutil.WatchNamespaceEnvVar))\n\n\tnamespaceConfigs := make(map[string]cache.Config)\n\tif len(namespaces) != 0 {\n\t\tlog.Info(\"Watching namespaces\", \"namespaces\", namespaces)\n\t\tfor _, namespace := range namespaces {\n\t\t\tnamespaceConfigs[namespace] = cache.Config{}\n\t\t\tif namespace == metav1.NamespaceAll {\n\t\t\t\tnamespaceConfigs[namespace] = cache.Config{\n\t\t\t\t\tLabelSelector: labels.Everything(),\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\tlog.Info(\"Watching all namespaces\")\n\t\t// in order to properly establish cluster level watches\n\t\t// we need to override the default label selectors configured\n\t\t// in later config steps\n\t\tnamespaceConfigs[metav1.NamespaceAll] = cache.Config{\n\t\t\tLabelSelector: labels.Everything(),\n\t\t}\n\t}\n\n\toptions.Cache.DefaultNamespaces = namespaceConfigs\n}\n\nfunc splitNamespaces(namespaces string) []string {\n\tlist := strings.Split(namespaces, \",\")\n\tvar out []string\n\tfor _, ns := range list {\n\t\ttrimmed := strings.TrimSpace(ns)\n\t\tif trimmed != \"\" {\n\t\t\tout = append(out, trimmed)\n\t\t}\n\t}\n\treturn out\n}\n\nfunc configureSelectors(opts *manager.Options, ws []watches.Watch, sch *apimachruntime.Scheme) error {\n\tselectorsByObject := map[client.Object]cache.ByObject{}\n\tchartNames := make([]string, 0, len(ws))\n\tfor _, w := range ws {\n\t\tsch.AddKnownTypeWithName(w.GroupVersionKind, &unstructured.Unstructured{})\n\n\t\tcrObj := &unstructured.Unstructured{}\n\t\tcrObj.SetGroupVersionKind(w.GroupVersionKind)\n\t\tsel, err := metav1.LabelSelectorAsSelector(&w.Selector)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"unable to parse watch selector for %s: %v\", w.GroupVersionKind, err)\n\t\t}\n\t\tselectorsByObject[crObj] = cache.ByObject{Label: sel}\n\n\t\tchrt, err := loader.LoadDir(w.ChartDir)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"unable to load chart for %s: %v\", w.GroupVersionKind, err)\n\t\t}\n\t\tchartNames = append(chartNames, chrt.Name())\n\n\t}\n\treq, err := labels.NewRequirement(\"helm.sdk.operatorframework.io/chart\", selection.In, chartNames)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to create label requirement for cache default selector: %v\", err)\n\t}\n\tdefaultSelector := labels.NewSelector().Add(*req)\n\n\topts.Cache.ByObject = selectorsByObject\n\topts.Cache.DefaultLabelSelector = defaultSelector\n\treturn nil\n}\n"
  },
  {
    "path": "internal/cmd/helm-operator/version/cmd.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage version\n\nimport (\n\t\"fmt\"\n\t\"runtime\"\n\n\t\"github.com/spf13/cobra\"\n\n\tver \"github.com/operator-framework/operator-sdk/internal/version\"\n)\n\nfunc NewCmd() *cobra.Command {\n\tversionCmd := &cobra.Command{\n\t\tUse:   \"version\",\n\t\tShort: \"Prints the version of operator-sdk\",\n\t\tRun: func(_ *cobra.Command, _ []string) {\n\t\t\trun()\n\t\t},\n\t}\n\treturn versionCmd\n}\n\nfunc run() {\n\tversion := ver.GitVersion\n\tif version == \"unknown\" {\n\t\tversion = ver.Version\n\t}\n\tfmt.Printf(\"helm-operator version: %q, commit: %q, kubernetes version: %q, go version: %q, GOOS: %q, GOARCH: %q\\n\",\n\t\tversion, ver.GitCommit, ver.KubernetesVersion, runtime.Version(), runtime.GOOS, runtime.GOARCH)\n}\n"
  },
  {
    "path": "internal/cmd/helm-operator/version/cmd_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage version\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"runtime\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\n\tver \"github.com/operator-framework/operator-sdk/internal/version\"\n)\n\nvar _ = Describe(\"Running a version command\", func() {\n\tDescribe(\"NewCmd\", func() {\n\t\tIt(\"builds a cobra command\", func() {\n\t\t\tcmd := NewCmd()\n\t\t\tExpect(cmd).NotTo(BeNil())\n\t\t\tExpect(cmd.Use).NotTo(Equal(\"\"))\n\t\t\tExpect(cmd.Short).NotTo(Equal(\"\"))\n\t\t})\n\t})\n\tDescribe(\"run\", func() {\n\t\tIt(\"prints the correct version info\", func() {\n\t\t\tr, w, _ := os.Pipe()\n\t\t\ttmp := os.Stdout\n\t\t\tdefer func() {\n\t\t\t\tos.Stdout = tmp\n\t\t\t}()\n\t\t\tos.Stdout = w\n\t\t\tgo func() {\n\t\t\t\trun()\n\t\t\t\tw.Close()\n\t\t\t}()\n\t\t\tstdout, err := io.ReadAll(r)\n\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\tstdoutString := string(stdout)\n\t\t\tversion := ver.GitVersion\n\t\t\tif version == \"unknown\" {\n\t\t\t\tversion = ver.Version\n\t\t\t}\n\t\t\tExpect(stdoutString).To(ContainSubstring(fmt.Sprintf(\"version: %q\", version)))\n\t\t\tExpect(stdoutString).To(ContainSubstring(fmt.Sprintf(\"commit: %q\", ver.GitCommit)))\n\t\t\tExpect(stdoutString).To(ContainSubstring(fmt.Sprintf(\"kubernetes version: %q\", ver.KubernetesVersion)))\n\t\t\tExpect(stdoutString).To(ContainSubstring(fmt.Sprintf(\"go version: %q\", runtime.Version())))\n\t\t\tExpect(stdoutString).To(ContainSubstring(fmt.Sprintf(\"GOOS: %q\", runtime.GOOS)))\n\t\t\tExpect(stdoutString).To(ContainSubstring(fmt.Sprintf(\"GOARCH: %q\", runtime.GOARCH)))\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "internal/cmd/helm-operator/version/version_suite_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage version_test\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nfunc TestVersion(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"Version Cmd Suite\")\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/alpha/config3alphato3/cmd.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage config3alphato3\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/cobra\"\n\t\"sigs.k8s.io/yaml\"\n)\n\nfunc NewCmd() *cobra.Command {\n\treturn &cobra.Command{\n\t\tUse:   \"config-3alpha-to-3\",\n\t\tShort: \"Convert your PROJECT config file from version 3-alpha to 3\",\n\t\tLong: `Your PROJECT file contains config data specified by some version.\nThis version is not a kubernetes-style version. In general, alpha and beta config versions\nare unstable and support for them is dropped once a stable version is released.\nThe 3-alpha version has recently become stable (3), and therefore is no longer\nsupported by operator-sdk v1.5+. This command is intended to migrate 3-alpha PROJECT files\nto 3 with as few manual modifications required as possible.\n`,\n\t\tRunE: func(_ *cobra.Command, _ []string) (err error) {\n\t\t\tcfgBytes, err := os.ReadFile(\"PROJECT\")\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"%v (config-3alpha-to-3 must be run from project root)\", err)\n\t\t\t}\n\n\t\t\tif ver, err := getConfigVersion(cfgBytes); err == nil && ver != v3alpha {\n\t\t\t\tfmt.Println(\"Your PROJECT config file is not convertible at version\", ver)\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\tb, err := convertConfig3AlphaTo3(cfgBytes)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif err := os.WriteFile(\"PROJECT\", b, 0666); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tfmt.Println(\"Your PROJECT config file has been converted from version 3-alpha to 3. \" +\n\t\t\t\t\"Please make sure all config data is correct.\")\n\n\t\t\treturn nil\n\t\t},\n\t}\n}\n\n// RootPersistentPreRun prints a helpful message on any exit caused by kubebuilder's\n// config unmarshal step finding \"3-alpha\", since the CLI will not recognize this version.\n// Add this to the root command (`operator-sdk`).\nvar RootPersistentPreRun = func(_ *cobra.Command, _ []string) {\n\tif cfgBytes, err := os.ReadFile(\"PROJECT\"); err == nil {\n\t\tif ver, err := getConfigVersion(cfgBytes); err == nil && ver == v3alpha {\n\t\t\tlog.Warn(\"Config version 3-alpha has been stabilized as 3, and 3-alpha is no longer supported. \" +\n\t\t\t\t\"Run `operator-sdk alpha config-3alpha-to-3` to upgrade your PROJECT config file to version 3\",\n\t\t\t)\n\t\t}\n\t}\n}\n\nfunc getConfigVersion(b []byte) (string, error) {\n\tvar verObj struct {\n\t\tVersion string `json:\"version\"`\n\t}\n\treturn verObj.Version, yaml.Unmarshal(b, &verObj)\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/alpha/config3alphato3/convert_config_3-alpha_to_3.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage config3alphato3\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"errors\"\n\t\"os\"\n\t\"path\"\n\t\"regexp\"\n\t\"strings\"\n\t\"text/template\"\n\n\t\"golang.org/x/mod/modfile\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/model/resource\"\n\t\"sigs.k8s.io/yaml\"\n)\n\nvar (\n\tv3alpha   = \"3-alpha\"\n\tversionRe = regexp.MustCompile(`version:[ ]*(?:\")?3-alpha(?:\")?`)\n)\n\ntype templObj struct {\n\tIsGo      bool\n\tResources []resource.Resource\n}\n\n// convertConfig3AlphaTo3 returns cfgBytes converted to 3 iff cfgBytes is version 3-alpha.\nfunc convertConfig3AlphaTo3(cfgBytes []byte) (_ []byte, err error) {\n\ttObj := templObj{}\n\tcfgObj := make(map[string]any, 5)\n\tif err := yaml.Unmarshal(cfgBytes, &cfgObj); err != nil {\n\t\treturn nil, err\n\t}\n\n\tif version, hasVersion := cfgObj[\"version\"]; !hasVersion || version.(string) != v3alpha {\n\t\treturn cfgBytes, nil\n\t}\n\n\tcfgBytes = versionRe.ReplaceAll(cfgBytes, []byte(`version: \"3\"`))\n\n\tvar modulePath string\n\tlayout := cfgObj[\"layout\"].(string)\n\tisGo := strings.HasPrefix(layout, \"go.kubebuilder.io/\")\n\tif isGo {\n\t\tif modulePath, err = getModulePath(); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\tmultigroupObj, hasMultigroup := cfgObj[\"multigroup\"]\n\tisMultigroup := hasMultigroup && multigroupObj.(bool)\n\n\tif obj, hasRes := cfgObj[\"resources\"]; hasRes {\n\t\t// Default to empty domain if no domain information is found.\n\t\tdomain := \"\"\n\t\tif domainObj, ok := cfgObj[\"domain\"]; ok {\n\t\t\tdomain = domainObj.(string)\n\t\t}\n\n\t\tresObjs := obj.([]any)\n\t\tresources := make([]resource.Resource, len(resObjs))\n\n\t\tfor i, resObj := range resObjs {\n\t\t\tresources[i].Domain = domain\n\n\t\t\tres := resObj.(map[string]any)\n\t\t\tif groupObj, ok := res[\"group\"]; ok {\n\t\t\t\tresources[i].Group = groupObj.(string)\n\t\t\t}\n\t\t\tif versionObj, ok := res[\"version\"]; ok {\n\t\t\t\tresources[i].Version = versionObj.(string)\n\t\t\t}\n\t\t\tif kindObj, ok := res[\"kind\"]; ok {\n\t\t\t\tresources[i].Kind = kindObj.(string)\n\t\t\t}\n\n\t\t\tif isGo {\n\t\t\t\t// Only Go projects use \"resources[*].path\".\n\t\t\t\tvar apiPath string\n\t\t\t\tif isMultigroup {\n\t\t\t\t\tapiPath = path.Join(\"api\", resources[i].Group, resources[i].Version)\n\t\t\t\t} else {\n\t\t\t\t\tapiPath = path.Join(\"api\", resources[i].Version)\n\t\t\t\t}\n\t\t\t\tresources[i].Path = path.Join(modulePath, apiPath)\n\t\t\t}\n\n\t\t\t// Only set \"resources[i].api\" if \"crdVersion\" is present. Otherwise there is\n\t\t\t// likely no API defined by the project.\n\t\t\tif crdVersionObj, ok := res[\"crdVersion\"]; ok {\n\t\t\t\tresources[i].API = &resource.API{\n\t\t\t\t\tCRDVersion: crdVersionObj.(string),\n\t\t\t\t}\n\t\t\t} else if k8sDomain, found := coreGroups[resources[i].Group]; found {\n\t\t\t\t// Core type case.\n\t\t\t\tresources[i].Domain = k8sDomain\n\t\t\t\tresources[i].Path = path.Join(\"k8s.io\", \"api\", resources[i].Group, resources[i].Version)\n\t\t\t}\n\t\t\t// Only set \"resources[i].webhooks\" if \"webhookVersion\" is present. Otherwise there is\n\t\t\t// likely no webhook defined by the project.\n\t\t\tif whVersionObj, ok := res[\"webhookVersion\"]; ok {\n\t\t\t\tresources[i].Webhooks = &resource.Webhooks{\n\t\t\t\t\tWebhookVersion: whVersionObj.(string),\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ttObj.Resources = resources\n\t\ttObj.IsGo = isGo\n\n\t\tout := bytes.Buffer{}\n\t\tt := template.Must(template.New(\"\").Parse(tmpl))\n\t\tif err := t.Execute(&out, tObj); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\t// Scan for resources, then replace only reources to preserve comments/order of the rest of PROJECT.\n\t\tscanner := bufio.NewScanner(bytes.NewBuffer(cfgBytes))\n\t\tstart, end := -1, len(cfgBytes)\n\t\tfor scanner.Scan() {\n\t\t\ttext := scanner.Text()\n\t\t\tif strings.HasPrefix(text, \"resources:\") {\n\t\t\t\tstart = bytes.Index(cfgBytes, []byte(\"resources:\"))\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif start != -1 && strings.Contains(text, \":\") && !strings.HasPrefix(text, \" \") {\n\t\t\t\tkey := strings.TrimRightFunc(text, func(c rune) bool {\n\t\t\t\t\treturn c != ':'\n\t\t\t\t})\n\t\t\t\tif _, hasKey := cfgObj[strings.TrimSuffix(key, \":\")]; hasKey {\n\t\t\t\t\tend = bytes.Index(cfgBytes, []byte(text))\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif start == -1 {\n\t\t\treturn nil, errors.New(\"internal error: resources key not found in scanner\")\n\t\t}\n\t\tcfgBytes = append(cfgBytes[:start], append(out.Bytes(), cfgBytes[end:]...)...)\n\t}\n\n\treturn cfgBytes, nil\n}\n\n// Make this a var so it can be mocked in tests.\nvar getModulePath = func() (string, error) {\n\tb, err := os.ReadFile(\"go.mod\")\n\treturn modfile.ModulePath(b), err\n}\n\n// Comment-heavy \"resources\" template.\nconst tmpl = `resources:\n{{- $isGo := .IsGo }}\n{{- range $i, $res := .Resources }}\n-{{- if $res.API }} api:\n    {{- if $res.API.CRDVersion }}\n    crdVersion: {{ $res.API.CRDVersion }}\n    {{- else }}\n    # TODO(user): Change this API's CRD version if not v1.\n    crdVersion: v1\n    {{- end }}\n    # TODO(user): Uncomment the below line if this resource's CRD is namespace scoped, else delete it.\n    # namespaced: true\n  {{- end }}\n  {{- if $isGo }}\n  # TODO(user): Uncomment the below line if this resource implements a controller, else delete it.\n  # controller: true\n  {{- end }}\n  {{- if $res.Domain }}\n  domain: {{ $res.Domain }}\n  {{- end }}\n  group: {{ $res.GVK.Group }}\n  kind: {{ $res.GVK.Kind }}\n  {{- if $res.Path }}\n  # TODO(user): Update the package path for your API if the below value is incorrect.\n  path: {{ $res.Path }}\n  {{- end }}\n  version: {{ $res.GVK.Version }}\n  {{- if $res.Webhooks }}\n  webhooks:\n    # TODO(user): Uncomment the below line if this resource's webhook implements a conversion webhook, else delete it.\n    # conversion: true\n    # TODO(user): Uncomment the below line if this resource's webhook implements a defaulting webhook, else delete it.\n    # defaulting: true\n    # TODO(user): Uncomment the below line if this resource's webhook implements a validating webhook, else delete it.\n    # validation: true\n    {{- if $res.Webhooks.WebhookVersion }}\n    webhookVersion: {{ $res.Webhooks.WebhookVersion }}\n    {{- else }}\n    # TODO(user): Change this API's webhook configuration version to the correct version if not v1.\n    webhookVersion: v1\n    {{- end }}\n  {{- end }}\n{{- end }}\n`\n\n// coreGroups maps a native k8s group to its domain. Several do not have a domain.\nvar coreGroups = map[string]string{\n\t\"admission\":             \"k8s.io\",\n\t\"admissionregistration\": \"k8s.io\",\n\t\"apps\":                  \"\",\n\t\"auditregistration\":     \"k8s.io\",\n\t\"apiextensions\":         \"k8s.io\",\n\t\"authentication\":        \"k8s.io\",\n\t\"authorization\":         \"k8s.io\",\n\t\"autoscaling\":           \"\",\n\t\"batch\":                 \"\",\n\t\"certificates\":          \"k8s.io\",\n\t\"coordination\":          \"k8s.io\",\n\t\"core\":                  \"\",\n\t\"events\":                \"k8s.io\",\n\t\"extensions\":            \"\",\n\t\"imagepolicy\":           \"k8s.io\",\n\t\"networking\":            \"k8s.io\",\n\t\"node\":                  \"k8s.io\",\n\t\"metrics\":               \"k8s.io\",\n\t\"policy\":                \"\",\n\t\"rbac.authorization\":    \"k8s.io\",\n\t\"scheduling\":            \"k8s.io\",\n\t\"setting\":               \"k8s.io\",\n\t\"storage\":               \"k8s.io\",\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/alpha/config3alphato3/convert_config_3-alpha_to_3_test.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage config3alphato3\n\nimport (\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\t. \"github.com/onsi/gomega/format\"\n)\n\nvar _ = Describe(\"ConvertConfig3AlphaTo3\", func() {\n\tTruncatedDiff = false\n\t// Mock go.mod reading to test \"resources[*].path\"\n\tgetModulePath = func() (string, error) {\n\t\treturn \"github.com/example/memcached-operator\", nil\n\t}\n\tDescribeTable(\"should return the expected config\",\n\t\tfunc(inputCfgStr, expectedCfgStr string) {\n\t\t\toutput, err := convertConfig3AlphaTo3([]byte(inputCfgStr))\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\tExpect(string(output)).To(MatchYAML(expectedCfgStr))\n\t\t},\n\t\tEntry(\"no resources\", noResourcesConfig, noResourcesConfigExp),\n\t\tEntry(\"basic\", basicConfig, basicConfigExp),\n\t\tEntry(\"complex\", complexConfig, complexConfigExp),\n\t\tEntry(\"no domain\", noDomainConfig, noDomainConfigExp),\n\t)\n})\n\nconst (\n\tbasicConfig = `domain: example.com\nlayout: ansible.sdk.operatorframework.io/v1\nprojectName: memcached-operator\nresources:\n- crdVersion: v1\n  group: cache\n  kind: Memcached\n  version: v1alpha1\nversion: 3-alpha\n`\n\tbasicConfigExp = `domain: example.com\nlayout: ansible.sdk.operatorframework.io/v1\nprojectName: memcached-operator\nresources:\n- api:\n    crdVersion: v1\n    # TODO(user): Uncomment the below line if this resource's CRD is namespace scoped, else delete it.\n    # namespaced: true\n  # TODO(user): Uncomment the below line if this resource implements a controller, else delete it.\n  # controller: true\n  domain: example.com\n  group: cache\n  kind: Memcached\n  version: v1alpha1\nversion: \"3\"\n`\n)\n\nconst (\n\tnoDomainConfig = `layout: ansible.sdk.operatorframework.io/v1\nprojectName: memcached-operator\nresources:\n- crdVersion: v1\n  group: cache\n  kind: Memcached\n  version: v1alpha1\nversion: 3-alpha`\n\tnoDomainConfigExp = `layout: ansible.sdk.operatorframework.io/v1\nprojectName: memcached-operator\nresources:\n- api:\n    crdVersion: v1\n    # TODO(user): Uncomment the below line if this resource's CRD is namespace scoped, else delete it.\n    # namespaced: true\n  # TODO(user): Uncomment the below line if this resource implements a controller, else delete it.\n  # controller: true\n  group: cache\n  kind: Memcached\n  version: v1alpha1\nversion: \"3\"`\n)\n\nconst (\n\tnoResourcesConfig = `domain: example.com\nlayout: ansible.sdk.operatorframework.io/v1\nprojectName: memcached-operator\nversion: 3-alpha\n`\n\tnoResourcesConfigExp = `domain: example.com\nlayout: ansible.sdk.operatorframework.io/v1\nprojectName: memcached-operator\nversion: \"3\"\n`\n)\n\nconst (\n\tcomplexConfig = `domain: example.com\nlayout: go.kubebuilder.io/v3\nprojectName: memcached-operator\nresources:\n- crdVersion: v1\n  group: cache\n  kind: Memcached\n  version: v1alpha1\n  webhookVersion: v1\n- crdVersion: v1\n  group: cache\n  kind: MemcachedRS\n  version: v1alpha1\n- # This is a builtin type\n  group: apps\n  kind: Deployment\n  version: v1\n- # This is an internal type that looks like a core/v1.Pod\n  crdVersion: v1\n  group: core\n  kind: Pod\n  version: v1\nplugins:\n  manifests.sdk.operatorframework.io/v2: {}\n  scorecard.sdk.operatorframework.io/v2: {}\nversion: 3-alpha\n`\n\tcomplexConfigExp = `domain: example.com\nlayout: go.kubebuilder.io/v3\nprojectName: memcached-operator\nresources:\n- api:\n    crdVersion: v1\n    # TODO(user): Uncomment the below line if this resource's CRD is namespace scoped, else delete it.\n    # namespaced: true\n  # TODO(user): Uncomment the below line if this resource implements a controller, else delete it.\n  # controller: true\n  domain: example.com\n  group: cache\n  kind: Memcached\n  # TODO(user): Update the package path for your API if the below value is incorrect.\n  path: github.com/example/memcached-operator/api/v1alpha1\n  version: v1alpha1\n  webhooks:\n    # TODO(user): Uncomment the below line if this resource's webhook implements a conversion webhook, else delete it.\n    # conversion: true\n    # TODO(user): Uncomment the below line if this resource's webhook implements a defaulting webhook, else delete it.\n    # defaulting: true\n    # TODO(user): Uncomment the below line if this resource's webhook implements a validating webhook, else delete it.\n    # validation: true\n    webhookVersion: v1\n- api:\n    crdVersion: v1\n    # TODO(user): Uncomment the below line if this resource's CRD is namespace scoped, else delete it.\n    # namespaced: true\n  # TODO(user): Uncomment the below line if this resource implements a controller, else delete it.\n  # controller: true\n  domain: example.com\n  group: cache\n  kind: MemcachedRS\n  # TODO(user): Update the package path for your API if the below value is incorrect.\n  path: github.com/example/memcached-operator/api/v1alpha1\n  version: v1alpha1\n- # TODO(user): Uncomment the below line if this resource implements a controller, else delete it.\n  # controller: true\n  group: apps\n  kind: Deployment\n  # TODO(user): Update the package path for your API if the below value is incorrect.\n  path: k8s.io/api/apps/v1\n  version: v1\n- api:\n    crdVersion: v1\n    # TODO(user): Uncomment the below line if this resource's CRD is namespace scoped, else delete it.\n    # namespaced: true\n  # TODO(user): Uncomment the below line if this resource implements a controller, else delete it.\n  # controller: true\n  domain: example.com\n  group: core\n  kind: Pod\n  # TODO(user): Update the package path for your API if the below value is incorrect.\n  path: github.com/example/memcached-operator/api/v1\n  version: v1\nplugins:\n  manifests.sdk.operatorframework.io/v2: {}\n  scorecard.sdk.operatorframework.io/v2: {}\nversion: \"3\"\n`\n)\n"
  },
  {
    "path": "internal/cmd/operator-sdk/alpha/config3alphato3/suite_test.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage config3alphato3\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nfunc TestInternal(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"Internal Suite\")\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/bundle/bundle_suite_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage bundle_test\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nfunc TestBundle(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"Bundle Cmd Suite\")\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/bundle/cmd.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage bundle\n\nimport (\n\t\"github.com/spf13/cobra\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/bundle/validate\"\n)\n\nfunc NewCmd() *cobra.Command {\n\tcmd := &cobra.Command{\n\t\tUse:   \"bundle\",\n\t\tShort: \"Manage operator bundle metadata\",\n\t\tLong: `Manage bundle builds, bundle metadata generation, and bundle validation.\nAn operator bundle is a portable operator packaging format understood by Kubernetes\nnative software, like the Operator Lifecycle Manager.\n\nMore information about operator bundles and metadata:\nhttps://github.com/operator-framework/operator-registry/blob/master/docs/design/operator-bundle.md\n\nMore information about the integration with OLM via SDK:\nhttps://sdk.operatorframework.io/docs/olm-integration\n`,\n\t}\n\n\tcmd.AddCommand(\n\t\tvalidate.NewCmd(),\n\t)\n\treturn cmd\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/bundle/cmd_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage bundle\n\nimport (\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nvar _ = Describe(\"Running a bundle command\", func() {\n\tDescribe(\"NewCmd\", func() {\n\t\tIt(\"builds and returns a cobra command with the correct subcommand\", func() {\n\t\t\tcmd := NewCmd()\n\t\t\tExpect(cmd).NotTo(BeNil())\n\n\t\t\tsubcommands := cmd.Commands()\n\t\t\tExpect(subcommands).To(HaveLen(1))\n\t\t\tExpect(subcommands[0].Use).To(Equal(\"validate\"))\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "internal/cmd/operator-sdk/bundle/validate/cmd.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage validate\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/cobra\"\n\t\"github.com/spf13/viper\"\n\t\"k8s.io/apimachinery/pkg/labels\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/bundle/validate/internal\"\n\t\"github.com/operator-framework/operator-sdk/internal/flags\"\n)\n\nconst (\n\tlongHelp = `The 'operator-sdk bundle validate' command can validate both content and format of an operator bundle\nimage or an operator bundle directory on-disk containing operator metadata and manifests. This command will exit\nwith an exit code of 1 if any validation errors arise, and 0 if only warnings arise or all validators pass.\n\nA valid bundle is defined by the bundle spec (linked below), therefore the default validator ensures a bundle conforms to\nthat spec. If you want to ensure that your bundle is valid for an optional superset of requirements such as to those\nrequired to publish your operator on operatorhub.io, then you will need to run one or more supported optional validators.\nSet '--list-optional' to list which optional validators are supported, and how they are grouped by label.\n\nMore information about operator bundles and metadata:\nhttps://github.com/operator-framework/operator-registry/blob/master/docs/design/operator-bundle.md\n\nNOTE: if validating an image, the image must exist in a remote registry, not just locally.\n`\n\n\texamples = `This example assumes you either have a *pullable* bundle image,\nor something similar to the following operator bundle layout present locally:\n\n  $ tree ./bundle\n  ./bundle\n  ├── manifests\n  │   ├── cache.my.domain_memcacheds.yaml\n  │   └── memcached-operator.clusterserviceversion.yaml\n  └── metadata\n      └── annotations.yaml\n\nTo validate a local bundle:\n\n  $ operator-sdk bundle validate ./bundle\n\nTo build and validate a *pullable* bundle image:\n\n  $ operator-sdk bundle validate <some-registry>/<operator-bundle-name>:<tag>\n\nTo list and run optional validators, which are specified by a label selector:\n\n  $ operator-sdk bundle validate --list-optional\n  NAME           LABELS                     DESCRIPTION\n  operatorhub    name=operatorhub           OperatorHub.io metadata validation.\n                 suite=operatorframework\n\nTo validate a bundle against the entire suite of validators for Operator Framework, in addition to required bundle validators:\n\n  $ operator-sdk bundle validate ./bundle --select-optional suite=operatorframework\n\nThe OperatorHub.io validator in the operatorframework optional suite allows you to validate that your manifests can work with a Kubernetes cluster of a particular version using the k8s-version optional key value:\n\n  $ operator-sdk bundle validate ./bundle --select-optional suite=operatorframework --optional-values=k8s-version=1.22\n\nTo validate a bundle against the validator for operatorhub.io specifically, in addition to required bundle validators:\n\n  $ operator-sdk bundle validate ./bundle --select-optional name=operatorhub\n\nThis validator allows check the bundle against an specific Kubernetes cluster version using the k8s-version optional key value:\n\n  $ operator-sdk bundle validate ./bundle --select-optional name=operatorhub --optional-values=k8s-version=1.22\n\n[Deprecated] To validate a bundle against the (alpha) validator for Community Operators specifically, in addition to required bundle validators:\n\n  $ operator-sdk bundle validate ./bundle --select-optional name=community --optional-values=index-path=bundle.Dockerfile\n\nTo validate a bundle against the validator for Good Practices specifically, in addition to required bundle validators:\n\n  $ operator-sdk bundle validate ./bundle --select-optional name=good-practices\n\nTo validate a bundle against the (alpha) validator for Deprecated APIs specifically, in addition to required bundle validators:\n\n  $ operator-sdk bundle validate ./bundle --select-optional name=alpha-deprecated-apis --optional-values=k8s-version=1.22\n\nTo validate a bundle against an external validator, in addition to required bundle validators:\n\n  $ operator-sdk bundle validate ./bundle --alpha-select-external /path/to/external-validator[:/path/to/optional-second-validator]\n\nTo validate a bundle against the (alpha) validator for Multiple Architectures bundle validation, in addition to required bundle validators:\n\nIMPORTANT: To use this option it is required to have access to pull the images defined on the CSV.\n\n  $ operator-sdk bundle validate ./bundle --select-optional name=multiarch \n\nNOTE: The --optional-values can be used to inform the container-tools that should be used i.e. \"--optional-values=container-tools=docker\".\nThe valid values for the container-tools optional value are [docker, podman, none]. If no value is supplied then the command will default to using docker to inspect the images.\nMore info: https://github.com/operator-framework/api/blob/master/pkg/validation/internal/multiarch.go\n`\n)\n\n// NewCmd returns a command that will validate an operator bundle.\nfunc NewCmd() *cobra.Command {\n\tc := bundleValidateCmd{}\n\tcmd := &cobra.Command{\n\t\tUse:     \"validate\",\n\t\tShort:   \"Validate an operator bundle\",\n\t\tLong:    longHelp,\n\t\tExample: examples,\n\t\tRunE: func(_ *cobra.Command, args []string) (err error) {\n\t\t\t// Always print non-output logs to stderr as to not pollute actual command output.\n\t\t\t// Note that it allows the JSON result be redirected to the Stdout. E.g\n\t\t\t// if we run the command with `| jq . > result.json` the command will print just the logs\n\t\t\t// and the file will have only the JSON result.\n\t\t\tlogger := createLogger(viper.GetBool(flags.VerboseOpt))\n\n\t\t\tif c.selector, err = labels.Parse(c.selectorRaw); err != nil {\n\t\t\t\tlogger.Fatal(err)\n\t\t\t}\n\n\t\t\tif err = c.validate(args); err != nil {\n\t\t\t\treturn fmt.Errorf(\"invalid command args: %v\", err)\n\t\t\t}\n\n\t\t\tif c.listOptional {\n\t\t\t\tif err = c.list(); err != nil {\n\t\t\t\t\tlogger.Fatal(err)\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\tif c.selectorRaw == \"name=community\" {\n\t\t\t\tlogger.Warnf(\"The Optional(stage: alpha) Community Operator bundle validator is deprecated and\" +\n\t\t\t\t\t\" will be removed in a future release. You can do these checks using the external validator: \" +\n\t\t\t\t\t\"https://github.com/redhat-openshift-ecosystem/ocp-olm-catalog-validator/\")\n\t\t\t}\n\n\t\t\tresult, err := c.run(logger, args[0])\n\t\t\tif err != nil {\n\t\t\t\tlogger.Fatal(err)\n\t\t\t}\n\t\t\tfailed, err := result.PrintWithFormat(c.outputFormat)\n\t\t\tif err != nil {\n\t\t\t\tlogger.Fatal(err)\n\t\t\t}\n\n\t\t\t// if a test failed don't print that it was successful\n\t\t\tif failed {\n\t\t\t\tos.Exit(1)\n\t\t\t}\n\n\t\t\tlogger.Info(\"All validation tests have completed successfully\")\n\t\t\treturn nil\n\t\t},\n\t}\n\n\tc.addToFlagSet(cmd.Flags())\n\n\treturn cmd\n}\n\n// createLogger creates a new logrus Entry that is optionally verbose.\nfunc createLogger(verbose bool) *log.Entry {\n\tlogger := log.NewEntry(internal.NewLoggerTo(os.Stderr))\n\tif verbose {\n\t\tlogger.Logger.SetLevel(log.DebugLevel)\n\t}\n\treturn logger\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/bundle/validate/cmd_suite_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage validate\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nfunc TestValidate(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"Validate Suite\")\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/bundle/validate/internal/logger.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage internal\n\nimport (\n\t\"io\"\n\n\tlog \"github.com/sirupsen/logrus\"\n)\n\n// NewLoggerTo returns a logger that writes logs to w.\nfunc NewLoggerTo(w io.Writer) *log.Logger {\n\tlogger := log.New()\n\tlogger.SetOutput(w)\n\treturn logger\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/bundle/validate/optional.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage validate\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"io\"\n\t\"text/tabwriter\"\n\n\tapimanifests \"github.com/operator-framework/api/pkg/manifests\"\n\tapivalidation \"github.com/operator-framework/api/pkg/validation\"\n\tapierrors \"github.com/operator-framework/api/pkg/validation/errors\"\n\tinterfaces \"github.com/operator-framework/api/pkg/validation/interfaces\"\n\t\"k8s.io/apimachinery/pkg/labels\"\n)\n\n// Keys for label selectors to be used by all validators.\nconst (\n\tnameKey  = \"name\"\n\tsuiteKey = \"suite\"\n)\n\n// optionalValidators is a list of validators with their name, labels for CLI usage, and a light description.\nvar optionalValidators = validators{\n\t{\n\t\tValidator: apivalidation.OperatorHubV2Validator,\n\t\tname:      \"operatorhubv2\",\n\t\tlabels: map[string]string{\n\t\t\tnameKey:  \"operatorhubv2\",\n\t\t\tsuiteKey: \"operatorframework\",\n\t\t},\n\t\tdesc: \"OperatorHub.io metadata validation. \",\n\t},\n\t{\n\t\tValidator: apivalidation.StandardCapabilitiesValidator,\n\t\tname:      \"capabilities\",\n\t\tlabels: map[string]string{\n\t\t\tnameKey:  \"capabilities\",\n\t\t\tsuiteKey: \"operatorframework\",\n\t\t},\n\t\tdesc: \"OperatorHub.io capabilities metadata validation. \",\n\t},\n\t{\n\t\tValidator: apivalidation.StandardCategoriesValidator,\n\t\tname:      \"categories\",\n\t\tlabels: map[string]string{\n\t\t\tnameKey:  \"categories\",\n\t\t\tsuiteKey: \"operatorframework\",\n\t\t},\n\t\tdesc: \"OperatorHub.io categories metadata validation. \",\n\t},\n\t{\n\t\tValidator: apivalidation.OperatorHubValidator, // nolint:staticcheck\n\t\tname:      \"operatorhub\",\n\t\tlabels: map[string]string{\n\t\t\tnameKey: \"operatorhub\",\n\t\t},\n\t\tdesc: \"Deprecated OperatorHub.io metadata validation. \",\n\t},\n\t{\n\t\tValidator: apivalidation.CommunityOperatorValidator,\n\t\tname:      \"community\",\n\t\tlabels: map[string]string{\n\t\t\tnameKey: \"community\",\n\t\t},\n\t\tdesc: \"(stage: alpha) Community Operator bundle validation. See https://github.com/operator-framework/community-operators/blob/master/docs/packaging-required-fields.md\",\n\t},\n\t{\n\t\tValidator: apivalidation.AlphaDeprecatedAPIsValidator,\n\t\tname:      \"alpha-deprecated-apis\",\n\t\tlabels: map[string]string{\n\t\t\tnameKey:  \"alpha-deprecated-apis\",\n\t\t\tsuiteKey: \"operatorframework\",\n\t\t},\n\t\tdesc: \"(stage: alpha) Deprecated APIs bundle validation. This validator can help you out verify if your bundle contains manifests which uses deprecated APIs. More info: https://kubernetes.io/docs/reference/using-api/deprecation-guide/\",\n\t},\n\t{\n\t\tValidator: apivalidation.GoodPracticesValidator,\n\t\tname:      \"good-practices\",\n\t\tlabels: map[string]string{\n\t\t\tnameKey:  \"good-practices\",\n\t\t\tsuiteKey: \"operatorframework\",\n\t\t},\n\t\tdesc: \"Good Practices bundle validation. This validator validates the bundle against criteria and suggestions defined as good practices for bundles under the operator-framework solutions. More info: https://sdk.operatorframework.io/docs/best-practices/.\",\n\t},\n\t{\n\t\tValidator: apivalidation.MultipleArchitecturesValidator,\n\t\tname:      \"multiarch\",\n\t\tlabels: map[string]string{\n\t\t\tnameKey: \"multiarch\",\n\t\t},\n\t\tdesc: \"(Alpha) Multiple Architectures bundle validation. This validator validates the bundle against criteria defined to configure the support for multiple architectures. More info: https://olm.operatorframework.io/docs/advanced-tasks/ship-operator-supporting-multiarch/.\",\n\t},\n}\n\n// runOptionalValidators runs optional validators selected by sel on bundle.\nfunc runOptionalValidators(bundle *apimanifests.Bundle, sel labels.Selector, optionalValues map[string]string) []apierrors.ManifestResult {\n\treturn optionalValidators.run(bundle, sel, optionalValues)\n}\n\n// listOptionalValidators lists all optional validators.\nfunc listOptionalValidators(w io.Writer) error {\n\t_, err := fmt.Fprint(w, optionalValidators.String())\n\treturn err\n}\n\n// validator can validate a set of bundle objects and report information about those objects.\ntype validator struct {\n\tinterfaces.Validator\n\tname   string\n\tlabels map[string]string\n\tdesc   string\n}\n\ntype validators []validator\n\nfunc (vals validators) String() string {\n\tout := &bytes.Buffer{}\n\ttw := tabwriter.NewWriter(out, 8, 4, 4, ' ', 0)\n\tfmt.Fprintf(tw, \"NAME\\tLABELS\\tDESCRIPTION\\n\")\n\tfor _, val := range vals {\n\t\tvar labelStrs []string\n\t\tfor k, v := range val.labels {\n\t\t\tlabelStrs = append(labelStrs, fmt.Sprintf(\"%s=%s\", k, v))\n\t\t}\n\t\tif len(labelStrs) != 0 {\n\t\t\tfmt.Fprintf(tw, \"%s\\t%s\\t%s\\n\", val.name, labelStrs[0], val.desc)\n\t\t}\n\t\tif len(labelStrs) > 1 {\n\t\t\tfor _, labelStr := range labelStrs[1:] {\n\t\t\t\tfmt.Fprintf(tw, \"\\t%s\\t\\n\", labelStr)\n\t\t\t}\n\t\t}\n\t}\n\ttw.Flush()\n\treturn out.String()\n}\n\n// checkMatches returns an error if sel does not match any validators. This method helps the CLI\n// to fail early in case of erroneous input.\nfunc (vals validators) checkMatches(sel labels.Selector) error {\n\tfor _, v := range vals {\n\t\tif sel.Matches(labels.Set(v.labels)) {\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn fmt.Errorf(\"selector %q does not match any validator labels\", sel.String())\n}\n\n// run runs optional validators selected by sel on bundle.\nfunc (vals validators) run(bundle *apimanifests.Bundle, sel labels.Selector, optionalValues map[string]string) (results []apierrors.ManifestResult) {\n\t// No selector set, do not run any optional validators.\n\tif sel == nil || sel.String() == \"\" {\n\t\treturn results\n\t}\n\n\t// Pass all exposed bundle objects to the validator, since the underlying validator could filter by type\n\t// or arbitrary unstructured object keys.\n\t// NB(estroz): we may also want to pass metadata to these validators, however the set of metadata in a bundle\n\t// object is not complete (only dependencies, no annotations).\n\tobjs := bundle.ObjectsToValidate()\n\tfor _, obj := range bundle.Objects {\n\t\tobjs = append(objs, obj)\n\t}\n\n\t// Pass the --optional-values. e.g. --optional-values=\"k8s-version=1.22\"\n\t// or --optional-values=\"image-path=bundle.Dockerfile\"\n\tobjs = append(objs, optionalValues)\n\n\tfor _, v := range vals {\n\t\tif sel.Matches(labels.Set(v.labels)) {\n\t\t\tresults = append(results, v.Validate(objs...)...)\n\t\t}\n\t}\n\n\treturn results\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/bundle/validate/optional_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage validate\n\nimport (\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\tapimanifests \"github.com/operator-framework/api/pkg/manifests\"\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\tapierrors \"github.com/operator-framework/api/pkg/validation/errors\"\n\t\"k8s.io/apimachinery/pkg/labels\"\n)\n\nvar _ = Describe(\"Running optional validators\", func() {\n\tvar (\n\t\tvals validators\n\t)\n\n\tBeforeEach(func() {\n\t\tvals = validators{}\n\t})\n\n\tDescribe(\"run\", func() {\n\t\tvar (\n\t\t\tbundle  *apimanifests.Bundle\n\t\t\tresults []apierrors.ManifestResult\n\t\t\tsel     labels.Selector\n\t\t)\n\n\t\tBeforeEach(func() {\n\t\t\tvals = optionalValidators[:1]\n\t\t})\n\n\t\tIt(\"runs no validators for an empty selector\", func() {\n\t\t\tbundle = &apimanifests.Bundle{}\n\t\t\tsel = labels.SelectorFromSet(map[string]string{})\n\t\t\tExpect(vals.run(bundle, sel, nil)).To(BeEmpty())\n\t\t})\n\t\tIt(\"runs a validator for one selector on an empty bundle\", func() {\n\t\t\tbundle = &apimanifests.Bundle{}\n\t\t\tsel = labels.SelectorFromSet(map[string]string{\n\t\t\t\tsuiteKey: \"operatorframework\",\n\t\t\t})\n\t\t\tresults = vals.run(bundle, sel, map[string]string{\"k8s-version\": \"1.22\"})\n\t\t\tExpect(results).To(HaveLen(1))\n\t\t\tExpect(results[0].Errors).To(HaveLen(1))\n\t\t})\n\t\tIt(\"runs a validator for one selector on a bundle\", func() {\n\t\t\tbundle = &apimanifests.Bundle{}\n\t\t\tbundle.CSV = &v1alpha1.ClusterServiceVersion{}\n\t\t\tsel = labels.SelectorFromSet(map[string]string{\n\t\t\t\tsuiteKey: \"operatorframework\",\n\t\t\t})\n\t\t\tresults = vals.run(bundle, sel, nil)\n\t\t\tExpect(results).To(HaveLen(1))\n\t\t\t// Only test that more than one error was returned than the empty bundle case, which\n\t\t\t// indicates validation happening.\n\t\t\tExpect(len(results[0].Errors)).To(BeNumerically(\">\", 1))\n\t\t})\n\t})\n\n\tDescribe(\"checkMatches\", func() {\n\t\tvar (\n\t\t\tsel labels.Selector\n\t\t\terr error\n\t\t)\n\n\t\tIt(\"returns an error for an empty selector with no validators\", func() {\n\t\t\tsel = labels.SelectorFromSet(map[string]string{})\n\t\t\terr = vals.checkMatches(sel)\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t})\n\t\tIt(\"returns an error for an unmatched selector with no validators\", func() {\n\t\t\tsel = labels.SelectorFromSet(map[string]string{\n\t\t\t\tsuiteKey: \"operatorframework\",\n\t\t\t})\n\t\t\terr = vals.checkMatches(sel)\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t})\n\t\tIt(\"returns no error for an unmatched selector with all optional validators\", func() {\n\t\t\tsel = labels.SelectorFromSet(map[string]string{\n\t\t\t\tsuiteKey: \"operatorframework\",\n\t\t\t})\n\t\t\tvals = optionalValidators\n\t\t\terr = vals.checkMatches(sel)\n\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t})\n\t})\n\n})\n"
  },
  {
    "path": "internal/cmd/operator-sdk/bundle/validate/validate.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage validate\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\n\tapimanifests \"github.com/operator-framework/api/pkg/manifests\"\n\t\"github.com/operator-framework/operator-registry/pkg/containertools\"\n\tregistryimage \"github.com/operator-framework/operator-registry/pkg/image\"\n\t\"github.com/operator-framework/operator-registry/pkg/image/containerdregistry\"\n\t\"github.com/operator-framework/operator-registry/pkg/image/execregistry\"\n\tregistrybundle \"github.com/operator-framework/operator-registry/pkg/lib/bundle\"\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/pflag\"\n\t\"k8s.io/apimachinery/pkg/labels\"\n\n\tinternalregistry \"github.com/operator-framework/operator-sdk/internal/registry\"\n\t\"github.com/operator-framework/operator-sdk/internal/validate\"\n)\n\ntype bundleValidateCmd struct {\n\tdirectory           string\n\timageBuilder        string\n\toutputFormat        string\n\tselectorRaw         string\n\tselector            labels.Selector\n\tlistOptional        bool\n\toptionalValues      map[string]string\n\talphaSelectExternal string\n}\n\n// validate verifies the command args\nfunc (c bundleValidateCmd) validate(args []string) error {\n\tif c.listOptional {\n\t\treturn nil\n\t}\n\n\tif len(args) != 1 {\n\t\treturn errors.New(\"an image tag or directory is a required argument\")\n\t}\n\tif c.outputFormat != validate.JSONAlpha1Output && c.outputFormat != validate.TextOutput {\n\t\treturn fmt.Errorf(\"invalid value for output flag: %v\", c.outputFormat)\n\t}\n\n\t// Check optional selector.\n\tif c.selectorRaw != \"\" {\n\t\tif err := optionalValidators.checkMatches(c.selector); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// TODO: add a \"permissive\" flag to toggle whether warnings also cause a non-zero\n// exit code to be returned (true by default).\nfunc (c *bundleValidateCmd) addToFlagSet(fs *pflag.FlagSet) {\n\tfs.StringVarP(&c.imageBuilder, \"image-builder\", \"b\", \"docker\",\n\t\t\"Tool to pull and unpack bundle images. Only used when validating a bundle image. \"+\n\t\t\t\"One of: [docker, podman, none]\")\n\tfs.StringVar(&c.selectorRaw, \"select-optional\", \"\",\n\t\t\"Label selector to select optional validators to run. \"+\n\t\t\t\"Run this command with '--list-optional' to list available optional validators\")\n\tfs.BoolVar(&c.listOptional, \"list-optional\", false,\n\t\t\"List all optional validators available. When set, no validators will be run\")\n\n\toptionalValueEmpty := map[string]string{}\n\tfs.StringToStringVarP(&c.optionalValues, \"optional-values\", \"\", optionalValueEmpty,\n\t\t\"Inform a []string map of key=values which can be used by the validator. e.g. to check the operator bundle \"+\n\t\t\t\"against an Kubernetes version that it is intended to be distributed use `--optional-values=k8s-version=1.22`\")\n\n\tfs.StringVarP(&c.outputFormat, \"output\", \"o\", validate.TextOutput,\n\t\t\"Result format for results. One of: [text, json-alpha1]. Note: output format types containing \"+\n\t\t\t\"\\\"alphaX\\\" are subject to change and not covered by guarantees of stable APIs.\")\n\n\t// alpha-select-external should be set to a Unix path list\n\t// (\"/path/to/e1.sh:/path/to/e2\") containing the list of entrypoints to\n\t// external (out of code tree) validator scripts or binaries to run.\n\t// Requirements for entrypoints:\n\t//  - Entrypoints must be executable by the user running the parent process.\n\t//  - The stdout output of an entrypoint *must* conform to the JSON\n\t//    representation of Result so results can be parsed and collated\n\t//    with other internal validators.\n\t//  - An entrypoint should exit 1 and print output to stderr only if the\n\t//    entrypoint itself fails for some reason. If the bundle fails to\n\t//    pass validation, that information  should be encoded in the Result\n\t//    printed to stdout as a Type=\\\"error\\\".\n\t//\n\t// WARNING: the script or binary at the base of this path will be\n\t// executed arbitrarily, so make sure you check the contents of that\n\t// script or binary prior to running.\n\tfs.StringVar(&c.alphaSelectExternal, \"alpha-select-external\", \"\",\n\t\t\"Selector to select external validators to run. It should be set to a Unix path list (\\\"/path/to/e1.sh:/path/to/e2\\\")\")\n}\n\nfunc (c bundleValidateCmd) run(logger *log.Entry, bundleRaw string) (res *validate.Result, err error) {\n\t// Create a registry to validate bundle files and optionally unpack the image with.\n\treg, err := newImageRegistryForTool(logger, c.imageBuilder)\n\tif err != nil {\n\t\treturn res, fmt.Errorf(\"error creating image registry: %v\", err)\n\t}\n\tdefer func() {\n\t\tif err := reg.Destroy(); err != nil {\n\t\t\tlogger.Errorf(\"Error destroying image registry: %v\", err)\n\t\t}\n\t}()\n\n\t// If bundle isn't a directory, assume it's an image.\n\tif isExist(bundleRaw) {\n\t\tif c.directory, err = relWd(bundleRaw); err != nil {\n\t\t\treturn res, err\n\t\t}\n\t} else {\n\t\tc.directory, err = os.MkdirTemp(\"\", \"bundle-\")\n\t\tif err != nil {\n\t\t\treturn res, err\n\t\t}\n\t\tdefer func() {\n\t\t\tif err := os.RemoveAll(c.directory); err != nil {\n\t\t\t\tlogger.Errorf(\"Error removing temp bundle dir: %v\", err)\n\t\t\t}\n\t\t}()\n\n\t\tlogger.Info(\"Unpacking image layers\")\n\n\t\tif err := c.unpackImageIntoDir(reg, bundleRaw, c.directory); err != nil {\n\t\t\treturn res, fmt.Errorf(\"error unpacking image %s: %v\", bundleRaw, err)\n\t\t}\n\t}\n\n\t// Read the bundle object and metadata from the created/passed in directory.\n\tbundle, mediaType, err := getBundleDataFromDir(c.directory)\n\tif err != nil {\n\t\treturn res, err\n\t}\n\n\t// Create Result to be output.\n\tres = validate.NewResult()\n\n\tlogger = logger.WithFields(log.Fields{\n\t\t\"bundle-dir\":     c.directory,\n\t\t\"container-tool\": c.imageBuilder,\n\t})\n\tval := registrybundle.NewImageValidator(reg, logger)\n\n\t// Validate bundle format.\n\tif err := val.ValidateBundleFormat(c.directory); err != nil {\n\t\tres.AddError(fmt.Errorf(\"error validating format in %s: %v\", c.directory, err))\n\t}\n\n\t// Validate bundle content.\n\tresults := internalregistry.ValidateBundleContent(logger, bundle, mediaType)\n\tres.AddManifestResults(results...)\n\n\t// Run optional validators.\n\tresults = runOptionalValidators(bundle, c.selector, c.optionalValues)\n\tres.AddManifestResults(results...)\n\n\t// TODO: (zeus) consider making this a runExternalValidators method similar\n\t// to the optional one above\n\n\t// Run external validators, if enabled.\n\tif entrypoints, isEnabled := validate.GetExternalValidatorEntrypoints(c.alphaSelectExternal); isEnabled {\n\t\tlogger.Debugf(\"Running external validators: %+q\", entrypoints)\n\t\t// TODO(estroz): enable timeout.\n\t\tctx := context.Background()\n\t\tress, err := validate.RunExternalValidators(ctx, entrypoints, c.directory)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tres.AddManifestResults(ress...)\n\t}\n\n\treturn res, nil\n}\n\n// list prints a list of validators that can be turned off/on by selectors to stdout.\nfunc (c bundleValidateCmd) list() error {\n\treturn listOptionalValidators(os.Stdout)\n}\n\n// getBundleDataFromDir returns the bundle object and associated metadata from dir, if any.\nfunc getBundleDataFromDir(dir string) (*apimanifests.Bundle, string, error) {\n\t// Gather bundle metadata.\n\tmetadata, _, err := internalregistry.FindBundleMetadata(dir)\n\tif err != nil {\n\t\treturn nil, \"\", err\n\t}\n\tmanifestsDirName, hasLabel := metadata.GetManifestsDir()\n\tif !hasLabel {\n\t\tmanifestsDirName = registrybundle.ManifestsDir\n\t}\n\tmanifestsDir := filepath.Join(dir, manifestsDirName)\n\t// Detect mediaType.\n\tmediaType, err := registrybundle.GetMediaType(manifestsDir)\n\tif err != nil {\n\t\treturn nil, \"\", err\n\t}\n\t// Read the bundle.\n\tbundle, err := apimanifests.GetBundleFromDir(manifestsDir)\n\tif err != nil {\n\t\treturn nil, \"\", err\n\t}\n\treturn bundle, mediaType, nil\n}\n\n// newImageRegistryForTool returns an image registry based on what type of image tool is passed.\n// If toolStr is empty, a containerd registry is returned.\nfunc newImageRegistryForTool(logger *log.Entry, toolStr string) (reg registryimage.Registry, err error) {\n\tswitch toolStr {\n\tcase containertools.DockerTool.String():\n\t\treg, err = execregistry.NewRegistry(containertools.DockerTool, logger)\n\tcase containertools.PodmanTool.String():\n\t\treg, err = execregistry.NewRegistry(containertools.PodmanTool, logger)\n\tcase containertools.NoneTool.String():\n\t\treg, err = containerdregistry.NewRegistry(\n\t\t\tcontainerdregistry.WithLog(logger),\n\t\t\t// In case reg.Destroy() fails in the caller, make it obvious where this cache came from.\n\t\t\tcontainerdregistry.WithCacheDir(filepath.Join(os.TempDir(), \"bundle-validate-cache\")),\n\t\t)\n\tdefault:\n\t\terr = fmt.Errorf(\"unrecognized image-builder option: %s\", toolStr)\n\t}\n\treturn reg, err\n}\n\n// unpackImageIntoDir writes files in image layers found in image imageTag to dir.\nfunc (c bundleValidateCmd) unpackImageIntoDir(reg registryimage.Registry, imageTag, dir string) error {\n\tlogger := log.WithFields(log.Fields{\n\t\t\"bundle-dir\":     dir,\n\t\t\"container-tool\": c.imageBuilder,\n\t})\n\tval := registrybundle.NewImageValidator(reg, logger)\n\n\treturn val.PullBundleImage(imageTag, dir)\n}\n\n// relWd returns the path of dir relative to the current working directory\nfunc relWd(dir string) (out string, err error) {\n\tif out, err = filepath.Abs(dir); err != nil {\n\t\treturn \"\", err\n\t}\n\twd, err := os.Getwd()\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\treturn filepath.Rel(wd, out)\n}\n\n// isExist returns true if path exists.\nfunc isExist(path string) bool {\n\t_, err := os.Stat(path)\n\treturn err == nil || os.IsExist(err)\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/bundle/validate/validate_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage validate\n\nimport (\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/pflag\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/validate\"\n)\n\nvar _ = Describe(\"Running a bundle validate command\", func() {\n\tDescribe(\"NewCmd\", func() {\n\t\tvar (\n\t\t\tcmd  = NewCmd()\n\t\t\tflag *pflag.Flag\n\t\t)\n\n\t\tIt(\"builds and returns a cobra command\", func() {\n\t\t\tExpect(cmd).NotTo(BeNil())\n\n\t\t\tflag = cmd.Flags().Lookup(\"image-builder\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\t\t\tExpect(flag.Shorthand).To(Equal(\"b\"))\n\t\t\tExpect(flag.DefValue).To(Equal(\"docker\"))\n\n\t\t\tflag = cmd.Flags().Lookup(\"select-optional\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\n\t\t\tflag = cmd.Flags().Lookup(\"list-optional\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\n\t\t\tflag = cmd.Flags().Lookup(\"output\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\t\t\tExpect(flag.Shorthand).To(Equal(\"o\"))\n\t\t\tExpect(flag.DefValue).To(Equal(validate.TextOutput))\n\t\t})\n\t})\n\n\tDescribe(\"Creating a logger\", func() {\n\t\tIt(\"that is Info Level when not verbose\", func() {\n\t\t\tverbose := false\n\t\t\tlogger := createLogger(verbose)\n\t\t\tExpect(logger.Logger.GetLevel()).To(Equal(log.InfoLevel))\n\t\t})\n\t\tIt(\"that is Debug level if verbose\", func() {\n\t\t\tverbose := true\n\t\t\tlogger := createLogger(verbose)\n\t\t\tExpect(logger.Logger.GetLevel()).To(Equal(log.DebugLevel))\n\t\t})\n\t})\n\n\tDescribe(\"validate\", func() {\n\t\tvar cmd bundleValidateCmd\n\t\tBeforeEach(func() {\n\t\t\tcmd = bundleValidateCmd{}\n\t\t})\n\n\t\tIt(\"fails with no args\", func() {\n\t\t\terr := cmd.validate([]string{})\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t\tExpect(err.Error()).To(Equal(\"an image tag or directory is a required argument\"))\n\t\t})\n\t\tIt(\"fails with more than one arg\", func() {\n\t\t\terr := cmd.validate([]string{\"a\", \"b\"})\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t\tExpect(err.Error()).To(Equal(\"an image tag or directory is a required argument\"))\n\t\t})\n\n\t\tIt(\"fails if the output format isnt text or json-alpha1\", func() {\n\t\t\twrongArg := \"json-alpha2\"\n\t\t\tcmd.outputFormat = wrongArg\n\t\t\terr := cmd.validate([]string{\"quay.io/person/example\"})\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t\tExpect(err.Error()).To(Equal(\"invalid value for output flag: \" + wrongArg))\n\t\t})\n\n\t\tIt(\"succeeds if the arg is text or json-alpha1\", func() {\n\t\t\tcmd.outputFormat = \"text\"\n\t\t\terr := cmd.validate([]string{\"quay.io/person/example\"})\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tcmd.outputFormat = \"json-alpha1\"\n\t\t\terr = cmd.validate([]string{\"quay.io/person/example\"})\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "internal/cmd/operator-sdk/cleanup/cmd.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage cleanup\n\nimport (\n\t\"context\"\n\t\"errors\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/cobra\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/olm/operator\"\n)\n\nfunc NewCmd() *cobra.Command {\n\tcfg := &operator.Configuration{}\n\tu := operator.NewUninstall(cfg)\n\tcmd := &cobra.Command{\n\t\tUse:     \"cleanup <operatorPackageName>\",\n\t\tShort:   \"Clean up an Operator deployed with the 'run' subcommand\",\n\t\tLong:    \"This command has subcommands that will destroy an Operator deployed with OLM.\",\n\t\tArgs:    cobra.ExactArgs(1),\n\t\tPreRunE: func(*cobra.Command, []string) error { return cfg.Load() },\n\t\tRun: func(cmd *cobra.Command, args []string) {\n\t\t\tu.Package = args[0]\n\t\t\tu.DeleteOperatorGroupNames = []string{operator.SDKOperatorGroupName}\n\t\t\tu.Logf = log.Infof\n\n\t\t\tctx, cancel := context.WithTimeout(cmd.Context(), cfg.Timeout)\n\t\t\tdefer cancel()\n\n\t\t\terr := u.Run(ctx)\n\t\t\tvar pkgErr *operator.ErrPackageNotFound\n\t\t\tswitch {\n\t\t\tcase errors.As(err, &pkgErr):\n\t\t\t\tlog.Warnf(\"Cleanup operator: %v\\n\", pkgErr)\n\t\t\tcase err != nil:\n\t\t\t\tlog.Fatalf(\"Cleanup operator: %v\\n\", err)\n\t\t\tdefault:\n\t\t\t\tlog.Infof(\"Operator %q uninstalled\\n\", u.Package)\n\t\t\t}\n\t\t},\n\t}\n\n\tcfg.BindFlags(cmd.Flags())\n\tu.BindFlags(cmd.Flags())\n\t// --service-account is meaningless here.\n\tif err := cmd.Flags().MarkHidden(\"service-account\"); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\treturn cmd\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/cli/cli.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage cli\n\nimport (\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/cobra\"\n\t\"github.com/spf13/viper\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/cli\"\n\tcfgv3 \"sigs.k8s.io/kubebuilder/v4/pkg/config/v3\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/model/stage\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/plugin\"\n\tkustomizev2 \"sigs.k8s.io/kubebuilder/v4/pkg/plugins/common/kustomize/v2\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/plugins/golang\"\n\n\tdeployimagev1alpha \"sigs.k8s.io/kubebuilder/v4/pkg/plugins/golang/deploy-image/v1alpha1\"\n\tgolangv4 \"sigs.k8s.io/kubebuilder/v4/pkg/plugins/golang/v4\"\n\tgrafanav1alpha \"sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/grafana/v1alpha\"\n\n\tansiblev1 \"github.com/operator-framework/ansible-operator-plugins/pkg/plugins/ansible/v1\"\n\t\"github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/alpha/config3alphato3\"\n\t\"github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/bundle\"\n\t\"github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/cleanup\"\n\t\"github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/generate\"\n\t\"github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/olm\"\n\t\"github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/pkgmantobundle\"\n\t\"github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/run\"\n\t\"github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/scorecard\"\n\t\"github.com/operator-framework/operator-sdk/internal/flags\"\n\t\"github.com/operator-framework/operator-sdk/internal/plugins\"\n\thelmv1 \"github.com/operator-framework/operator-sdk/internal/plugins/helm/v1\"\n\tmanifestsv2 \"github.com/operator-framework/operator-sdk/internal/plugins/manifests/v2\"\n\tscorecardv2 \"github.com/operator-framework/operator-sdk/internal/plugins/scorecard/v2\"\n\t\"github.com/operator-framework/operator-sdk/internal/util/projutil\"\n)\n\nvar (\n\tcommands = []*cobra.Command{\n\t\tbundle.NewCmd(),\n\t\tcleanup.NewCmd(),\n\t\tgenerate.NewCmd(),\n\t\tolm.NewCmd(),\n\t\trun.NewCmd(),\n\t\tscorecard.NewCmd(),\n\t\tpkgmantobundle.NewCmd(),\n\t}\n\talphaCommands = []*cobra.Command{\n\t\tconfig3alphato3.NewCmd(),\n\t}\n)\n\nfunc Run() error {\n\tc, _ := GetPluginsCLIAndRoot()\n\treturn c.Run()\n}\n\n// GetPluginsCLIAndRoot returns the plugins based CLI configured to use operator-sdk as the root command\n// This CLI can run kubebuilder commands and certain SDK specific commands that are aligned for\n// the kubebuilder project layout\nfunc GetPluginsCLIAndRoot() (*cli.CLI, *cobra.Command) {\n\tgov4Bundle, _ := plugin.NewBundleWithOptions(\n\t\tplugin.WithName(golang.DefaultNameQualifier),\n\t\tplugin.WithVersion(golangv4.Plugin{}.Version()),\n\t\tplugin.WithPlugins(\n\t\t\tkustomizev2.Plugin{},\n\t\t\tgolangv4.Plugin{},\n\t\t\tmanifestsv2.Plugin{},\n\t\t\tscorecardv2.Plugin{},\n\t\t),\n\t)\n\n\tansibleBundle, _ := plugin.NewBundleWithOptions(\n\t\tplugin.WithName(\"ansible\"+plugins.DefaultNameQualifier),\n\t\tplugin.WithVersion(plugin.Version{Number: 1}),\n\t\tplugin.WithPlugins(\n\t\t\tkustomizev2.Plugin{},\n\t\t\tansiblev1.Plugin{},\n\t\t\tmanifestsv2.Plugin{},\n\t\t\tscorecardv2.Plugin{},\n\t\t),\n\t)\n\n\thelmBundle, _ := plugin.NewBundleWithOptions(\n\t\tplugin.WithName(\"helm\"+plugins.DefaultNameQualifier),\n\t\tplugin.WithVersion(plugin.Version{Number: 1}),\n\t\tplugin.WithPlugins(\n\t\t\tkustomizev2.Plugin{},\n\t\t\thelmv1.Plugin{},\n\t\t\tmanifestsv2.Plugin{},\n\t\t\tscorecardv2.Plugin{},\n\t\t),\n\t)\n\n\tdeployImageBundle, _ := plugin.NewBundleWithOptions(\n\t\tplugin.WithName(\"deploy-image.\"+golang.DefaultNameQualifier),\n\t\tplugin.WithVersion(plugin.Version{Number: 1, Stage: stage.Alpha}),\n\t\tplugin.WithPlugins(\n\t\t\tdeployimagev1alpha.Plugin{},\n\t\t\tmanifestsv2.Plugin{},\n\t\t),\n\t)\n\tc, err := cli.New(\n\t\tcli.WithCommandName(\"operator-sdk\"),\n\t\tcli.WithVersion(makeVersionString()),\n\t\tcli.WithPlugins(\n\t\t\tansibleBundle,\n\t\t\tgov4Bundle,\n\t\t\thelmBundle,\n\t\t\tgrafanav1alpha.Plugin{},\n\t\t\tdeployImageBundle,\n\t\t),\n\t\tcli.WithDefaultPlugins(cfgv3.Version, gov4Bundle),\n\t\tcli.WithDefaultProjectVersion(cfgv3.Version),\n\t\tcli.WithExtraCommands(commands...),\n\t\tcli.WithExtraAlphaCommands(alphaCommands...),\n\t\tcli.WithCompletion(),\n\t)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// We can get the whole CLI for doc-gen/completion from the root of any\n\t// command added to a CLI.\n\troot := commands[0].Root()\n\n\t// Configure --verbose globally.\n\t// TODO(estroz): upstream PR for global --verbose.\n\troot.PersistentFlags().Bool(flags.VerboseOpt, false, \"Enable verbose logging\")\n\tif err := viper.BindPFlags(root.PersistentFlags()); err != nil {\n\t\tlog.Fatalf(\"Failed to bind %s flags: %v\", root.Name(), err)\n\t}\n\troot.PersistentPreRun = rootPersistentPreRun\n\n\treturn c, root\n}\n\nfunc rootPersistentPreRun(cmd *cobra.Command, args []string) {\n\tif viper.GetBool(flags.VerboseOpt) {\n\t\tif err := projutil.SetGoVerbose(); err != nil {\n\t\t\tlog.Fatalf(\"Could not set GOFLAGS: (%v)\", err)\n\t\t}\n\t\tlog.SetLevel(log.DebugLevel)\n\t\tlog.Debug(\"Debug logging is set\")\n\t}\n\n\tconfig3alphato3.RootPersistentPreRun(cmd, args)\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/cli/cli_suite_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage cli\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nfunc TestVersion(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"CLI Suite\")\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/cli/version.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage cli\n\nimport (\n\t\"fmt\"\n\t\"runtime\"\n\n\tver \"github.com/operator-framework/operator-sdk/internal/version\"\n)\n\nfunc makeVersionString() string {\n\treturn fmt.Sprintf(\"operator-sdk version: %q, commit: %q, kubernetes version: %q, go version: %q, GOOS: %q, GOARCH: %q\",\n\t\tver.GitVersion, ver.GitCommit, ver.KubernetesVersion, runtime.Version(), runtime.GOOS, runtime.GOARCH)\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/cli/version_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage cli\n\nimport (\n\t\"fmt\"\n\t\"runtime\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\n\tver \"github.com/operator-framework/operator-sdk/internal/version\"\n)\n\nvar _ = Describe(\"printVersion\", func() {\n\tIt(\"prints the correct version info\", func() {\n\t\texpVersion := makeVersionString()\n\t\tversion := ver.GitVersion\n\t\tif version == \"unknown\" {\n\t\t\tversion = ver.Version\n\t\t}\n\t\tExpect(expVersion).To(ContainSubstring(fmt.Sprintf(\"version: %q\", version)))\n\t\tExpect(expVersion).To(ContainSubstring(fmt.Sprintf(\"commit: %q\", ver.GitCommit)))\n\t\tExpect(expVersion).To(ContainSubstring(fmt.Sprintf(\"kubernetes version: %q\", ver.KubernetesVersion)))\n\t\tExpect(expVersion).To(ContainSubstring(fmt.Sprintf(\"go version: %q\", runtime.Version())))\n\t\tExpect(expVersion).To(ContainSubstring(fmt.Sprintf(\"GOOS: %q\", runtime.GOOS)))\n\t\tExpect(expVersion).To(ContainSubstring(fmt.Sprintf(\"GOARCH: %q\", runtime.GOARCH)))\n\t})\n})\n"
  },
  {
    "path": "internal/cmd/operator-sdk/generate/bundle/bundle.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage bundle\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\n\t\"sigs.k8s.io/yaml\"\n\n\t\"github.com/operator-framework/api/pkg/apis/scorecard/v1alpha3\"\n\t\"github.com/operator-framework/operator-manifest-tools/pkg/image\"\n\t\"github.com/operator-framework/operator-manifest-tools/pkg/imageresolver\"\n\t\"github.com/operator-framework/operator-manifest-tools/pkg/pullspec\"\n\t\"github.com/operator-framework/operator-registry/pkg/lib/bundle\"\n\tmetricsannotations \"github.com/operator-framework/operator-sdk/internal/annotations/metrics\"\n\tgenutil \"github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/generate/internal\"\n\tgencsv \"github.com/operator-framework/operator-sdk/internal/generate/clusterserviceversion\"\n\t\"github.com/operator-framework/operator-sdk/internal/generate/clusterserviceversion/bases\"\n\t\"github.com/operator-framework/operator-sdk/internal/generate/collector\"\n\t\"github.com/operator-framework/operator-sdk/internal/registry\"\n\t\"github.com/operator-framework/operator-sdk/internal/scorecard\"\n\t\"github.com/operator-framework/operator-sdk/internal/util/bundleutil\"\n)\n\nconst (\n\tlongHelp = `\nRunning 'generate bundle' is the first step to publishing your operator to a catalog and deploying it with OLM.\nThis command both generates and packages files into an on-disk representation of an operator called a bundle.\nA bundle consists of a ClusterServiceVersion (CSV), CustomResourceDefinitions (CRDs),\nmanifests not part of the CSV but required by the operator, some metadata (annotations.yaml),\nand a bundle.Dockerfile to build a bundle image.\n\nA CSV manifest is generated by collecting data from the set of manifests passed to this command (see below),\nsuch as CRDs, RBAC, etc., and applying that data to a \"base\" CSV manifest. This base CSV can contain metadata,\nadded by hand or by the 'generate kustomize manifests' command, and can be passed in like any other manifest\n(see below) or by file at the exact path '<kustomize-dir>/bases/<package-name>.clusterserviceversion.yaml'.\nBe aware that 'generate bundle' idempotently regenerates a bundle, so all non-metadata values in a base\nwill be overwritten. If no base was passed in, input manifest data will be applied to an empty CSV.\n\nThere are two ways to pass the to-be-bundled set of manifests to this command: stdin via a Unix pipe,\nor in a directory using '--input-dir'. See command help for more information on these modes.\nPassing a directory is useful for running 'generate bundle' outside of a project or within a project\nthat does not use kustomize and/or contains cluster-ready manifests on disk.\n\nSet '--version' to supply a semantic version for your bundle if you are creating one\nfor the first time or upgrading an existing one.\n\nIf '--output-dir' is set and you wish to build bundle images from that directory,\neither manually update your bundle.Dockerfile or set '--overwrite'.\n\nMore information on bundles:\nhttps://github.com/operator-framework/operator-registry/#manifest-format\n`\n\n\texamples = `\n  # If running within a project or in a project that uses kustomize to generate manifests,\n\t# make sure a kustomize directory exists that looks like the following 'config/manifests' directory:\n  $ tree config/manifests\n  config/manifests\n  ├── bases\n  │   └── memcached-operator.clusterserviceversion.yaml\n  └── kustomization.yaml\n\n  # Generate a 0.0.1 bundle by passing manifests to stdin:\n  $ kustomize build config/manifests | operator-sdk generate bundle --version 0.0.1\n  Generating bundle version 0.0.1\n  ...\n\n  # If running outside of a project or in a project that does not use kustomize to generate manifests,\n\t# make sure cluster-ready manifests are available on disk:\n  $ tree deploy/\n  deploy/\n  ├── crds\n  │   └── cache.my.domain_memcacheds.yaml\n  ├── deployment.yaml\n  ├── role.yaml\n  ├── role_binding.yaml\n  ├── service_account.yaml\n  └── webhooks.yaml\n\n  # Generate a 0.0.1 bundle by passing manifests by dir:\n  $ operator-sdk generate bundle --input-dir deploy --version 0.0.1\n  Generating bundle version 0.0.1\n  ...\n\n  # After running in either of the above modes, you should see this directory structure:\n  $ tree bundle/\n  bundle/\n  ├── manifests\n  │   ├── cache.my.domain_memcacheds.yaml\n  │   └── memcached-operator.clusterserviceversion.yaml\n  └── metadata\n      └── annotations.yaml\n`\n)\n\n// defaultRootDir is the default root directory in which to generate bundle files.\nconst defaultRootDir = \"bundle\"\n\n// setDefaults sets defaults useful to all modes of this subcommand.\nfunc (c *bundleCmd) setDefaults() (err error) {\n\tif c.packageName, c.layout, err = genutil.GetPackageNameAndLayout(c.packageName); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// validateManifests validates c for bundle manifests generation.\nfunc (c bundleCmd) validateManifests() (err error) {\n\tif c.version != \"\" {\n\t\tif err := genutil.ValidateVersion(c.version); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// The three possible usage modes (stdin, inputDir, and legacy dirs) are mutually exclusive\n\t// and one must be chosen.\n\tisPipeReader := genutil.IsPipeReader()\n\tisInputDir := c.inputDir != \"\"\n\tisLegacyDirs := c.deployDir != \"\" || c.crdsDir != \"\"\n\tswitch {\n\tcase !isPipeReader && !isInputDir && !isLegacyDirs:\n\t\treturn errors.New(\"one of stdin, --input-dir, or --deploy-dir (and optionally --crds-dir) must be set\")\n\tcase isPipeReader && (isInputDir || isLegacyDirs):\n\t\treturn errors.New(\"none of --input-dir, --deploy-dir, or --crds-dir may be set if reading from stdin\")\n\tcase isInputDir && isLegacyDirs:\n\t\treturn errors.New(\"only one of --input-dir or --deploy-dir (and optionally --crds-dir) may be set if not reading from stdin\")\n\t}\n\n\tif c.stdout {\n\t\tif c.outputDir != \"\" {\n\t\t\treturn errors.New(\"--output-dir cannot be set if writing to stdout\")\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// TODO: Move this to bundleutil package\n// runManifests generates bundle manifests.\nfunc (c bundleCmd) runManifests() (err error) {\n\n\tc.println(\"Generating bundle manifests\")\n\n\tif !c.stdout && c.outputDir == \"\" {\n\t\tc.outputDir = defaultRootDir\n\t}\n\n\tcol := &collector.Manifests{}\n\tswitch {\n\tcase genutil.IsPipeReader():\n\t\terr = col.UpdateFromReader(os.Stdin)\n\tcase c.deployDir != \"\" && c.crdsDir != \"\":\n\t\terr = col.UpdateFromDirs(c.deployDir, c.crdsDir)\n\tcase c.deployDir != \"\": // If only deployDir is set, use as input dir.\n\t\tc.inputDir = c.deployDir\n\t\tfallthrough\n\tcase c.inputDir != \"\":\n\t\terr = col.UpdateFromDir(c.inputDir)\n\t}\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// If no CSV was initially read, a kustomize base can be used at the default base path.\n\t// Only read from kustomizeDir if a base exists so users can still generate a barebones CSV.\n\tbaseCSVPath := filepath.Join(c.kustomizeDir, \"bases\", c.packageName+\".clusterserviceversion.yaml\")\n\tif noCSVStdin := len(col.ClusterServiceVersions) == 0; noCSVStdin && genutil.IsExist(baseCSVPath) {\n\t\tbase, err := bases.ClusterServiceVersion{BasePath: baseCSVPath}.GetBase()\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error reading CSV base: %v\", err)\n\t\t}\n\t\tcol.ClusterServiceVersions = append(col.ClusterServiceVersions, *base)\n\t} else if noCSVStdin {\n\t\tc.println(\"Building a ClusterServiceVersion without an existing base\")\n\t}\n\n\trelatedImages, err := genutil.FindRelatedImages(col)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tvar opts []gencsv.Option\n\tstdout := genutil.NewMultiManifestWriter(os.Stdout)\n\tif c.stdout {\n\t\topts = append(opts, gencsv.WithWriter(stdout))\n\t} else {\n\t\topts = append(opts, gencsv.WithBundleWriter(c.outputDir))\n\t}\n\n\tcsvGen := gencsv.Generator{\n\t\tOperatorName:         c.packageName,\n\t\tVersion:              c.version,\n\t\tCollector:            col,\n\t\tAnnotations:          metricsannotations.MakeBundleObjectAnnotations(c.layout),\n\t\tExtraServiceAccounts: c.extraServiceAccounts,\n\t\tRelatedImages:        relatedImages,\n\t}\n\tif err := csvGen.Generate(opts...); err != nil {\n\t\treturn fmt.Errorf(\"error generating ClusterServiceVersion: %v\", err)\n\t}\n\n\tobjs := genutil.GetManifestObjects(col, c.extraServiceAccounts)\n\tif c.stdout {\n\t\tif err := genutil.WriteObjects(stdout, objs...); err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\tdir := filepath.Join(c.outputDir, bundle.ManifestsDir)\n\t\tif err := genutil.WriteObjectsToFiles(dir, objs...); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// Pin images to digests if enabled\n\tif c.useImageDigests {\n\t\tc.println(\"pinning image versions to digests instead of tags\")\n\t\tif err := c.pinImages(filepath.Join(c.outputDir, \"manifests\")); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// Write the scorecard config if it was passed.\n\tif err := writeScorecardConfig(c.outputDir, col.ScorecardConfig); err != nil {\n\t\treturn fmt.Errorf(\"error writing bundle scorecard config: %v\", err)\n\t}\n\n\tc.println(\"Bundle manifests generated successfully in\", c.outputDir)\n\n\treturn nil\n\n}\n\n// writeScorecardConfig writes cfg to dir at the hard-coded config path 'config.yaml'.\nfunc writeScorecardConfig(dir string, cfg v1alpha3.Configuration) error {\n\t// Skip writing if config is empty.\n\tif cfg.Metadata.Name == \"\" {\n\t\treturn nil\n\t}\n\n\tb, err := yaml.Marshal(cfg)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tcfgDir := filepath.Join(dir, filepath.FromSlash(scorecard.DefaultConfigDir))\n\tif err := os.MkdirAll(cfgDir, 0755); err != nil {\n\t\treturn err\n\t}\n\tscorecardConfigPath := filepath.Join(cfgDir, scorecard.ConfigFileName)\n\treturn os.WriteFile(scorecardConfigPath, b, 0666)\n}\n\n// runMetadata generates a bundle.Dockerfile and bundle metadata.\nfunc (c bundleCmd) runMetadata() error {\n\tc.println(\"Generating bundle metadata\")\n\tif c.outputDir == \"\" {\n\t\tc.outputDir = defaultRootDir\n\t}\n\n\t// If metadata already exists, only overwrite it if directed to.\n\tbundleRoot := c.inputDir\n\tif bundleRoot == \"\" {\n\t\tbundleRoot = c.outputDir\n\t}\n\n\t// Find metadata from output directory only of it exists on disk.\n\tif genutil.IsExist(bundleRoot) {\n\t\tif _, _, err := registry.FindBundleMetadata(bundleRoot); err != nil {\n\t\t\tmerr := registry.MetadataNotFoundError(\"\")\n\t\t\tif !errors.As(err, &merr) {\n\t\t\t\treturn err\n\t\t\t}\n\t\t} else if !c.overwrite {\n\t\t\treturn nil\n\t\t}\n\t}\n\n\tscorecardConfigPath := filepath.Join(bundleRoot, scorecard.DefaultConfigDir, scorecard.ConfigFileName)\n\n\tbundleMetadata := bundleutil.BundleMetaData{\n\t\tBundleDir:            c.outputDir,\n\t\tPackageName:          c.packageName,\n\t\tChannels:             c.channels,\n\t\tDefaultChannel:       c.defaultChannel,\n\t\tOtherLabels:          metricsannotations.MakeBundleMetadataLabels(c.layout),\n\t\tIsScoreConfigPresent: genutil.IsExist(scorecardConfigPath),\n\t}\n\n\treturn bundleMetadata.GenerateMetadata()\n}\n\n// pinImages is used to replace all image tags in the given manifests with digests\nfunc (c bundleCmd) pinImages(manifestPath string) error {\n\tmanifests, err := pullspec.FromDirectory(manifestPath, nil)\n\tif err != nil {\n\t\treturn err\n\t}\n\tresolverArgs := make(map[string]string)\n\tresolverArgs[\"usedefault\"] = \"true\"\n\tresolver, err := imageresolver.GetResolver(imageresolver.ResolverCrane, resolverArgs)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif err := image.Pin(resolver, manifests); err != nil {\n\t\treturn err\n\t}\n\n\tfor _, manifest := range manifests {\n\t\tif err := manifest.Dump(nil); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/generate/bundle/cmd.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage bundle\n\nimport (\n\t\"fmt\"\n\t\"path/filepath\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/cobra\"\n\t\"github.com/spf13/pflag\"\n)\n\n//nolint:maligned\ntype bundleCmd struct {\n\t// Options to turn on different parts of bundling.\n\tmanifests bool\n\tmetadata  bool\n\n\t// Common options.\n\tversion      string\n\tinputDir     string\n\toutputDir    string\n\tkustomizeDir string\n\tdeployDir    string\n\tcrdsDir      string\n\tstdout       bool\n\tquiet        bool\n\t// ServiceAccount names to consider outside of the operator's service account.\n\textraServiceAccounts []string\n\n\t// Metadata options.\n\tchannels       string\n\tdefaultChannel string\n\toverwrite      bool\n\n\t// These are set if a PROJECT config is not present.\n\tlayout      string\n\tpackageName string\n\n\t// Use Image Digests flag to toggle using traditional Image tags vs SHA Digests\n\tuseImageDigests bool\n}\n\n// NewCmd returns the 'bundle' command configured for the new project layout.\nfunc NewCmd() *cobra.Command {\n\tc := &bundleCmd{}\n\tcmd := &cobra.Command{\n\t\tUse:     \"bundle\",\n\t\tShort:   \"Generates bundle data for the operator\",\n\t\tLong:    longHelp,\n\t\tExample: examples,\n\t\tRunE: func(cmd *cobra.Command, args []string) error {\n\t\t\tif len(args) != 0 {\n\t\t\t\treturn fmt.Errorf(\"command %s doesn't accept any arguments\", cmd.CommandPath())\n\t\t\t}\n\n\t\t\t// Generate manifests and metadata by default if no flags are set so the default behavior is \"do everything\".\n\t\t\tfs := cmd.Flags()\n\t\t\tif !fs.Changed(\"metadata\") && !fs.Changed(\"manifests\") {\n\t\t\t\tc.manifests = true\n\t\t\t\tc.metadata = true\n\t\t\t\tif c.version == \"\" {\n\t\t\t\t\tc.println(\"Generating bundle\")\n\t\t\t\t} else {\n\t\t\t\t\tc.println(\"Generating bundle version\", c.version)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif err := c.setDefaults(); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\t// Validate command args before running so a preceding mode doesn't run\n\t\t\t// before a following validation fails.\n\t\t\tif c.manifests {\n\t\t\t\tif err := c.validateManifests(); err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"invalid command options: %v\", err)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Run command logic.\n\t\t\tif c.manifests {\n\t\t\t\tif err := c.runManifests(); err != nil {\n\t\t\t\t\tlog.Fatalf(\"Error generating bundle manifests: %v\", err)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif c.metadata {\n\t\t\t\tif err := c.runMetadata(); err != nil {\n\t\t\t\t\tlog.Fatalf(\"Error generating bundle metadata: %v\", err)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn nil\n\t\t},\n\t}\n\n\tc.addFlagsTo(cmd.Flags())\n\n\treturn cmd\n}\n\nfunc (c *bundleCmd) addFlagsTo(fs *pflag.FlagSet) {\n\tfs.BoolVar(&c.manifests, \"manifests\", false, \"Generate bundle manifests\")\n\tfs.BoolVar(&c.metadata, \"metadata\", false, \"Generate bundle metadata and Dockerfile\")\n\n\tfs.StringVarP(&c.version, \"version\", \"v\", \"\", \"Semantic version of the operator in the generated bundle. \"+\n\t\t\"Only set if creating a new bundle or upgrading your operator\")\n\tfs.StringVar(&c.inputDir, \"input-dir\", \"\", \"Directory to read cluster-ready operator manifests from. \"+\n\t\t\"This option is mutually exclusive with --deploy-dir/--crds-dir and piping to stdin. \"+\n\t\t\"This option should not be passed an existing bundle directory, as this bundle will not contain the correct \"+\n\t\t\"set of manifests required to generate a CSV. Use --kustomize-dir to pass a base CSV\")\n\tfs.StringVar(&c.outputDir, \"output-dir\", \"\", \"Directory to write the bundle to\")\n\t// TODO(estroz): deprecate this in favor of --intput-dir.\n\tfs.StringVar(&c.deployDir, \"deploy-dir\", \"\", \"Directory to read cluster-ready operator manifests from. \"+\n\t\t\"If --crds-dir is not set, CRDs are ready from this directory. \"+\n\t\t\"This option is mutually exclusive with --input-dir and piping to stdin\")\n\t// TODO(estroz): deprecate this in favor of --intput-dir.\n\tfs.StringVar(&c.crdsDir, \"crds-dir\", \"\", \"Directory to read cluster-ready CustomResoureDefinition manifests from. \"+\n\t\t\"This option can only be used if --deploy-dir is set\")\n\tfs.StringVar(&c.kustomizeDir, \"kustomize-dir\", filepath.Join(\"config\", \"manifests\"),\n\t\t\"Directory containing kustomize bases in a \\\"bases\\\" dir and a kustomization.yaml for operator-framework manifests\")\n\tfs.StringVar(&c.channels, \"channels\", \"alpha\", \"A comma-separated list of channels the bundle belongs to\")\n\tfs.StringVar(&c.defaultChannel, \"default-channel\", \"\", \"The default channel for the bundle\")\n\tfs.StringSliceVar(&c.extraServiceAccounts, \"extra-service-accounts\", nil,\n\t\t\"Names of service accounts, outside of the operator's Deployment account, \"+\n\t\t\t\"that have bindings to {Cluster}Roles that should be added to the CSV\")\n\tfs.BoolVar(&c.overwrite, \"overwrite\", true, \"Overwrite the bundle's metadata and Dockerfile if they exist\")\n\tfs.BoolVarP(&c.quiet, \"quiet\", \"q\", false, \"Run in quiet mode\")\n\tfs.BoolVar(&c.stdout, \"stdout\", false, \"Write bundle manifest to stdout\")\n\n\tfs.StringVar(&c.packageName, \"package\", \"\", \"Bundle's package name\")\n\n\tfs.BoolVar(&c.useImageDigests, \"use-image-digests\", false, \"Use SHA Digest for images\")\n}\n\nfunc (c bundleCmd) println(a ...any) {\n\tif !c.quiet && !c.stdout {\n\t\tfmt.Println(a...)\n\t}\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/generate/cmd.go",
    "content": "// Copyright 2018 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage generate\n\nimport (\n\t\"github.com/spf13/cobra\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/generate/bundle\"\n\t\"github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/generate/kustomize\"\n\t\"github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/generate/packagemanifests\"\n)\n\n// NewCmd returns the 'generate' command configured for the new project layout.\nfunc NewCmd() *cobra.Command {\n\tcmd := &cobra.Command{\n\t\tUse:   \"generate <generator>\",\n\t\tShort: \"Invokes a specific generator\",\n\t\tLong: `The 'operator-sdk generate' command invokes a specific generator to generate\ncode or manifests.`,\n\t}\n\n\tcmd.AddCommand(\n\t\tkustomize.NewCmd(),\n\t\tbundle.NewCmd(),\n\t\tpackagemanifests.NewCmd(),\n\t)\n\treturn cmd\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/generate/internal/genutil.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage genutil\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/blang/semver/v4\"\n\t\"github.com/operator-framework/operator-sdk/internal/util/projutil\"\n\tapiextv1 \"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1\"\n\tapiextv1beta1 \"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client\"\n\t\"sigs.k8s.io/yaml\"\n)\n\n// ValidateVersion returns an error if version is not a strict semantic version.\nfunc ValidateVersion(version string) error {\n\tv, err := semver.Parse(version)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"%s is not a valid semantic version: %v\", version, err)\n\t}\n\t// Ensures numerical values composing csvVersion don't contain leading 0's,\n\t// ex. 01.01.01\n\tif v.String() != version {\n\t\treturn fmt.Errorf(\"version %s contains bad values (parses to %s)\", version, v)\n\t}\n\treturn nil\n}\n\n// IsPipeReader returns true if stdin is an open pipe, i.e. the caller can\n// accept input from stdin.\nfunc IsPipeReader() bool {\n\tinfo, err := os.Stdin.Stat()\n\tif err != nil {\n\t\treturn false\n\t}\n\treturn info.Mode()&os.ModeNamedPipe != 0\n}\n\n// WriteObjects writes each object in objs to w.\nfunc WriteObjects(w io.Writer, objs ...client.Object) error {\n\tfor _, obj := range objs {\n\t\tif err := writeObject(w, obj); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\n// WriteObjectsToFiles creates dir then writes each object in objs to a file in dir.\nfunc WriteObjectsToFiles(dir string, objs ...client.Object) error {\n\tif err := os.MkdirAll(dir, 0755); err != nil {\n\t\treturn err\n\t}\n\n\tseenFiles := make(map[string]struct{})\n\t// Use the number of dupliates in file names so users can debug duplicate file behavior.\n\tdupCount := 0\n\tfor _, obj := range objs {\n\t\tvar fileName string\n\t\tswitch t := obj.(type) {\n\t\tcase *apiextv1.CustomResourceDefinition:\n\t\t\tif t.Spec.Group != \"\" && t.Spec.Names.Plural != \"\" {\n\t\t\t\tfileName = makeCRDFileName(t.Spec.Group, t.Spec.Names.Plural)\n\t\t\t} else {\n\t\t\t\tfileName = makeObjectFileName(t)\n\t\t\t}\n\t\tcase *apiextv1beta1.CustomResourceDefinition:\n\t\t\tif t.Spec.Group != \"\" && t.Spec.Names.Plural != \"\" {\n\t\t\t\tfileName = makeCRDFileName(t.Spec.Group, t.Spec.Names.Plural)\n\t\t\t} else {\n\t\t\t\tfileName = makeObjectFileName(t)\n\t\t\t}\n\t\tdefault:\n\t\t\tfileName = makeObjectFileName(t)\n\t\t}\n\n\t\tif _, hasFile := seenFiles[fileName]; hasFile {\n\t\t\tfileName = fmt.Sprintf(\"dup%d_%s\", dupCount, fileName)\n\t\t\tdupCount++\n\t\t}\n\t\tif err := writeObjectToFile(dir, obj, fileName); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tseenFiles[fileName] = struct{}{}\n\t}\n\treturn nil\n}\n\nfunc makeCRDFileName(group, resource string) string {\n\treturn fmt.Sprintf(\"%s_%s.yaml\", group, resource)\n}\n\nfunc makeObjectFileName(obj client.Object) string {\n\tgvk := obj.GetObjectKind().GroupVersionKind()\n\tif gvk.Group == \"\" {\n\t\treturn fmt.Sprintf(\"%s_%s_%s.yaml\", obj.GetName(), gvk.Version, strings.ToLower(gvk.Kind))\n\t}\n\treturn fmt.Sprintf(\"%s_%s_%s_%s.yaml\", obj.GetName(), gvk.Group, gvk.Version, strings.ToLower(gvk.Kind))\n}\n\n// writeObjectToFile marshals crd to bytes and writes them to dir in file.\nfunc writeObjectToFile(dir string, obj any, fileName string) error {\n\tf, err := os.Create(filepath.Join(dir, fileName))\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer f.Close()\n\treturn writeObject(f, obj)\n}\n\n// writeObject marshals crd to bytes and writes them to w.\nfunc writeObject(w io.Writer, obj any) error {\n\tb, err := yaml.Marshal(obj)\n\tif err != nil {\n\t\treturn err\n\t}\n\t_, err = w.Write(b)\n\treturn err\n}\n\n// multiManifestWriter writes a multi-part manifest by prepending \"---\"\n// to the argument of io.Writer.Write().\ntype multiManifestWriter struct {\n\tio.Writer\n}\n\nfunc (w *multiManifestWriter) Write(b []byte) (int, error) {\n\treturn w.Writer.Write(append([]byte(\"\\n---\\n\"), bytes.TrimSpace(b)...))\n}\n\n// NewMultiManifestWriter returns a multi-part manifest writer. Use this writer\n// if writing a package or bundle to stdout or a single file.\nfunc NewMultiManifestWriter(w io.Writer) io.Writer {\n\treturn &multiManifestWriter{w}\n}\n\n// IsNotExist returns true if path does not exist on disk.\nfunc IsNotExist(path string) bool {\n\tif path == \"\" {\n\t\treturn true\n\t}\n\t_, err := os.Stat(path)\n\treturn err != nil && errors.Is(err, os.ErrNotExist)\n}\n\n// IsExist returns true if path exists on disk.\nfunc IsExist(path string) bool {\n\tif path == \"\" {\n\t\treturn false\n\t}\n\t_, err := os.Stat(path)\n\treturn err == nil || errors.Is(err, os.ErrExist)\n}\n\n// GetPackageNameAndLayout returns packageName and layout, if any, for a project.\n// These values are determined by project version and whether a PROJECT file exists.\nfunc GetPackageNameAndLayout(defaultPackageName string) (packageName string, layout string, _ error) {\n\tpackageName = defaultPackageName\n\tif projutil.HasProjectFile() {\n\t\tcfg, err := projutil.ReadConfig()\n\t\tif err != nil {\n\t\t\treturn \"\", \"\", err\n\t\t}\n\t\tif packageName == \"\" {\n\t\t\tpackageName = cfg.GetProjectName()\n\t\t\tif packageName == \"\" {\n\t\t\t\treturn \"\", \"\", errors.New(\"--package <name> must be set if \\\"projectName\\\" is not set in the PROJECT config file\")\n\t\t\t}\n\t\t}\n\t\tlayout = projutil.GetProjectLayout(cfg)\n\t} else {\n\t\tif packageName == \"\" {\n\t\t\treturn \"\", \"\", errors.New(\"--package <name> must be set if PROJECT config file is not present\")\n\t\t}\n\t\tlayout = \"unknown\"\n\t}\n\treturn packageName, layout, nil\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/generate/internal/genutil_suite_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage genutil\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nfunc TestGenutil(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"Collector Suite\")\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/generate/internal/manifests.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage genutil\n\nimport (\n\t\"github.com/operator-framework/operator-registry/pkg/lib/bundle\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/generate/collector\"\n)\n\n// GetManifestObjects returns all objects to be written to a manifests directory from collector.Manifests.\nfunc GetManifestObjects(c *collector.Manifests, extraSAs []string) (objs []client.Object) {\n\t// All CRDs passed in should be written.\n\tfor i := range c.V1CustomResourceDefinitions {\n\t\tobjs = append(objs, &c.V1CustomResourceDefinitions[i])\n\t}\n\tfor i := range c.V1beta1CustomResourceDefinitions {\n\t\tobjs = append(objs, &c.V1beta1CustomResourceDefinitions[i])\n\t}\n\n\t// All Services passed in should be written.\n\tfor i := range c.Services {\n\t\tobjs = append(objs, &c.Services[i])\n\t}\n\n\t// Add all other supported kinds\n\tfor i := range c.Others {\n\t\tobj := &c.Others[i]\n\t\tif supported, _ := bundle.IsSupported(obj.GroupVersionKind().Kind); supported {\n\t\t\tobjs = append(objs, obj)\n\t\t}\n\t}\n\n\t// RBAC objects (including ServiceAccounts) that are not a part of the CSV should be written.\n\t_, _, rbacObjs := c.SplitCSVPermissionsObjects(extraSAs)\n\tobjs = append(objs, rbacObjs...)\n\n\tremoveNamespace(objs)\n\treturn objs\n}\n\n// removeNamespace removes the namespace field of resources intended to be inserted into\n// an OLM manifests directory.\n//\n// This is required to pass OLM validations which require that namespaced resources do\n// not include explicit namespace settings. OLM automatically installs namespaced\n// resources in the same namespace that the operator is installed in, which is determined\n// at runtime, not bundle/packagemanifests creation time.\nfunc removeNamespace(objs []client.Object) {\n\tfor _, obj := range objs {\n\t\tobj.SetNamespace(\"\")\n\t}\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/generate/internal/manifests_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage genutil\n\nimport (\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\trbacv1 \"k8s.io/api/rbac/v1\"\n\tapiextensionsv1 \"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1\"\n\tapiextensionsv1beta1 \"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/generate/collector\"\n)\n\nvar _ = Describe(\"GetManifestObjects\", func() {\n\tIt(\"should unset the namespace\", func() {\n\t\tm := collector.Manifests{\n\t\t\tRoles: []rbacv1.Role{\n\t\t\t\t{ObjectMeta: metav1.ObjectMeta{Namespace: \"foo\", Name: \"foo\"}},\n\t\t\t\t{ObjectMeta: metav1.ObjectMeta{Namespace: \"bar\"}},\n\t\t\t},\n\t\t\tClusterRoles: []rbacv1.ClusterRole{\n\t\t\t\t{ObjectMeta: metav1.ObjectMeta{Namespace: \"bar\"}},\n\t\t\t},\n\t\t\tServiceAccounts: []corev1.ServiceAccount{\n\t\t\t\t{ObjectMeta: metav1.ObjectMeta{Namespace: \"foo\", Name: \"foo\"}},\n\t\t\t\t{ObjectMeta: metav1.ObjectMeta{Namespace: \"bar\"}},\n\t\t\t},\n\t\t\tV1beta1CustomResourceDefinitions: []apiextensionsv1beta1.CustomResourceDefinition{\n\t\t\t\t{ObjectMeta: metav1.ObjectMeta{Namespace: \"bar\"}},\n\t\t\t},\n\t\t\tV1CustomResourceDefinitions: []apiextensionsv1.CustomResourceDefinition{\n\t\t\t\t{ObjectMeta: metav1.ObjectMeta{Namespace: \"bar\"}},\n\t\t\t},\n\t\t}\n\t\tobjs := GetManifestObjects(&m, nil)\n\t\tExpect(objs).To(HaveLen(len(m.Roles) + len(m.ClusterRoles) + len(m.ServiceAccounts) + len(m.V1CustomResourceDefinitions) + len(m.V1beta1CustomResourceDefinitions)))\n\t\tfor _, obj := range objs {\n\t\t\tExpect(obj.GetNamespace()).To(BeEmpty())\n\t\t}\n\t})\n})\n"
  },
  {
    "path": "internal/cmd/operator-sdk/generate/internal/relatedimages.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage genutil\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\n\toperatorsv1alpha1 \"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\t\"github.com/operator-framework/operator-sdk/internal/generate/collector\"\n\tlog \"github.com/sirupsen/logrus\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\t\"k8s.io/utils/set\"\n)\n\n// FindRelatedImages looks in the controller manager's environment for images used by the operator.\nfunc FindRelatedImages(manifestCol *collector.Manifests) ([]operatorsv1alpha1.RelatedImage, error) {\n\tcol := relatedImageCollector{\n\t\trelatedImages:           []*relatedImage{},\n\t\trelatedImagesByName:     make(map[string][]*relatedImage),\n\t\trelatedImagesByImageRef: make(map[string][]*relatedImage),\n\t\tseenRelatedImages:       set.Set[string]{},\n\t}\n\n\tfor _, deployment := range manifestCol.Deployments {\n\t\tcontainers := append(deployment.Spec.Template.Spec.Containers, deployment.Spec.Template.Spec.InitContainers...)\n\t\tfor _, container := range containers {\n\t\t\t// containerRef can just be the deployment if there's only one container\n\t\t\t// otherwise we need {{ deployment.Name }}-{{ container.Name }}\n\t\t\tcontainerRef := deployment.Name\n\t\t\tif len(containers) > 1 {\n\t\t\t\tcontainerRef += \"-\" + container.Name\n\t\t\t}\n\n\t\t\tif err := col.collectFromEnvironment(containerRef, container.Env); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\t}\n\n\treturn col.collectedRelatedImages(), nil\n}\n\nconst relatedImagePrefix = \"RELATED_IMAGE_\"\n\ntype relatedImage struct {\n\tname         string\n\timageRef     string\n\tcontainerRef string // If 1 container then {{deployment}} else {{deployment}}-{{container}}\n}\n\ntype relatedImageCollector struct {\n\trelatedImages           []*relatedImage\n\trelatedImagesByName     map[string][]*relatedImage\n\trelatedImagesByImageRef map[string][]*relatedImage\n\tseenRelatedImages       set.Set[string]\n}\n\nfunc (c *relatedImageCollector) collectFromEnvironment(containerRef string, env []corev1.EnvVar) error {\n\tfor _, envVar := range env {\n\t\tif strings.HasPrefix(envVar.Name, relatedImagePrefix) {\n\t\t\tif envVar.ValueFrom != nil {\n\t\t\t\treturn fmt.Errorf(\"related images with valueFrom field unsupported, found in %s`\", envVar.Name)\n\t\t\t}\n\n\t\t\tname := c.formatName(envVar.Name)\n\t\t\tc.collect(name, envVar.Value, containerRef)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (c *relatedImageCollector) collect(name, imageRef, containerRef string) {\n\t// Don't add exact duplicates (same name and image)\n\tkey := name + \"-\" + imageRef\n\tif c.seenRelatedImages.Has(key) {\n\t\treturn\n\t}\n\tc.seenRelatedImages.Insert(key)\n\n\trelatedImg := relatedImage{\n\t\tname:         name,\n\t\timageRef:     imageRef,\n\t\tcontainerRef: containerRef,\n\t}\n\n\tc.relatedImages = append(c.relatedImages, &relatedImg)\n\tif relatedImages, ok := c.relatedImagesByName[name]; ok {\n\t\tc.relatedImagesByName[name] = append(relatedImages, &relatedImg)\n\t} else {\n\t\tc.relatedImagesByName[name] = []*relatedImage{&relatedImg}\n\t}\n\n\tif relatedImages, ok := c.relatedImagesByImageRef[imageRef]; ok {\n\t\tc.relatedImagesByImageRef[imageRef] = append(relatedImages, &relatedImg)\n\t} else {\n\t\tc.relatedImagesByImageRef[imageRef] = []*relatedImage{&relatedImg}\n\t}\n}\n\nfunc (c *relatedImageCollector) collectedRelatedImages() []operatorsv1alpha1.RelatedImage {\n\tfinal := make([]operatorsv1alpha1.RelatedImage, 0, len(c.relatedImages))\n\n\tfor _, relatedImage := range c.relatedImages {\n\t\tname := relatedImage.name\n\n\t\t// Prefix the name with the containerRef on name collisions.\n\t\tif len(c.relatedImagesByName[relatedImage.name]) > 1 {\n\t\t\tname = relatedImage.containerRef + \"-\" + name\n\t\t}\n\n\t\t// Only add the related image to the final list if it's the first occurrence of an image.\n\t\t// Blank out the name since the image is used multiple times and warn the user.\n\t\t// Multiple containers using she same related image should use the same exact name.\n\t\tif relatedImages := c.relatedImagesByImageRef[relatedImage.imageRef]; len(relatedImages) > 1 {\n\t\t\tif relatedImages[0].name != relatedImage.name {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tname = \"\"\n\t\t\tlog.Warnf(\n\t\t\t\t\"warning: multiple related images with the same image ref, %q, and different names found.\"+\n\t\t\t\t\t\"The image will only be listed once with an empty name.\"+\n\t\t\t\t\t\"It is recmmended to either remove the duplicate or use the exact same name.\",\n\t\t\t\trelatedImage.name,\n\t\t\t)\n\t\t}\n\n\t\tfinal = append(final, operatorsv1alpha1.RelatedImage{Name: name, Image: relatedImage.imageRef})\n\t}\n\n\treturn final\n}\n\n// formatName transforms RELATED_IMAGE_This_IS_a_cool_image to this-is-a-cool-image\nfunc (c *relatedImageCollector) formatName(name string) string {\n\treturn strings.ToLower(strings.ReplaceAll(strings.TrimPrefix(name, relatedImagePrefix), \"_\", \"-\"))\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/generate/internal/relatedimages_test.go",
    "content": "// Copyright 2022 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage genutil_test\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"strings\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\toperatorsv1alpha1 \"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\tgenutil \"github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/generate/internal\"\n\t\"github.com/operator-framework/operator-sdk/internal/generate/collector\"\n\tlog \"github.com/sirupsen/logrus\"\n\tappsv1 \"k8s.io/api/apps/v1\"\n\tcorev1 \"k8s.io/api/core/v1\"\n)\n\nvar _ = BeforeSuite(func() {\n\tlog.SetOutput(io.Discard)\n})\n\nvar _ = Describe(\"FindRelatedImages\", func() {\n\tvar images = struct {\n\t\tmemcached       string\n\t\tmemcachedLatest string\n\t\tnginx           string\n\t}{\"memcached:1.4.36-alpine\", \"memcached:alpine\", \"nginx:1.21.6\"}\n\n\tDescribeTable(\"Valid related image definitions\",\n\t\tfunc(deployments []appsv1.Deployment, expected []operatorsv1alpha1.RelatedImage) {\n\t\t\tcol := collector.Manifests{Deployments: deployments}\n\t\t\trelatedImages, err := genutil.FindRelatedImages(&col)\n\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\tExpect(relatedImages).To(Equal(expected))\n\t\t},\n\t\tEntry(\"One related image\", []appsv1.Deployment{\n\t\t\tdeployment(\"controller-manager\", container(\"manager\", relatedImageEnvVar(\"MEMCACHED\", images.memcached))),\n\t\t}, []operatorsv1alpha1.RelatedImage{\n\t\t\trelatedImage(\"memcached\", images.memcached),\n\t\t}),\n\t\tEntry(\"Two related images\", []appsv1.Deployment{\n\t\t\tdeployment(\"controller-manager\", container(\"manager\",\n\t\t\t\trelatedImageEnvVar(\"MEMCACHED\", images.memcached),\n\t\t\t\trelatedImageEnvVar(\"NGINX\", images.nginx),\n\t\t\t)),\n\t\t}, []operatorsv1alpha1.RelatedImage{\n\t\t\trelatedImage(\"memcached\", images.memcached),\n\t\t\trelatedImage(\"nginx\", images.nginx),\n\t\t}),\n\t\tEntry(\"No related images\", []appsv1.Deployment{\n\t\t\tdeployment(\"controller-manager\", container(\"manager\")),\n\t\t}, []operatorsv1alpha1.RelatedImage{}),\n\t\tEntry(\"Two related image across different containers\", []appsv1.Deployment{\n\t\t\tdeployment(\"controller-manager\",\n\t\t\t\tcontainer(\"manager\", relatedImageEnvVar(\"MEMCACHED\", images.memcached)),\n\t\t\t\tcontainer(\"manager-proxy\", relatedImageEnvVar(\"NGINX\", images.nginx)),\n\t\t\t),\n\t\t}, []operatorsv1alpha1.RelatedImage{\n\t\t\trelatedImage(\"memcached\", images.memcached),\n\t\t\trelatedImage(\"nginx\", images.nginx),\n\t\t}),\n\t\tEntry(\"Two related image across different deployments\", []appsv1.Deployment{\n\t\t\tdeployment(\"controller-manager\", container(\"manager\", relatedImageEnvVar(\"MEMCACHED\", images.memcached))),\n\t\t\tdeployment(\"controller-manager-proxy\", container(\"proxy\", relatedImageEnvVar(\"NGINX\", images.nginx))),\n\t\t}, []operatorsv1alpha1.RelatedImage{\n\t\t\trelatedImage(\"memcached\", images.memcached),\n\t\t\trelatedImage(\"nginx\", images.nginx),\n\t\t}),\n\t\tEntry(\"Two related images with the same name and image\", []appsv1.Deployment{\n\t\t\tdeployment(\"controller-manager\",\n\t\t\t\tcontainer(\"manager\", relatedImageEnvVar(\"MEMCACHED\", images.memcached)),\n\t\t\t\tcontainer(\"manager-canary\", relatedImageEnvVar(\"MEMCACHED\", images.memcached)),\n\t\t\t),\n\t\t}, []operatorsv1alpha1.RelatedImage{\n\t\t\trelatedImage(\"memcached\", images.memcached),\n\t\t}),\n\t\tEntry(\"Two related images with the same name and different images\", []appsv1.Deployment{\n\t\t\tdeployment(\"controller-manager\",\n\t\t\t\tcontainer(\"manager\", relatedImageEnvVar(\"MEMCACHED\", images.memcached)),\n\t\t\t\tcontainer(\"manager-canary\", relatedImageEnvVar(\"MEMCACHED\", images.memcachedLatest)),\n\t\t\t),\n\t\t}, []operatorsv1alpha1.RelatedImage{\n\t\t\trelatedImage(\"controller-manager-manager-memcached\", images.memcached),\n\t\t\trelatedImage(\"controller-manager-manager-canary-memcached\", images.memcachedLatest),\n\t\t}),\n\t\tEntry(\"Two related images with the same name and different images in separate deployments\", []appsv1.Deployment{\n\t\t\tdeployment(\"controller-manager\", container(\"manager\", relatedImageEnvVar(\"MEMCACHED\", images.memcached))),\n\t\t\tdeployment(\"controller-manager-canary\",\n\t\t\t\tcontainer(\"manager\", relatedImageEnvVar(\"MEMCACHED\", images.memcachedLatest)),\n\t\t\t),\n\t\t}, []operatorsv1alpha1.RelatedImage{\n\t\t\trelatedImage(\"controller-manager-memcached\", images.memcached),\n\t\t\trelatedImage(\"controller-manager-canary-memcached\", images.memcachedLatest),\n\t\t}),\n\t\tEntry(\"Two related images with different names and the same image\", []appsv1.Deployment{\n\t\t\tdeployment(\"controller-manager\",\n\t\t\t\tcontainer(\"manager\", relatedImageEnvVar(\"MEMCACHED\", images.memcached)),\n\t\t\t\tcontainer(\"manager-canary\", relatedImageEnvVar(\"MEMCACHED_CANARY\", images.memcached)),\n\t\t\t),\n\t\t}, []operatorsv1alpha1.RelatedImage{\n\t\t\trelatedImage(\"\", images.memcached),\n\t\t}),\n\t\tEntry(\"Three related images with both a name and image overlap\", []appsv1.Deployment{\n\t\t\tdeployment(\"controller-manager\",\n\t\t\t\tcontainer(\"manager\", relatedImageEnvVar(\"MEMCACHED\", images.memcached)),\n\t\t\t\tcontainer(\"manager-replica\", relatedImageEnvVar(\"MEMCACHED\", images.memcachedLatest)),\n\t\t\t\tcontainer(\"manager-canary\", relatedImageEnvVar(\"MEMCACHED_CANARY\", images.memcached)),\n\t\t\t),\n\t\t}, []operatorsv1alpha1.RelatedImage{\n\t\t\trelatedImage(\"\", images.memcached),\n\t\t\trelatedImage(\"controller-manager-manager-replica-memcached\", images.memcachedLatest),\n\t\t}),\n\t)\n\n\tContext(\"There is an invald environment variable\", func() {\n\t\tvar (\n\t\t\trelatedImages []operatorsv1alpha1.RelatedImage\n\t\t\terr           error\n\t\t)\n\n\t\tBeforeEach(func() {\n\t\t\td := deployment(\"controller-manager\",\n\t\t\t\tcontainer(\"manager\", relatedImageEnvVar(\"MEMCACHED\", images.memcached)),\n\t\t\t)\n\t\t\td.Spec.Template.Spec.Containers[0].Env[0].Value = \"\"\n\t\t\td.Spec.Template.Spec.Containers[0].Env[0].ValueFrom = &corev1.EnvVarSource{}\n\t\t\tcol := collector.Manifests{Deployments: []appsv1.Deployment{d}}\n\t\t\trelatedImages, err = genutil.FindRelatedImages(&col)\n\t\t})\n\n\t\tIt(\"should return an error\", func() {\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t})\n\n\t\tIt(\"should not return any related images\", func() {\n\t\t\tExpect(relatedImages).To(BeNil())\n\t\t})\n\n\t\tIt(\"should tell you which environment variable was invalid\", func() {\n\t\t\tExpect(err.Error()).To(ContainSubstring(\"RELATED_IMAGE_MEMCACHED\"))\n\t\t})\n\t})\n})\n\nvar _ = AfterSuite(func() {\n\tlog.SetOutput(os.Stdout)\n})\n\nfunc relatedImage(name, image string) operatorsv1alpha1.RelatedImage {\n\treturn operatorsv1alpha1.RelatedImage{Name: name, Image: image}\n}\n\nfunc relatedImageEnvVar(name, image string) string {\n\treturn fmt.Sprintf(\"RELATED_IMAGE_%s=%s\", name, image)\n}\n\nfunc deployment(name string, containers ...corev1.Container) appsv1.Deployment {\n\tvar d appsv1.Deployment\n\td.Name = name\n\td.Spec.Template.Spec.Containers = containers\n\treturn d\n}\n\nfunc container(name string, envVars ...string) corev1.Container {\n\tvar c corev1.Container\n\tc.Name = name\n\tc.Env = make([]corev1.EnvVar, len(envVars))\n\tfor i, envVar := range envVars {\n\t\tenvVarParts := strings.Split(envVar, \"=\")\n\t\tif len(envVarParts) != 2 {\n\t\t\tpanic(\"invalid environment variable: \" + envVar + \"\\nShould be in the form 'name=value'\")\n\t\t}\n\n\t\tc.Env[i] = corev1.EnvVar{Name: envVarParts[0], Value: envVarParts[1]}\n\t}\n\n\treturn c\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/generate/kustomize/cmd.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage kustomize\n\nimport (\n\t\"github.com/spf13/cobra\"\n)\n\n// NewCmd returns the 'kustomize' subcommand.\nfunc NewCmd() *cobra.Command {\n\tcmd := &cobra.Command{\n\t\tUse:   \"kustomize\",\n\t\tShort: \"Contains subcommands that generate operator-framework kustomize data for the operator\",\n\t}\n\n\tcmd.AddCommand(\n\t\tnewManifestsCmd(),\n\t)\n\n\treturn cmd\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/generate/kustomize/manifests.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage kustomize\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\tmanifestsv2 \"github.com/operator-framework/operator-sdk/internal/plugins/manifests/v2\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/afero\"\n\t\"github.com/spf13/cobra\"\n\t\"github.com/spf13/pflag\"\n\t\"k8s.io/apimachinery/pkg/runtime/schema\"\n\t\"k8s.io/apimachinery/pkg/util/validation\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/config\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/machinery\"\n\t\"sigs.k8s.io/yaml\"\n\n\tgenutil \"github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/generate/internal\"\n\t\"github.com/operator-framework/operator-sdk/internal/generate/clusterserviceversion/bases\"\n\ttemplatemanifests \"github.com/operator-framework/operator-sdk/internal/plugins/manifests/v2/templates/config/manifests\"\n\t\"github.com/operator-framework/operator-sdk/internal/util/k8sutil\"\n\t\"github.com/operator-framework/operator-sdk/internal/util/projutil\"\n)\n\nconst longHelp = `\nRunning 'generate kustomize manifests' will (re)generate kustomize bases and a kustomization.yaml in\n'config/manifests', which are used to build operator-framework manifests by other operator-sdk commands.\nThis command will interactively ask for UI metadata, an important component of manifest bases,\nby default unless a base already exists or you set '--interactive=false'.\n`\n\nconst examples = `\n  $ operator-sdk generate kustomize manifests\n\n  Display name for the operator (required):\n  > memcached-operator\n  ...\n\n  $ tree config/manifests\n  config/manifests\n  ├── bases\n  │   └── memcached-operator.clusterserviceversion.yaml\n  └── kustomization.yaml\n\n  # After generating kustomize bases and a kustomization.yaml, you can generate a bundle or package manifests.\n\n  # To generate a bundle:\n  $ kustomize build config/manifests | operator-sdk generate bundle --version 0.0.1\n\n  # To generate package manifests:\n  $ kustomize build config/manifests | operator-sdk generate packagemanifests --version 0.0.1\n`\n\n//nolint:maligned\ntype manifestsCmd struct {\n\tpackageName string\n\tinputDir    string\n\toutputDir   string\n\tapisDir     string\n\tquiet       bool\n\n\t// Interactive options.\n\tinteractiveLevel projutil.InteractiveLevel\n\tinteractive      bool\n}\n\n// newManifestsCmd returns the 'manifests' command configured for the new project layout.\nfunc newManifestsCmd() *cobra.Command {\n\tc := &manifestsCmd{}\n\tcmd := &cobra.Command{\n\t\tUse:     \"manifests\",\n\t\tShort:   \"Generates kustomize bases and a kustomization.yaml for operator-framework manifests\",\n\t\tLong:    longHelp,\n\t\tExample: examples,\n\t\tRunE: func(cmd *cobra.Command, args []string) error {\n\t\t\tif len(args) != 0 {\n\t\t\t\treturn fmt.Errorf(\"command %s doesn't accept any arguments\", cmd.CommandPath())\n\t\t\t}\n\n\t\t\t// Check if the user has any specific preference to enable/disable interactive prompts.\n\t\t\t// Default behaviour is to disable the prompt unless a base does not exist.\n\t\t\tif cmd.Flags().Changed(\"interactive\") {\n\t\t\t\tif c.interactive {\n\t\t\t\t\tc.interactiveLevel = projutil.InteractiveOnAll\n\t\t\t\t} else {\n\t\t\t\t\tc.interactiveLevel = projutil.InteractiveHardOff\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcfg, err := projutil.ReadConfig()\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"error reading configuration: %v\", err)\n\t\t\t}\n\n\t\t\tif err = c.setDefaults(cfg); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\t// Run command logic.\n\t\t\tif err = c.run(cfg); err != nil {\n\t\t\t\tlog.Fatalf(\"Error generating kustomize files: %v\", err)\n\t\t\t}\n\n\t\t\treturn nil\n\t\t},\n\t}\n\n\tc.addFlagsTo(cmd.Flags())\n\n\treturn cmd\n}\n\nfunc (c *manifestsCmd) addFlagsTo(fs *pflag.FlagSet) {\n\tfs.StringVar(&c.packageName, \"package\", \"\", \"Package name\")\n\tfs.StringVar(&c.inputDir, \"input-dir\", \"\", \"Directory containing existing kustomize files\")\n\tfs.StringVar(&c.outputDir, \"output-dir\", \"\", \"Directory to write kustomize files\")\n\tfs.StringVar(&c.apisDir, \"apis-dir\", \"\", \"Root directory for API type defintions\")\n\tfs.BoolVarP(&c.quiet, \"quiet\", \"q\", false, \"Run in quiet mode\")\n\tfs.BoolVar(&c.interactive, \"interactive\", false, \"When set to false, if no kustomize base exists, an interactive \"+\n\t\t\"command prompt will be presented to accept non-inferrable metadata\")\n}\n\n// defaultDir is the default directory in which to generate kustomize bases and the kustomization.yaml.\nvar defaultDir = filepath.Join(\"config\", \"manifests\")\n\n// setDefaults sets command defaults.\nfunc (c *manifestsCmd) setDefaults(cfg config.Config) error {\n\tif c.packageName == \"\" {\n\t\tc.packageName = cfg.GetProjectName()\n\t}\n\n\tif c.inputDir == \"\" {\n\t\tc.inputDir = defaultDir\n\t}\n\tif c.outputDir == \"\" {\n\t\tc.outputDir = defaultDir\n\t}\n\n\tif c.apisDir == \"\" {\n\t\tc.apisDir = \"api\"\n\t}\n\treturn nil\n}\n\n// run generates kustomize bundle bases and a kustomization.yaml if one does not exist.\nfunc (c manifestsCmd) run(cfg config.Config) error {\n\n\tif !c.quiet {\n\t\tfmt.Println(\"Generating kustomize files in\", c.outputDir)\n\t}\n\n\t// Older config layouts do not have a ProjectName field, so use the current directory name.\n\tif c.packageName == \"\" {\n\t\tdir, err := os.Getwd()\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error getting current directory: %v\", err)\n\t\t}\n\t\tc.packageName = strings.ToLower(filepath.Base(dir))\n\t\tif err := validation.IsDNS1123Label(c.packageName); err != nil {\n\t\t\treturn fmt.Errorf(\"project name (%s) is invalid: %v\", c.packageName, err)\n\t\t}\n\t}\n\n\toperatorType := projutil.PluginChainToOperatorType(cfg.GetPluginChain())\n\trelBasePath := filepath.Join(\"bases\", c.packageName+\".clusterserviceversion.yaml\")\n\tbasePath := filepath.Join(c.inputDir, relBasePath)\n\tgvks, err := getGVKs(cfg)\n\tif err != nil {\n\t\treturn err\n\t}\n\tbase := bases.ClusterServiceVersion{\n\t\tOperatorName: c.packageName,\n\t\tOperatorType: operatorType,\n\t\tAPIsDir:      c.apisDir,\n\t\tInteractive:  requiresInteraction(basePath, c.interactiveLevel),\n\t\tGVKs:         gvks,\n\t}\n\t// Set BasePath only if it exists. If it doesn't, a new base will be generated\n\t// if BasePath is empty.\n\tif genutil.IsExist(basePath) {\n\t\tbase.BasePath = basePath\n\t}\n\tcsv, err := base.GetBase()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error getting ClusterServiceVersion base: %v\", err)\n\t}\n\n\tcsvBytes, err := k8sutil.GetObjectBytes(csv, yaml.Marshal)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error marshaling CSV base: %v\", err)\n\t}\n\n\t// todo: remove it when the OLM starts to support https://github.com/operator-framework/api/pull/100\n\tconst cleanup = \"cleanup:\\n    enabled: false\\n  \"\n\tcsvBytes = bytes.ReplaceAll(csvBytes, []byte(cleanup), []byte(\"\"))\n\n\tif err = os.MkdirAll(filepath.Join(c.outputDir, \"bases\"), 0755); err != nil {\n\t\treturn err\n\t}\n\toutputPath := filepath.Join(c.outputDir, relBasePath)\n\tif err = os.WriteFile(outputPath, csvBytes, 0644); err != nil {\n\t\treturn fmt.Errorf(\"error writing CSV base: %v\", err)\n\t}\n\n\t// Write a kustomization.yaml to outputDir if one does not exist.\n\tkustomization := templatemanifests.Kustomization{\n\t\t// we need perform different scaffold when we know that is using kustomize version 4.x\n\t\t// and is Golang Type\n\t\tSupportsKustomizeV4: manifestsv2.HasSupportForKustomizeV4(cfg),\n\t\tSupportsWebhooks:    operatorType == projutil.OperatorTypeGo,\n\t}\n\t// Ensure the path to the manifest directory is correctly carried through\n\tkustomization.Path = c.outputDir\n\terr = machinery.NewScaffold(machinery.Filesystem{FS: afero.NewOsFs()}, machinery.WithConfig(cfg)).Execute(\n\t\t&kustomization,\n\t)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error scaffolding manifests: %v\", err)\n\t}\n\n\tif !c.quiet {\n\t\tfmt.Println(\"Kustomize files generated successfully\")\n\t}\n\n\treturn nil\n}\n\n// requiresInteraction checks if the combination of ilvl and basePath existence\n// requires the generator prompt a user interactively.\nfunc requiresInteraction(basePath string, ilvl projutil.InteractiveLevel) bool {\n\treturn (ilvl == projutil.InteractiveSoftOff && genutil.IsNotExist(basePath)) || ilvl == projutil.InteractiveOnAll\n}\n\nfunc getGVKs(cfg config.Config) ([]schema.GroupVersionKind, error) {\n\tresources, err := cfg.GetResources()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tgvks := make([]schema.GroupVersionKind, len(resources))\n\tfor i, gvk := range resources {\n\t\tgvks[i].Group = gvk.QualifiedGroup()\n\t\tgvks[i].Version = gvk.Version\n\t\tgvks[i].Kind = gvk.Kind\n\t}\n\treturn gvks, nil\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/generate/packagemanifests/cmd.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage packagemanifests\n\nimport (\n\t\"fmt\"\n\t\"path/filepath\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/cobra\"\n\t\"github.com/spf13/pflag\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/generate/packagemanifest\"\n)\n\n//nolint:maligned\ntype packagemanifestsCmd struct {\n\t// Common options.\n\tversion       string\n\tfromVersion   string\n\tinputDir      string\n\toutputDir     string\n\tkustomizeDir  string\n\tdeployDir     string\n\tcrdsDir       string\n\tupdateObjects bool\n\tstdout        bool\n\tquiet         bool\n\n\t// Package manifest options.\n\tchannelName      string\n\tisDefaultChannel bool\n\n\t// These are set if a PROJECT config is not present.\n\tlayout      string\n\tpackageName string\n\t// Backend generator\n\tgenerator packagemanifest.Generator\n}\n\n// NewCmd returns the 'packagemanifests' command configured for the new project layout.\nfunc NewCmd() *cobra.Command {\n\tc := &packagemanifestsCmd{}\n\n\tcmd := &cobra.Command{\n\t\tUse: \"packagemanifests\",\n\t\tDeprecated: \"support for the packagemanifests format will be removed in operator-sdk v2.0.0. Use bundles \" +\n\t\t\t\"to package your operator instead. Migrate your packagemanifest to a bundle using \" +\n\t\t\t\"'operator-sdk pkgman-to-bundle' command. Run 'operator-sdk pkgman-to-bundle --help' \" +\n\t\t\t\"for more details.\",\n\t\tShort:   \"Generates package manifests data for the operator\",\n\t\tLong:    longHelp,\n\t\tExample: examples,\n\t\tRunE: func(cmd *cobra.Command, args []string) error {\n\t\t\tif len(args) != 0 {\n\t\t\t\treturn fmt.Errorf(\"command %s doesn't accept any arguments\", cmd.CommandPath())\n\t\t\t}\n\n\t\t\tif err := c.setDefaults(); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tif err := c.validate(); err != nil {\n\t\t\t\treturn fmt.Errorf(\"invalid command options: %v\", err)\n\t\t\t}\n\t\t\tif err := c.run(); err != nil {\n\t\t\t\tlog.Fatalf(\"Error generating package manifests: %v\", err)\n\t\t\t}\n\n\t\t\treturn nil\n\t\t},\n\t}\n\n\tc.addFlagsTo(cmd.Flags())\n\n\treturn cmd\n}\n\nfunc (c *packagemanifestsCmd) addFlagsTo(fs *pflag.FlagSet) {\n\tfs.StringVarP(&c.version, \"version\", \"v\", \"\", \"Semantic version of the packaged operator\")\n\tfs.StringVar(&c.fromVersion, \"from-version\", \"\", \"Semantic version of the operator being upgraded from\")\n\tfs.StringVar(&c.inputDir, \"input-dir\", defaultRootDir, \"Directory to read existing package manifests from. \"+\n\t\t\"This directory is the parent of individual versioned package directories, and different from --deploy-dir\")\n\tfs.StringVar(&c.outputDir, \"output-dir\", \"\", \"Directory in which to write package manifests\")\n\tfs.StringVar(&c.kustomizeDir, \"kustomize-dir\", filepath.Join(\"config\", \"manifests\"),\n\t\t\"Directory containing kustomize bases in a \\\"bases\\\" dir and a kustomization.yaml for operator-framework manifests\")\n\tfs.StringVar(&c.deployDir, \"deploy-dir\", \"\", \"Directory to read cluster-ready operator manifests from. \"+\n\t\t\"If --crds-dir is not set, CRDs are ready from this directory\")\n\tfs.StringVar(&c.crdsDir, \"crds-dir\", \"\", \"Directory to read cluster-ready CustomResoureDefinition manifests from. \"+\n\t\t\"This option can only be used if --deploy-dir is set\")\n\tfs.StringVar(&c.channelName, \"channel\", \"\", \"Channel name for the generated package\")\n\tfs.BoolVar(&c.isDefaultChannel, \"default-channel\", false, \"Use the channel passed to --channel \"+\n\t\t\"as the package manifest file's default channel\")\n\tfs.BoolVar(&c.updateObjects, \"update-objects\", true, \"Update non-CSV objects in this package, \"+\n\t\t\"ex. CustomResoureDefinitions, Roles\")\n\tfs.BoolVarP(&c.quiet, \"quiet\", \"q\", false, \"Run in quiet mode\")\n\tfs.BoolVar(&c.stdout, \"stdout\", false, \"Write package to stdout\")\n\n\tfs.StringVar(&c.packageName, \"package\", \"\", \"Package name\")\n}\n\nfunc (c packagemanifestsCmd) println(a ...any) {\n\tif !c.quiet && !c.stdout {\n\t\tfmt.Println(a...)\n\t}\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/generate/packagemanifests/cmd_test.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage packagemanifests\n\nimport (\n\t\"path/filepath\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nvar _ = Describe(\"Creating a generate packagemanifests command\", func() {\n\tDescribe(\"NewCmd\", func() {\n\t\tIt(\"builds and returns a cobra command\", func() {\n\t\t\tcmd := NewCmd()\n\t\t\tExpect(cmd).NotTo(BeNil())\n\n\t\t\tflag := cmd.Flags().Lookup(\"version\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\t\t\tExpect(flag.Shorthand).To(Equal(\"v\"))\n\t\t\tExpect(flag.Usage).ToNot(Equal(\"\"))\n\n\t\t\tflag = cmd.Flags().Lookup(\"from-version\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\t\t\tExpect(flag.Usage).ToNot(Equal(\"\"))\n\n\t\t\tflag = cmd.Flags().Lookup(\"input-dir\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\t\t\tExpect(flag.Usage).ToNot(Equal(\"\"))\n\n\t\t\tflag = cmd.Flags().Lookup(\"output-dir\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\t\t\tExpect(flag.Usage).ToNot(Equal(\"\"))\n\n\t\t\tflag = cmd.Flags().Lookup(\"kustomize-dir\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\t\t\tExpect(flag.DefValue).To(Equal(filepath.Join(\"config\", \"manifests\")))\n\t\t\tExpect(flag.Usage).ToNot(Equal(\"\"))\n\n\t\t\tflag = cmd.Flags().Lookup(\"deploy-dir\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\t\t\tExpect(flag.Usage).ToNot(Equal(\"\"))\n\n\t\t\tflag = cmd.Flags().Lookup(\"crds-dir\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\t\t\tExpect(flag.Usage).ToNot(Equal(\"\"))\n\n\t\t\tflag = cmd.Flags().Lookup(\"channel\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\t\t\tExpect(flag.Usage).ToNot(Equal(\"\"))\n\n\t\t\tflag = cmd.Flags().Lookup(\"default-channel\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\t\t\tExpect(flag.DefValue).To(Equal(\"false\"))\n\t\t\tExpect(flag.Usage).ToNot(Equal(\"\"))\n\n\t\t\tflag = cmd.Flags().Lookup(\"update-objects\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\t\t\tExpect(flag.DefValue).To(Equal(\"true\"))\n\t\t\tExpect(flag.Usage).ToNot(Equal(\"\"))\n\n\t\t\tflag = cmd.Flags().Lookup(\"quiet\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\t\t\tExpect(flag.Shorthand).To(Equal(\"q\"))\n\t\t\tExpect(flag.DefValue).To(Equal(\"false\"))\n\t\t\tExpect(flag.Usage).ToNot(Equal(\"\"))\n\n\t\t\tflag = cmd.Flags().Lookup(\"stdout\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\t\t\tExpect(flag.DefValue).To(Equal(\"false\"))\n\t\t\tExpect(flag.Usage).ToNot(Equal(\"\"))\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage packagemanifests\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\n\tmetricsannotations \"github.com/operator-framework/operator-sdk/internal/annotations/metrics\"\n\tgenutil \"github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/generate/internal\"\n\tgencsv \"github.com/operator-framework/operator-sdk/internal/generate/clusterserviceversion\"\n\t\"github.com/operator-framework/operator-sdk/internal/generate/clusterserviceversion/bases\"\n\t\"github.com/operator-framework/operator-sdk/internal/generate/collector\"\n\tgenpkg \"github.com/operator-framework/operator-sdk/internal/generate/packagemanifest\"\n)\n\nconst (\n\tlongHelp = `\nThis command generates a set of manifests in a versioned directory and a package manifest file for\nyour operator. Each versioned directory consists of a ClusterServiceVersion (CSV), CustomResourceDefinitions (CRDs),\nand manifests not part of the CSV but required by the operator.\n\nA CSV manifest is generated by collecting data from the set of manifests passed to this command (see below),\nsuch as CRDs, RBAC, etc., and applying that data to a \"base\" CSV manifest. This base CSV can contain metadata,\nadded by hand or by the 'generate kustomize manifests' command, and can be passed in like any other manifest\n(see below) or by file at the exact path '<kustomize-dir>/bases/<package-name>.clusterserviceversion.yaml'.\nBe aware that 'generate packagemanifests' idempotently regenerates a packagemanifests directory,\nso all non-metadata values in a base will be overwritten. If no base was passed in, input manifest data\nwill be applied to an empty CSV.\n\nThere are two ways to pass the to-be-packaged set of manifests to this command: stdin via a Unix pipe,\nor in a directory using '--input-dir'. See command help for more information on these modes.\nPassing a directory is useful for running 'generate packagemanifests' outside of a project or within a project\nthat does not use kustomize and/or contains cluster-ready manifests on disk.\n\nSet '--version' to supply a semantic version for your new package.\n\nMore information on the package manifests format:\nhttps://github.com/operator-framework/operator-registry/#manifest-format\n`\n\n\texamples = `\n  # If running within a project, make sure a 'config' kustomize directory exists and has a 'config/manifests':\n  $ tree config/manifests\n  config/manifests\n  ├── bases\n  │   └── memcached-operator.clusterserviceversion.yaml\n  └── kustomization.yaml\n\n  # Generate a 0.0.1 packagemanifests by passing manifests to stdin:\n  $ kustomize build config/manifests | operator-sdk generate packagemanifests --version 0.0.1\n  Generating package manifests version 0.0.1\n  ...\n\n  # If running outside of a project, make sure cluster-ready manifests are available on disk:\n  $ tree deploy/\n  deploy/\n  ├── crds\n  │   └── cache.my.domain_memcacheds.yaml\n  ├── deployment.yaml\n  ├── role.yaml\n  ├── role_binding.yaml\n  ├── service_account.yaml\n  └── webhooks.yaml\n\n  # Generate a 0.0.1 packagemanifests by passing manifests by dir:\n  $ operator-sdk generate packagemanifests --deploy-dir deploy --version 0.0.1\n  Generating package manifests version 0.0.1\n  ...\n\n  # After running in either of the above modes, you should see this directory structure:\n  $ tree packagemanifests/\n  packagemanifests/\n  ├── 0.0.1\n  │   ├── cache.my.domain_memcacheds.yaml\n  │   └── memcached-operator.clusterserviceversion.yaml\n  └── memcached-operator.package.yaml\n`\n)\n\n// defaultRootDir is the default root directory in which to generate package manifests files.\nconst defaultRootDir = \"packagemanifests\"\n\n// setDefaults sets command defaults.\nfunc (c *packagemanifestsCmd) setDefaults() (err error) {\n\tif c.packageName, c.layout, err = genutil.GetPackageNameAndLayout(c.packageName); err != nil {\n\t\treturn err\n\t}\n\n\tif !c.stdout && c.outputDir == \"\" {\n\t\tc.outputDir = defaultRootDir\n\t}\n\n\tc.generator = genpkg.NewGenerator()\n\n\treturn nil\n}\n\n// validate validates c for package manifests generation.\nfunc (c packagemanifestsCmd) validate() error {\n\n\tif c.version != \"\" {\n\t\tif err := genutil.ValidateVersion(c.version); err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\treturn errors.New(\"--version must be set\")\n\t}\n\n\tif c.fromVersion != \"\" {\n\t\tif err := genutil.ValidateVersion(c.fromVersion); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tif c.inputDir == \"\" {\n\t\treturn errors.New(\"--input-dir must be set\")\n\t}\n\n\tif !genutil.IsPipeReader() {\n\t\tif c.deployDir == \"\" {\n\t\t\treturn errors.New(\"--deploy-dir must be set if not reading from stdin\")\n\t\t}\n\t\tif c.crdsDir == \"\" {\n\t\t\treturn errors.New(\"--crds-dir must be set if not reading from stdin\")\n\t\t}\n\t}\n\n\tif c.stdout {\n\t\tif c.outputDir != \"\" {\n\t\t\treturn errors.New(\"--output-dir cannot be set if writing to stdout\")\n\t\t}\n\t}\n\n\tif c.isDefaultChannel && c.channelName == \"\" {\n\t\treturn fmt.Errorf(\"--default-channel can only be set if --channel is set\")\n\t}\n\n\treturn nil\n}\n\n// run generates package manifests.\nfunc (c packagemanifestsCmd) run() error {\n\n\tc.println(\"Generating package manifests version\", c.version)\n\n\tif err := c.generatePackageManifest(); err != nil {\n\t\treturn err\n\t}\n\n\tcol := &collector.Manifests{}\n\tif genutil.IsPipeReader() {\n\t\tif err := col.UpdateFromReader(os.Stdin); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tif c.deployDir != \"\" {\n\t\tif err := col.UpdateFromDirs(c.deployDir, c.crdsDir); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// If no CSV was initially read, a kustomize base can be used at the default base path.\n\t// Only read from kustomizeDir if a base exists so users can still generate a barebones CSV.\n\tbaseCSVPath := filepath.Join(c.kustomizeDir, \"bases\", c.packageName+\".clusterserviceversion.yaml\")\n\tif noCSVStdin := len(col.ClusterServiceVersions) == 0; noCSVStdin && genutil.IsExist(baseCSVPath) {\n\t\tbase, err := bases.ClusterServiceVersion{BasePath: baseCSVPath}.GetBase()\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error reading CSV base: %v\", err)\n\t\t}\n\t\tcol.ClusterServiceVersions = append(col.ClusterServiceVersions, *base)\n\t} else if noCSVStdin {\n\t\tc.println(\"Building a ClusterServiceVersion without an existing base\")\n\t}\n\n\tvar opts []gencsv.Option\n\tstdout := genutil.NewMultiManifestWriter(os.Stdout)\n\tif c.stdout {\n\t\topts = append(opts, gencsv.WithWriter(stdout))\n\t} else {\n\t\topts = append(opts, gencsv.WithPackageWriter(c.outputDir))\n\t}\n\n\tcsvGen := gencsv.Generator{\n\t\tOperatorName: c.packageName,\n\t\tVersion:      c.version,\n\t\tFromVersion:  c.fromVersion,\n\t\tCollector:    col,\n\t\tAnnotations:  metricsannotations.MakeBundleObjectAnnotations(c.layout),\n\t}\n\tif err := csvGen.Generate(opts...); err != nil {\n\t\treturn fmt.Errorf(\"error generating ClusterServiceVersion: %v\", err)\n\t}\n\n\tif c.updateObjects {\n\t\t// Extra ServiceAccounts not supported by this command.\n\t\tobjs := genutil.GetManifestObjects(col, nil)\n\t\tif c.stdout {\n\t\t\tif err := genutil.WriteObjects(stdout, objs...); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t} else {\n\t\t\tdir := filepath.Join(c.outputDir, c.version)\n\t\t\tif err := genutil.WriteObjectsToFiles(dir, objs...); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\n\tc.println(\"Package manifests generated successfully in\", c.outputDir)\n\n\treturn nil\n}\n\nfunc (c packagemanifestsCmd) generatePackageManifest() error {\n\t//copy of genpkg withfilewriter()\n\t//move out of internal util pkg?\n\tif err := os.MkdirAll(c.outputDir, 0755); err != nil {\n\t\treturn err\n\t}\n\n\topts := genpkg.Options{\n\t\tBaseDir:          c.inputDir,\n\t\tChannelName:      c.channelName,\n\t\tIsDefaultChannel: c.isDefaultChannel,\n\t}\n\n\treturn c.generator.Generate(c.packageName, c.version, c.outputDir, opts)\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests_suite_test.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage packagemanifests\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nfunc TestPackagemanifests(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"Packagemanifests Suite\")\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/generate/packagemanifests/packagemanifests_test.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage packagemanifests\n\nimport (\n\t\"errors\"\n\t\"os\"\n\t\"path/filepath\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\t\"github.com/operator-framework/operator-sdk/internal/generate/packagemanifest\"\n\t\"github.com/operator-framework/operator-sdk/internal/generate/packagemanifest/packagemanifestfakes\"\n)\n\nvar _ = Describe(\"Running a generate packagemanifests command\", func() {\n\tvar (\n\t\tc            packagemanifestsCmd\n\t\tcrdsDir      string\n\t\tdeployDir    string\n\t\tinputDir     string\n\t\tkustomizeDir string\n\t\tversionOne   string\n\n\t\toriginalDir string\n\t\ttestDataDir string\n\t)\n\tBeforeEach(func() {\n\t\tc = packagemanifestsCmd{}\n\t\tcrdsDir = \"crds\"\n\t\tdeployDir = \"deploy\"\n\t\tinputDir = \"input\"\n\t\tkustomizeDir = \"kustomize\"\n\t\tversionOne = \"1.0.0\"\n\n\t\toriginalDir = filepath.Join(\"..\", \"..\", \"..\", \"..\", \"internal\", \"cmd\", \"operator-sdk\", \"generate\", \"packagemanifests\")\n\t\ttestDataDir = filepath.Join(\"..\", \"..\", \"..\", \"..\", \"..\", \"testdata\", \"go\", \"v4\", \"memcached-operator\")\n\t})\n\tDescribe(\"validate\", func() {\n\t\tIt(\"fails if no version is provided\", func() {\n\t\t\terr := c.validate()\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t\tExpect(err.Error()).To(ContainSubstring(\"version must be set\"))\n\t\t})\n\t\tIt(\"fails if a non-parsable version is provided\", func() {\n\t\t\tc.version = \"potato\"\n\n\t\t\terr := c.validate()\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t\tExpect(err.Error()).To(ContainSubstring(\"potato is not a valid semantic version\"))\n\t\t})\n\t\tIt(\"fails if an a non-parsable from-version is provided\", func() {\n\t\t\tc.version = versionOne\n\t\t\tc.fromVersion = \"1.0.a\"\n\n\t\t\terr := c.validate()\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t\tExpect(err.Error()).To(ContainSubstring(\"1.0.a is not a valid semantic version\"))\n\t\t})\n\t\tIt(\"fails if an input-dir is not provided\", func() {\n\t\t\tc.version = versionOne\n\n\t\t\terr := c.validate()\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t\tExpect(err.Error()).To(ContainSubstring(\"input-dir must be set\"))\n\t\t})\n\t\tIt(\"fails if a deploy-dir is not provided while not reading from stdin\", func() {\n\t\t\tc.version = versionOne\n\t\t\tc.inputDir = inputDir\n\t\t\tc.kustomizeDir = kustomizeDir\n\n\t\t\terr := c.validate()\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t\tExpect(err.Error()).To(ContainSubstring(\"deploy-dir must be set if not reading from stdin\"))\n\t\t})\n\t\tIt(\"fails if a crds-dir is not provided while not reading from stdin\", func() {\n\t\t\tc.version = versionOne\n\t\t\tc.inputDir = inputDir\n\t\t\tc.kustomizeDir = kustomizeDir\n\t\t\tc.deployDir = deployDir\n\n\t\t\terr := c.validate()\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t\tExpect(err.Error()).To(ContainSubstring(\"must be set if not reading from stdin\"))\n\t\t})\n\t\tIt(\"allows deply-dir and crds-dir to not be set if reading from a pipe such as stdin\", func() {\n\t\t\tc.version = versionOne\n\t\t\tc.inputDir = inputDir\n\t\t\tc.kustomizeDir = kustomizeDir\n\t\t\tr, _, err := os.Pipe()\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\torigStdin := os.Stdin\n\t\t\tdefer func() { os.Stdin = origStdin }()\n\t\t\tos.Stdin = r\n\n\t\t\terr = c.validate()\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t})\n\t\tIt(\"fails if an output-dir is set while set to write to stdout\", func() {\n\t\t\tc.version = versionOne\n\t\t\tc.inputDir = inputDir\n\t\t\tc.kustomizeDir = kustomizeDir\n\t\t\tc.deployDir = deployDir\n\t\t\tc.crdsDir = crdsDir\n\t\t\tc.stdout = true\n\t\t\tc.outputDir = \"output/\"\n\n\t\t\terr := c.validate()\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t\tExpect(err.Error()).To(ContainSubstring(\"output-dir cannot be set if writing to stdout\"))\n\t\t})\n\t\tIt(\"fails if default-channel is set but channel is not provided\", func() {\n\t\t\tc.version = versionOne\n\t\t\tc.inputDir = inputDir\n\t\t\tc.kustomizeDir = kustomizeDir\n\t\t\tc.deployDir = deployDir\n\t\t\tc.crdsDir = crdsDir\n\t\t\tc.isDefaultChannel = true\n\n\t\t\terr := c.validate()\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t\tExpect(err.Error()).To(ContainSubstring(\"default-channel can only be set if --channel is set\"))\n\t\t})\n\t\tIt(\"validates successfully\", func() {\n\t\t\tc.version = versionOne\n\t\t\tc.fromVersion = \"0.1.2\"\n\t\t\tc.inputDir = inputDir\n\t\t\tc.kustomizeDir = kustomizeDir\n\t\t\tc.deployDir = deployDir\n\t\t\tc.crdsDir = \"crds/\"\n\n\t\t\terr := c.validate()\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t})\n\t\tIt(\"succeeds if both default-channel and channel are set\", func() {\n\t\t\tc.version = versionOne\n\t\t\tc.inputDir = inputDir\n\t\t\tc.kustomizeDir = kustomizeDir\n\t\t\tc.deployDir = deployDir\n\t\t\tc.crdsDir = crdsDir\n\t\t\tc.isDefaultChannel = true\n\t\t\tc.channelName = \"alpha\"\n\n\t\t\terr := c.validate()\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t})\n\t})\n\tDescribe(\"setDefaults\", func() {\n\t\tContext(\"no project file is present\", func() {\n\t\t\tIt(\"fails if no correct operator name can be found\", func() {\n\t\t\t\terr := c.setDefaults()\n\t\t\t\tExpect(err).To(HaveOccurred())\n\t\t\t\tExpect(err.Error()).To(ContainSubstring(\"--package <name> must be set if PROJECT config file is not present\"))\n\t\t\t})\n\t\t\tIt(\"sets fields on the command to default values\", func() {\n\t\t\t\tc.packageName = \"apricot\"\n\n\t\t\t\terr := c.setDefaults()\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t\tExpect(c.inputDir).To(Equal(\"\"))\n\t\t\t\tExpect(c.outputDir).To(Equal(defaultRootDir))\n\t\t\t\tExpect(c.generator).ToNot(BeNil())\n\t\t\t\tExpect(c.layout).To(Equal(\"unknown\"))\n\t\t\t})\n\t\t\tIt(\"does not set outputDir if stdout has been set\", func() {\n\t\t\t\tc.packageName = \"banana\"\n\t\t\t\tc.stdout = true\n\n\t\t\t\terr := c.setDefaults()\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t\tExpect(c.outputDir).To(Equal(\"\"))\n\t\t\t})\n\t\t})\n\t\tContext(\"a valid project file is present\", func() {\n\t\t\tBeforeEach(func() {\n\t\t\t\terr := os.Chdir(testDataDir)\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t})\n\t\t\tAfterEach(func() {\n\t\t\t\terr := os.Chdir(originalDir)\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t})\n\t\t\tIt(\"reads the data from the project file\", func() {\n\t\t\t\terr := c.setDefaults()\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t\tExpect(c.packageName).To(Equal(\"memcached-operator\"))\n\t\t\t\tExpect(c.layout).To(Equal(\"go.kubebuilder.io/v4\"))\n\t\t\t})\n\t\t\tIt(\"doesn't overwrite the package name if it's already set\", func() {\n\t\t\t\tc.packageName = \"cherry\"\n\n\t\t\t\terr := c.setDefaults()\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t\tExpect(c.packageName).To(Equal(\"cherry\"))\n\t\t\t\tExpect(c.layout).To(Equal(\"go.kubebuilder.io/v4\"))\n\t\t\t})\n\t\t})\n\t\tContext(\"an invalid project file is present\", func() {\n\t\t\tBeforeEach(func() {\n\t\t\t\terr := os.Chdir(\"testdata\")\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t})\n\t\t\tAfterEach(func() {\n\t\t\t\terr := os.Chdir(\"..\")\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t})\n\t\t\tIt(\"reads the data from the project file\", func() {\n\t\t\t\terr := c.setDefaults()\n\t\t\t\tExpect(err).To(HaveOccurred())\n\t\t\t\tExpect(err.Error()).To(ContainSubstring(\"did not find expected key\"))\n\t\t\t})\n\t\t})\n\t})\n\tDescribe(\"generatePackageManifest\", func() {\n\t\tvar fakeGen packagemanifestfakes.FakeGenerator\n\t\tBeforeEach(func() {\n\t\t\tc.channelName = \"apple\"\n\t\t\tc.generator = &fakeGen\n\t\t\tc.inputDir = \"banana/\"\n\t\t\tc.isDefaultChannel = true\n\t\t\tc.outputDir = os.TempDir()\n\t\t\tc.packageName = \"cherry\"\n\t\t\tc.version = \"1.2.3\"\n\t\t})\n\t\tIt(\"calls the package manifest generator with the correct params\", func() {\n\t\t\terr := c.generatePackageManifest()\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\tExpect(fakeGen.GenerateCallCount()).To(Equal(1))\n\t\t\tparamName, paramVersion, paramOutputDir, paramOpt := fakeGen.GenerateArgsForCall(0)\n\t\t\tExpect(paramName).To(Equal(c.packageName))\n\t\t\tExpect(paramVersion).To(Equal(c.version))\n\t\t\tExpect(paramOutputDir).To(Equal(c.outputDir))\n\t\t\tExpect((paramOpt)).To(Equal(packagemanifest.Options{\n\t\t\t\tBaseDir:          c.inputDir,\n\t\t\t\tChannelName:      c.channelName,\n\t\t\t\tIsDefaultChannel: c.isDefaultChannel,\n\t\t\t}))\n\t\t})\n\t\tIt(\"bubbles up errors from the generator\", func() {\n\t\t\tpotatoErr := errors.New(\"potato error\")\n\t\t\tfakeGen.GenerateReturns(potatoErr)\n\n\t\t\terr := c.generatePackageManifest()\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t\tExpect(err.Error()).To(ContainSubstring(potatoErr.Error()))\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "internal/cmd/operator-sdk/generate/packagemanifests/testdata/PROJECT",
    "content": "domain: example.com\nlayout: go.kubebuilder.io/v3-alpha\nprojectName: memcached-operator\nrepo: github.com/example/memcached-operator\nresources:\n    - crdVersion: v1\n  group: cache\n  kind: Memcached\n  version: v1alpha1\n  webhookVersion: v1\nversion: 3-alpha\nplugins:\n  manifests.sdk.operatorframework.io/v2: {}\n  scorecard.sdk.operatorframework.io/v2: {}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/olm/cmd.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage olm\n\nimport (\n\t\"github.com/spf13/cobra\"\n)\n\nfunc NewCmd() *cobra.Command {\n\tcmd := &cobra.Command{\n\t\tUse:   \"olm\",\n\t\tShort: \"Manage the Operator Lifecycle Manager installation in your cluster\",\n\t}\n\tcmd.AddCommand(\n\t\tnewInstallCmd(),\n\t\tnewStatusCmd(),\n\t\tnewUninstallCmd(),\n\t)\n\treturn cmd\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/olm/cmd_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage olm\n\nimport (\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nvar _ = Describe(\"Running an olm command\", func() {\n\tDescribe(\"NewCmd\", func() {\n\t\tIt(\"builds a cobra command with the correct subcommands\", func() {\n\t\t\tcmd := NewCmd()\n\t\t\tExpect(cmd).NotTo(BeNil())\n\t\t\tExpect(cmd.Use).NotTo(BeNil())\n\t\t\tExpect(cmd.Short).NotTo(BeNil())\n\n\t\t\tsubcommands := cmd.Commands()\n\t\t\tExpect(subcommands).To(HaveLen(3))\n\t\t\tExpect(subcommands[0].Use).To(Equal(\"install\"))\n\t\t\tExpect(subcommands[1].Use).To(Equal(\"status\"))\n\t\t\tExpect(subcommands[2].Use).To(Equal(\"uninstall\"))\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "internal/cmd/operator-sdk/olm/install.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage olm\n\nimport (\n\t\"github.com/operator-framework/operator-sdk/internal/olm/installer\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/cobra\"\n)\n\nfunc newInstallCmd() *cobra.Command {\n\tmgr := &installer.Manager{}\n\tcmd := &cobra.Command{\n\t\tUse:   \"install\",\n\t\tShort: \"Install Operator Lifecycle Manager in your cluster\",\n\t\tRunE: func(_ *cobra.Command, _ []string) error {\n\t\t\tif err := mgr.Install(); err != nil {\n\t\t\t\tlog.Fatalf(\"Failed to install OLM version %q: %s\", mgr.Version, err)\n\t\t\t}\n\t\t\treturn nil\n\t\t},\n\t}\n\n\tcmd.Flags().StringVar(&mgr.Version, \"version\", installer.DefaultVersion, \"version of OLM resources to install\")\n\tmgr.AddToFlagSet(cmd.Flags())\n\treturn cmd\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/olm/install_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage olm\n\nimport (\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/olm/installer\"\n)\n\nvar _ = Describe(\"Running an olm install command\", func() {\n\tDescribe(\"newInstallCmd\", func() {\n\t\tIt(\"builds a cobra command\", func() {\n\t\t\tcmd := newInstallCmd()\n\t\t\tExpect(cmd).NotTo(BeNil())\n\t\t\tExpect(cmd.Use).NotTo(BeNil())\n\t\t\tExpect(cmd.Short).NotTo(BeNil())\n\n\t\t\tflag := cmd.Flags().Lookup(\"version\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\t\t\tExpect(flag.DefValue).To(Equal(installer.DefaultVersion))\n\t\t\tExpect(flag.Usage).NotTo(BeNil())\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "internal/cmd/operator-sdk/olm/olm_suite_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage olm_test\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nfunc TestOlm(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"Olm Cmd Suite\")\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/olm/status.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage olm\n\nimport (\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/cobra\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/olm/installer\"\n)\n\nfunc newStatusCmd() *cobra.Command {\n\tmgr := installer.Manager{}\n\tcmd := &cobra.Command{\n\t\tUse:   \"status\",\n\t\tShort: \"Get the status of the Operator Lifecycle Manager installation in your cluster\",\n\t\tRunE: func(_ *cobra.Command, _ []string) error {\n\t\t\tif err := mgr.Status(); err != nil {\n\t\t\t\tlog.Fatalf(\"Failed to get OLM status: %s\", err)\n\t\t\t}\n\t\t\treturn nil\n\t\t},\n\t}\n\n\tcmd.Flags().StringVar(&mgr.OLMNamespace, \"olm-namespace\", installer.DefaultOLMNamespace, \"namespace where OLM is installed\")\n\tcmd.Flags().StringVar(&mgr.Version, \"version\", \"\", \"version of OLM installed on cluster; if unset\"+\n\t\t\"operator-sdk attempts to auto-discover the version\")\n\tmgr.AddToFlagSet(cmd.Flags())\n\treturn cmd\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/olm/status_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage olm\n\nimport (\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/olm/installer\"\n)\n\nvar _ = Describe(\"Running an olm status command\", func() {\n\tDescribe(\"newStatusCmd\", func() {\n\t\tIt(\"builds a cobra command\", func() {\n\t\t\tcmd := newStatusCmd()\n\t\t\tExpect(cmd).NotTo(BeNil())\n\t\t\tExpect(cmd.Use).NotTo(BeNil())\n\t\t\tExpect(cmd.Short).NotTo(BeNil())\n\n\t\t\tflag := cmd.Flags().Lookup(\"olm-namespace\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\t\t\tExpect(flag.DefValue).To(Equal(installer.DefaultOLMNamespace))\n\t\t\tExpect(flag.Usage).NotTo(BeNil())\n\n\t\t\tflag = cmd.Flags().Lookup(\"version\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\t\t\tExpect(flag.DefValue).To(Equal(\"\"))\n\t\t\tExpect(flag.Usage).NotTo(BeNil())\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "internal/cmd/operator-sdk/olm/uninstall.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage olm\n\nimport (\n\t\"github.com/operator-framework/operator-sdk/internal/olm/installer\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/cobra\"\n)\n\nfunc newUninstallCmd() *cobra.Command {\n\tmgr := installer.Manager{}\n\tcmd := &cobra.Command{\n\t\tUse:   \"uninstall\",\n\t\tShort: \"Uninstall Operator Lifecycle Manager from your cluster\",\n\t\tRunE: func(_ *cobra.Command, _ []string) error {\n\t\t\tif err := mgr.Uninstall(); err != nil {\n\t\t\t\tlog.Fatalf(\"Failed to uninstall OLM: %s\", err)\n\t\t\t}\n\t\t\treturn nil\n\t\t},\n\t}\n\n\tcmd.Flags().StringVar(&mgr.Version, \"version\", \"\", \"version of OLM resources to uninstall.\")\n\tcmd.Flags().StringVar(&mgr.OLMNamespace, \"olm-namespace\", installer.DefaultOLMNamespace,\n\t\t\"namespace from where OLM is to be uninstalled.\")\n\tmgr.AddToFlagSet(cmd.Flags())\n\treturn cmd\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/olm/uninstall_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage olm\n\nimport (\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\t\"github.com/operator-framework/operator-sdk/internal/olm/installer\"\n)\n\nvar _ = Describe(\"Running an olm uninstall command\", func() {\n\tDescribe(\"newUninstallCmd\", func() {\n\t\tIt(\"builds a cobra command\", func() {\n\t\t\tcmd := newUninstallCmd()\n\t\t\tExpect(cmd).NotTo(BeNil())\n\t\t\tExpect(cmd.Use).NotTo(BeNil())\n\t\t\tExpect(cmd.Short).NotTo(BeNil())\n\n\t\t\tflag := cmd.Flags().Lookup(\"version\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\t\t\tExpect(flag.DefValue).To(Equal(\"\"))\n\t\t\tExpect(flag.Usage).NotTo(BeNil())\n\n\t\t\tflag = cmd.Flags().Lookup(\"olm-namespace\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\t\t\tExpect(flag.DefValue).To(Equal(installer.DefaultOLMNamespace))\n\t\t\tExpect(flag.Usage).NotTo(BeNil())\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "internal/cmd/operator-sdk/pkgmantobundle/cmd.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage pkgmantobundle\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/operator-framework/api/pkg/apis/scorecard/v1alpha3\"\n\tapimanifests \"github.com/operator-framework/api/pkg/manifests\"\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/cobra\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/annotations/metrics\"\n\t\"github.com/operator-framework/operator-sdk/internal/util/bundleutil\"\n\t\"github.com/operator-framework/operator-sdk/internal/util/k8sutil\"\n)\n\nconst (\n\tlongHelp = `\n'pkgman-to-bundle' command helps in migrating OLM packagemanifests to bundles which is the preferred OLM packaging format.\nThis command takes an input packagemanifest directory and generates bundles for each of the versions of manifests present in\nthe input directory. Additionally, it also provides the flexibility to build bundle images for each of the generated bundles.\n\nThe generated bundles are always written on disk. Location for the generated bundles can be specified using '--output-dir'. If not\nspecified, the default location would be 'bundle/' directory.\n\nThe base container image name for the bundles can be provided using '--image-tag-base' flag. This should be provided without the tag, since the tag\nfor the images would be the bundle version, (ie) image names will be in the format <base_image>:<bundle_version>.\n\nSpecify the build command for building container images using '--build-cmd' flag. The default build command is 'docker build'. The command will\nneed to be in the 'PATH' or fully qualified path name should be provided.\n`\n\n\texamples = `\n\n# Provide the packagemanifests directory as input to the command. Consider the packagemanifests directory to have the following\n# structure:\n\n$ tree packagemanifests/\npackagemanifests\n└── etcd\n    ├── 0.0.1\n    │   ├── etcdcluster.crd.yaml\n    │   └── etcdoperator.clusterserviceversion.yaml\n    ├── 0.0.2\n    │   ├── etcdbackup.crd.yaml\n    │   ├── etcdcluster.crd.yaml\n    │   ├── etcdoperator.v0.0.2.clusterserviceversion.yaml\n    │   └── etcdrestore.crd.yaml\n    └── etcd.package.yaml\n\n# Run the following command to generate bundles in the default 'bundle/' directory with the base-container image name\n# to be 'quay.io/example/etcd'\n$ operator-sdk pkgman-to-bundle packagemanifests --image-tag-base quay.io/example/etcd\nINFO[0000] Packagemanifests will be migrated to bundles in bundle directory\nINFO[0000] Creating bundle/bundle-0.0.1/bundle.Dockerfile\nINFO[0000] Creating bundle/bundle-0.0.1/metadata/annotations.yaml\n...\n\n# After running the above command, the bundles will be generated in 'bundles/' directory.\n$ tree bundles/\nbundles/\n├── bundle-0.0.1\n│   ├── bundle\n│   │   ├── manifests\n│   │   │   ├── etcdcluster.crd.yaml\n│   │   │   ├── etcdoperator.clusterserviceversion.yaml\n│   │   ├── metadata\n│   │   │   └── annotations.yaml\n│   │   └── tests\n│   │       └── scorecard\n│   │           └── config.yaml\n│   └── bundle.Dockerfile\n└── bundle-0.0.2\n    ├── bundle\n    │   ├── manifests\n    │   │   ├── etcdbackup.crd.yaml\n    │   │   ├── etcdcluster.crd.yaml\n    │   │   ├── etcdoperator.v0.0.2.clusterserviceversion.yaml\n    │   │   ├── etcdrestore.crd.yaml\n    │   └── metadata\n    │       └── annotations.yaml\n    └── bundle.Dockerfile\n\nA custom command to build bundle images can also be specified using the '--build-cmd' flag. For example,\n\n$ operator-sdk pkgman-to-bundle packagemanifests --image-tag-base quay.io/example/etcd --build-cmd \"podman build -f bundle.Dockerfile . -t\"\n\nImages for the both the bundles will be built with the following names: quay.io/example/etcd:0.0.1 and quay.io/example/etcd:0.0.2.\n`\n)\n\nvar defaultSubBundleDir = \"bundle\"\n\ntype pkgManToBundleCmd struct {\n\t// Input packagemanifest directory.\n\tpkgmanifestDir string\n\n\t// Optional flags for generating and building bundles.\n\toutputDir string\n\tbaseImg   string\n\tbuildCmd  string\n}\n\n// NewCmd returns the pkgManToBundleCmd configured with the provided input options.\nfunc NewCmd() *cobra.Command {\n\tp := pkgManToBundleCmd{}\n\n\tpkgManToBundleCmd := &cobra.Command{\n\t\tUse:     \"pkgman-to-bundle <packagemanifestdir>\",\n\t\tShort:   \"Migrates packagemanifests to bundles\",\n\t\tLong:    longHelp,\n\t\tExample: examples,\n\t\tPreRunE: func(_ *cobra.Command, args []string) (err error) {\n\t\t\treturn p.validate(args)\n\t\t},\n\t\tRunE: func(_ *cobra.Command, args []string) (err error) {\n\t\t\tp.pkgmanifestDir = args[0]\n\t\t\treturn p.run()\n\t\t},\n\t}\n\n\tpkgManToBundleCmd.Flags().StringVar(&p.outputDir, \"output-dir\", \"bundles\", \"Directory to write bundle to.\")\n\tpkgManToBundleCmd.Flags().StringVar(&p.baseImg, \"image-tag-base\", \"\", \"Base container image name for bundle image tags, \"+\n\t\t\"ex. my.reg/foo/bar-operator-bundle will become my.reg/foo/bar-operator-bundle:${package-dir-name} for each child directory name in the packagemanifests directory\")\n\n\t// TODO(varsha): enable users to provide a template to the command so that it can be run in all child directories to build image.\n\tpkgManToBundleCmd.Flags().StringVar(&p.buildCmd, \"build-cmd\", \"\", \"Build command to be run for building images. By default 'docker build' is run.\")\n\n\treturn pkgManToBundleCmd\n}\n\n// Generate the bundles from the provided packagemanifest directory.\nfunc (p *pkgManToBundleCmd) run() (err error) {\n\n\t// error if output bundle directory already exists.\n\tif _, err = os.Stat(p.outputDir); !errors.Is(err, os.ErrNotExist) {\n\t\treturn fmt.Errorf(\"output directory: %s for bundles already exists\", p.outputDir)\n\t}\n\n\tlog.Infof(\"Packagemanifests will be migrated to bundles in %s directory\", p.outputDir)\n\n\t// Skipping bundles here, since that's not required and could be empty for a manifest directory.\n\tpackages, _, err := apimanifests.GetManifestsDir(p.pkgmanifestDir)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif packages.IsEmpty() {\n\t\treturn fmt.Errorf(\"no packages found in the directory %s\", p.pkgmanifestDir)\n\t}\n\n\t// get package metadata required for annotations.yaml and bundle.Dockerfile.\n\tpackageName, defaultChannel, channelsByCSV, err := getPackageMetadata(packages)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error obtaining metadata from directory %s: %v\", p.pkgmanifestDir, err)\n\t}\n\n\tdirectories, err := os.ReadDir(p.pkgmanifestDir)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// iterate through each of the subdirectories to generate respective bundles for each of them.\n\tfor _, dir := range directories {\n\t\tif dir.IsDir() {\n\t\t\t// this is required to extract project layout and SDK version information.\n\t\t\totherLabels, channels, err := getSDKStampsAndChannels(filepath.Join(p.pkgmanifestDir, dir.Name()), defaultChannel, channelsByCSV)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"error getting CSV from provided packagemanifest %v\", err)\n\t\t\t}\n\n\t\t\tbundleMetaData := bundleutil.BundleMetaData{\n\t\t\t\tBundleDir:       filepath.Join(p.outputDir, \"bundle-\"+dir.Name(), defaultSubBundleDir),\n\t\t\t\tPackageName:     packageName,\n\t\t\t\tChannels:        channels,\n\t\t\t\tDefaultChannel:  defaultChannel,\n\t\t\t\tPkgmanifestPath: filepath.Join(p.pkgmanifestDir, dir.Name()),\n\t\t\t\tOtherLabels:     otherLabels,\n\t\t\t\tBaseImage:       p.baseImg,\n\t\t\t\tBuildCommand:    p.buildCmd,\n\t\t\t}\n\n\t\t\tif err := bundleMetaData.CopyOperatorManifests(); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\t// get the location of scorecard config file from the current packagemanifest directory.\n\t\t\tscorecardConfigPath, err := getScorecardConfigPath(bundleMetaData.PkgmanifestPath)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\t// if scorecard config is present, then copy it to tests/scorecard directory\n\t\t\t// in bundle.\n\t\t\tif scorecardConfigPath != \"\" {\n\t\t\t\tbundleMetaData.IsScoreConfigPresent = true\n\t\t\t\tif err := bundleMetaData.WriteScorecardConfig(scorecardConfigPath); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif err := bundleMetaData.GenerateMetadata(); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\t// build image when base image name is provided.\n\t\t\tif p.baseImg != \"\" {\n\t\t\t\tif err := bundleMetaData.BuildBundleImage(dir.Name()); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t}\n\treturn nil\n}\n\n// getScorecardConfigPath looks for the path of scorecard config file in the directory.\nfunc getScorecardConfigPath(inputDir string) (string, error) {\n\tvar scorecardConfigPath string\n\n\terr := filepath.Walk(inputDir, func(path string, info os.FileInfo, err error) error {\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tif !info.IsDir() {\n\t\t\tb, err := os.ReadFile(path)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\ttypeMeta, err := k8sutil.GetTypeMetaFromBytes(b)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tif typeMeta.Kind == v1alpha3.ConfigurationKind {\n\t\t\t\tif len(scorecardConfigPath) != 0 {\n\t\t\t\t\treturn fmt.Errorf(\"multiple scorrecard config files found in packagemanifest directory %s\", inputDir)\n\t\t\t\t}\n\t\t\t\tscorecardConfigPath = path\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t})\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\treturn scorecardConfigPath, nil\n}\n\nfunc getSDKStampsAndChannels(path, defaultChannel string, channelsByCSV map[string][]string) (map[string]string, string, error) {\n\tbundle, err := apimanifests.GetBundleFromDir(path)\n\tif err != nil {\n\t\treturn nil, \"\", err\n\t}\n\n\tsdkLabels, err := getSDKStamps(bundle)\n\tif err != nil {\n\t\treturn nil, \"\", err\n\t}\n\n\t// Find channels matching the CSV names\n\tchannels := getChannelsByCSV(bundle, channelsByCSV, defaultChannel)\n\n\treturn sdkLabels, channels, nil\n}\n\n// getSDKStamps parses the CSV and gets SDK stamps.\nfunc getSDKStamps(bundle *apimanifests.Bundle) (map[string]string, error) {\n\tif bundle.CSV == nil {\n\t\treturn nil, fmt.Errorf(\"cannot find CSV from manifests package\")\n\t}\n\n\t// Extract SDK layout and version from CSV annotations.\n\tcsvAnnotations := bundle.CSV.GetAnnotations()\n\tsdkLabels := make(map[string]string)\n\n\tfor key, value := range csvAnnotations {\n\t\tif key == metrics.BuilderObjectAnnotation {\n\t\t\tsdkLabels[key] = value\n\t\t}\n\n\t\tif key == metrics.LayoutObjectAnnotation {\n\t\t\tsdkLabels[key] = value\n\t\t}\n\t}\n\n\treturn sdkLabels, nil\n}\n\n// getChannelsByCSV creates a list for channels for the currentCSV. For other versions of manifests which\n// are not present in the manifest, the defaultChannel is added.\nfunc getChannelsByCSV(bundle *apimanifests.Bundle, channelsByCSV map[string][]string, defaultChannel string) (channels string) {\n\t// Find channels matching the CSV names\n\tchannelNames := channelsByCSV[bundle.CSV.GetName()]\n\tchannels = strings.Join(channelNames, \",\")\n\n\t// TODO: verify if we have to add this validation since while building bundles if channel is not specified\n\t// we add the default channel.\n\tif channels == \"\" {\n\t\tchannels = defaultChannel\n\t\tlog.Infof(\"Supported channels cannot be identified from CSV %s, using default channel %s\", bundle.CSV.GetName(), defaultChannel)\n\t}\n\n\treturn channels\n}\n\nfunc getPackageMetadata(pkg *apimanifests.PackageManifest) (packagename, defaultChannel string, channelsByCSV map[string][]string, err error) {\n\tpackagename = pkg.PackageName\n\tif packagename == \"\" {\n\t\terr = fmt.Errorf(\"cannot find packagename from the manifest directory\")\n\t\treturn\n\t}\n\n\tdefaultChannel = pkg.DefaultChannelName\n\tif defaultChannel == \"\" {\n\t\terr = fmt.Errorf(\"cannot find the default channel for package %q\", packagename)\n\t\treturn\n\t}\n\n\tchannelsByCSV = make(map[string][]string)\n\n\tfor _, p := range pkg.Channels {\n\t\tif _, ok := channelsByCSV[p.CurrentCSVName]; !ok {\n\t\t\tchannelsByCSV[p.CurrentCSVName] = make([]string, 0)\n\t\t}\n\t\tchannelsByCSV[p.CurrentCSVName] = append(channelsByCSV[p.CurrentCSVName], p.Name)\n\t}\n\n\treturn\n}\n\nfunc (p *pkgManToBundleCmd) validate(args []string) error {\n\tif len(args) != 1 {\n\t\treturn fmt.Errorf(\"a package manifest directory argument is required\")\n\t}\n\n\tif len(p.baseImg) == 0 && len(p.buildCmd) != 0 {\n\t\treturn fmt.Errorf(\"base image needs to be specified to build bundle image\")\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/pkgmantobundle/cmd_test.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage pkgmantobundle\n\nimport (\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nvar _ = Describe(\"Migrating packagemanifests to bundle command\", func() {\n\tDescribe(\"NewCmd\", func() {\n\t\tcmd := NewCmd()\n\t\tExpect(cmd).NotTo(BeNil())\n\n\t\tflag := cmd.Flags().Lookup(\"output-dir\")\n\t\tExpect(flag).NotTo(BeNil())\n\t\tExpect(flag.Usage).ToNot(Equal(\"\"))\n\t\tExpect(flag.DefValue).To(Equal(\"bundles\"))\n\n\t\tflag = cmd.Flags().Lookup(\"image-tag-base\")\n\t\tExpect(flag).NotTo(BeNil())\n\t\tExpect(flag.Usage).ToNot(Equal(\"\"))\n\n\t\tflag = cmd.Flags().Lookup(\"build-cmd\")\n\t\tExpect(flag).NotTo(BeNil())\n\t\tExpect(flag.Usage).ToNot(Equal(\"\"))\n\t})\n})\n"
  },
  {
    "path": "internal/cmd/operator-sdk/pkgmantobundle/pkgmantobundle_suite_test.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage pkgmantobundle\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nfunc TestPackagemanifestsToBundle(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"pkgman-To-Bundle Suite\")\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/pkgmantobundle/pkgmantobundle_test.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage pkgmantobundle\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"reflect\"\n\n\tapimanifests \"github.com/operator-framework/api/pkg/manifests\"\n\toperatorsv1alpha1 \"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\t\"github.com/operator-framework/operator-sdk/internal/util/projutil\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nvar _ = Describe(\"Running pkgmanToBundle command\", func() {\n\tvar (\n\t\tp         pkgManToBundleCmd\n\t\tpkgManDir string\n\t\toutputDir = \"bundle-output\"\n\t)\n\n\tBeforeEach(func() {\n\t\tp = pkgManToBundleCmd{}\n\t})\n\n\tDescribe(\"validate\", func() {\n\t\tIt(\"fail if anything other than one argumanet for packagemanifest directory is provided\", func() {\n\t\t\terr := p.validate([]string{})\n\t\t\tExpect(err).To(HaveOccurred())\n\n\t\t\terr = p.validate([]string{\"one\", \"two\"})\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t})\n\n\t\tIt(\"succeeds if exactly one argument is provided\", func() {\n\t\t\terr := p.validate([]string{\"inputdir\"})\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t})\n\t})\n\n\tDescribe(\"migrate packagemanifests to bundle \", func() {\n\t\tAfterEach(func() {\n\t\t\terr := os.RemoveAll(outputDir)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t})\n\n\t\tIt(\"should generate multiple bundles for each version of manifests\", func() {\n\t\t\t// Specify input package manifest directory and output directory\n\t\t\tpkgManDir = filepath.Join(\"testdata\", \"packagemanifests\")\n\n\t\t\tp.pkgmanifestDir = pkgManDir\n\t\t\tp.outputDir = outputDir\n\t\t\tp.baseImg = \"quay.io/example/memcached-operator\"\n\n\t\t\terr := p.run()\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"Verifying the number of bundles created\")\n\t\t\tExpect(getNumberOfDirectories(p.outputDir)).To(BeEquivalentTo(2))\n\n\t\t\tBy(\"Verifying that each of them are valid bundles and their package name\")\n\t\t\tbundles, err := os.ReadDir(p.outputDir)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tfor _, bundle := range bundles {\n\t\t\t\tb, err := apimanifests.GetBundleFromDir(filepath.Join(p.outputDir, bundle.Name()))\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t\tExpect(b).NotTo(BeNil())\n\n\t\t\t\t// Verifying that bundle contains required files\n\t\t\t\tExpect(fileExists(filepath.Join(p.outputDir, bundle.Name(), \"bundle.Dockerfile\"))).To(BeTrue())\n\t\t\t\tExpect(fileExists(filepath.Join(p.outputDir, bundle.Name(), defaultSubBundleDir, \"metadata\", \"annotations.yaml\"))).To(BeTrue())\n\t\t\t\tExpect(b.CSV).NotTo(BeNil())\n\t\t\t\tExpect(b.V1CRDs).NotTo(BeNil())\n\n\t\t\t\t// Verify if scorecard config exiss in the bundle\n\t\t\t\tif bundle.Name() == \"bundle-0.0.1\" {\n\t\t\t\t\tExpect(fileExists(filepath.Join(p.outputDir, bundle.Name(), defaultSubBundleDir, \"tests\", \"scorecard\", \"config.yaml\"))).To(BeTrue())\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\n\t\tIt(\"should build image when build command is provided\", func() {\n\t\t\t// Specify input package manifest directory and output directory\n\t\t\tpkgManDir = filepath.Join(\"testdata\", \"packagemanifests\")\n\n\t\t\tp.pkgmanifestDir = pkgManDir\n\t\t\tp.outputDir = outputDir\n\t\t\tp.baseImg = \"quay.io/example/memcached-operator\"\n\t\t\tp.buildCmd = \"docker build -f bundle.Dockerfile . -t\"\n\n\t\t\terr := p.run()\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t})\n\n\t\tIt(\"should error when output directory already exists\", func() {\n\t\t\terr := os.Mkdir(outputDir, projutil.DirMode)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tp.outputDir = outputDir\n\t\t\terr = p.run()\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t\tExpect(err.Error()).To(ContainSubstring(fmt.Sprintf(\"output directory: %s for bundles already exists\", p.outputDir)))\n\t\t})\n\t})\n\n\tDescribe(\"getSDKStampsAndChannels\", func() {\n\t\tDescribe(\"getSDKStamps\", func() {\n\t\t\tIt(\"should be able to extract SDK stamps from CSV\", func() {\n\t\t\t\tannotations := map[string]string{\n\t\t\t\t\t\"operators.operatorframework.io/builder\":        \"operator-sdk-v1.5.0\",\n\t\t\t\t\t\"operators.operatorframework.io/project_layout\": \"go.kubebuilder.io/v4\",\n\t\t\t\t}\n\n\t\t\t\tcsv := operatorsv1alpha1.ClusterServiceVersion{\n\t\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\t\tAnnotations: annotations,\n\t\t\t\t\t},\n\t\t\t\t}\n\n\t\t\t\tbundle := apimanifests.Bundle{\n\t\t\t\t\tCSV: &csv,\n\t\t\t\t}\n\n\t\t\t\tstamps, err := getSDKStamps(&bundle)\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t\tExpect(len(stamps)).To(BeEquivalentTo(2))\n\t\t\t\tExpect(reflect.DeepEqual(annotations, stamps)).To(BeTrue())\n\n\t\t\t})\n\n\t\t\tIt(\"should error when bundle is empty\", func() {\n\t\t\t\tstamps, err := getSDKStamps(&apimanifests.Bundle{})\n\t\t\t\tExpect(err).To(HaveOccurred())\n\t\t\t\tExpect(stamps).To(BeNil())\n\n\t\t\t})\n\t\t})\n\n\t\tDescribe(\"getChannelsByCSV\", func() {\n\t\t\tbundle := apimanifests.Bundle{\n\t\t\t\tCSV: &operatorsv1alpha1.ClusterServiceVersion{\n\t\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\t\tName: \"memcached-operator:0.0.1\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\n\t\t\tdefaultChannel := \"gamma\"\n\n\t\t\tIt(\"should get the list of channels for corresponding CSV\", func() {\n\t\t\t\tchannels := map[string][]string{\n\t\t\t\t\t\"memcached-operator:0.0.1\": {\"alpha\", \"beta\"},\n\t\t\t\t}\n\n\t\t\t\tch := getChannelsByCSV(&bundle, channels, defaultChannel)\n\t\t\t\tExpect(ch).To(BeEquivalentTo(\"alpha,beta\"))\n\t\t\t})\n\n\t\t\tIt(\"if no channel is provided, default to candidate\", func() {\n\t\t\t\tchannels := map[string][]string{}\n\t\t\t\tch := getChannelsByCSV(&bundle, channels, defaultChannel)\n\t\t\t\tExpect(ch).To(BeEquivalentTo(defaultChannel))\n\t\t\t})\n\t\t})\n\t})\n\n\tDescribe(\"getPackageMetadata\", func() {\n\t\tvar (\n\t\t\tpkg apimanifests.PackageManifest\n\t\t)\n\n\t\tBeforeEach(func() {\n\t\t\tpkg = apimanifests.PackageManifest{\n\t\t\t\tPackageName:        \"memcached-operator\",\n\t\t\t\tDefaultChannelName: \"alpha\",\n\t\t\t\tChannels: []apimanifests.PackageChannel{\n\t\t\t\t\t{\n\t\t\t\t\t\tName:           \"alpha\",\n\t\t\t\t\t\tCurrentCSVName: \"memcached-operator:v1.0.0\",\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tName:           \"beta\",\n\t\t\t\t\t\tCurrentCSVName: \"memcached-operator:v1.0.1\",\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tName:           \"alpha\",\n\t\t\t\t\t\tCurrentCSVName: \"memcached-operator:v1.0.1\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\n\t\t})\n\n\t\tIt(\"should return pkgName, channels and channelsByCSV\", func() {\n\t\t\tpkgName, defaultChannel, channelByCSV, err := getPackageMetadata(&pkg)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\tExpect(defaultChannel).To(BeEquivalentTo(\"alpha\"))\n\t\t\tExpect(pkgName).To(BeEquivalentTo(\"memcached-operator\"))\n\t\t\tExpect(len(channelByCSV[\"memcached-operator:v1.0.0\"])).To(BeEquivalentTo(1))\n\t\t\tExpect(len(channelByCSV[\"memcached-operator:v1.0.1\"])).To(BeEquivalentTo(2))\n\t\t})\n\n\t\tIt(\"return error when packagename is not found\", func() {\n\t\t\tpkg.PackageName = \"\"\n\t\t\t_, _, _, err := getPackageMetadata(&pkg)\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t\tExpect(err.Error()).To(ContainSubstring(\"cannot find packagename from the manifest directory\"))\n\t\t})\n\n\t\tIt(\"should error when defaultChannel name is empty\", func() {\n\t\t\tpkg.DefaultChannelName = \"\"\n\t\t\t_, _, _, err := getPackageMetadata(&pkg)\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t\tExpect(err.Error()).To(ContainSubstring(\"cannot find the default channel for package\"))\n\t\t})\n\t})\n})\n\nfunc getNumberOfDirectories(inputDir string) int {\n\tcount := 0\n\n\tdirs, err := os.ReadDir(inputDir)\n\tExpect(err).NotTo(HaveOccurred())\n\n\tfor _, d := range dirs {\n\t\tif d.IsDir() {\n\t\t\tcount++\n\t\t}\n\t}\n\treturn count\n}\n\nfunc fileExists(path string) bool {\n\tif _, err := os.Stat(path); !os.IsNotExist(err) {\n\t\treturn true\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/pkgmantobundle/testdata/packagemanifests/0.0.1/cache.example.com_memcacheds.yaml",
    "content": "apiVersion: apiextensions.k8s.io/v1\nkind: CustomResourceDefinition\nmetadata:\n  annotations:\n    controller-gen.kubebuilder.io/version: v0.4.1\n  creationTimestamp: null\n  name: memcacheds.cache.example.com\nspec:\n  group: cache.example.com\n  names:\n    kind: Memcached\n    listKind: MemcachedList\n    plural: memcacheds\n    singular: memcached\n  scope: Namespaced\n  versions:\n  - name: v1alpha1\n    schema:\n      openAPIV3Schema:\n        description: Memcached is the Schema for the memcacheds API\n        properties:\n          apiVersion:\n            description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'\n            type: string\n          kind:\n            description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'\n            type: string\n          metadata:\n            type: object\n          spec:\n            description: MemcachedSpec defines the desired state of Memcached\n            properties:\n              foo:\n                description: Foo is an example field of Memcached. Edit memcached_types.go to remove/update\n                type: string\n            type: object\n          status:\n            description: MemcachedStatus defines the observed state of Memcached\n            type: object\n        type: object\n    served: true\n    storage: true\n    subresources:\n      status: {}\nstatus:\n  acceptedNames:\n    kind: \"\"\n    plural: \"\"\n  conditions: []\n  storedVersions: []\n"
  },
  {
    "path": "internal/cmd/operator-sdk/pkgmantobundle/testdata/packagemanifests/0.0.1/memcached-operator-controller-manager-metrics-service_v1_service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  creationTimestamp: null\n  labels:\n    control-plane: controller-manager\n  name: memcached-operator-controller-manager-metrics-service\nspec:\n  ports:\n  - name: https\n    port: 8443\n    targetPort: https\n  selector:\n    control-plane: controller-manager\nstatus:\n  loadBalancer: {}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/pkgmantobundle/testdata/packagemanifests/0.0.1/memcached-operator-controller-manager_v1_serviceaccount.yaml",
    "content": "apiVersion: v1\nkind: ServiceAccount\nmetadata:\n  creationTimestamp: null\n  name: memcached-operator-controller-manager\n"
  },
  {
    "path": "internal/cmd/operator-sdk/pkgmantobundle/testdata/packagemanifests/0.0.1/memcached-operator-manager-config_v1_configmap.yaml",
    "content": "apiVersion: v1\ndata:\n  controller_manager_config.yaml: |\n    apiVersion: controller-runtime.sigs.k8s.io/v1alpha1\n    kind: ControllerManagerConfig\n    health:\n      healthProbeBindAddress: :8081\n    metrics:\n      bindAddress: 127.0.0.1:8080\n    webhook:\n      port: 9443\n    leaderElection:\n      leaderElect: true\n      resourceName: 86f835c3.example.com\nkind: ConfigMap\nmetadata:\n  name: memcached-operator-manager-config\n"
  },
  {
    "path": "internal/cmd/operator-sdk/pkgmantobundle/testdata/packagemanifests/0.0.1/memcached-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  creationTimestamp: null\n  name: memcached-operator-metrics-reader\nrules:\n- nonResourceURLs:\n  - /metrics\n  verbs:\n  - get\n"
  },
  {
    "path": "internal/cmd/operator-sdk/pkgmantobundle/testdata/packagemanifests/0.0.1/memcached-operator.clusterserviceversion.yaml",
    "content": "apiVersion: operators.coreos.com/v1alpha1\nkind: ClusterServiceVersion\nmetadata:\n  annotations:\n    alm-examples: |-\n      [\n        {\n          \"apiVersion\": \"cache.example.com/v1alpha1\",\n          \"kind\": \"Memcached\",\n          \"metadata\": {\n            \"name\": \"memcached-sample\"\n          },\n          \"spec\": {\n            \"foo\": \"bar\"\n          }\n        }\n      ]\n    capabilities: Basic Install\n    operators.operatorframework.io/builder: operator-sdk-v1.5.0+git\n    operators.operatorframework.io/project_layout: go.kubebuilder.io/v3\n  name: memcached-operator.v0.0.1\n  namespace: placeholder\nspec:\n  apiservicedefinitions: {}\n  customresourcedefinitions:\n    owned:\n    - description: Memcached is the Schema for the memcacheds API\n      displayName: Memcached\n      kind: Memcached\n      name: memcacheds.cache.example.com\n      version: v1alpha1\n  description: description\n  displayName: memcached\n  icon:\n  - base64data: \"\"\n    mediatype: \"\"\n  install:\n    spec:\n      clusterPermissions:\n      - rules:\n        - apiGroups:\n          - cache.example.com\n          resources:\n          - memcacheds\n          verbs:\n          - create\n          - delete\n          - get\n          - list\n          - patch\n          - update\n          - watch\n        - apiGroups:\n          - cache.example.com\n          resources:\n          - memcacheds/finalizers\n          verbs:\n          - update\n        - apiGroups:\n          - cache.example.com\n          resources:\n          - memcacheds/status\n          verbs:\n          - get\n          - patch\n          - update\n        - apiGroups:\n          - authentication.k8s.io\n          resources:\n          - tokenreviews\n          verbs:\n          - create\n        - apiGroups:\n          - authorization.k8s.io\n          resources:\n          - subjectaccessreviews\n          verbs:\n          - create\n        serviceAccountName: memcached-operator-controller-manager\n      deployments:\n      - name: memcached-operator-controller-manager\n        spec:\n          replicas: 1\n          selector:\n            matchLabels:\n              control-plane: controller-manager\n          strategy: {}\n          template:\n            metadata:\n              labels:\n                control-plane: controller-manager\n            spec:\n              containers:\n              - args:\n                - --secure-listen-address=0.0.0.0:8443\n                - --upstream=http://127.0.0.1:8080/\n                - --logtostderr=true\n                - --v=10\n                image: gcr.io/kubebuilder/kube-rbac-proxy:v0.8.0\n                name: kube-rbac-proxy\n                ports:\n                - containerPort: 8443\n                  name: https\n                resources: {}\n              - args:\n                - --health-probe-bind-address=:8081\n                - --metrics-bind-address=127.0.0.1:8080\n                - --leader-elect\n                command:\n                - /manager\n                image: controller:latest\n                livenessProbe:\n                  httpGet:\n                    path: /healthz\n                    port: 8081\n                  initialDelaySeconds: 15\n                  periodSeconds: 20\n                name: manager\n                readinessProbe:\n                  httpGet:\n                    path: /readyz\n                    port: 8081\n                  initialDelaySeconds: 5\n                  periodSeconds: 10\n                resources:\n                  limits:\n                    cpu: 100m\n                    memory: 30Mi\n                  requests:\n                    cpu: 100m\n                    memory: 20Mi\n                securityContext:\n                  allowPrivilegeEscalation: false\n              securityContext:\n                runAsNonRoot: true\n              serviceAccountName: memcached-operator-controller-manager\n              terminationGracePeriodSeconds: 10\n      permissions:\n      - rules:\n        - apiGroups:\n          - \"\"\n          - coordination.k8s.io\n          resources:\n          - configmaps\n          - leases\n          verbs:\n          - get\n          - list\n          - watch\n          - create\n          - update\n          - patch\n          - delete\n        - apiGroups:\n          - \"\"\n          resources:\n          - events\n          verbs:\n          - create\n          - patch\n        serviceAccountName: memcached-operator-controller-manager\n    strategy: deployment\n  installModes:\n  - supported: false\n    type: OwnNamespace\n  - supported: false\n    type: SingleNamespace\n  - supported: false\n    type: MultiNamespace\n  - supported: true\n    type: AllNamespaces\n  keywords:\n  - asd\n  - afd\n  links:\n  - name: Memcached Operator\n    url: https://memcached-operator.domain\n  maintainers:\n  - email: email\n    name: name\n  maturity: alpha\n  provider:\n    name: redhat\n    url: url\n  version: 0.0.1\n"
  },
  {
    "path": "internal/cmd/operator-sdk/pkgmantobundle/testdata/packagemanifests/0.0.1/scorecard-config.yaml",
    "content": "apiVersion: scorecard.operatorframework.io/v1alpha3\nkind: Configuration\nmetadata:\n  name: config\nstages:\n- parallel: true\n  tests:\n  - entrypoint:\n    - scorecard-test\n    - basic-check-spec\n    image: quay.io/operator-framework/scorecard-test:v1.5.0\n    labels:\n      suite: basic\n      test: basic-check-spec-test\n  - entrypoint:\n    - scorecard-test\n    - olm-bundle-validation\n    image: quay.io/operator-framework/scorecard-test:v1.5.0\n    labels:\n      suite: olm\n      test: olm-bundle-validation-test\n  - entrypoint:\n    - scorecard-test\n    - olm-crds-have-validation\n    image: quay.io/operator-framework/scorecard-test:v1.5.0\n    labels:\n      suite: olm\n      test: olm-crds-have-validation-test\n  - entrypoint:\n    - scorecard-test\n    - olm-crds-have-resources\n    image: quay.io/operator-framework/scorecard-test:v1.5.0\n    labels:\n      suite: olm\n      test: olm-crds-have-resources-test\n  - entrypoint:\n    - scorecard-test\n    - olm-spec-descriptors\n    image: quay.io/operator-framework/scorecard-test:v1.5.0\n    labels:\n      suite: olm\n      test: olm-spec-descriptors-test\n  - entrypoint:\n    - scorecard-test\n    - olm-status-descriptors\n    image: quay.io/operator-framework/scorecard-test:v1.5.0\n    labels:\n      suite: olm\n      test: olm-status-descriptors-test"
  },
  {
    "path": "internal/cmd/operator-sdk/pkgmantobundle/testdata/packagemanifests/0.0.2/cache.example.com_memcacheds.yaml",
    "content": "apiVersion: apiextensions.k8s.io/v1\nkind: CustomResourceDefinition\nmetadata:\n  annotations:\n    controller-gen.kubebuilder.io/version: v0.4.1\n  creationTimestamp: null\n  name: memcacheds.cache.example.com\nspec:\n  group: cache.example.com\n  names:\n    kind: Memcached\n    listKind: MemcachedList\n    plural: memcacheds\n    singular: memcached\n  scope: Namespaced\n  versions:\n  - name: v1alpha1\n    schema:\n      openAPIV3Schema:\n        description: Memcached is the Schema for the memcacheds API\n        properties:\n          apiVersion:\n            description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'\n            type: string\n          kind:\n            description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'\n            type: string\n          metadata:\n            type: object\n          spec:\n            description: MemcachedSpec defines the desired state of Memcached\n            properties:\n              foo:\n                description: Foo is an example field of Memcached. Edit memcached_types.go to remove/update\n                type: string\n            type: object\n          status:\n            description: MemcachedStatus defines the observed state of Memcached\n            type: object\n        type: object\n    served: true\n    storage: true\n    subresources:\n      status: {}\nstatus:\n  acceptedNames:\n    kind: \"\"\n    plural: \"\"\n  conditions: []\n  storedVersions: []\n"
  },
  {
    "path": "internal/cmd/operator-sdk/pkgmantobundle/testdata/packagemanifests/0.0.2/memcached-operator-controller-manager-metrics-service_v1_service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  creationTimestamp: null\n  labels:\n    control-plane: controller-manager\n  name: memcached-operator-controller-manager-metrics-service\nspec:\n  ports:\n  - name: https\n    port: 8443\n    targetPort: https\n  selector:\n    control-plane: controller-manager\nstatus:\n  loadBalancer: {}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/pkgmantobundle/testdata/packagemanifests/0.0.2/memcached-operator-controller-manager_v1_serviceaccount.yaml",
    "content": "apiVersion: v1\nkind: ServiceAccount\nmetadata:\n  creationTimestamp: null\n  name: memcached-operator-controller-manager\n"
  },
  {
    "path": "internal/cmd/operator-sdk/pkgmantobundle/testdata/packagemanifests/0.0.2/memcached-operator-manager-config_v1_configmap.yaml",
    "content": "apiVersion: v1\ndata:\n  controller_manager_config.yaml: |\n    apiVersion: controller-runtime.sigs.k8s.io/v1alpha1\n    kind: ControllerManagerConfig\n    health:\n      healthProbeBindAddress: :8081\n    metrics:\n      bindAddress: 127.0.0.1:8080\n    webhook:\n      port: 9443\n    leaderElection:\n      leaderElect: true\n      resourceName: 86f835c3.example.com\nkind: ConfigMap\nmetadata:\n  name: memcached-operator-manager-config\n"
  },
  {
    "path": "internal/cmd/operator-sdk/pkgmantobundle/testdata/packagemanifests/0.0.2/memcached-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  creationTimestamp: null\n  name: memcached-operator-metrics-reader\nrules:\n- nonResourceURLs:\n  - /metrics\n  verbs:\n  - get\n"
  },
  {
    "path": "internal/cmd/operator-sdk/pkgmantobundle/testdata/packagemanifests/0.0.2/memcached-operator.clusterserviceversion.yaml",
    "content": "apiVersion: operators.coreos.com/v1alpha1\nkind: ClusterServiceVersion\nmetadata:\n  annotations:\n    alm-examples: |-\n      [\n        {\n          \"apiVersion\": \"cache.example.com/v1alpha1\",\n          \"kind\": \"Memcached\",\n          \"metadata\": {\n            \"name\": \"memcached-sample\"\n          },\n          \"spec\": {\n            \"foo\": \"bar\"\n          }\n        }\n      ]\n    capabilities: Basic Install\n    operators.operatorframework.io/builder: operator-sdk-v1.5.0+git\n    operators.operatorframework.io/project_layout: go.kubebuilder.io/v3\n  name: memcached-operator.v0.0.2\n  namespace: placeholder\nspec:\n  apiservicedefinitions: {}\n  customresourcedefinitions:\n    owned:\n    - description: Memcached is the Schema for the memcacheds API\n      displayName: Memcached\n      kind: Memcached\n      name: memcacheds.cache.example.com\n      version: v1alpha1\n  description: description\n  displayName: memcached\n  icon:\n  - base64data: \"\"\n    mediatype: \"\"\n  install:\n    spec:\n      clusterPermissions:\n      - rules:\n        - apiGroups:\n          - cache.example.com\n          resources:\n          - memcacheds\n          verbs:\n          - create\n          - delete\n          - get\n          - list\n          - patch\n          - update\n          - watch\n        - apiGroups:\n          - cache.example.com\n          resources:\n          - memcacheds/finalizers\n          verbs:\n          - update\n        - apiGroups:\n          - cache.example.com\n          resources:\n          - memcacheds/status\n          verbs:\n          - get\n          - patch\n          - update\n        - apiGroups:\n          - authentication.k8s.io\n          resources:\n          - tokenreviews\n          verbs:\n          - create\n        - apiGroups:\n          - authorization.k8s.io\n          resources:\n          - subjectaccessreviews\n          verbs:\n          - create\n        serviceAccountName: memcached-operator-controller-manager\n      deployments:\n      - name: memcached-operator-controller-manager\n        spec:\n          replicas: 1\n          selector:\n            matchLabels:\n              control-plane: controller-manager\n          strategy: {}\n          template:\n            metadata:\n              labels:\n                control-plane: controller-manager\n            spec:\n              containers:\n              - args:\n                - --secure-listen-address=0.0.0.0:8443\n                - --upstream=http://127.0.0.1:8080/\n                - --logtostderr=true\n                - --v=10\n                image: gcr.io/kubebuilder/kube-rbac-proxy:v0.8.0\n                name: kube-rbac-proxy\n                ports:\n                - containerPort: 8443\n                  name: https\n                resources: {}\n              - args:\n                - --health-probe-bind-address=:8081\n                - --metrics-bind-address=127.0.0.1:8080\n                - --leader-elect\n                command:\n                - /manager\n                image: controller:latest\n                livenessProbe:\n                  httpGet:\n                    path: /healthz\n                    port: 8081\n                  initialDelaySeconds: 15\n                  periodSeconds: 20\n                name: manager\n                readinessProbe:\n                  httpGet:\n                    path: /readyz\n                    port: 8081\n                  initialDelaySeconds: 5\n                  periodSeconds: 10\n                resources:\n                  limits:\n                    cpu: 100m\n                    memory: 30Mi\n                  requests:\n                    cpu: 100m\n                    memory: 20Mi\n                securityContext:\n                  allowPrivilegeEscalation: false\n              securityContext:\n                runAsNonRoot: true\n              serviceAccountName: memcached-operator-controller-manager\n              terminationGracePeriodSeconds: 10\n      permissions:\n      - rules:\n        - apiGroups:\n          - \"\"\n          - coordination.k8s.io\n          resources:\n          - configmaps\n          - leases\n          verbs:\n          - get\n          - list\n          - watch\n          - create\n          - update\n          - patch\n          - delete\n        - apiGroups:\n          - \"\"\n          resources:\n          - events\n          verbs:\n          - create\n          - patch\n        serviceAccountName: memcached-operator-controller-manager\n    strategy: deployment\n  installModes:\n  - supported: false\n    type: OwnNamespace\n  - supported: false\n    type: SingleNamespace\n  - supported: false\n    type: MultiNamespace\n  - supported: true\n    type: AllNamespaces\n  keywords:\n  - asd\n  - afd\n  links:\n  - name: Memcached Operator\n    url: https://memcached-operator.domain\n  maintainers:\n  - email: email\n    name: name\n  maturity: alpha\n  provider:\n    name: redhat\n    url: url\n  version: 0.0.2\n"
  },
  {
    "path": "internal/cmd/operator-sdk/pkgmantobundle/testdata/packagemanifests/memcached-operator.package.yaml",
    "content": "channels:\n- currentCSV: memcached-operator.v0.0.1\n  name: memcached-operator.v0.0.1\n- currentCSV: memcached-operator.v0.0.2\n  name: memcached-operator.v0.0.2\ndefaultChannel: alpha\npackageName: memcached-operator\n"
  },
  {
    "path": "internal/cmd/operator-sdk/run/bundle/cmd.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage bundle\n\nimport (\n\t\"context\"\n\n\t\"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/cobra\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/olm/operator\"\n\t\"github.com/operator-framework/operator-sdk/internal/olm/operator/bundle\"\n)\n\nfunc NewCmd(cfg *operator.Configuration) *cobra.Command {\n\ti := bundle.NewInstall(cfg)\n\tcmd := &cobra.Command{\n\t\tUse:   \"bundle <bundle-image>\",\n\t\tShort: \"Deploy an Operator in the bundle format with OLM\",\n\t\tLong: `The single argument to this command is a bundle image, with the full registry path specified.\nIf using a docker.io image, you must specify docker.io(/<namespace>)?/<bundle-image-name>:<tag>.\nIf the bundle image provided is a SQLite index, it must be pullable by the cluster as SQLite images are pulled from the cluster.\nIf the bundle image provided is a File-Based Catalog (FBC) index, it will be pulled on the local machine.\n\nThe main purpose of this command is to streamline running the bundle without having to provide an index image with the bundle already included.\n\nThe ` + \"`--index-image`\" + ` flag specifies an index image in which to inject the given bundle. It can be specified to resolve dependencies for a bundle. \nThis is an optional flag which will default to ` + \"`quay.io/operator-framework/opm:latest`.\" + `\nThe index image provided should **NOT** already have the bundle. A limitation of the index image flag is that it does not check the upgrade graph\nas the annotations for channels are ignored but it is still a useful flag to have to validate the dependencies. \nFor example: It does not fail fast when the bundle version provided is <= ChannelHead.\n`,\n\t\tArgs:    cobra.ExactArgs(1),\n\t\tPreRunE: func(*cobra.Command, []string) error { return cfg.Load() },\n\t\tRun: func(cmd *cobra.Command, args []string) {\n\t\t\tctx, cancel := context.WithTimeout(cmd.Context(), cfg.Timeout)\n\t\t\tdefer cancel()\n\n\t\t\ti.BundleImage = args[0]\n\n\t\t\t// TODO(joelanford): Add cleanup logic if this fails?\n\t\t\t_, err := i.Run(ctx)\n\t\t\tif err != nil {\n\t\t\t\tlogrus.Fatalf(\"Failed to run bundle: %v\\n\", err)\n\t\t\t}\n\t\t},\n\t}\n\n\tcfg.BindFlags(cmd.Flags())\n\ti.BindFlags(cmd.Flags())\n\n\treturn cmd\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/run/bundleupgrade/cmd.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage bundleupgrade\n\nimport (\n\t\"context\"\n\n\t\"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/cobra\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/olm/operator\"\n\t\"github.com/operator-framework/operator-sdk/internal/olm/operator/bundleupgrade\"\n)\n\nfunc NewCmd(cfg *operator.Configuration) *cobra.Command {\n\tu := bundleupgrade.NewUpgrade(cfg)\n\tcmd := &cobra.Command{\n\t\tUse:   \"bundle-upgrade <bundle-image>\",\n\t\tShort: \"Upgrade an Operator previously installed in the bundle format with OLM\",\n\t\tLong: `The single argument to this command is a bundle image, with the full registry path specified.\nIf using a docker.io image, you must specify docker.io(/<namespace>)?/<bundle-image-name>:<tag>.\nIf the bundle image provided is a SQLite index, it must be pullable by the cluster as SQLite images are pulled from the cluster.\nIf the bundle image provided is a File-Based Catalog (FBC) index, it will be pulled on the local machine.`,\n\t\tArgs:    cobra.ExactArgs(1),\n\t\tPreRunE: func(*cobra.Command, []string) error { return cfg.Load() },\n\t\tRun: func(cmd *cobra.Command, args []string) {\n\t\t\tctx, cancel := context.WithTimeout(cmd.Context(), cfg.Timeout)\n\t\t\tdefer cancel()\n\n\t\t\tu.BundleImage = args[0]\n\n\t\t\t_, err := u.Run(ctx)\n\t\t\tif err != nil {\n\t\t\t\tlogrus.Fatalf(\"Failed to run bundle upgrade: %v\\n\", err)\n\t\t\t}\n\t\t},\n\t}\n\n\tcfg.BindFlags(cmd.Flags())\n\tu.BindFlags(cmd.Flags())\n\n\treturn cmd\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/run/cmd.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage run\n\nimport (\n\t\"github.com/spf13/cobra\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/run/bundle\"\n\t\"github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/run/bundleupgrade\"\n\t\"github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/run/packagemanifests\"\n\t\"github.com/operator-framework/operator-sdk/internal/olm/operator\"\n)\n\nfunc NewCmd() *cobra.Command {\n\tcmd := &cobra.Command{\n\t\tUse:   \"run\",\n\t\tShort: \"Run an Operator in a variety of environments\",\n\t\tLong:  `This command has subcommands that will deploy your Operator with OLM.`,\n\t}\n\n\tcfg := &operator.Configuration{}\n\n\tcmd.AddCommand(\n\t\tbundle.NewCmd(cfg),\n\t\tbundleupgrade.NewCmd(cfg),\n\t\tpackagemanifests.NewCmd(cfg),\n\t)\n\n\treturn cmd\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/run/cmd_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage run\n\nimport (\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nvar _ = Describe(\"Running a run command\", func() {\n\tDescribe(\"NewCmd\", func() {\n\t\tIt(\"builds a cobra command with the correct subcommands\", func() {\n\t\t\tcmd := NewCmd()\n\t\t\tExpect(cmd).NotTo(BeNil())\n\t\t\tExpect(cmd.Use).NotTo(BeNil())\n\t\t\tExpect(cmd.Short).NotTo(BeNil())\n\t\t\tExpect(cmd.Long).NotTo(BeNil())\n\n\t\t\tsubcommands := cmd.Commands()\n\t\t\tExpect(subcommands).To(HaveLen(3))\n\t\t\tExpect(subcommands[0].Use).To(Equal(\"bundle <bundle-image>\"))\n\t\t\tExpect(subcommands[1].Use).To(Equal(\"bundle-upgrade <bundle-image>\"))\n\t\t\tExpect(subcommands[2].Use).To(Equal(\"packagemanifests [packagemanifests-root-dir]\"))\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "internal/cmd/operator-sdk/run/packagemanifests/packagemanifests.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage packagemanifests\n\nimport (\n\t\"context\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/cobra\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/olm/operator\"\n\t\"github.com/operator-framework/operator-sdk/internal/olm/operator/packagemanifests\"\n)\n\nfunc NewCmd(cfg *operator.Configuration) *cobra.Command {\n\ti := packagemanifests.NewInstall(cfg)\n\tcmd := &cobra.Command{\n\t\tUse: \"packagemanifests [packagemanifests-root-dir]\",\n\t\tDeprecated: \"support for the packagemanifests format will be removed in operator-sdk v2.0.0. Use bundles to \" +\n\t\t\t\"package your operator instead. Migrate your packagemanifest to a bundle using \" +\n\t\t\t\"'operator-sdk pkgman-to-bundle' command. Run 'operator-sdk pkgman-to-bundle --help' \" +\n\t\t\t\"for more details.\",\n\t\tShort: \"Deploy an Operator in the package manifests format with OLM\",\n\t\tLong: `'run packagemanifests' deploys an Operator's package manifests with OLM. The command's argument\nwill default to './packagemanifests' if unset; if set, the argument must be a package manifests root directory,\nex. '<project-root>/packagemanifests'.`,\n\t\tAliases: []string{\"pm\"},\n\t\tArgs:    cobra.MaximumNArgs(1),\n\t\tPreRunE: func(*cobra.Command, []string) error { return cfg.Load() },\n\t\tRun: func(cmd *cobra.Command, args []string) {\n\t\t\tctx, cancel := context.WithTimeout(cmd.Context(), cfg.Timeout)\n\t\t\tdefer cancel()\n\n\t\t\tif len(args) == 0 {\n\t\t\t\ti.PackageManifestsDirectory = \"packagemanifests\"\n\t\t\t} else {\n\t\t\t\ti.PackageManifestsDirectory = args[0]\n\t\t\t}\n\n\t\t\t// TODO(joelanford): Add cleanup logic if this fails?\n\t\t\t_, err := i.Run(ctx)\n\t\t\tif err != nil {\n\t\t\t\tlog.Fatalf(\"Failed to run packagemanifests: %v\\n\", err)\n\t\t\t}\n\t\t},\n\t}\n\n\tcfg.BindFlags(cmd.Flags())\n\ti.BindFlags(cmd.Flags())\n\t// Not implemented.\n\tif err := cmd.Flags().MarkHidden(\"service-account\"); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\treturn cmd\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/run/packagemanifests/packagemanifests_suite_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage packagemanifests_test\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nfunc TestRun(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"Packagemanifests Cmd Suite\")\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/run/packagemanifests/packagemanifests_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage packagemanifests\n\nimport (\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/olm/operator\"\n)\n\nvar _ = Describe(\"Running a run packagemanifests command\", func() {\n\tDescribe(\"NewCmd\", func() {\n\t\tIt(\"builds a cobra command\", func() {\n\t\t\tcfg := &operator.Configuration{}\n\t\t\tcmd := NewCmd(cfg)\n\t\t\tExpect(cmd).NotTo(BeNil())\n\t\t\tExpect(cmd.Use).NotTo(BeNil())\n\t\t\tExpect(cmd.Short).NotTo(BeNil())\n\t\t\tExpect(cmd.Long).NotTo(BeNil())\n\t\t\taliases := cmd.Aliases\n\t\t\tExpect(aliases).To(HaveLen(1))\n\t\t\tExpect(aliases[0]).To(Equal(\"pm\"))\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "internal/cmd/operator-sdk/run/run_suite_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage run_test\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nfunc TestRun(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"Run Cmd Suite\")\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/scorecard/cmd.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage scorecard\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"encoding/xml\"\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/operator-framework/api/pkg/apis/scorecard/v1alpha3\"\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/cobra\"\n\t\"github.com/spf13/viper\"\n\t\"k8s.io/apimachinery/pkg/labels\"\n\n\tscorecardannotations \"github.com/operator-framework/operator-sdk/internal/annotations/scorecard\"\n\txunit \"github.com/operator-framework/operator-sdk/internal/cmd/operator-sdk/scorecard/xunit\"\n\t\"github.com/operator-framework/operator-sdk/internal/flags\"\n\tregistryutil \"github.com/operator-framework/operator-sdk/internal/registry\"\n\t\"github.com/operator-framework/operator-sdk/internal/scorecard\"\n)\n\ntype scorecardCmd struct {\n\tbundle         string\n\tconfig         string\n\tkubeconfig     string\n\tnamespace      string\n\toutputFormat   string\n\tselector       string\n\tserviceAccount string\n\tlist           bool\n\tskipCleanup    bool\n\twaitTime       time.Duration\n\tstorageImage   string\n\tuntarImage     string\n\ttestOutput     string\n\tpodSecurity    string\n}\n\nfunc NewCmd() *cobra.Command {\n\tc := scorecardCmd{}\n\n\tscorecardCmd := &cobra.Command{\n\t\tUse:   \"scorecard\",\n\t\tShort: \"Runs scorecard\",\n\t\t// TODO: describe what the purpose of the command is, why someone would want\n\t\t// to run it, etc.\n\t\tLong: `Has flags to configure dsl, bundle, and selector. This command takes\none argument, either a bundle image or directory containing manifests and metadata.\nIf the argument holds an image tag, it must be present remotely.`,\n\t\tPreRunE: func(_ *cobra.Command, args []string) (err error) {\n\t\t\treturn c.validate(args)\n\t\t},\n\t\tRunE: func(_ *cobra.Command, args []string) (err error) {\n\t\t\tc.bundle = args[0]\n\t\t\treturn c.run()\n\t\t},\n\t}\n\n\tscorecardCmd.Flags().StringVar(&c.kubeconfig, \"kubeconfig\", \"\", \"kubeconfig path\")\n\tscorecardCmd.Flags().StringVarP(&c.selector, \"selector\", \"l\", \"\", \"label selector to determine which tests are run\")\n\tscorecardCmd.Flags().StringVarP(&c.config, \"config\", \"c\", \"\", \"path to scorecard config file\")\n\tscorecardCmd.Flags().StringVarP(&c.namespace, \"namespace\", \"n\", \"\", \"namespace to run the test images in\")\n\tscorecardCmd.Flags().StringVarP(&c.outputFormat, \"output\", \"o\", \"text\",\n\t\t\"Output format for results. Valid values: text, json, xunit\")\n\tscorecardCmd.Flags().StringVar(&c.podSecurity, \"pod-security\", \"legacy\", \"option to run scorecard with legacy pod security context\")\n\tscorecardCmd.Flags().StringVarP(&c.serviceAccount, \"service-account\", \"s\", \"default\",\n\t\t\"Service account to use for tests\")\n\tscorecardCmd.Flags().BoolVarP(&c.list, \"list\", \"L\", false,\n\t\t\"Option to enable listing which tests are run\")\n\tscorecardCmd.Flags().BoolVarP(&c.skipCleanup, \"skip-cleanup\", \"x\", false,\n\t\t\"Disable resource cleanup after tests are run\")\n\tscorecardCmd.Flags().DurationVarP(&c.waitTime, \"wait-time\", \"w\", 30*time.Second,\n\t\t\"seconds to wait for tests to complete. Example: 35s\")\n\t// Please note that for Operator-sdk + Preflight + DCI integration in disconnected environments,\n\t// it is necessary to refer to storage-image and untar-image using their digests instead of tags.\n\t// If you need to make changes to these images, please ensure that you always use the digests.\n\tscorecardCmd.Flags().StringVarP(&c.storageImage, \"storage-image\", \"b\",\n\t\t\"quay.io/operator-framework/scorecard-storage@sha256:a3bfda71281393c7794cabdd39c563fb050d3020fd0b642ea164646bdd39a0e2\",\n\t\t\"Storage image to be used by the Scorecard pod\")\n\t// Use the digest of the latest scorecard-untar image\n\tscorecardCmd.Flags().StringVarP(&c.untarImage, \"untar-image\", \"u\",\n\t\t\"quay.io/operator-framework/scorecard-untar@sha256:2e728c5e67a7f4dec0df157a322dd5671212e8ae60f69137463bd4fdfbff8747\",\n\t\t\"Untar image to be used by the Scorecard pod\")\n\tscorecardCmd.Flags().StringVarP(&c.testOutput, \"test-output\", \"t\", \"test-output\",\n\t\t\"Test output directory.\")\n\n\treturn scorecardCmd\n}\n\nfunc (c *scorecardCmd) printOutput(output v1alpha3.TestList) error {\n\tswitch c.outputFormat {\n\tcase \"text\":\n\t\tif len(output.Items) == 0 {\n\t\t\tfmt.Println(\"0 tests selected\")\n\t\t\treturn nil\n\t\t}\n\t\tfor _, test := range output.Items {\n\t\t\tfmt.Println(test.MarshalText())\n\t\t}\n\tcase \"json\":\n\t\tbytes, err := json.MarshalIndent(output, \"\", \"  \")\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"marshal json error: %v\", err)\n\t\t}\n\t\tfmt.Printf(\"%s\\n\", string(bytes))\n\tcase \"xunit\":\n\t\txunitOutput := c.convertXunit(output)\n\t\tbytes, err := xml.MarshalIndent(xunitOutput, \"\", \"  \")\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"marshal xml error: %v\", err)\n\t\t}\n\t\tfmt.Printf(\"%s\\n\", string(bytes))\n\tdefault:\n\t\treturn fmt.Errorf(\"invalid output format selected\")\n\t}\n\treturn nil\n}\n\nfunc (c *scorecardCmd) convertXunit(output v1alpha3.TestList) xunit.TestSuites {\n\tconst (\n\t\timagePropName        = \"spec.image\"\n\t\tentrypointPropName   = \"spec.entrypoint\"\n\t\ttestPropName         = \"labels.test\"\n\t\tclusterPhasePropName = \"labels.cluster-phase\"\n\t)\n\n\tsuites := make([]xunit.TestSuite, 0, len(output.Items))\n\tfor i, item := range output.Items {\n\t\tsuiteName, ok := item.Spec.Labels[\"test\"]\n\t\tif !ok {\n\t\t\tsuiteName = fmt.Sprintf(\"testsuite-%03d\", i+1)\n\t\t}\n\n\t\tts := xunit.NewSuite(suiteName)\n\t\tts.AddProperty(imagePropName, item.Spec.Image)\n\t\tts.AddProperty(entrypointPropName, strings.Join(item.Spec.Entrypoint, \" \"))\n\t\tts.AddProperty(testPropName, suiteName)\n\t\tif phase, ok := item.Spec.Labels[\"cluster-phase\"]; ok {\n\t\t\tts.AddProperty(clusterPhasePropName, phase)\n\t\t}\n\n\t\tfor _, tc := range item.Status.Results {\n\t\t\tswitch tc.State {\n\t\t\tcase v1alpha3.PassState:\n\t\t\t\tts.AddSuccess(tc.Name, tc.CreationTimestamp.Time, tc.Log)\n\t\t\tcase v1alpha3.FailState:\n\t\t\t\tts.AddFailure(tc.Name, tc.CreationTimestamp.Time, tc.Log, strings.Join(tc.Errors, \"\\n\"))\n\t\t\tcase v1alpha3.ErrorState:\n\t\t\t\tts.AddError(tc.Name, tc.CreationTimestamp.Time, tc.Log, strings.Join(tc.Errors, \"\\n\"))\n\t\t\t}\n\t\t}\n\n\t\tsuites = append(suites, ts)\n\t}\n\n\treturn xunit.NewTestSuites(\"scorecard\", suites)\n}\n\nfunc (c *scorecardCmd) run() (err error) {\n\t// Extract bundle image contents if bundle is inferred to be an image.\n\tif _, err = os.Stat(c.bundle); err != nil && errors.Is(err, os.ErrNotExist) {\n\t\tif c.bundle, err = extractBundleImage(c.bundle); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tdefer func() {\n\t\t\tif err := os.RemoveAll(c.bundle); err != nil {\n\t\t\t\tlog.Error(err)\n\t\t\t}\n\t\t}()\n\t}\n\n\tmetadata, _, err := registryutil.FindBundleMetadata(c.bundle)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tpodSecFlag := true\n\tswitch c.podSecurity {\n\tcase \"restricted\":\n\t\tpodSecFlag = true\n\tcase \"legacy\":\n\t\tpodSecFlag = false\n\t}\n\n\to := scorecard.Scorecard{\n\t\tSkipCleanup: c.skipCleanup,\n\t\tPodSecurity: podSecFlag,\n\t}\n\n\tconfigPath := c.config\n\tif configPath == \"\" {\n\t\tconfigDir, hasDir := scorecardannotations.GetConfigDir(metadata)\n\t\tif !hasDir {\n\t\t\tconfigDir = filepath.FromSlash(scorecard.DefaultConfigDir)\n\t\t}\n\t\tconfigPath = filepath.Join(c.bundle, configDir, scorecard.ConfigFileName)\n\t}\n\to.Config, err = scorecard.LoadConfig(configPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"could not find config file %w\", err)\n\t}\n\n\to.Selector, err = labels.Parse(c.selector)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"could not parse selector %w\", err)\n\t}\n\n\tvar scorecardTests v1alpha3.TestList\n\tif c.list {\n\t\tscorecardTests = o.List()\n\t} else {\n\t\trunnerSA := c.serviceAccount\n\t\tif o.Config.ServiceAccount != \"\" {\n\t\t\trunnerSA = o.Config.ServiceAccount\n\t\t}\n\t\trunner := scorecard.PodTestRunner{\n\t\t\tServiceAccount: runnerSA,\n\t\t\tNamespace:      scorecard.GetKubeNamespace(c.kubeconfig, c.namespace),\n\t\t\tBundlePath:     c.bundle,\n\t\t\tTestOutput:     c.testOutput,\n\t\t\tBundleMetadata: metadata,\n\t\t\tStorageImage:   c.storageImage,\n\t\t\tUntarImage:     c.untarImage,\n\t\t}\n\n\t\t// Only get the client if running tests.\n\t\tif runner.Client, runner.RESTConfig, err = scorecard.GetKubeClient(c.kubeconfig); err != nil {\n\t\t\treturn fmt.Errorf(\"error getting kubernetes client: %w\", err)\n\t\t}\n\n\t\to.TestRunner = &runner\n\n\t\tctx, cancel := context.WithTimeout(context.Background(), c.waitTime)\n\t\tdefer cancel()\n\n\t\tscorecardTests, err = o.Run(ctx)\n\t\tif err != nil {\n\t\t\t// if we got a timeout; printout the test results if there are any\n\t\t\tif err == context.DeadlineExceeded {\n\t\t\t\tif errpo := c.printOutput(scorecardTests); errpo != nil {\n\t\t\t\t\tlog.Fatal(errpo)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn fmt.Errorf(\"error running tests %w\", err)\n\t\t}\n\t}\n\n\tif err := c.printOutput(scorecardTests); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tif hasFailingTest(scorecardTests) {\n\t\tos.Exit(1)\n\t}\n\treturn nil\n}\n\nfunc hasFailingTest(list v1alpha3.TestList) bool {\n\tfor _, t := range list.Items {\n\t\tfor _, r := range t.Status.Results {\n\t\t\tif r.State != v1alpha3.PassState {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t}\n\treturn false\n}\n\nfunc (c *scorecardCmd) validate(args []string) error {\n\tif len(args) != 1 {\n\t\treturn fmt.Errorf(\"a bundle image or directory argument is required\")\n\t}\n\treturn nil\n}\n\n// extractBundleImage returns bundleImage's path on disk post-extraction.\nfunc extractBundleImage(bundleImage string) (string, error) {\n\t// Discard bundle extraction logs unless user sets verbose mode.\n\tlogger := registryutil.DiscardLogger()\n\tif viper.GetBool(flags.VerboseOpt) {\n\t\tlogger = log.WithFields(log.Fields{\"bundle\": bundleImage})\n\t}\n\t// FEAT: enable explicit local image extraction.\n\treturn registryutil.ExtractBundleImage(context.TODO(), logger, bundleImage, false, false, false)\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/scorecard/cmd_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage scorecard\n\nimport (\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nvar _ = Describe(\"Running the scorecard command\", func() {\n\tDescribe(\"NewCmd\", func() {\n\t\tIt(\"builds and returns a cobra command\", func() {\n\t\t\tcmd := NewCmd()\n\t\t\tExpect(cmd).NotTo(BeNil())\n\n\t\t\tflag := cmd.Flags().Lookup(\"kubeconfig\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\n\t\t\tflag = cmd.Flags().Lookup(\"selector\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\t\t\tExpect(flag.Shorthand).To(Equal(\"l\"))\n\n\t\t\tflag = cmd.Flags().Lookup(\"config\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\t\t\tExpect(flag.Shorthand).To(Equal(\"c\"))\n\n\t\t\tflag = cmd.Flags().Lookup(\"namespace\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\t\t\tExpect(flag.Shorthand).To(Equal(\"n\"))\n\t\t\tExpect(flag.DefValue).To(Equal(\"\"))\n\n\t\t\tflag = cmd.Flags().Lookup(\"output\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\t\t\tExpect(flag.Shorthand).To(Equal(\"o\"))\n\t\t\tExpect(flag.DefValue).To(Equal(\"text\"))\n\n\t\t\tflag = cmd.Flags().Lookup(\"service-account\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\t\t\tExpect(flag.Shorthand).To(Equal(\"s\"))\n\t\t\tExpect(flag.DefValue).To(Equal(\"default\"))\n\n\t\t\tflag = cmd.Flags().Lookup(\"list\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\t\t\tExpect(flag.Shorthand).To(Equal(\"L\"))\n\t\t\tExpect(flag.DefValue).To(Equal(\"false\"))\n\n\t\t\tflag = cmd.Flags().Lookup(\"skip-cleanup\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\t\t\tExpect(flag.Shorthand).To(Equal(\"x\"))\n\t\t\tExpect(flag.DefValue).To(Equal(\"false\"))\n\n\t\t\tflag = cmd.Flags().Lookup(\"wait-time\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\t\t\tExpect(flag.Shorthand).To(Equal(\"w\"))\n\t\t\tExpect(flag.DefValue).To(Equal(\"30s\"))\n\n\t\t\tflag = cmd.Flags().Lookup(\"storage-image\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\t\t\tExpect(flag.Shorthand).To(Equal(\"b\"))\n\t\t\t// Use the digest of the latest scorecard-storage image\n\t\t\tExpect(flag.DefValue).To(Equal(\"quay.io/operator-framework/scorecard-storage@sha256:a3bfda71281393c7794cabdd39c563fb050d3020fd0b642ea164646bdd39a0e2\"))\n\n\t\t\tflag = cmd.Flags().Lookup(\"untar-image\")\n\t\t\tExpect(flag).NotTo(BeNil())\n\t\t\tExpect(flag.Shorthand).To(Equal(\"u\"))\n\t\t\t// Use the digest of the latest scorecard-untar image\n\t\t\tExpect(flag.DefValue).To(Equal(\"quay.io/operator-framework/scorecard-untar@sha256:2e728c5e67a7f4dec0df157a322dd5671212e8ae60f69137463bd4fdfbff8747\"))\n\t\t})\n\t})\n\n\tDescribe(\"validate\", func() {\n\t\tvar cmd scorecardCmd\n\t\tBeforeEach(func() {\n\t\t\tcmd = scorecardCmd{}\n\t\t})\n\t\tIt(\"fails if anything other than exactly one arg is provided\", func() {\n\t\t\terr := cmd.validate([]string{})\n\t\t\tExpect(err).To(HaveOccurred())\n\n\t\t\terr = cmd.validate([]string{\"apple\", \"banana\"})\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t})\n\n\t\tIt(\"succeeds if exactly one arg is provided\", func() {\n\t\t\tinput := \"cherry\"\n\t\t\terr := cmd.validate([]string{input})\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "internal/cmd/operator-sdk/scorecard/scorecard_suite_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage scorecard_test\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nfunc TestScorecard(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"Scorecard Cmd Suite\")\n}\n"
  },
  {
    "path": "internal/cmd/operator-sdk/scorecard/xunit/xunit.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage xunitapi\n\nimport (\n\t\"encoding/xml\"\n\t\"time\"\n)\n\n// NewTestSuites returns a new XUnit result from the given test suites.\nfunc NewTestSuites(name string, testSuites []TestSuite) TestSuites {\n\treturn TestSuites{\n\t\tName:       name,\n\t\tTestSuites: testSuites,\n\t}\n}\n\n// TestSuites is the top level object for amassing Xunit test results\ntype TestSuites struct {\n\tXMLName    xml.Name    `xml:\"testsuites\"` // Component name: <testsuites>\n\tName       string      `xml:\"name,attr\"`\n\tTestSuites []TestSuite `xml:\"testsuite\"`\n}\n\n// Preperty is a named property that will be formatted as an XML tag.\ntype Property struct {\n\tName  string `xml:\"name,attr\"`\n\tValue any    `xml:\"value,attr\"`\n}\n\n// TestSuite contains for details about a test beyond the final status\ntype TestSuite struct {\n\tName       string `xml:\"name,attr\"`\n\tProperties struct {\n\t\tProperties []Property `xml:\"property\"`\n\t} `xml:\"properties,omitempty\"`\n\tTestCases []TestCase `xml:\"testcase,omitempty\"`\n\tTests     int        `xml:\"tests,attr\"`\n\tSkipped   int        `xml:\"skipped,attr\"`\n\tFailures  int        `xml:\"failures,attr\"`\n\tErrors    int        `xml:\"errors,attr\"`\n}\n\n// NewSuite creates a new test suite with the given name.\nfunc NewSuite(name string) TestSuite {\n\treturn TestSuite{Name: name}\n}\n\n// AddProperty adds the property key/value to the test suite.\nfunc (ts *TestSuite) AddProperty(name, value string) {\n\tts.Properties.Properties = append(ts.Properties.Properties, Property{Name: name, Value: value})\n}\n\n// AddSuccess adds a passing test case to the suite.\nfunc (ts *TestSuite) AddSuccess(name string, time time.Time, logs string) {\n\tts.addTest(name, time, logs, nil)\n}\n\n// AddFailure adds a failed test case to the suite.\nfunc (ts *TestSuite) AddFailure(name string, time time.Time, logs, msg string) {\n\tts.Failures++\n\tts.addTest(name, time, logs, &Result{\n\t\tXMLName: xml.Name{Local: \"failure\"},\n\t\tType:    \"failure\",\n\t\tMessage: msg,\n\t})\n}\n\n// AddError adds an errored test case to the suite.\nfunc (ts *TestSuite) AddError(name string, time time.Time, logs, msg string) {\n\tts.Errors++\n\tts.addTest(name, time, logs, &Result{\n\t\tXMLName: xml.Name{Local: \"error\"},\n\t\tType:    \"error\",\n\t\tMessage: msg,\n\t})\n}\n\nfunc (ts *TestSuite) addTest(name string, time time.Time, logs string, result *Result) {\n\tts.Tests++\n\tts.TestCases = append(ts.TestCases, TestCase{\n\t\tName:      name,\n\t\tTime:      time,\n\t\tSystemOut: logs,\n\t\tResult:    result,\n\t})\n}\n\n// TestCase contains information about an individual test case.\ntype TestCase struct {\n\tName      string    `xml:\"name,attr\"`\n\tTime      time.Time `xml:\"time,attr\"`\n\tSystemOut string    `xml:\"system-out\"`\n\tResult    *Result   `xml:\",omitempty\"`\n}\n\n// Result represents the final state of the test case.\ntype Result struct {\n\tXMLName xml.Name\n\tType    string `xml:\"type,attr\"`\n\tMessage string `xml:\",innerxml\"`\n}\n"
  },
  {
    "path": "internal/flags/flags.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage flags\n\n// global command-line flags\nconst (\n\tVerboseOpt = \"verbose\"\n)\n"
  },
  {
    "path": "internal/generate/clusterserviceversion/bases/clusterserviceversion.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage bases\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"os\"\n\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\tlog \"github.com/sirupsen/logrus\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/runtime/schema\"\n\t\"sigs.k8s.io/yaml\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/generate/clusterserviceversion/bases/definitions\"\n\t\"github.com/operator-framework/operator-sdk/internal/util/k8sutil\"\n\t\"github.com/operator-framework/operator-sdk/internal/util/projutil\"\n)\n\n// ClusterServiceVersion configures the v1alpha1.ClusterServiceVersion\n// that GetBase() returns.\ntype ClusterServiceVersion struct {\n\t// BasePath is the path to the base being read. If empty, GetBase() returns\n\t// a default base.\n\tBasePath string\n\t// OperatorName is the operator's name, ex. app-operator\n\tOperatorName string\n\t// OperatorType\n\tOperatorType projutil.OperatorType\n\t// APIsDir contains project API definition files.\n\tAPIsDir string\n\t// GVKs are all GroupVersionKinds in the project.\n\tGVKs []schema.GroupVersionKind\n\t// Interactive turns on an interactive prompt.\n\tInteractive bool\n\n\t// Fields for input to the base.\n\tDisplayName  string\n\tDescription  string\n\tMaturity     string\n\tCapabilities string\n\tKeywords     []string\n\tProvider     v1alpha1.AppLink\n\tLinks        []v1alpha1.AppLink\n\tMaintainers  []v1alpha1.Maintainer\n\tIcon         []v1alpha1.Icon // TODO(estroz): read icon bytes from files.\n}\n\n// GetBase returns a base v1alpha1.ClusterServiceVersion, populated\n// either with default values or, if b.BasePath is set, bytes from disk.\nfunc (b ClusterServiceVersion) GetBase() (base *v1alpha1.ClusterServiceVersion, err error) {\n\tif b.BasePath != \"\" {\n\t\tif base, err = readClusterServiceVersionBase(b.BasePath); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error reading existing ClusterServiceVersion base %s: %v\", b.BasePath, err)\n\t\t}\n\t\t// Auto-migrate bases with names matching \"<operator name>.vX.Y.Z\", which\n\t\t// may cause problems with the CSV validator.\n\t\tif base.GetName() == b.OperatorName+\".vX.Y.Z\" {\n\t\t\tbase.SetName(fmt.Sprintf(\"%s.v%s\", b.OperatorName, base.Spec.Version.String()))\n\t\t}\n\t} else {\n\t\tb.setDefaults()\n\t\tbase = b.newBase()\n\t}\n\n\t// Interactively fill in UI metadata.\n\tif b.Interactive {\n\t\tmeta := &uiMetadata{}\n\t\tmeta.runInteractivePrompt()\n\t\tmeta.apply(base)\n\t}\n\n\tif b.APIsDir != \"\" {\n\t\tswitch b.OperatorType {\n\t\tcase projutil.OperatorTypeGo:\n\t\t\t// Update descriptions from the APIs dir.\n\t\t\terr = definitions.ApplyDefinitionsForKeysGo(base, b.APIsDir, b.GVKs)\n\t\t}\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error generating ClusterServiceVersion definitions metadata: %w\", err)\n\t\t}\n\t}\n\n\treturn base, nil\n}\n\n// New returns a base with default data with name opertorName.\nfunc New(operatorName string) *v1alpha1.ClusterServiceVersion {\n\tb := ClusterServiceVersion{OperatorName: operatorName}\n\tb.setDefaults()\n\treturn b.newBase()\n}\n\n// setDefaults sets default values in b using b's existing values.\nfunc (b *ClusterServiceVersion) setDefaults() {\n\tif b.DisplayName == \"\" {\n\t\tb.DisplayName = k8sutil.GetDisplayName(b.OperatorName)\n\t}\n\tif b.Description == \"\" {\n\t\tb.Description = b.DisplayName + \" description. TODO.\"\n\t}\n\tif b.Maturity == \"\" {\n\t\tb.Maturity = \"alpha\"\n\t}\n\tif b.Capabilities == \"\" {\n\t\tb.Capabilities = \"Basic Install\"\n\t}\n\tif len(b.Keywords) == 0 || b.Keywords[0] == \"\" {\n\t\tb.Keywords = []string{b.OperatorName}\n\t}\n\tif len(b.Links) == 0 || b.Links[0] == (v1alpha1.AppLink{}) {\n\t\tb.Links = []v1alpha1.AppLink{\n\t\t\t{\n\t\t\t\tName: b.DisplayName,\n\t\t\t\tURL:  fmt.Sprintf(\"https://%s.domain\", b.OperatorName),\n\t\t\t},\n\t\t}\n\t}\n\tif len(b.Icon) == 0 {\n\t\tb.Icon = make([]v1alpha1.Icon, 1)\n\t}\n\tif b.Provider == (v1alpha1.AppLink{}) {\n\t\tb.Provider = v1alpha1.AppLink{\n\t\t\tName: \"Provider Name\",\n\t\t\tURL:  \"https://your.domain\",\n\t\t}\n\t}\n\tif len(b.Maintainers) == 0 || b.Maintainers[0] == (v1alpha1.Maintainer{}) {\n\t\tb.Maintainers = []v1alpha1.Maintainer{\n\t\t\t{\n\t\t\t\tName:  \"Maintainer Name\",\n\t\t\t\tEmail: \"your@email.com\",\n\t\t\t},\n\t\t}\n\t}\n}\n\n// newBase returns a base v1alpha1.ClusterServiceVersion to modify.\nfunc (b ClusterServiceVersion) newBase() *v1alpha1.ClusterServiceVersion {\n\treturn &v1alpha1.ClusterServiceVersion{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tAPIVersion: v1alpha1.ClusterServiceVersionAPIVersion,\n\t\t\tKind:       v1alpha1.ClusterServiceVersionKind,\n\t\t},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      b.OperatorName + \".v0.0.0\",\n\t\t\tNamespace: \"placeholder\",\n\t\t\tAnnotations: map[string]string{\n\t\t\t\t\"capabilities\": b.Capabilities,\n\t\t\t\t\"alm-examples\": \"[]\",\n\t\t\t},\n\t\t},\n\t\tSpec: v1alpha1.ClusterServiceVersionSpec{\n\t\t\tDisplayName: b.DisplayName,\n\t\t\tDescription: b.Description,\n\t\t\tProvider:    b.Provider,\n\t\t\tMaintainers: b.Maintainers,\n\t\t\tLinks:       b.Links,\n\t\t\tMaturity:    b.Maturity,\n\t\t\tKeywords:    b.Keywords,\n\t\t\tIcon:        b.Icon,\n\t\t\tInstallModes: []v1alpha1.InstallMode{\n\t\t\t\t{Type: v1alpha1.InstallModeTypeOwnNamespace, Supported: false},\n\t\t\t\t{Type: v1alpha1.InstallModeTypeSingleNamespace, Supported: false},\n\t\t\t\t{Type: v1alpha1.InstallModeTypeMultiNamespace, Supported: false},\n\t\t\t\t{Type: v1alpha1.InstallModeTypeAllNamespaces, Supported: true},\n\t\t\t},\n\t\t},\n\t}\n}\n\n// readClusterServiceVersionBase returns the ClusterServiceVersion base at path.\n// If no base is found, readClusterServiceVersionBase returns an error.\nfunc readClusterServiceVersionBase(path string) (*v1alpha1.ClusterServiceVersion, error) {\n\tb, err := os.ReadFile(path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tscanner := k8sutil.NewYAMLScanner(bytes.NewBuffer(b))\n\tfor scanner.Scan() {\n\t\tmanifest := scanner.Bytes()\n\t\ttypeMeta, err := k8sutil.GetTypeMetaFromBytes(manifest)\n\t\tif err != nil {\n\t\t\tlog.Debugf(\"Skipping non-Object manifest %s: %v\", path, err)\n\t\t\tcontinue\n\t\t}\n\t\tif typeMeta.Kind == v1alpha1.ClusterServiceVersionKind {\n\t\t\tcsv := &v1alpha1.ClusterServiceVersion{}\n\t\t\tif err := yaml.Unmarshal(manifest, csv); err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"error unmarshaling ClusterServiceVersion from manifest %s: %v\", path, err)\n\t\t\t}\n\t\t\treturn csv, nil\n\t\t}\n\t}\n\tif err = scanner.Err(); err != nil {\n\t\treturn nil, fmt.Errorf(\"error scanning manifest %s: %v\", path, err)\n\t}\n\n\treturn nil, fmt.Errorf(\"no ClusterServiceVersion manifest in %s\", path)\n}\n"
  },
  {
    "path": "internal/generate/clusterserviceversion/bases/definitions/ast.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage definitions\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"go/ast\"\n\t\"strconv\"\n\n\t\"golang.org/x/tools/go/packages\"\n\t\"sigs.k8s.io/controller-tools/pkg/crd\"\n\t\"sigs.k8s.io/controller-tools/pkg/loader\"\n\t\"sigs.k8s.io/controller-tools/pkg/markers\"\n)\n\n// importIdents maps import identifiers to a list of corresponding path and file containing that path.\n// For example, consider the set of 2 files, one containing 'import foo \"my/foo\"' and the other 'import foo \"your/foo\"'.\n// Then the map would be: map[\"foo\"][]struct{{f: (file 1), path: \"my/foo\"},{f: (file 2), path: \"your/foo\"}}.\ntype importIdents map[string][]struct {\n\tf    *ast.File\n\tpath string\n}\n\n// newImportIdents creates an importIdents from all imports in pkg.\nfunc newImportIdents(pkg *loader.Package) (importIdents, error) {\n\timportIDs := make(map[string][]struct {\n\t\tf    *ast.File\n\t\tpath string\n\t})\n\tfor _, file := range pkg.Syntax {\n\t\tfor _, impSpec := range file.Imports {\n\t\t\tval, err := strconv.Unquote(impSpec.Path.Value)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\t// Most imports are not locally named, so the real package name should be used.\n\t\t\tvar impName string\n\t\t\tif imp, hasImp := pkg.Imports()[val]; hasImp {\n\t\t\t\timpName = imp.Name\n\t\t\t}\n\t\t\t// impSpec.Name will not be empty for locally named imports\n\t\t\tif impSpec.Name != nil {\n\t\t\t\timpName = impSpec.Name.Name\n\t\t\t}\n\t\t\timportIDs[impName] = append(importIDs[impName], struct {\n\t\t\t\tf    *ast.File\n\t\t\t\tpath string\n\t\t\t}{file, val})\n\t\t}\n\t}\n\treturn importIDs, nil\n}\n\n// findPackagePathForSelExpr returns the package path corresponding to the package name used in expr if it exists in im.\nfunc (im importIdents) findPackagePathForSelExpr(expr *ast.SelectorExpr) (pkgPath string) {\n\t// X contains the name being selected from.\n\txIdent, isIdent := expr.X.(*ast.Ident)\n\tif !isIdent {\n\t\treturn \"\"\n\t}\n\t// Imports for all import statements where local import name == name being selected from.\n\timports, hasImports := im[xIdent.String()]\n\tif !hasImports {\n\t\treturn \"\"\n\t}\n\n\t// Short-circuit if only one import.\n\tif len(imports) == 1 {\n\t\tpkgPath = imports[0].path\n\t} else {\n\t\t// If multiple files contain the same local import name, check to see which file contains the selector expression.\n\t\tfor _, imp := range imports {\n\t\t\tif imp.f.Pos() <= expr.Pos() && imp.f.End() >= expr.End() {\n\t\t\t\tpkgPath = imp.path\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\treturn loader.NonVendorPath(pkgPath)\n}\n\n// getMarkedChildrenOfField collects all marked fields from type declarations starting at rootField in depth-first order.\nfunc (g generator) getMarkedChildrenOfField(rootPkg *loader.Package, rootField markers.FieldInfo) (map[crd.TypeIdent][]*fieldInfo, error) {\n\t// Gather all types and imports needed to build the BFS tree.\n\trootPkg.NeedTypesInfo()\n\timportIDs, err := newImportIdents(rootPkg)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// ast.Inspect will not traverse into fields, so iteratively collect them and to check for markers.\n\tnextFields := []*fieldInfo{{FieldInfo: rootField}}\n\tmarkedFields := map[crd.TypeIdent][]*fieldInfo{}\n\tfor len(nextFields) > 0 {\n\t\tfields := []*fieldInfo{}\n\t\tfor _, field := range nextFields {\n\t\t\tast.Inspect(field.RawField, func(n ast.Node) bool {\n\t\t\t\tif n == nil {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\n\t\t\t\tvar ident crd.TypeIdent\n\t\t\t\tswitch nt := n.(type) {\n\t\t\t\tcase *ast.SelectorExpr: // Type definition in an imported package.\n\t\t\t\t\tpkgPath := importIDs.findPackagePathForSelExpr(nt)\n\t\t\t\t\tif pkgPath == \"\" {\n\t\t\t\t\t\t// Found no reference to pkgPath in any file.\n\t\t\t\t\t\treturn true\n\t\t\t\t\t}\n\t\t\t\t\tif pkg, hasImport := rootPkg.Imports()[pkgPath]; hasImport {\n\t\t\t\t\t\tpkg.NeedTypesInfo()\n\t\t\t\t\t\tident = crd.TypeIdent{Package: pkg, Name: nt.Sel.Name}\n\t\t\t\t\t}\n\t\t\t\tcase *ast.Ident: // Local type definition.\n\t\t\t\t\t// Only look at type idents or references to type idents in other files.\n\t\t\t\t\tif nt.Obj == nil || nt.Obj.Kind == ast.Typ {\n\t\t\t\t\t\tident = crd.TypeIdent{Package: rootPkg, Name: nt.Name}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Check if the field's type is a known types.\n\t\t\t\tinfo, hasInfo := g.types[ident]\n\t\t\t\tif ident == (crd.TypeIdent{}) || !hasInfo {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\n\t\t\t\t// Add all child fields to the list to search next.\n\t\t\t\tfor _, finfo := range info.Fields {\n\t\t\t\t\tsegment, err := getPathSegmentForField(finfo)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\trootPkg.AddError(fmt.Errorf(\"error getting path from type %s field %s: %v\", info.Name, finfo.Name, err))\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\t// Add extra information to the segment if it comes from a certain field type.\n\t\t\t\t\tswitch finfo.RawField.Type.(type) {\n\t\t\t\t\tcase *ast.ArrayType:\n\t\t\t\t\t\t// arrayFieldGroup case.\n\t\t\t\t\t\tif segment != ignoredTag && segment != inlinedTag {\n\t\t\t\t\t\t\tsegment += \"[0]\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// Create a new set of path segments using the parent's segments\n\t\t\t\t\t// and add the field to the next fields to search.\n\t\t\t\t\tparentSegments := make([]string, len(field.pathSegments), len(field.pathSegments)+1)\n\t\t\t\t\tcopy(parentSegments, field.pathSegments)\n\t\t\t\t\tf := &fieldInfo{\n\t\t\t\t\t\tFieldInfo:    finfo,\n\t\t\t\t\t\tpathSegments: append(parentSegments, segment),\n\t\t\t\t\t}\n\t\t\t\t\tfields = append(fields, f)\n\t\t\t\t\t// Marked fields get collected for the caller to parse.\n\t\t\t\t\tif len(finfo.Markers) != 0 {\n\t\t\t\t\t\tmarkedFields[ident] = append(markedFields[ident], f)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn true\n\t\t\t})\n\t\t}\n\t\tnextFields = fields\n\t}\n\n\tif loader.PrintErrors([]*loader.Package{rootPkg}, packages.TypeError) {\n\t\treturn nil, errors.New(\"package had type errors\")\n\t}\n\n\treturn markedFields, nil\n}\n"
  },
  {
    "path": "internal/generate/clusterserviceversion/bases/definitions/crd.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage definitions\n\nimport (\n\t\"fmt\"\n\t\"math\"\n\t\"reflect\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"github.com/fatih/structtag\"\n\t\"github.com/markbates/inflect\"\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\t\"k8s.io/apimachinery/pkg/runtime/schema\"\n\t\"k8s.io/apimachinery/pkg/version\"\n\t\"sigs.k8s.io/controller-tools/pkg/crd\"\n\tcrdmarkers \"sigs.k8s.io/controller-tools/pkg/crd/markers\"\n\t\"sigs.k8s.io/controller-tools/pkg/loader\"\n\t\"sigs.k8s.io/controller-tools/pkg/markers\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/util/k8sutil\"\n)\n\n// MakeFullGroupFromName returns everything but the first element of a CRD name,\n// which by definition is <resource>.<full group>.\nfunc MakeFullGroupFromName(name string) string {\n\treturn getHalfBySep(name, \".\", 1)\n}\n\n// MakeGroupFromFullGroup returns the first element of an API group, ex. \"foo\" of \"foo.example.com\".\nfunc MakeGroupFromFullGroup(group string) string {\n\treturn getHalfBySep(group, \".\", 0)\n}\n\n// getHalfBySep splits s by the first sep encountered and returns the first\n// (half = 0) or second (half = 1) element of the result.\nfunc getHalfBySep(s, sep string, half uint) string {\n\tif split := strings.SplitN(s, sep, 2); len(split) == 2 && half < 2 {\n\t\treturn split[half]\n\t}\n\treturn s\n}\n\n// buildCRDDescriptionFromType builds a crdDescription for the Go API defined\n// by key from markers and type information in g.types.\nfunc (g generator) buildCRDDescriptionFromType(gvk schema.GroupVersionKind, typeIdent crd.TypeIdent, kindType *markers.TypeInfo) (v1alpha1.CRDDescription, int, error) {\n\n\t// Initialize the description.\n\tdescription := v1alpha1.CRDDescription{\n\t\tDescription: kindType.Doc,\n\t\tDisplayName: k8sutil.GetDisplayName(gvk.Kind),\n\t\tVersion:     gvk.Version,\n\t\tKind:        gvk.Kind,\n\t}\n\n\t// Parse resources and displayName from the kind type's markers.\n\tdescriptionOrder := math.MaxInt32\n\tfor _, markers := range kindType.Markers {\n\t\tfor _, marker := range markers {\n\t\t\tswitch d := marker.(type) {\n\t\t\tcase Description:\n\t\t\t\tif d.Order != nil {\n\t\t\t\t\tdescriptionOrder = *d.Order\n\t\t\t\t}\n\t\t\t\tif d.DisplayName != \"\" {\n\t\t\t\t\tdescription.DisplayName = d.DisplayName\n\t\t\t\t}\n\t\t\t\tif len(d.Resources) != 0 {\n\t\t\t\t\trefs, err := d.Resources.toResourceReferences()\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn v1alpha1.CRDDescription{}, 0, err\n\t\t\t\t\t}\n\t\t\t\t\tdescription.Resources = append(description.Resources, refs...)\n\t\t\t\t}\n\t\t\tcase crdmarkers.Resource:\n\t\t\t\tif d.Path != \"\" {\n\t\t\t\t\tdescription.Name = fmt.Sprintf(\"%s.%s\", d.Path, gvk.Group)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t// The default, if the resource marker's path value is not set, is to use a pluralized form of lowercase kind.\n\tif description.Name == \"\" {\n\t\tdescription.Name = fmt.Sprintf(\"%s.%s\", inflect.Pluralize(strings.ToLower(gvk.Kind)), gvk.Group)\n\t}\n\tsortResources(description.Resources)\n\n\tspecDescriptors, err := g.getTypedDescriptors(typeIdent.Package, kindType, reflect.TypeOf(v1alpha1.SpecDescriptor{}), spec)\n\tif err != nil {\n\t\treturn v1alpha1.CRDDescription{}, 0, err\n\t}\n\tfor _, d := range specDescriptors {\n\t\tdescription.SpecDescriptors = append(description.SpecDescriptors, d.(v1alpha1.SpecDescriptor))\n\t}\n\n\tstatusDescriptors, err := g.getTypedDescriptors(typeIdent.Package, kindType, reflect.TypeOf(v1alpha1.StatusDescriptor{}), status)\n\tif err != nil {\n\t\treturn v1alpha1.CRDDescription{}, 0, err\n\t}\n\tfor _, d := range statusDescriptors {\n\t\tdescription.StatusDescriptors = append(description.StatusDescriptors, d.(v1alpha1.StatusDescriptor))\n\t}\n\n\treturn description, descriptionOrder, nil\n}\n\nfunc (g generator) getTypedDescriptors(pkg *loader.Package, kindType *markers.TypeInfo, t reflect.Type, descType string) ([]any, error) {\n\t// Find child in the kind type.\n\tchild, err := findChildForDescType(kindType, descType)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Find annotated fields of child and parse them into descriptors.\n\tmarkedFields, err := g.getMarkedChildrenOfField(pkg, child)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn getTypedDescriptors(markedFields, t, descType), nil\n}\n\nfunc getTypedDescriptors(markedFields map[crd.TypeIdent][]*fieldInfo, t reflect.Type, descType string) (descriptors []any) {\n\tdescriptorBuckets := make(map[int][]reflect.Value)\n\torders := make([]int, 0)\n\tfor _, fields := range markedFields {\n\t\tfor _, field := range fields {\n\t\t\tv := reflect.New(t)\n\t\t\tif order, include := field.setDescriptorFields(v, descType); include {\n\t\t\t\tdescriptorBuckets[order] = append(descriptorBuckets[order], reflect.Indirect(v))\n\t\t\t\torders = append(orders, order)\n\t\t\t}\n\t\t}\n\t}\n\tsort.Ints(orders)\n\n\tdescriptorVals := make([]reflect.Value, 0)\n\tfor _, order := range orders {\n\t\tif bucket, hasOrder := descriptorBuckets[order]; hasOrder {\n\t\t\tsortDescriptors(bucket)\n\t\t\tdescriptorVals = append(descriptorVals, bucket...)\n\t\t\tdelete(descriptorBuckets, order)\n\t\t}\n\t}\n\n\tfor _, v := range descriptorVals {\n\t\tdescriptors = append(descriptors, v.Interface())\n\t}\n\n\treturn descriptors\n}\n\n// findChildForDescType returns a field with a tag matching string(typ) by searching all top-level fields in info.\n// If no field is found, an error is returned.\nfunc findChildForDescType(info *markers.TypeInfo, descType string) (markers.FieldInfo, error) {\n\tfor _, field := range info.Fields {\n\t\ttags, err := structtag.Parse(string(field.Tag))\n\t\tif err != nil {\n\t\t\treturn markers.FieldInfo{}, err\n\t\t}\n\t\tjsonTag, err := tags.Get(\"json\")\n\t\tif err == nil && jsonTag.Name == descType {\n\t\t\treturn field, nil\n\t\t}\n\t}\n\treturn markers.FieldInfo{}, fmt.Errorf(\"no %s found for type %s\", descType, info.Name)\n}\n\n// sortDescriptors sorts a slice of structs with a Path field by comparing Path strings naturally.\nfunc sortDescriptors(values []reflect.Value) {\n\tsort.Slice(values, func(i, j int) bool {\n\t\treturn values[i].FieldByName(\"Path\").String() < values[j].FieldByName(\"Path\").String()\n\t})\n}\n\n// sortResources sorts a slice of structs with Name, Kind, and Version fields\n// by comparing those field's strings in natural order.\nfunc sortResources(rs []v1alpha1.APIResourceReference) {\n\tsort.Slice(rs, func(i, j int) bool {\n\t\tif rs[i].Name == rs[j].Name {\n\t\t\tif rs[i].Kind == rs[j].Kind {\n\t\t\t\treturn version.CompareKubeAwareVersionStrings(rs[i].Version, rs[j].Version) > 0\n\t\t\t}\n\t\t\treturn rs[i].Kind < rs[j].Kind\n\t\t}\n\t\treturn rs[i].Name < rs[j].Name\n\t})\n}\n"
  },
  {
    "path": "internal/generate/clusterserviceversion/bases/definitions/crd_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage definitions\n\nimport (\n\t\"math/rand\"\n\t\"reflect\"\n\t\"sort\"\n\t\"time\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\t\"golang.org/x/text/cases\"\n\t\"golang.org/x/text/language\"\n\t\"sigs.k8s.io/controller-tools/pkg/crd\"\n\t\"sigs.k8s.io/controller-tools/pkg/loader\"\n\t\"sigs.k8s.io/controller-tools/pkg/markers\"\n\tkbutil \"sigs.k8s.io/kubebuilder/v4/pkg/plugin/util\"\n)\n\nvar _ = Describe(\"getTypedDescriptors\", func() {\n\tvar (\n\t\tmarkedFields map[crd.TypeIdent][]*fieldInfo\n\t\tout          []any\n\t)\n\n\tBeforeEach(func() {\n\t\tmarkedFields = make(map[crd.TypeIdent][]*fieldInfo)\n\t})\n\n\tIt(\"handles an empty set of marked fields\", func() {\n\t\tout = getTypedDescriptors(markedFields, reflect.TypeOf(v1alpha1.SpecDescriptor{}), spec)\n\t\tExpect(out).To(BeEmpty())\n\t})\n\tIt(\"returns one spec descriptor for one spec marker on a field\", func() {\n\t\tmarkedFields[crd.TypeIdent{}] = []*fieldInfo{\n\t\t\t{\n\t\t\t\tFieldInfo: markers.FieldInfo{\n\t\t\t\t\tMarkers: markers.MarkerValues{\n\t\t\t\t\t\t\"\": []any{\n\t\t\t\t\t\t\tDescriptor{\"spec\", \"Foo\", []string{\"urn:alm:descriptor:com.tectonic.ui:text\"}, nil},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\t\tout = getTypedDescriptors(markedFields, reflect.TypeOf(v1alpha1.SpecDescriptor{}), spec)\n\t\tExpect(out).To(HaveLen(1))\n\t\tExpect(out).To(BeEquivalentTo([]any{\n\t\t\tv1alpha1.SpecDescriptor{\n\t\t\t\tDisplayName:  \"Foo\",\n\t\t\t\tXDescriptors: []string{\"urn:alm:descriptor:com.tectonic.ui:text\"},\n\t\t\t},\n\t\t}))\n\t})\n\tIt(\"returns no spec descriptors for one status marker on a field\", func() {\n\t\tmarkedFields[crd.TypeIdent{}] = []*fieldInfo{\n\t\t\t{\n\t\t\t\tFieldInfo: markers.FieldInfo{\n\t\t\t\t\tMarkers: markers.MarkerValues{\n\t\t\t\t\t\t\"\": []any{\n\t\t\t\t\t\t\tDescriptor{\"status\", \"Foo\", []string{\"urn:alm:descriptor:com.tectonic.ui:text\"}, nil},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\t\tout = getTypedDescriptors(markedFields, reflect.TypeOf(v1alpha1.SpecDescriptor{}), spec)\n\t\tExpect(out).To(BeEmpty())\n\t})\n\tIt(\"returns one status descriptor for one status marker on a field\", func() {\n\t\tmarkedFields[crd.TypeIdent{}] = []*fieldInfo{\n\t\t\t{\n\t\t\t\tFieldInfo: markers.FieldInfo{\n\t\t\t\t\tMarkers: markers.MarkerValues{\n\t\t\t\t\t\t\"\": []any{\n\t\t\t\t\t\t\tDescriptor{\"status\", \"Foo\", []string{\"urn:alm:descriptor:com.tectonic.ui:text\"}, nil},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\t\tout = getTypedDescriptors(markedFields, reflect.TypeOf(v1alpha1.StatusDescriptor{}), status)\n\t\tExpect(out).To(HaveLen(1))\n\t\tExpect(out).To(BeEquivalentTo([]any{\n\t\t\tv1alpha1.StatusDescriptor{\n\t\t\t\tDisplayName:  \"Foo\",\n\t\t\t\tXDescriptors: []string{\"urn:alm:descriptor:com.tectonic.ui:text\"},\n\t\t\t},\n\t\t}))\n\t})\n\tIt(\"returns one spec descriptor for three spec markers and one status marker on a field\", func() {\n\t\tmarkedFields[crd.TypeIdent{}] = []*fieldInfo{\n\t\t\t{\n\t\t\t\tFieldInfo: markers.FieldInfo{\n\t\t\t\t\tMarkers: markers.MarkerValues{\n\t\t\t\t\t\t\"\": []any{\n\t\t\t\t\t\t\tDescriptor{\"spec\", \"Foo\", nil, nil},\n\t\t\t\t\t\t\tDescriptor{\"spec\", \"\", nil, intPtr(2)},\n\t\t\t\t\t\t\tDescriptor{\"spec\", \"\", []string{\"urn:alm:descriptor:com.tectonic.ui:text\"}, nil},\n\t\t\t\t\t\t\tDescriptor{\"status\", \"\", []string{\"urn:alm:descriptor:com.tectonic.ui:arrayFieldGroup:blah\"}, nil},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tpathSegments: []string{\"foo\", inlinedTag, \"bar\", \"baz\"},\n\t\t\t},\n\t\t}\n\t\tout = getTypedDescriptors(markedFields, reflect.TypeOf(v1alpha1.SpecDescriptor{}), spec)\n\t\tExpect(out).To(HaveLen(1))\n\t\tExpect(out).To(BeEquivalentTo([]any{\n\t\t\tv1alpha1.SpecDescriptor{\n\t\t\t\tDisplayName:  \"Foo\",\n\t\t\t\tXDescriptors: []string{\"urn:alm:descriptor:com.tectonic.ui:text\"},\n\t\t\t\tPath:         \"foo.bar.baz\",\n\t\t\t},\n\t\t}))\n\t})\n\tIt(\"returns two spec descriptor for spec markers on two different fields\", func() {\n\t\tmarkedFields[crd.TypeIdent{}] = []*fieldInfo{\n\t\t\t{\n\t\t\t\tFieldInfo: markers.FieldInfo{\n\t\t\t\t\tMarkers: markers.MarkerValues{\n\t\t\t\t\t\t\"\": []any{Descriptor{\"spec\", \"Foo\", nil, intPtr(1)}},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tpathSegments: []string{\"foo\"},\n\t\t\t},\n\t\t\t{\n\t\t\t\tFieldInfo: markers.FieldInfo{\n\t\t\t\t\tMarkers: markers.MarkerValues{\n\t\t\t\t\t\t\"\": []any{Descriptor{\"spec\", \"Bar\", nil, intPtr(0)}},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tpathSegments: []string{\"bar\"},\n\t\t\t},\n\t\t}\n\t\tout = getTypedDescriptors(markedFields, reflect.TypeOf(v1alpha1.SpecDescriptor{}), spec)\n\t\tExpect(out).To(HaveLen(2))\n\t\tExpect(out).To(BeEquivalentTo([]any{\n\t\t\tv1alpha1.SpecDescriptor{DisplayName: \"Bar\", Path: \"bar\"},\n\t\t\tv1alpha1.SpecDescriptor{DisplayName: \"Foo\", Path: \"foo\"},\n\t\t}))\n\t})\n\tIt(\"returns multiple sorted spec descriptors with all orders set\", func() {\n\t\tmarkedFields, expected := makeMockMarkedFields()\n\t\tout = getTypedDescriptors(markedFields, reflect.TypeOf(v1alpha1.SpecDescriptor{}), spec)\n\t\tExpect(out).To(HaveLen(len(expected)))\n\t\tExpect(out).To(BeEquivalentTo(expected))\n\t})\n})\n\nfunc intPtr(i int) *int { return &i }\n\n// makeMockMarkedFields returns a randomly generated mock marked field set,\n// and the expected sorted set of descriptors.\nfunc makeMockMarkedFields() (markedFields map[crd.TypeIdent][]*fieldInfo, expected []any) {\n\tdescBuckets := make(map[int][]v1alpha1.SpecDescriptor, 100)\n\tr := rand.New(rand.NewSource(time.Now().UnixNano()))\n\tmarkedFields = make(map[crd.TypeIdent][]*fieldInfo, 100)\n\tfor i := 0; i < 100; i++ {\n\t\ts, err := kbutil.RandomSuffix()\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t\tcaser := cases.Title(language.AmericanEnglish)\n\t\tname := caser.String(s)\n\t\torder := r.Int() % 200 // Very likely to get one conflict.\n\t\tident := crd.TypeIdent{Package: &loader.Package{}, Name: name}\n\t\tif _, hasName := markedFields[ident]; hasName {\n\t\t\tcontinue\n\t\t}\n\t\tmarkedFields[ident] = []*fieldInfo{\n\t\t\t{\n\t\t\t\tFieldInfo: markers.FieldInfo{\n\t\t\t\t\tMarkers: markers.MarkerValues{\n\t\t\t\t\t\t\"\": []any{Descriptor{\"spec\", name, nil, intPtr(order)}},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tpathSegments: []string{s},\n\t\t\t},\n\t\t}\n\t\tdescBuckets[order] = append(descBuckets[order], v1alpha1.SpecDescriptor{DisplayName: name, Path: s})\n\t}\n\n\torders := make([]int, 0, 100)\n\tfor order := range descBuckets {\n\t\torders = append(orders, order)\n\t}\n\tsort.Ints(orders)\n\n\tfor _, order := range orders {\n\t\tbucket := descBuckets[order]\n\t\tsort.Slice(bucket, func(i, j int) bool { return bucket[i].DisplayName < bucket[j].DisplayName })\n\t\tfor _, d := range bucket {\n\t\t\texpected = append(expected, d)\n\t\t}\n\t}\n\n\treturn markedFields, expected\n}\n"
  },
  {
    "path": "internal/generate/clusterserviceversion/bases/definitions/definitions.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage definitions\n\nimport (\n\t\"errors\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sort\"\n\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\tlog \"github.com/sirupsen/logrus\"\n\t\"golang.org/x/tools/go/packages\"\n\t\"k8s.io/apimachinery/pkg/runtime/schema\"\n\tapiversion \"k8s.io/apimachinery/pkg/version\"\n\t\"sigs.k8s.io/controller-tools/pkg/crd\"\n\t\"sigs.k8s.io/controller-tools/pkg/genall\"\n\t\"sigs.k8s.io/controller-tools/pkg/loader\"\n\t\"sigs.k8s.io/controller-tools/pkg/markers\"\n)\n\ntype descriptionValues struct {\n\tcrdOrder int\n\tcrd      v1alpha1.CRDDescription\n\t// TODO(estroz): support apiServiceDescriptions\n}\n\n// ApplyDefinitionsForKeysGo collects markers and AST info on Go type declarations and struct fields\n// to populate csv spec fields. Go code with relevant markers and information is expected to be\n// in a package under apisRootDir and match a GVK in keys.\nfunc ApplyDefinitionsForKeysGo(csv *v1alpha1.ClusterServiceVersion, apisRootDir string, gvks []schema.GroupVersionKind) error {\n\t// Skip definitions parsing if dir doesn't exist, otherwise g.contextForRoots() will error.\n\tif _, err := os.Stat(apisRootDir); err != nil && errors.Is(err, os.ErrNotExist) {\n\t\tlog.Warnf(\"Skipping definitions parsing: APIs root dir %q does not exist\", apisRootDir)\n\t\treturn nil\n\t}\n\n\twd, err := os.Getwd()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Create a generator context for type-checking and loading all packages under apisRootDir.\n\t// The \"$(pwd)/<package>/...\" syntax directs the loader to load all packages under apisRootDir.\n\tg := &generator{}\n\tctx, err := g.contextForRoots(filepath.Join(wd, apisRootDir) + \"/...\")\n\tif err != nil {\n\t\treturn err\n\t}\n\t// Collect Go types from the API root.\n\tg.needTypes(ctx)\n\tif loader.PrintErrors(ctx.Roots, packages.TypeError) {\n\t\treturn errors.New(\"one or more API packages had type errors\")\n\t}\n\n\tgvkSet := make(map[schema.GroupVersionKind]struct{}, len(gvks))\n\tfor _, gvk := range gvks {\n\t\tgvkSet[gvk] = struct{}{}\n\t}\n\n\t// Create definitions for kind types found under the collected roots.\n\tdefinitionsByGVK := make(map[schema.GroupVersionKind]*descriptionValues)\n\tfor typeIdent, typeInfo := range g.types {\n\t\tif gv, hasGV := g.groupVersions[typeIdent.Package]; hasGV {\n\t\t\tgvk := gv.WithKind(typeIdent.Name)\n\t\t\t// Type is one of the GVKs specified by the caller.\n\t\t\tif _, hasGVK := gvkSet[gvk]; hasGVK {\n\t\t\t\tcrd, crdOrder, err := g.buildCRDDescriptionFromType(gvk, typeIdent, typeInfo)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tdefinitionsByGVK[gvk] = &descriptionValues{\n\t\t\t\t\tcrdOrder: crdOrder,\n\t\t\t\t\tcrd:      crd,\n\t\t\t\t}\n\t\t\t\tdelete(gvkSet, gvk)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Leftover GVKs are ignored because their types can't be found.\n\tfor _, gvk := range gvkSet {\n\t\tlog.Warnf(\"Skipping definitions parsing for API %s: Go type not found\", gvk)\n\t}\n\n\t// Update csv with all values parsed.\n\tupdateDefinitionsByKey(csv, definitionsByGVK)\n\n\treturn nil\n}\n\n// updateDefinitionsByKey updates owned definitions that already exist in csv or adds new definitions that do not.\nfunc updateDefinitionsByKey(csv *v1alpha1.ClusterServiceVersion, defsByGVK map[schema.GroupVersionKind]*descriptionValues) {\n\t// Create a set of buckets for all generated descriptions.\n\t// Multiple descriptions can belong to the same order.\n\tcrdBuckets := make(map[int][]v1alpha1.CRDDescription)\n\tfor _, values := range defsByGVK {\n\t\tcrdBuckets[values.crdOrder] = append(crdBuckets[values.crdOrder], values.crd)\n\t}\n\n\t// Sort generated buckets before adding non-generated descriptions so users can\n\t// set their order manually.\n\tfor _, bucket := range crdBuckets {\n\t\tsort.Slice(bucket, lessForCRDDescription(bucket))\n\t}\n\n\t// Append non-generated descriptions to the end of their buckets,\n\t// treating their indices as order.\n\tfor i, crd := range csv.Spec.CustomResourceDefinitions.Owned {\n\t\tif _, hasKey := defsByGVK[descToGVK(crd)]; !hasKey {\n\t\t\tcrdBuckets[i] = append(crdBuckets[i], csv.Spec.CustomResourceDefinitions.Owned[i])\n\t\t}\n\t}\n\n\t// De-duplciate and sort order ints for appending bucket contents in-order.\n\tcrdOrders := make([]int, 0, len(crdBuckets))\n\tfor order := range crdBuckets {\n\t\tcrdOrders = append(crdOrders, order)\n\t}\n\tsort.Ints(crdOrders)\n\n\t// Update descriptions.\n\tcsv.Spec.CustomResourceDefinitions.Owned = make([]v1alpha1.CRDDescription, 0, len(crdBuckets))\n\tfor _, order := range crdOrders {\n\t\tcsv.Spec.CustomResourceDefinitions.Owned = append(csv.Spec.CustomResourceDefinitions.Owned, crdBuckets[order]...)\n\t}\n}\n\n// lessForCRDDescription returns a less func for descs. Used for sorting a list of CRDDescriptions.\nfunc lessForCRDDescription(descs []v1alpha1.CRDDescription) func(i, j int) bool {\n\treturn func(i, j int) bool {\n\t\tif descs[i].Name == descs[j].Name {\n\t\t\tif descs[i].Kind == descs[j].Kind {\n\t\t\t\treturn apiversion.CompareKubeAwareVersionStrings(descs[i].Version, descs[j].Version) > 0\n\t\t\t}\n\t\t\treturn descs[i].Kind < descs[j].Kind\n\t\t}\n\t\treturn descs[i].Name < descs[j].Name\n\t}\n}\n\n// descToGVK convert desc to a GVK type.\nfunc descToGVK(desc v1alpha1.CRDDescription) (gvk schema.GroupVersionKind) {\n\tgvk.Group = MakeFullGroupFromName(desc.Name)\n\tgvk.Version = desc.Version\n\tgvk.Kind = desc.Kind\n\treturn gvk\n}\n\n// generator creates API definitions from type information for a set of roots.\ntype generator struct {\n\ttypes         map[crd.TypeIdent]*markers.TypeInfo\n\tgroupVersions map[*loader.Package]schema.GroupVersion\n}\n\n// contextForRoots creates a context that can populate a generator for a set of roots loaded from dirs.\n// These roots contain data for registered markers.\nfunc (g *generator) contextForRoots(dirs ...string) (ctx *genall.GenerationContext, err error) {\n\troots, err := loader.LoadRoots(dirs...)\n\tif err != nil {\n\t\treturn ctx, err\n\t}\n\tregistry := &markers.Registry{}\n\tif err := registerMarkers(registry); err != nil {\n\t\treturn ctx, err\n\t}\n\treturn &genall.GenerationContext{\n\t\tCollector: &markers.Collector{\n\t\t\tRegistry: registry,\n\t\t},\n\t\tRoots:     roots,\n\t\tInputRule: genall.InputFromFileSystem,\n\t\tChecker:   &loader.TypeChecker{},\n\t}, nil\n}\n\n// needTypes sets types in the generator for a given context.\n// Adapted from https://github.com/kubernetes-sigs/controller-tools/blob/868d39a/pkg/crd/parser.go#L121\nfunc (g *generator) needTypes(ctx *genall.GenerationContext) {\n\tg.types = make(map[crd.TypeIdent]*markers.TypeInfo)\n\tg.groupVersions = make(map[*loader.Package]schema.GroupVersion)\n\tfor _, root := range ctx.Roots {\n\t\tpkgMarkers, err := markers.PackageMarkers(ctx.Collector, root)\n\t\tif err != nil {\n\t\t\troot.AddError(err)\n\t\t} else {\n\t\t\t// Explicitly skip this package.\n\t\t\tif skipPkg := pkgMarkers.Get(\"kubebuilder:skip\"); skipPkg != nil {\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// Get group name and optionall version name from package markers.\n\t\t\tif nameVal := pkgMarkers.Get(\"groupName\"); nameVal != nil {\n\t\t\t\tversionVal := root.Name\n\t\t\t\tif versionMarker := pkgMarkers.Get(\"versionName\"); versionMarker != nil {\n\t\t\t\t\tversionVal = versionMarker.(string)\n\t\t\t\t}\n\n\t\t\t\tg.groupVersions[root] = schema.GroupVersion{\n\t\t\t\t\tVersion: versionVal,\n\t\t\t\t\tGroup:   nameVal.(string),\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Add all types indexed by their package and type name.\n\t\tf := func(info *markers.TypeInfo) {\n\t\t\tident := crd.TypeIdent{\n\t\t\t\tPackage: root,\n\t\t\t\tName:    info.Name,\n\t\t\t}\n\t\t\tg.types[ident] = info\n\t\t}\n\t\tif err := markers.EachType(ctx.Collector, root, f); err != nil {\n\t\t\troot.AddError(err)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/generate/clusterserviceversion/bases/definitions/definitions_suite_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage definitions\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nfunc TestGenerator(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"Definitions Suite\")\n}\n"
  },
  {
    "path": "internal/generate/clusterserviceversion/bases/definitions/definitions_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage definitions\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\t\"github.com/stretchr/testify/assert\"\n\t\"k8s.io/apimachinery/pkg/runtime/schema\"\n)\n\n// TODO(estroz): migrate to ginkgo/gomega\n\nvar (\n\ttestDataDir = filepath.Join(\"..\", \"..\", \"..\", \"testdata\", \"go\")\n)\n\nfunc TestApplyDefinitionsForKeysGo(t *testing.T) {\n\n\twd, err := os.Getwd()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif err := os.Chdir(testDataDir); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer func() {\n\t\tif err = os.Chdir(wd); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}()\n\n\t//nolint:dupl\n\tcases := []struct {\n\t\tdescription  string\n\t\tapisDir      string\n\t\tcsv          *v1alpha1.ClusterServiceVersion\n\t\tgvks         []schema.GroupVersionKind\n\t\texpectedCRDs v1alpha1.CustomResourceDefinitions\n\t\twantErr      bool\n\t}{\n\t\t{\n\t\t\tdescription: \"Populate CRDDescription successfully\",\n\t\t\tapisDir:     \"api\",\n\t\t\tcsv:         &v1alpha1.ClusterServiceVersion{},\n\t\t\tgvks: []schema.GroupVersionKind{\n\t\t\t\t{Group: \"cache.example.com\", Version: \"v1alpha2\", Kind: \"Dummy\"},\n\t\t\t},\n\t\t\texpectedCRDs: v1alpha1.CustomResourceDefinitions{\n\t\t\t\tOwned: []v1alpha1.CRDDescription{\n\t\t\t\t\t{\n\t\t\t\t\t\tName:        \"dummys.cache.example.com\",\n\t\t\t\t\t\tKind:        \"Dummy\",\n\t\t\t\t\t\tVersion:     \"v1alpha2\",\n\t\t\t\t\t\tDisplayName: \"Dummy App\",\n\t\t\t\t\t\tDescription: \"Dummy is the Schema for the dummy API\",\n\t\t\t\t\t\tResources: []v1alpha1.APIResourceReference{\n\t\t\t\t\t\t\t{Name: \"dummy-deployment\", Kind: \"Deployment\", Version: \"v1\"},\n\t\t\t\t\t\t\t{Name: \"dummy-pod\", Kind: \"Pod\", Version: \"v1\"},\n\t\t\t\t\t\t\t{Name: \"dummy-replicaset\", Kind: \"ReplicaSet\", Version: \"v1beta2\"},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tSpecDescriptors: []v1alpha1.SpecDescriptor{\n\t\t\t\t\t\t\t{Path: \"sideCar\", DisplayName: \"Side Car\"},\n\t\t\t\t\t\t\t{Path: \"size\", DisplayName: \"dummy-size\", Description: \"Should be in spec\",\n\t\t\t\t\t\t\t\tXDescriptors: []string{\"urn:alm:descriptor:com.tectonic.ui:podCount\"}},\n\t\t\t\t\t\t\t{Path: \"useful.containers\", DisplayName: \"Containers\"},\n\t\t\t\t\t\t\t{Path: \"wheels\", DisplayName: \"Wheels\",\n\t\t\t\t\t\t\t\tDescription:  \"Should be in spec, but should not have array index in path\",\n\t\t\t\t\t\t\t\tXDescriptors: []string{\"urn:alm:descriptor:com.tectonic.ui:text\"}},\n\t\t\t\t\t\t\t{Path: \"wheels[0].type\", DisplayName: \"Wheel Type\",\n\t\t\t\t\t\t\t\tDescription: \"Type should be in spec with path equal to wheels[0].type\",\n\t\t\t\t\t\t\t\tXDescriptors: []string{\n\t\t\t\t\t\t\t\t\t\"urn:alm:descriptor:com.tectonic.ui:arrayFieldGroup:wheels\",\n\t\t\t\t\t\t\t\t\t\"urn:alm:descriptor:com.tectonic.ui:text\",\n\t\t\t\t\t\t\t\t}},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tStatusDescriptors: []v1alpha1.StatusDescriptor{\n\t\t\t\t\t\t\t{Path: \"hog.engine\", DisplayName: \"boss-hog-engine\", Description: \"Should be in status but not spec, since Hog isn't in DummySpec\"},\n\t\t\t\t\t\t\t{Path: \"hog.foo\", DisplayName: \"Public\"},\n\t\t\t\t\t\t\t{Path: \"hog.seatMaterial\", DisplayName: \"Seat Material\"},\n\t\t\t\t\t\t\t{Path: \"hog.seatMaterial\", DisplayName: \"Seat Material\"},\n\t\t\t\t\t\t\t{Path: \"nodes\", DisplayName: \"Nodes\", Description: \"Should be in status but not spec, since DummyStatus isn't in DummySpec\"},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdescription: \"Populate CRDDescription with non-standard spec type successfully\",\n\t\t\tapisDir:     \"api\",\n\t\t\tcsv:         &v1alpha1.ClusterServiceVersion{},\n\t\t\tgvks: []schema.GroupVersionKind{\n\t\t\t\t{Group: \"cache.example.com\", Version: \"v1alpha2\", Kind: \"OtherDummy\"},\n\t\t\t},\n\t\t\texpectedCRDs: v1alpha1.CustomResourceDefinitions{\n\t\t\t\tOwned: []v1alpha1.CRDDescription{\n\t\t\t\t\t{\n\t\t\t\t\t\tName:        \"otherdummies.cache.example.com\",\n\t\t\t\t\t\tKind:        \"OtherDummy\",\n\t\t\t\t\t\tVersion:     \"v1alpha2\",\n\t\t\t\t\t\tDisplayName: \"Other Dummy App\",\n\t\t\t\t\t\tDescription: \"OtherDummy is the Schema for the other dummy API\",\n\t\t\t\t\t\tResources: []v1alpha1.APIResourceReference{\n\t\t\t\t\t\t\t{Name: \"other-dummy-pod\", Kind: \"Pod\", Version: \"v1\"},\n\t\t\t\t\t\t\t{Name: \"other-dummy-service\", Kind: \"Service\", Version: \"v1\"},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tSpecDescriptors: []v1alpha1.SpecDescriptor{\n\t\t\t\t\t\t\t{Path: \"engine\", DisplayName: \"Engine\", Description: \"Should be in status but not spec, since Hog isn't in DummySpec\"},\n\t\t\t\t\t\t\t{Path: \"foo\", DisplayName: \"Public\"},\n\t\t\t\t\t\t\t{Path: \"seatMaterial\", DisplayName: \"Seat Material\"},\n\t\t\t\t\t\t\t{Path: \"seatMaterial\", DisplayName: \"Seat Material\"},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tStatusDescriptors: []v1alpha1.StatusDescriptor{\n\t\t\t\t\t\t\t{Path: \"nothing\", DisplayName: \"Nothing\", Description: \"Should be in status but not spec, since this isn't a spec type\"},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdescription: \"Populate CRDDescription with GVKs with same GK and different versions\",\n\t\t\tapisDir:     \"api\",\n\t\t\tcsv:         &v1alpha1.ClusterServiceVersion{},\n\t\t\tgvks: []schema.GroupVersionKind{\n\t\t\t\t{Group: \"cache.example.com\", Version: \"v1alpha1\", Kind: \"Memcached\"},\n\t\t\t\t{Group: \"cache.example.com\", Version: \"v1alpha2\", Kind: \"Memcached\"},\n\t\t\t},\n\t\t\texpectedCRDs: v1alpha1.CustomResourceDefinitions{\n\t\t\t\tOwned: []v1alpha1.CRDDescription{\n\t\t\t\t\t{\n\t\t\t\t\t\tName: \"memcacheds.cache.example.com\", Version: \"v1alpha2\", Kind: \"Memcached\",\n\t\t\t\t\t\tDisplayName: \"Memcached App\",\n\t\t\t\t\t\tDescription: \"Memcached is the Schema for the memcacheds API\",\n\t\t\t\t\t\tSpecDescriptors: []v1alpha1.SpecDescriptor{\n\t\t\t\t\t\t\t{Path: \"size\", DisplayName: \"Size\", Description: \"Size is the size of the memcached deployment\"},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tStatusDescriptors: []v1alpha1.StatusDescriptor{\n\t\t\t\t\t\t\t{Path: \"nodes\", DisplayName: \"Nodes\", Description: \"Nodes are the names of the memcached pods\"},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tName: \"memcacheds.cache.example.com\", Version: \"v1alpha1\", Kind: \"Memcached\",\n\t\t\t\t\t\tDisplayName: \"Memcached App Display Name\",\n\t\t\t\t\t\tDescription: \"Memcached is the Schema for the memcacheds API\",\n\t\t\t\t\t\tStatusDescriptors: []v1alpha1.StatusDescriptor{\n\t\t\t\t\t\t\t{Path: \"nodes\", DisplayName: \"Nodes\", Description: \"Nodes are the names of the memcached pods\"},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tSpecDescriptors: []v1alpha1.SpecDescriptor{\n\t\t\t\t\t\t\t{Path: \"containers\", DisplayName: \"Containers\"},\n\t\t\t\t\t\t\t{Path: \"providers\", DisplayName: \"Providers\", Description: \"List of Providers\"},\n\t\t\t\t\t\t\t{Path: \"providers[0].foo\", DisplayName: \"Foo Provider\", Description: \"Foo represents the Foo provider\"},\n\t\t\t\t\t\t\t{Path: \"providers[0].foo.credentialsSecret\", DisplayName: \"Secret Containing the Credentials\",\n\t\t\t\t\t\t\t\tDescription:  \"CredentialsSecret is a reference to a secret containing authentication details for the Foo server\",\n\t\t\t\t\t\t\t\tXDescriptors: []string{\"urn:alm:descriptor:io.kubernetes:Secret\"},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tPath: \"providers[0].foo.credentialsSecret.key\", DisplayName: \"Key within the secret\",\n\t\t\t\t\t\t\t\tDescription:  \"Key represents the specific key to reference from the secret\",\n\t\t\t\t\t\t\t\tXDescriptors: []string{\"urn:alm:descriptor:com.tectonic.ui:advanced\", \"urn:alm:descriptor:com.tectonic.ui:text\"},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tPath: \"providers[0].foo.credentialsSecret.name\", DisplayName: \"Name of the secret\",\n\t\t\t\t\t\t\t\tDescription:  \"Name represents the name of the secret\",\n\t\t\t\t\t\t\t\tXDescriptors: []string{\"urn:alm:descriptor:com.tectonic.ui:advanced\", \"urn:alm:descriptor:com.tectonic.ui:text\"},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tPath: \"providers[0].foo.credentialsSecret.namespace\", DisplayName: \"Namespace containing the secret\",\n\t\t\t\t\t\t\t\tDescription:  \"Namespace represents the namespace containing the secret\",\n\t\t\t\t\t\t\t\tXDescriptors: []string{\"urn:alm:descriptor:com.tectonic.ui:advanced\", \"urn:alm:descriptor:com.tectonic.ui:text\"},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tPath: \"size\", DisplayName: \"Size\", Description: \"Size is the size of the memcached deployment\"},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdescription: \"Do not change definitions with non-existent type\",\n\t\t\tapisDir:     \"api\",\n\t\t\tcsv: &v1alpha1.ClusterServiceVersion{\n\t\t\t\tSpec: v1alpha1.ClusterServiceVersionSpec{\n\t\t\t\t\tCustomResourceDefinitions: v1alpha1.CustomResourceDefinitions{\n\t\t\t\t\t\tOwned: []v1alpha1.CRDDescription{\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tName: \"nokinds.cache.example.com\", Version: \"v1alpha2\", Kind: \"NoKind\",\n\t\t\t\t\t\t\t\tDisplayName: \"NoKind App\",\n\t\t\t\t\t\t\t\tDescription: \"NoKind is the Schema for the other nokind API\",\n\t\t\t\t\t\t\t\tResources: []v1alpha1.APIResourceReference{\n\t\t\t\t\t\t\t\t\t{Name: \"no-kind-pod\", Kind: \"Pod\", Version: \"v1\"},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tSpecDescriptors: []v1alpha1.SpecDescriptor{\n\t\t\t\t\t\t\t\t\t{Path: \"foo\", DisplayName: \"Foo\", Description: \"Should not be removed\"},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tStatusDescriptors: []v1alpha1.StatusDescriptor{\n\t\t\t\t\t\t\t\t\t{Path: \"bar\", DisplayName: \"Bar\", Description: \"Should not be removed\"},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tgvks: []schema.GroupVersionKind{\n\t\t\t\t{Group: \"cache.example.com\", Version: \"v1alpha2\", Kind: \"NoKind\"},\n\t\t\t},\n\t\t\texpectedCRDs: v1alpha1.CustomResourceDefinitions{\n\t\t\t\tOwned: []v1alpha1.CRDDescription{\n\t\t\t\t\t{\n\t\t\t\t\t\tName: \"nokinds.cache.example.com\", Version: \"v1alpha2\", Kind: \"NoKind\",\n\t\t\t\t\t\tDisplayName: \"NoKind App\",\n\t\t\t\t\t\tDescription: \"NoKind is the Schema for the other nokind API\",\n\t\t\t\t\t\tResources: []v1alpha1.APIResourceReference{\n\t\t\t\t\t\t\t{Name: \"no-kind-pod\", Kind: \"Pod\", Version: \"v1\"},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tSpecDescriptors: []v1alpha1.SpecDescriptor{\n\t\t\t\t\t\t\t{Path: \"foo\", DisplayName: \"Foo\", Description: \"Should not be removed\"},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tStatusDescriptors: []v1alpha1.StatusDescriptor{\n\t\t\t\t\t\t\t{Path: \"bar\", DisplayName: \"Bar\", Description: \"Should not be removed\"},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdescription: \"Return the CSV unchanged for non-existent APIs dir\",\n\t\t\tapisDir:     filepath.Join(\"pkg\", \"notexist\"),\n\t\t\tcsv: &v1alpha1.ClusterServiceVersion{\n\t\t\t\tSpec: v1alpha1.ClusterServiceVersionSpec{\n\t\t\t\t\tCustomResourceDefinitions: v1alpha1.CustomResourceDefinitions{\n\t\t\t\t\t\tOwned: []v1alpha1.CRDDescription{\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tName: \"nokinds.cache.example.com\", Version: \"v1alpha2\", Kind: \"NoKind\",\n\t\t\t\t\t\t\t\tDisplayName: \"NoKind App\",\n\t\t\t\t\t\t\t\tDescription: \"NoKind is the Schema for the other nokind API\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\texpectedCRDs: v1alpha1.CustomResourceDefinitions{\n\t\t\t\tOwned: []v1alpha1.CRDDescription{\n\t\t\t\t\t{\n\t\t\t\t\t\tName: \"nokinds.cache.example.com\", Version: \"v1alpha2\", Kind: \"NoKind\",\n\t\t\t\t\t\tDisplayName: \"NoKind App\",\n\t\t\t\t\t\tDescription: \"NoKind is the Schema for the other nokind API\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(c.description, func(t *testing.T) {\n\t\t\terr := ApplyDefinitionsForKeysGo(c.csv, c.apisDir, c.gvks)\n\t\t\tif !c.wantErr && err != nil {\n\t\t\t\tt.Errorf(\"Expected nil error, got %q\", err)\n\t\t\t} else if c.wantErr && err == nil {\n\t\t\t\tt.Errorf(\"Expected non-nil error, got nil error\")\n\t\t\t} else if !c.wantErr && err == nil {\n\t\t\t\tassert.Equal(t, c.expectedCRDs, c.csv.Spec.CustomResourceDefinitions)\n\t\t\t}\n\t\t})\n\t}\n}\n\nvar _ = Describe(\"updateDefinitionsByKey\", func() {\n\tvar (\n\t\tstartingCSV *v1alpha1.ClusterServiceVersion\n\t\tdefsByGVK   map[schema.GroupVersionKind]*descriptionValues\n\t)\n\n\tBeforeEach(func() {\n\t\tstartingCSV = &v1alpha1.ClusterServiceVersion{}\n\t\tdefsByGVK = make(map[schema.GroupVersionKind]*descriptionValues)\n\t})\n\n\tIt(\"handles an empty CSV and descriptions without error\", func() {\n\t\tupdateDefinitionsByKey(startingCSV, defsByGVK)\n\t\tExpect(startingCSV.Spec.CustomResourceDefinitions.Owned).To(Equal([]v1alpha1.CRDDescription{}))\n\t})\n\tIt(\"preserves ordering of two existing descriptions with no new descriptions\", func() {\n\t\towned := []v1alpha1.CRDDescription{\n\t\t\t{Name: \"memcacheds.cache.example.com\", Version: \"v1alpha1\", Kind: \"Memcached\"},\n\t\t\t{Name: \"memcached2s.cache.example.com\", Version: \"v1alpha1\", Kind: \"Memcached2\"},\n\t\t}\n\t\tstartingCSV.Spec.CustomResourceDefinitions.Owned = owned\n\t\tcsv := startingCSV.DeepCopy()\n\t\tupdateDefinitionsByKey(csv, defsByGVK)\n\t\tExpect(csv.Spec.CustomResourceDefinitions.Owned).To(Equal(owned))\n\t})\n\tIt(\"orders two unordered existing descriptions with no new descriptions\", func() {\n\t\towned := []v1alpha1.CRDDescription{\n\t\t\t{Name: \"memcached2s.cache.example.com\", Version: \"v1alpha1\", Kind: \"Memcached2\"},\n\t\t\t{Name: \"memcacheds.cache.example.com\", Version: \"v1alpha1\", Kind: \"Memcached\"},\n\t\t}\n\t\tstartingCSV.Spec.CustomResourceDefinitions.Owned = owned\n\t\tcsv := startingCSV.DeepCopy()\n\t\tupdateDefinitionsByKey(csv, defsByGVK)\n\t\tsort.Slice(owned, func(i, j int) bool { return owned[i].Name < owned[j].Name })\n\t\tExpect(csv.Spec.CustomResourceDefinitions.Owned).To(Equal(owned))\n\t})\n\tIt(\"orders two new descriptions with increasing orders with no existing descriptions\", func() {\n\t\tdesc1 := v1alpha1.CRDDescription{Name: \"memcached3s.cache.example.com\", Version: \"v1alpha1\", Kind: \"Memcached3\"}\n\t\tdesc2 := v1alpha1.CRDDescription{Name: \"memcached4s.cache.example.com\", Version: \"v1alpha1\", Kind: \"Memcached4\"}\n\t\tdefsByGVK[descToGVK(desc1)] = &descriptionValues{crdOrder: 0, crd: desc1}\n\t\tdefsByGVK[descToGVK(desc2)] = &descriptionValues{crdOrder: 1, crd: desc2}\n\n\t\texpected := []v1alpha1.CRDDescription{desc1, desc2}\n\t\tupdateDefinitionsByKey(startingCSV, defsByGVK)\n\t\tExpect(startingCSV.Spec.CustomResourceDefinitions.Owned).To(Equal(expected))\n\t})\n\tIt(\"orders two new descriptions with decreasing orders with no existing descriptions\", func() {\n\t\tdesc1 := v1alpha1.CRDDescription{Name: \"memcached3s.cache.example.com\", Version: \"v1alpha1\", Kind: \"Memcached3\"}\n\t\tdesc2 := v1alpha1.CRDDescription{Name: \"memcached4s.cache.example.com\", Version: \"v1alpha1\", Kind: \"Memcached4\"}\n\t\tdefsByGVK[descToGVK(desc1)] = &descriptionValues{crdOrder: 1, crd: desc1}\n\t\tdefsByGVK[descToGVK(desc2)] = &descriptionValues{crdOrder: 0, crd: desc2}\n\n\t\texpected := []v1alpha1.CRDDescription{desc2, desc1}\n\t\tupdateDefinitionsByKey(startingCSV, defsByGVK)\n\t\tExpect(startingCSV.Spec.CustomResourceDefinitions.Owned).To(Equal(expected))\n\t})\n\tIt(\"orders two new descriptions with the same order with no existing descriptions\", func() {\n\t\tdesc1 := v1alpha1.CRDDescription{Name: \"memcached3s.cache.example.com\", Version: \"v1alpha1\", Kind: \"Memcached3\"}\n\t\tdesc2 := v1alpha1.CRDDescription{Name: \"memcached4s.cache.example.com\", Version: \"v1alpha1\", Kind: \"Memcached4\"}\n\t\tdefsByGVK[descToGVK(desc1)] = &descriptionValues{crdOrder: 0, crd: desc1}\n\t\tdefsByGVK[descToGVK(desc2)] = &descriptionValues{crdOrder: 0, crd: desc2}\n\n\t\texpected := []v1alpha1.CRDDescription{desc1, desc2}\n\t\tupdateDefinitionsByKey(startingCSV, defsByGVK)\n\t\tExpect(startingCSV.Spec.CustomResourceDefinitions.Owned).To(Equal(expected))\n\t})\n\n\tIt(\"orders one new description after two existing descriptions\", func() {\n\t\tdesc1 := v1alpha1.CRDDescription{Name: \"memcached3s.cache.example.com\", Version: \"v1alpha1\", Kind: \"Memcached3\"}\n\t\tdefsByGVK[descToGVK(desc1)] = &descriptionValues{crdOrder: 2, crd: desc1}\n\n\t\towned := []v1alpha1.CRDDescription{\n\t\t\t{Name: \"memcached2s.cache.example.com\", Version: \"v1alpha1\", Kind: \"Memcached2\"},\n\t\t\t{Name: \"memcacheds.cache.example.com\", Version: \"v1alpha1\", Kind: \"Memcached\"},\n\t\t}\n\t\texpected := []v1alpha1.CRDDescription{owned[0], owned[1], desc1}\n\t\tstartingCSV.Spec.CustomResourceDefinitions.Owned = owned\n\t\tcsv := startingCSV.DeepCopy()\n\t\tupdateDefinitionsByKey(csv, defsByGVK)\n\t\tExpect(csv.Spec.CustomResourceDefinitions.Owned).To(Equal(expected))\n\t})\n\tIt(\"orders one new description between two existing descriptions\", func() {\n\t\tdesc1 := v1alpha1.CRDDescription{Name: \"memcached3s.cache.example.com\", Version: \"v1alpha1\", Kind: \"Memcached3\"}\n\t\tdefsByGVK[descToGVK(desc1)] = &descriptionValues{crdOrder: 0, crd: desc1}\n\n\t\towned := []v1alpha1.CRDDescription{\n\t\t\t{Name: \"memcached2s.cache.example.com\", Version: \"v1alpha1\", Kind: \"Memcached2\"},\n\t\t\t{Name: \"memcacheds.cache.example.com\", Version: \"v1alpha1\", Kind: \"Memcached\"},\n\t\t}\n\t\texpected := []v1alpha1.CRDDescription{desc1, owned[0], owned[1]}\n\t\tstartingCSV.Spec.CustomResourceDefinitions.Owned = owned\n\t\tcsv := startingCSV.DeepCopy()\n\t\tupdateDefinitionsByKey(csv, defsByGVK)\n\t\tExpect(csv.Spec.CustomResourceDefinitions.Owned).To(Equal(expected))\n\t})\n\tIt(\"orders two new descriptions with the same order with overlapping orders of two existing descriptions\", func() {\n\t\tdesc1 := v1alpha1.CRDDescription{Name: \"memcached3s.cache.example.com\", Version: \"v1alpha1\", Kind: \"Memcached3\"}\n\t\tdesc2 := v1alpha1.CRDDescription{Name: \"memcached4s.cache.example.com\", Version: \"v1alpha1\", Kind: \"Memcached4\"}\n\t\tdefsByGVK[descToGVK(desc1)] = &descriptionValues{crdOrder: 0, crd: desc1}\n\t\tdefsByGVK[descToGVK(desc2)] = &descriptionValues{crdOrder: 0, crd: desc2}\n\n\t\towned := []v1alpha1.CRDDescription{\n\t\t\t{Name: \"memcached2s.cache.example.com\", Version: \"v1alpha1\", Kind: \"Memcached2\"},\n\t\t\t{Name: \"memcacheds.cache.example.com\", Version: \"v1alpha1\", Kind: \"Memcached\"},\n\t\t}\n\t\texpected := []v1alpha1.CRDDescription{desc1, desc2, owned[0], owned[1]}\n\t\tstartingCSV.Spec.CustomResourceDefinitions.Owned = owned\n\t\tcsv := startingCSV.DeepCopy()\n\t\tupdateDefinitionsByKey(csv, defsByGVK)\n\t\tExpect(csv.Spec.CustomResourceDefinitions.Owned).To(Equal(expected))\n\t})\n\tIt(\"orders one new description with two existing descriptions, one of which is in defsByGVK\", func() {\n\t\tdesc1 := v1alpha1.CRDDescription{Name: \"memcached1s.cache.example.com\", Version: \"v1alpha1\", Kind: \"Memcached1\"}\n\t\tdesc2 := v1alpha1.CRDDescription{Name: \"memcached2s.cache.example.com\", Version: \"v1alpha1\", Kind: \"Memcached2\"}\n\t\tdefsByGVK[descToGVK(desc1)] = &descriptionValues{crdOrder: 1, crd: desc1}\n\t\tdefsByGVK[descToGVK(desc2)] = &descriptionValues{crdOrder: 0, crd: desc2}\n\n\t\towned := []v1alpha1.CRDDescription{\n\t\t\tdesc1,\n\t\t\t{Name: \"memcacheds.cache.example.com\", Version: \"v1alpha1\", Kind: \"Memcached\"},\n\t\t}\n\t\texpected := []v1alpha1.CRDDescription{desc2, desc1, owned[1]}\n\t\tstartingCSV.Spec.CustomResourceDefinitions.Owned = owned\n\t\tcsv := startingCSV.DeepCopy()\n\t\tupdateDefinitionsByKey(csv, defsByGVK)\n\t\tExpect(csv.Spec.CustomResourceDefinitions.Owned).To(Equal(expected))\n\t})\n\tIt(\"orders multiple new descriptions and existing descriptions\", func() {\n\t\tdesc1 := v1alpha1.CRDDescription{Name: \"memcached3s.cache.example.com\", Version: \"v1alpha1\", Kind: \"Memcached3\"}\n\t\tdesc2 := v1alpha1.CRDDescription{Name: \"memcached4s.cache.example.com\", Version: \"v1alpha1\", Kind: \"Memcached4\"}\n\t\tdesc3 := v1alpha1.CRDDescription{Name: \"foo1s.bar.example.com\", Version: \"v1alpha1\", Kind: \"Foo1\"}\n\t\tdesc4 := v1alpha1.CRDDescription{Name: \"foo2s.bar.example.com\", Version: \"v1alpha1\", Kind: \"Foo2\"}\n\t\tdesc5 := v1alpha1.CRDDescription{Name: \"bazs.bar.example.com\", Version: \"v1alpha1\", Kind: \"Baz\"}\n\t\tdefsByGVK[descToGVK(desc1)] = &descriptionValues{crdOrder: 0, crd: desc1}\n\t\tdefsByGVK[descToGVK(desc2)] = &descriptionValues{crdOrder: 3, crd: desc2}\n\t\tdefsByGVK[descToGVK(desc3)] = &descriptionValues{crdOrder: 1, crd: desc3}\n\t\tdefsByGVK[descToGVK(desc4)] = &descriptionValues{crdOrder: 0, crd: desc4}\n\t\tdefsByGVK[descToGVK(desc5)] = &descriptionValues{crdOrder: 10000, crd: desc5}\n\n\t\towned := []v1alpha1.CRDDescription{\n\t\t\tdesc2, // Has order 3 above.\n\t\t\t{Name: \"memcached2s.cache.example.com\", Version: \"v1alpha1\", Kind: \"Memcached2\"},\n\t\t\t{Name: \"memcacheds.cache.example.com\", Version: \"v1alpha1\", Kind: \"Memcached\"},\n\t\t\tdesc1, // Has order 0 above\n\t\t\t{Name: \"bar2.cache.example.com\", Version: \"v1alpha1\", Kind: \"Bar2\"},\n\t\t\t{Name: \"bar1.cache.example.com\", Version: \"v1alpha1\", Kind: \"Bar1\"},\n\t\t}\n\t\texpected := []v1alpha1.CRDDescription{desc4, desc1, desc3, owned[1], owned[2], desc2, owned[4], owned[5], desc5}\n\t\tstartingCSV.Spec.CustomResourceDefinitions.Owned = owned\n\t\tcsv := startingCSV.DeepCopy()\n\t\tupdateDefinitionsByKey(csv, defsByGVK)\n\t\tExpect(csv.Spec.CustomResourceDefinitions.Owned).To(Equal(expected))\n\t})\n})\n"
  },
  {
    "path": "internal/generate/clusterserviceversion/bases/definitions/markers.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage definitions\n\nimport (\n\t\"fmt\"\n\t\"math\"\n\t\"reflect\"\n\t\"strings\"\n\t\"unicode\"\n\n\t\"github.com/fatih/structtag\"\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\tcrdmarkers \"sigs.k8s.io/controller-tools/pkg/crd/markers\"\n\t\"sigs.k8s.io/controller-tools/pkg/markers\"\n\n\tsdkmarkers \"github.com/operator-framework/operator-sdk/internal/markers\"\n\t\"github.com/operator-framework/operator-sdk/internal/util/k8sutil\"\n)\n\nconst (\n\t// csvPrefix is the prefix for all csv marker names.\n\tcsvPrefix = sdkmarkers.Prefix + \":csv\"\n\t// crdMarkerName is the base marker name for all customresourcedefinitions markers.\n\tcrdMarkerName = csvPrefix + \":customresourcedefinitions\"\n)\n\nvar (\n\t//+operator-sdk:csv:customresourcedefinitions:displayName=\"string\",resources={ {kind,version,name} , ... }\n\ttypeDefinition = markers.Must(markers.MakeDefinition(crdMarkerName, markers.DescribesType, Description{}))\n\t//+operator-sdk:csv:customresourcedefinitions:type=<spec|status>,displayName=\"name\",xDescriptors=\"ui:elements:foo:bar\"\n\tfieldDefinition = markers.Must(markers.MakeDefinition(crdMarkerName, markers.DescribesField, Descriptor{}))\n)\n\n// registerMarkers adds type and field marker definitions to a registry.\nfunc registerMarkers(into *markers.Registry) error {\n\t// External definitions.\n\tif err := crdmarkers.Register(into); err != nil {\n\t\treturn fmt.Errorf(\"error registering external marker definition: %v\", err)\n\t}\n\n\tif err := into.Register(typeDefinition); err != nil {\n\t\treturn fmt.Errorf(\"error registering type definition: %v\", err)\n\t}\n\tinto.AddHelp(typeDefinition, Description{}.Help())\n\tif err := into.Register(fieldDefinition); err != nil {\n\t\treturn fmt.Errorf(\"error registering field definition: %v\", err)\n\t}\n\tinto.AddHelp(fieldDefinition, Descriptor{}.Help())\n\n\treturn nil\n}\n\n// Resource is a list of strings defining a CRD description resource.\ntype Resource []string\n\n// Resources is a list of resource definitions.\ntype Resources []Resource\n\n// +controllertools:marker:generateHelp:category=Description\n\n// Description is a type used to receive type-level CRD description markers.\ntype Description struct {\n\t// Resources is a list of string lists, each of which defines a CRD description resource. The marker format is:\n\t// { { \"kind\" , \"version\" ( , \"name\")? } , ... }\n\tResources Resources `marker:\",optional\"`\n\t// DisplayName is the displayName of a CRD description.\n\tDisplayName string `marker:\",optional\"`\n\t// Order determines which position in the list this description will take.\n\t// Markers with Order omitted have the highest Order, i.e. at the end of the list.\n\t// If more than one marker has the same Order, the corresponding descriptions\n\t// will be sorted alphabetically and placed above others with higher Orders.\n\tOrder *int `marker:\",optional\"`\n}\n\n// +controllertools:marker:generateHelp:category=Descriptor\n\n// Descriptor is a type used to receive field-level spec and status descriptor markers. Format of marker:\ntype Descriptor struct {\n\t// Type is one of: \"spec\", \"status\".\n\tType string `marker:\",optional\"`\n\t// DisplayName is the displayName of a spec or status description.\n\tDisplayName string `marker:\",optional\"`\n\t// XDescriptors is a list of UI path strings. The marker format is:\n\t// \"ui:element:foo,ui:element:bar\"\n\tXDescriptors []string `marker:\",optional\"`\n\t// Order determines which position in the list this descriptor will take.\n\t// Markers with Order omitted have the highest Order, i.e. at the end of the list.\n\t// If more than one marker has the same Order, the corresponding descriptors\n\t// will be sorted alphabetically and placed above others with higher Orders.\n\tOrder *int `marker:\",optional\"`\n}\n\n// toResourceReferences transforms Resources into a apiResourceReference slice.\nfunc (resources Resources) toResourceReferences() (rs []v1alpha1.APIResourceReference, err error) {\n\tfor _, resource := range resources {\n\t\tif l := len(resource); l < 2 {\n\t\t\treturn nil, fmt.Errorf(\"resource %+q did not have at least a kind and a version\", resource)\n\t\t}\n\t\tr := v1alpha1.APIResourceReference{\n\t\t\tKind:    strings.TrimSpace(resource[0]),\n\t\t\tVersion: strings.TrimSpace(resource[1]),\n\t\t}\n\t\tif len(resource) == 3 {\n\t\t\tr.Name = strings.TrimSpace(resource[2])\n\t\t}\n\t\trs = append(rs, r)\n\t}\n\treturn rs, nil\n}\n\n// fieldInfo is a markers.FieldInfo wrapper that also holds path segments.\ntype fieldInfo struct {\n\tmarkers.FieldInfo\n\tpathSegments []string\n}\n\nconst (\n\tspec   = \"spec\"\n\tstatus = \"status\"\n)\n\n// setDescriptorFields sets a struct with Description, Path, DisplayName, and XDescriptors fields by reflection.\nfunc (fi fieldInfo) setDescriptorFields(v reflect.Value, descType string) (int, bool) {\n\tpath, include := makePath(fi.pathSegments)\n\tif !include {\n\t\treturn 0, false\n\t}\n\n\tvar (\n\t\tseenDescType bool\n\t\tdisplayName  string\n\t\txDescriptors []string\n\t\torderPtr     *int\n\t)\n\tfor _, markers := range fi.Markers {\n\t\tfor _, marker := range markers {\n\t\t\td, isDescriptor := marker.(Descriptor)\n\t\t\tif isDescriptor && d.Type == descType {\n\t\t\t\tif d.Order != nil {\n\t\t\t\t\torderPtr = d.Order\n\t\t\t\t}\n\t\t\t\tif d.DisplayName != \"\" && displayName == \"\" {\n\t\t\t\t\tdisplayName = d.DisplayName\n\t\t\t\t}\n\t\t\t\txDescriptors = append(xDescriptors, d.XDescriptors...)\n\t\t\t\tseenDescType = true\n\t\t\t}\n\t\t}\n\t}\n\tif displayName == \"\" {\n\t\tdisplayName = k8sutil.GetDisplayName(fi.Name)\n\t}\n\n\tv.Elem().FieldByName(\"Description\").SetString(fi.Doc)\n\tv.Elem().FieldByName(\"Path\").SetString(path)\n\tv.Elem().FieldByName(\"DisplayName\").SetString(displayName)\n\tv.Elem().FieldByName(\"XDescriptors\").Set(reflect.ValueOf(xDescriptors))\n\n\torder := math.MaxInt64\n\tif orderPtr != nil {\n\t\torder = *orderPtr\n\t}\n\n\treturn order, seenDescType\n}\n\n// makePath creates a path string from raw path segments. These segments can encode extra information\n// about what field it came from. If a path should be ignored by the caller, it returns false.\nfunc makePath(rawSegments []string) (string, bool) {\n\tpathSegments := []string{}\n\tfor i, segment := range rawSegments {\n\t\tswitch {\n\t\tcase segment == ignoredTag:\n\t\t\t// Ignored fields are not serialized and therefore its own path segment\n\t\t\t// and those of its children should not be included in the path.\n\t\t\treturn \"\", false\n\t\tcase segment == inlinedTag:\n\t\t\t// Inlined struct types move their fields into their parents, so the path segment\n\t\t\t// of such a field should not be in the path if it is last in the path.\n\t\t\tif i == len(rawSegments)-1 {\n\t\t\t\treturn \"\", false\n\t\t\t}\n\t\t\tcontinue\n\t\tcase strings.HasSuffix(segment, \"[0]\") && i == len(rawSegments)-1:\n\t\t\t// Only include an arrayFieldGroup suffix if there is a child path segment.\n\t\t\tsegment = strings.TrimSuffix(segment, \"[0]\")\n\t\t}\n\t\tpathSegments = append(pathSegments, segment)\n\t}\n\treturn strings.Join(pathSegments, \".\"), true\n}\n\nconst (\n\tinlinedTag = \"##inline##\"\n\tignoredTag = \"##ignore##\"\n)\n\n// getPathSegmentForField parses a path segment from a field's tag.\nfunc getPathSegmentForField(finfo markers.FieldInfo) (string, error) {\n\t// Embedded fields are inlined and children may be included.\n\tif len(finfo.RawField.Names) == 0 {\n\t\treturn inlinedTag, nil\n\t}\n\t// Unexported fields should be ignored in downstream processing.\n\tif !isExported(finfo.Name) {\n\t\treturn ignoredTag, nil\n\t}\n\ttags, err := structtag.Parse(string(finfo.Tag))\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tjsonTag, err := tags.Get(\"json\")\n\tif err == nil {\n\t\t// Parse returns an error if no JSON tag is in tags, at which point we'll use another method to get path.\n\t\tswitch {\n\t\tcase contains(jsonTag.Options, \"inline\"):\n\t\t\treturn inlinedTag, nil\n\t\tcase jsonTag.Name == \"-\":\n\t\t\tif len(jsonTag.Options) == 0 {\n\t\t\t\treturn ignoredTag, nil\n\t\t\t}\n\t\t\treturn jsonTag.Name, nil\n\t\tcase jsonTag.Name != \"\":\n\t\t\treturn jsonTag.Name, nil\n\t\t}\n\t}\n\t// There is no JSON tag in tags or tag name is empty. Use info name as path as json.Marshal does.\n\treturn finfo.Name, nil\n}\n\n// isExported returns true if name is an exported struct field name.\nfunc isExported(name string) bool {\n\treturn len(name) != 0 && !unicode.IsLower(rune(name[0]))\n}\n\nfunc contains(options []string, key string) bool {\n\tfor _, opt := range options {\n\t\tif opt == key {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "internal/generate/clusterserviceversion/bases/definitions/markers_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage definitions\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n)\n\n// TODO(estroz): migrate to ginkgo/gomega\n\nfunc TestParseResource(t *testing.T) {\n\tcases := []struct {\n\t\tdescription string\n\t\tinput       Resources\n\t\texp         []v1alpha1.APIResourceReference\n\t\twantErr     bool\n\t}{\n\t\t{\n\t\t\t\"Resource with no name\",\n\t\t\tResources{{\"Pod\", \"v1\"}},\n\t\t\t[]v1alpha1.APIResourceReference{{Kind: \"Pod\", Version: \"v1\"}},\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t\"Resource with name\",\n\t\t\tResources{{\"Pod\", \"v1\", \"memcached-pod\"}},\n\t\t\t[]v1alpha1.APIResourceReference{{Kind: \"Pod\", Version: \"v1\", Name: \"memcached-pod\"}},\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t\"Resource with string literal name\",\n\t\t\tResources{{\"Pod\", \"v1\", `\"memcached-pod\"`}},\n\t\t\t[]v1alpha1.APIResourceReference{{Kind: \"Pod\", Version: \"v1\", Name: `\"memcached-pod\"`}},\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t\"Two resources\",\n\t\t\tResources{{\"Pod\", \"v1\", \"memcached-pod\"}, {\"Service\", \"v1\"}},\n\t\t\t[]v1alpha1.APIResourceReference{\n\t\t\t\t{Kind: \"Pod\", Version: \"v1\", Name: \"memcached-pod\"},\n\t\t\t\t{Kind: \"Service\", Version: \"v1\"},\n\t\t\t},\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t\"Empty resource string without quotes\",\n\t\t\tResources{{\"\"}},\n\t\t\t[]v1alpha1.APIResourceReference{},\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"Empty resource string with quotes\",\n\t\t\tResources{{`\"\"`}},\n\t\t\t[]v1alpha1.APIResourceReference{},\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"Resource string with no version\",\n\t\t\tResources{{\"Memcached\"}},\n\t\t\t[]v1alpha1.APIResourceReference{},\n\t\t\ttrue,\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\toutput, err := c.input.toResourceReferences()\n\t\tif err != nil {\n\t\t\tif !c.wantErr {\n\t\t\t\tt.Errorf(\"%s: expected nil error, got %q\", c.description, err)\n\t\t\t}\n\t\t\tcontinue\n\t\t} else if c.wantErr {\n\t\t\tt.Errorf(\"%s: expected non-nil error, got nil error\", c.description)\n\t\t\tcontinue\n\t\t}\n\n\t\tif !c.wantErr {\n\t\t\tif !reflect.DeepEqual(c.exp, output) {\n\t\t\t\tt.Errorf(\"%s: expected %s, got %s\", c.description, c.exp, output)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/generate/clusterserviceversion/bases/definitions/zz_generated.markerhelp.go",
    "content": "//go:build !ignore_autogenerated\n// +build !ignore_autogenerated\n\n// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Code generated by helpgen. DO NOT EDIT.\n\npackage definitions\n\nimport (\n\t\"sigs.k8s.io/controller-tools/pkg/markers\"\n)\n\nfunc (Description) Help() *markers.DefinitionHelp {\n\treturn &markers.DefinitionHelp{\n\t\tCategory: \"Description\",\n\t\tDetailedHelp: markers.DetailedHelp{\n\t\t\tSummary: \"is a type used to receive type-level CRD description markers.\",\n\t\t\tDetails: \"\",\n\t\t},\n\t\tFieldHelp: map[string]markers.DetailedHelp{\n\t\t\t\"Resources\": markers.DetailedHelp{\n\t\t\t\tSummary: \"is a list of string lists, each of which defines a CRD description resource. The marker format is: { { \\\"kind\\\" , \\\"version\\\" ( , \\\"name\\\")? } , ... }\",\n\t\t\t\tDetails: \"\",\n\t\t\t},\n\t\t\t\"DisplayName\": markers.DetailedHelp{\n\t\t\t\tSummary: \"is the displayName of a CRD description.\",\n\t\t\t\tDetails: \"\",\n\t\t\t},\n\t\t\t\"Order\": markers.DetailedHelp{\n\t\t\t\tSummary: \"determines which position in the list this description will take. Markers with Order omitted have the highest Order. If more than one marker has the same Order, the corresponding descriptions will be sorted alphabetically and placed above others with higher Orders.\",\n\t\t\t\tDetails: \"\",\n\t\t\t},\n\t\t},\n\t}\n}\n\nfunc (Descriptor) Help() *markers.DefinitionHelp {\n\treturn &markers.DefinitionHelp{\n\t\tCategory: \"Descriptor\",\n\t\tDetailedHelp: markers.DetailedHelp{\n\t\t\tSummary: \"is a type used to receive field-level spec and status descriptor markers. Format of marker:\",\n\t\t\tDetails: \"\",\n\t\t},\n\t\tFieldHelp: map[string]markers.DetailedHelp{\n\t\t\t\"Type\": markers.DetailedHelp{\n\t\t\t\tSummary: \"is one of: \\\"spec\\\", \\\"status\\\".\",\n\t\t\t\tDetails: \"\",\n\t\t\t},\n\t\t\t\"DisplayName\": markers.DetailedHelp{\n\t\t\t\tSummary: \"is the displayName of a spec or status description.\",\n\t\t\t\tDetails: \"\",\n\t\t\t},\n\t\t\t\"XDescriptors\": markers.DetailedHelp{\n\t\t\t\tSummary: \"is a list of UI path strings. The marker format is: \\\"ui:element:foo,ui:element:bar\\\"\",\n\t\t\t\tDetails: \"\",\n\t\t\t},\n\t\t\t\"Order\": markers.DetailedHelp{\n\t\t\t\tSummary: \"determines which position in the list this descriptor will take. Markers with Order omitted have the highest Order. If more than one marker has the same Order, the corresponding descriptors will be sorted alphabetically and placed above others with higher Orders.\",\n\t\t\t\tDetails: \"\",\n\t\t\t},\n\t\t},\n\t}\n}\n"
  },
  {
    "path": "internal/generate/clusterserviceversion/bases/metadata.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage bases\n\nimport (\n\t\"strings\"\n\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/util/projutil\"\n)\n\n// uiMetadata includes the list of CSV fields which would be asked\n// to the user while generating CSV.\ntype uiMetadata struct {\n\t// DisplayName is the name of the crd.\n\tDisplayName string\n\t// Description of the operator. Can include the features, limitations or\n\t// use-cases of the operator.\n\tDescription string\n\t// Name of the publishing entity behind the operator.\n\tProviderName string\n\t// URL related to the publishing entity behind the operator.\n\tProviderURL string\n\t// Keyword is a list of keywords describing the operator.\n\tKeywords []string\n\t// Maintainers is the list of organizational entities maintaining the operator.\n\tMaintainers []string\n\t// FEAT: read icon bytes from files.\n}\n\n// runInteractivePrompt prompts the user to provide input to uiMetadata fields.\nfunc (s *uiMetadata) runInteractivePrompt() {\n\ts.DisplayName = projutil.GetRequiredInput(\"Display name for the operator\")\n\ts.Description = projutil.GetRequiredInput(\"Description for the operator\")\n\ts.ProviderName = projutil.GetRequiredInput(\"Provider's name for the operator\")\n\ts.ProviderURL = projutil.GetOptionalInput(\"Any relevant URL for the provider name\")\n\ts.Keywords = projutil.GetStringArray(\"Comma-separated list of keywords for your operator\")\n\ts.Maintainers = projutil.GetStringArray(\"Comma-separated list of maintainers and their emails\" +\n\t\t\" (e.g. 'name1:email1, name2:email2')\")\n}\n\n// apply populates the CSV with the data in s.\nfunc (s uiMetadata) apply(csv *v1alpha1.ClusterServiceVersion) {\n\tif s.DisplayName != \"\" {\n\t\tcsv.Spec.DisplayName = s.DisplayName\n\t}\n\n\tif len(s.Keywords) != 0 {\n\t\tcsv.Spec.Keywords = s.Keywords\n\t}\n\n\tif s.Description != \"\" {\n\t\tcsv.Spec.Description = s.Description\n\t}\n\n\tif len(s.Maintainers) != 0 {\n\t\tmaintainers := make([]v1alpha1.Maintainer, 0)\n\t\tfor _, entity := range s.Maintainers {\n\t\t\tentityDetails := strings.Split(entity, \":\")\n\t\t\tif len(entityDetails) == 2 {\n\t\t\t\tm := v1alpha1.Maintainer{}\n\t\t\t\tm.Name, m.Email = entityDetails[0], entityDetails[1]\n\t\t\t\tmaintainers = append(maintainers, m)\n\t\t\t}\n\t\t}\n\t\tcsv.Spec.Maintainers = maintainers\n\t}\n\n\tif s.ProviderName != \"\" {\n\t\tprovider := v1alpha1.AppLink{}\n\t\tprovider.Name = s.ProviderName\n\t\tif s.ProviderURL != \"\" {\n\t\t\tprovider.URL = s.ProviderURL\n\t\t}\n\t\tcsv.Spec.Provider = provider\n\t}\n}\n"
  },
  {
    "path": "internal/generate/clusterserviceversion/bases/metadata_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage bases\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n)\n\nfunc TestMetadata(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"Metadata Suite\")\n}\n\nvar _ = Describe(\"Metadata\", func() {\n\n\tmeta := uiMetadata{\n\t\tDisplayName: \"Memcached Application\",\n\t\tKeywords:    []string{\"memcached\", \"app\"},\n\t\tDescription: \"Main enterprise application providing business critical features with \" +\n\t\t\t\"high availability and no manual intervention.\",\n\t\tProviderName: \"Example\",\n\t\tProviderURL:  \"www.example.com\",\n\t\tMaintainers:  []string{\"Some Corp:corp@example.com\"},\n\t}\n\n\tIt(\"populates an empty CSV\", func() {\n\t\tcsv := v1alpha1.ClusterServiceVersion{}\n\n\t\tmeta.apply(&csv)\n\n\t\tExpect(csv.Spec.DisplayName).To(Equal(meta.DisplayName))\n\t\tExpect(csv.Spec.Keywords).To(Equal(meta.Keywords))\n\t\tExpect(csv.Spec.Description).To(Equal(meta.Description))\n\t\tExpect(csv.Spec.Maintainers).To(Equal([]v1alpha1.Maintainer{{Name: \"Some Corp\", Email: \"corp@example.com\"}}))\n\t\tExpect(csv.Spec.Provider).To(Equal(v1alpha1.AppLink{Name: meta.ProviderName, URL: meta.ProviderURL}))\n\t})\n\n\tIt(\"populates a CSV with existing values\", func() {\n\t\tb := ClusterServiceVersion{OperatorName: \"test-operator\"}\n\t\tb.setDefaults()\n\t\tcsv := b.newBase()\n\n\t\tmeta.apply(csv)\n\n\t\tExpect(csv.Spec.DisplayName).To(Equal(meta.DisplayName))\n\t\tExpect(csv.Spec.Keywords).To(Equal(meta.Keywords))\n\t\tExpect(csv.Spec.Description).To(Equal(meta.Description))\n\t\tExpect(csv.Spec.Maintainers).To(Equal([]v1alpha1.Maintainer{{Name: \"Some Corp\", Email: \"corp@example.com\"}}))\n\t\tExpect(csv.Spec.Provider).To(Equal(v1alpha1.AppLink{Name: meta.ProviderName, URL: meta.ProviderURL}))\n\t})\n})\n"
  },
  {
    "path": "internal/generate/clusterserviceversion/clusterserviceversion.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage clusterserviceversion\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/blang/semver/v4\"\n\toperatorsv1alpha1 \"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\t\"github.com/operator-framework/operator-registry/pkg/lib/bundle\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/generate/clusterserviceversion/bases\"\n\t\"github.com/operator-framework/operator-sdk/internal/generate/collector\"\n\tgenutil \"github.com/operator-framework/operator-sdk/internal/generate/internal\"\n\t\"github.com/operator-framework/operator-sdk/internal/util/projutil\"\n)\n\nconst (\n\t// File extension for all ClusterServiceVersion manifests written by Generator.\n\tcsvYamlFileExt = \".clusterserviceversion.yaml\"\n)\n\nvar (\n\t// Internal errors.\n\tnoGetWriterError = genutil.InternalError(\"getWriter must be set\")\n)\n\n// ClusterServiceVersion configures ClusterServiceVersion manifest generation.\ntype Generator struct {\n\t// OperatorName is the operator's name, ex. app-operator.\n\tOperatorName string\n\t// Version is the CSV current version.\n\tVersion string\n\t// FromVersion is the version of a previous CSV to upgrade from.\n\tFromVersion string\n\t// Collector holds all manifests relevant to the Generator.\n\tCollector *collector.Manifests\n\t// Annotations are applied to the resulting CSV.\n\tAnnotations map[string]string\n\t// ExtraServiceAccounts are ServiceAccount names to consider when matching\n\t// {Cluster}Roles to include in a CSV via their Bindings.\n\tExtraServiceAccounts []string\n\t// RelatedImages are additional images used by the operator.\n\tRelatedImages []operatorsv1alpha1.RelatedImage\n\n\t// Func that returns the writer the generated CSV's bytes are written to.\n\tgetWriter func() (io.Writer, error)\n}\n\n// Option is a function that modifies a Generator.\ntype Option func(*Generator) error\n\n// WithWriter sets a Generator's writer to w.\nfunc WithWriter(w io.Writer) Option {\n\treturn func(g *Generator) error {\n\t\tg.getWriter = func() (io.Writer, error) {\n\t\t\treturn w, nil\n\t\t}\n\t\treturn nil\n\t}\n}\n\n// WithBundleWriter sets a Generator's writer to a bundle CSV file under\n// <dir>/manifests.\nfunc WithBundleWriter(dir string) Option {\n\treturn func(g *Generator) error {\n\t\tfileName := makeCSVFileName(g.OperatorName)\n\t\tg.getWriter = func() (io.Writer, error) {\n\t\t\treturn genutil.Open(filepath.Join(dir, bundle.ManifestsDir), fileName)\n\t\t}\n\t\treturn nil\n\t}\n}\n\n// WithPackageWriter sets a Generator's writer to a package CSV file under\n// <dir>/<version>.\nfunc WithPackageWriter(dir string) Option {\n\treturn func(g *Generator) error {\n\t\tfileName := makeCSVFileName(g.OperatorName)\n\t\tg.getWriter = func() (io.Writer, error) {\n\t\t\treturn genutil.Open(filepath.Join(dir, g.Version), fileName)\n\t\t}\n\t\treturn nil\n\t}\n}\n\n// Generate configures the generator with col and opts then runs it.\nfunc (g *Generator) Generate(opts ...Option) (err error) {\n\tfor _, opt := range opts {\n\t\tif err = opt(g); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tif g.getWriter == nil {\n\t\treturn noGetWriterError\n\t}\n\n\tcsv, err := g.generate()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Add extra annotations to csv\n\tg.setAnnotations(csv)\n\n\tw, err := g.getWriter()\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn genutil.WriteObject(w, csv)\n}\n\n// setSDKAnnotations adds SDK metric labels to the base if they do not exist.\nfunc (g Generator) setAnnotations(csv *operatorsv1alpha1.ClusterServiceVersion) {\n\tannotations := csv.GetAnnotations()\n\tif annotations == nil {\n\t\tannotations = make(map[string]string)\n\t}\n\tfor k, v := range g.Annotations {\n\t\tannotations[k] = v\n\t}\n\tcsv.SetAnnotations(annotations)\n}\n\n// generate runs a configured Generator.\nfunc (g *Generator) generate() (base *operatorsv1alpha1.ClusterServiceVersion, err error) {\n\tif g.Collector == nil {\n\t\treturn nil, fmt.Errorf(\"cannot generate CSV without a manifests collection\")\n\t}\n\n\t// Search for a CSV in the collector with a name matching the package name.\n\tcsvNamePrefix := g.OperatorName + \".\"\n\tfor _, csv := range g.Collector.ClusterServiceVersions {\n\t\tif base == nil && strings.HasPrefix(csv.GetName(), csvNamePrefix) {\n\t\t\tbase = csv.DeepCopy()\n\t\t}\n\t}\n\n\t// Use a default base if none was supplied.\n\tif base == nil {\n\t\tbase = bases.New(g.OperatorName)\n\t}\n\tif g.Version != \"\" {\n\t\t// Use the existing version/name unless g.Version is set.\n\t\tbase.SetName(genutil.MakeCSVName(g.OperatorName, g.Version))\n\t\tif base.Spec.Version.Version, err = semver.Parse(g.Version); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\tif g.FromVersion != \"\" {\n\t\tbase.Spec.Replaces = genutil.MakeCSVName(g.OperatorName, g.FromVersion)\n\t}\n\tbase.Spec.RelatedImages = g.RelatedImages\n\n\tif err := ApplyTo(g.Collector, base, g.ExtraServiceAccounts); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn base, nil\n}\n\n// makeCSVFileName returns a CSV file name containing name.\nfunc makeCSVFileName(name string) string {\n\treturn strings.ToLower(name) + csvYamlFileExt\n}\n\n// requiresInteraction checks if the combination of ilvl and basePath existence\n// requires the generator prompt a user interactively.\nfunc requiresInteraction(basePath string, ilvl projutil.InteractiveLevel) bool {\n\treturn (ilvl == projutil.InteractiveSoftOff && genutil.IsNotExist(basePath)) || ilvl == projutil.InteractiveOnAll\n}\n"
  },
  {
    "path": "internal/generate/clusterserviceversion/clusterserviceversion_suite_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage clusterserviceversion\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nfunc TestGenerator(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"Generator Suite\")\n}\n"
  },
  {
    "path": "internal/generate/clusterserviceversion/clusterserviceversion_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage clusterserviceversion\n\nimport (\n\t\"bytes\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/blang/semver/v4\"\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\t\"github.com/onsi/gomega/format\"\n\toperatorversion \"github.com/operator-framework/api/pkg/lib/version\"\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\t\"github.com/operator-framework/operator-registry/pkg/lib/bundle\"\n\tappsv1 \"k8s.io/api/apps/v1\"\n\t\"sigs.k8s.io/yaml\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/generate/clusterserviceversion/bases\"\n\t\"github.com/operator-framework/operator-sdk/internal/generate/collector\"\n\tgenutil \"github.com/operator-framework/operator-sdk/internal/generate/internal\"\n\t\"github.com/operator-framework/operator-sdk/internal/util/projutil\"\n)\n\nvar (\n\ttestDataDir           = filepath.Join(\"..\", \"testdata\")\n\tcsvDir                = filepath.Join(testDataDir, \"clusterserviceversions\")\n\tcsvBasesDir           = filepath.Join(csvDir, \"bases\")\n\tcsvNewLayoutBundleDir = filepath.Join(csvDir, \"output\")\n\n\tgoTestDataDir              = filepath.Join(testDataDir, \"go\")\n\tgoStaticDir                = filepath.Join(goTestDataDir, \"static\")\n\tgoBasicOperatorPath        = filepath.Join(goStaticDir, \"basic.operator.yaml\")\n\tgoMultiVersionOperatorPath = filepath.Join(goStaticDir, \"basic.multiversion.operator.yaml\")\n)\n\nvar (\n\tcol *collector.Manifests\n)\n\nvar (\n\t// Base CSVs\n\tbaseCSV, baseCSVUIMeta       *v1alpha1.ClusterServiceVersion\n\tbaseCSVStr, baseCSVUIMetaStr string\n\n\t// Updated CSVs\n\tnewCSV, newCSVUIMeta *v1alpha1.ClusterServiceVersion\n\tnewCSVUIMetaStr      string\n\n\t// Base Multiversion CSV\n\tbaseMultiVersionCSV *v1alpha1.ClusterServiceVersion\n\n\t// Multiversion CSVs\n\tmultiVersionCSVStr string\n)\n\nvar _ = Describe(\"Testing CRDs with single version\", func() {\n\tBeforeEach(func() {\n\t\tcol = &collector.Manifests{}\n\t\tcollectManifestsFromFileHelper(col, goBasicOperatorPath)\n\t\tinitTestCSVsHelper()\n\t})\n\n\tvar _ = Describe(\"Generating a ClusterServiceVersion\", func() {\n\t\tformat.TruncatedDiff = true\n\t\tformat.UseStringerRepresentation = true\n\n\t\tvar (\n\t\t\tg            Generator\n\t\t\tbuf          *bytes.Buffer\n\t\t\toperatorName = \"memcached-operator\"\n\t\t\tzeroZeroOne  = \"0.0.1\"\n\t\t\tzeroZeroTwo  = \"0.0.2\"\n\t\t)\n\n\t\tBeforeEach(func() {\n\t\t\tbuf = &bytes.Buffer{}\n\t\t})\n\n\t\tDescribe(\"for a Go project\", func() {\n\n\t\t\tContext(\"with correct Options\", func() {\n\n\t\t\t\tvar (\n\t\t\t\t\ttmp string\n\t\t\t\t\terr error\n\t\t\t\t)\n\n\t\t\t\tBeforeEach(func() {\n\t\t\t\t\ttmp, err = os.MkdirTemp(\".\", \"\")\n\t\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\t\tcol.ClusterServiceVersions = []v1alpha1.ClusterServiceVersion{*baseCSVUIMeta}\n\t\t\t\t})\n\n\t\t\t\tAfterEach(func() {\n\t\t\t\t\tif tmp != \"\" {\n\t\t\t\t\t\tos.RemoveAll(tmp)\n\t\t\t\t\t}\n\t\t\t\t\tcol.ClusterServiceVersions = nil\n\t\t\t\t})\n\n\t\t\t\tIt(\"should write a ClusterServiceVersion manifest to an io.Writer\", func() {\n\t\t\t\t\tg = Generator{\n\t\t\t\t\t\tOperatorName: operatorName,\n\t\t\t\t\t\tVersion:      zeroZeroOne,\n\t\t\t\t\t\tCollector:    col,\n\t\t\t\t\t}\n\t\t\t\t\topts := []Option{\n\t\t\t\t\t\tWithWriter(buf),\n\t\t\t\t\t}\n\t\t\t\t\tExpect(g.Generate(opts...)).ToNot(HaveOccurred())\n\t\t\t\t\tExpect(buf.String()).To(MatchYAML(newCSVUIMetaStr))\n\t\t\t\t})\n\t\t\t\tIt(\"should write a ClusterServiceVersion manifest to a bundle file\", func() {\n\t\t\t\t\tg = Generator{\n\t\t\t\t\t\tOperatorName: operatorName,\n\t\t\t\t\t\tVersion:      zeroZeroOne,\n\t\t\t\t\t\tCollector:    col,\n\t\t\t\t\t}\n\t\t\t\t\topts := []Option{\n\t\t\t\t\t\tWithBundleWriter(tmp),\n\t\t\t\t\t}\n\t\t\t\t\tExpect(g.Generate(opts...)).ToNot(HaveOccurred())\n\t\t\t\t\toutputFile := filepath.Join(tmp, bundle.ManifestsDir, makeCSVFileName(operatorName))\n\t\t\t\t\tExpect(outputFile).To(BeAnExistingFile())\n\t\t\t\t\tExpect(readFileHelper(outputFile)).To(MatchYAML(newCSVUIMetaStr))\n\t\t\t\t})\n\t\t\t\tIt(\"should write a ClusterServiceVersion manifest to a package file\", func() {\n\t\t\t\t\tg = Generator{\n\t\t\t\t\t\tOperatorName: operatorName,\n\t\t\t\t\t\tVersion:      zeroZeroOne,\n\t\t\t\t\t\tCollector:    col,\n\t\t\t\t\t}\n\t\t\t\t\topts := []Option{\n\t\t\t\t\t\tWithPackageWriter(tmp),\n\t\t\t\t\t}\n\t\t\t\t\tExpect(g.Generate(opts...)).ToNot(HaveOccurred())\n\t\t\t\t\toutputFile := filepath.Join(tmp, g.Version, makeCSVFileName(operatorName))\n\t\t\t\t\tExpect(outputFile).To(BeAnExistingFile())\n\t\t\t\t\tExpect(readFileHelper(outputFile)).To(MatchYAML(newCSVUIMetaStr))\n\t\t\t\t})\n\t\t\t})\n\n\t\t\tContext(\"with incorrect Options\", func() {\n\n\t\t\t\tBeforeEach(func() {\n\t\t\t\t\tg = Generator{\n\t\t\t\t\t\tOperatorName: operatorName,\n\t\t\t\t\t\tVersion:      zeroZeroOne,\n\t\t\t\t\t\tCollector:    col,\n\t\t\t\t\t}\n\t\t\t\t})\n\n\t\t\t\tIt(\"should return an error without any Options\", func() {\n\t\t\t\t\topts := []Option{}\n\t\t\t\t\tExpect(g.Generate(opts...)).To(MatchError(noGetWriterError))\n\t\t\t\t})\n\t\t\t})\n\n\t\t\tContext(\"to create a new ClusterServiceVersion\", func() {\n\t\t\t\tIt(\"should return a default object when no base is supplied\", func() {\n\t\t\t\t\tcol.ClusterServiceVersions = nil\n\t\t\t\t\tg = Generator{\n\t\t\t\t\t\tOperatorName: operatorName,\n\t\t\t\t\t\tVersion:      zeroZeroOne,\n\t\t\t\t\t\tCollector:    col,\n\t\t\t\t\t}\n\t\t\t\t\tcsv, err := g.generate()\n\t\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\t\tcol.ClusterServiceVersions = []v1alpha1.ClusterServiceVersion{*(bases.New(operatorName))}\n\t\t\t\t\tcsvExp, err := g.generate()\n\t\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\t\tExpect(csv).To(Equal(csvExp))\n\t\t\t\t})\n\n\t\t\t\tIt(\"should return a default object\", func() {\n\t\t\t\t\tcol.ClusterServiceVersions = []v1alpha1.ClusterServiceVersion{*baseCSV}\n\t\t\t\t\tg = Generator{\n\t\t\t\t\t\tOperatorName: operatorName,\n\t\t\t\t\t\tVersion:      zeroZeroOne,\n\t\t\t\t\t\tCollector:    col,\n\t\t\t\t\t}\n\t\t\t\t\tnewCSV.Annotations[\"createdAt\"] = time.Now().UTC().Format(time.RFC3339)\n\t\t\t\t\tcsv, err := g.generate()\n\t\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\t\tExpect(csv).To(Equal(newCSV))\n\t\t\t\t})\n\t\t\t\tIt(\"should return an object with '.spec.replaces' and '.metadata.annotations['olm.skipRange']'\", func() {\n\t\t\t\t\tbaseCSVUIMetaIn := baseCSVUIMeta.DeepCopy()\n\t\t\t\t\tbaseCSVUIMetaIn.GetAnnotations()[\"olm.skipRange\"] = \"<0.0.2\"\n\t\t\t\t\tbaseCSVUIMetaIn.Spec.Replaces = \"memcached-operator.v0.0.2\"\n\t\t\t\t\tcol.ClusterServiceVersions = []v1alpha1.ClusterServiceVersion{*baseCSVUIMetaIn}\n\t\t\t\t\tg = Generator{\n\t\t\t\t\t\tOperatorName: operatorName,\n\t\t\t\t\t\tVersion:      \"0.0.3\",\n\t\t\t\t\t\tCollector:    col,\n\t\t\t\t\t}\n\t\t\t\t\tcsv, err := g.generate()\n\t\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\t\tcsvExp := newCSVUIMeta.DeepCopy()\n\t\t\t\t\tcsvExp.SetName(\"memcached-operator.v0.0.3\")\n\t\t\t\t\tcsvExp.GetAnnotations()[\"olm.skipRange\"] = \"<0.0.2\"\n\t\t\t\t\tcsvExp.Annotations[\"createdAt\"] = time.Now().UTC().Format(time.RFC3339)\n\t\t\t\t\tcsvExp.Spec.Replaces = \"memcached-operator.v0.0.2\"\n\t\t\t\t\tcsvExp.Spec.Version.Patch = 3\n\t\t\t\t\tExpect(csv).To(Equal(csvExp))\n\t\t\t\t})\n\t\t\t\tIt(\"should return a new object with version set\", func() {\n\t\t\t\t\tcol.ClusterServiceVersions = []v1alpha1.ClusterServiceVersion{*baseCSVUIMeta}\n\t\t\t\t\tg = Generator{\n\t\t\t\t\t\tOperatorName: operatorName,\n\t\t\t\t\t\tVersion:      zeroZeroOne,\n\t\t\t\t\t\tCollector:    col,\n\t\t\t\t\t}\n\t\t\t\t\tnewCSVUIMeta.Annotations[\"createdAt\"] = time.Now().UTC().Format(time.RFC3339)\n\t\t\t\t\tcsv, err := g.generate()\n\t\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\t\tExpect(csv).To(Equal(newCSVUIMeta))\n\t\t\t\t})\n\t\t\t\tIt(\"should return a new object with base version and name preserved\", func() {\n\t\t\t\t\tcol.ClusterServiceVersions = []v1alpha1.ClusterServiceVersion{*newCSVUIMeta}\n\t\t\t\t\tg = Generator{\n\t\t\t\t\t\tOperatorName: operatorName,\n\t\t\t\t\t\tCollector:    col,\n\t\t\t\t\t}\n\t\t\t\t\tnewCSVUIMeta.Annotations[\"createdAt\"] = time.Now().UTC().Format(time.RFC3339)\n\t\t\t\t\tcsv, err := g.generate()\n\t\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\t\tExpect(csv).To(Equal(newCSVUIMeta))\n\t\t\t\t})\n\t\t\t})\n\n\t\t\tContext(\"to update an existing ClusterServiceVersion\", func() {\n\t\t\t\tIt(\"should return an updated object\", func() {\n\t\t\t\t\tg = Generator{\n\t\t\t\t\t\tOperatorName: operatorName,\n\t\t\t\t\t\tVersion:      zeroZeroOne,\n\t\t\t\t\t\tCollector: &collector.Manifests{\n\t\t\t\t\t\t\tClusterServiceVersions: []v1alpha1.ClusterServiceVersion{*newCSVUIMeta},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tAnnotations: map[string]string{\n\t\t\t\t\t\t\t\"createdAt\": time.Now().UTC().Format(time.RFC3339),\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t\t// Update the input's and expected CSV's Deployment image.\n\t\t\t\t\tcollectManifestsFromFileHelper(g.Collector, goBasicOperatorPath)\n\t\t\t\t\tExpect(g.Collector.Deployments).ToNot(BeEmpty())\n\t\t\t\t\timageTag := \"controller:v\" + g.Version\n\t\t\t\t\tmodifyDepImageHelper(&g.Collector.Deployments[0].Spec, imageTag)\n\t\t\t\t\tupdatedCSV := updateCSV(newCSVUIMeta, modifyCSVDepImageHelper(imageTag))\n\n\t\t\t\t\tcsv, err := g.generate()\n\t\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\t\tExpect(csv).To(Equal(updatedCSV))\n\n\t\t\t\t\t// verify if conversion webhooks are added\n\t\t\t\t\tExpect(csv.Spec.WebhookDefinitions).NotTo(BeEmpty())\n\t\t\t\t\tExpect(containsConversionWebhookDefinition(csv.Spec.WebhookDefinitions)).To(BeTrue())\n\t\t\t\t})\n\t\t\t})\n\n\t\t\tContext(\"to upgrade an existing ClusterServiceVersion\", func() {\n\t\t\t\tIt(\"should return an upgraded object\", func() {\n\t\t\t\t\tcol.ClusterServiceVersions = []v1alpha1.ClusterServiceVersion{*newCSVUIMeta}\n\t\t\t\t\tg = Generator{\n\t\t\t\t\t\tOperatorName: operatorName,\n\t\t\t\t\t\tVersion:      zeroZeroTwo,\n\t\t\t\t\t\tCollector:    col,\n\t\t\t\t\t}\n\t\t\t\t\tcsv, err := g.generate()\n\t\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\t\tExpect(csv).To(Equal(upgradeCSV(newCSVUIMeta, g.OperatorName, g.Version)))\n\t\t\t\t})\n\t\t\t})\n\t\t})\n\t})\n\n\tvar _ = Describe(\"Generation requires interaction\", func() {\n\t\tvar (\n\t\t\ttestExistingPath    = filepath.Join(csvBasesDir, \"memcached-operator.clusterserviceversion.yaml\")\n\t\t\ttestNotExistingPath = filepath.Join(csvBasesDir, \"notexist.clusterserviceversion.yaml\")\n\t\t)\n\n\t\tContext(\"when base path does not exist\", func() {\n\t\t\tIt(\"turning interaction off explicitly, it will returns false\", func() {\n\t\t\t\tExpect(requiresInteraction(testNotExistingPath, projutil.InteractiveHardOff)).To(BeFalse())\n\t\t\t})\n\t\t\tIt(\"turning interaction off implicitly, it will returns true\", func() {\n\t\t\t\tExpect(requiresInteraction(testNotExistingPath, projutil.InteractiveSoftOff)).To(BeTrue())\n\t\t\t})\n\t\t\tIt(\"turning interaction on explicitly, it will returns true\", func() {\n\t\t\t\tExpect(requiresInteraction(testNotExistingPath, projutil.InteractiveOnAll)).To(BeTrue())\n\t\t\t})\n\t\t})\n\n\t\tContext(\"when base path does exist\", func() {\n\t\t\tIt(\"turning interaction off explicitly, it will returns false\", func() {\n\t\t\t\tExpect(requiresInteraction(testExistingPath, projutil.InteractiveHardOff)).To(BeFalse())\n\t\t\t})\n\t\t\tIt(\"turning interaction off implicitly, it will returns false\", func() {\n\t\t\t\tExpect(requiresInteraction(testExistingPath, projutil.InteractiveSoftOff)).To(BeFalse())\n\t\t\t})\n\t\t\tIt(\"turning interaction on explicitly, it will returns true\", func() {\n\t\t\t\tExpect(requiresInteraction(testExistingPath, projutil.InteractiveOnAll)).To(BeTrue())\n\t\t\t})\n\t\t})\n\t})\n\n})\n\nvar _ = Describe(\"Testing CRDs with multiple version\", func() {\n\tBeforeEach(func() {\n\t\tcol = &collector.Manifests{}\n\t\tcollectManifestsFromFileHelper(col, goMultiVersionOperatorPath)\n\t\tinitTestMultiVersionCSVHelper()\n\t})\n\n\tvar _ = Describe(\"Generating a clusterserviceVersion\", func() {\n\t\tformat.TruncatedDiff = true\n\t\tformat.UseStringerRepresentation = true\n\n\t\tvar (\n\t\t\tg            Generator\n\t\t\tbuf          *bytes.Buffer\n\t\t\toperatorName = \"memcached-operator\"\n\t\t\tzeroZeroOne  = \"0.0.1\"\n\t\t)\n\n\t\tBeforeEach(func() {\n\t\t\tbuf = &bytes.Buffer{}\n\t\t})\n\n\t\tDescribe(\"for a go project\", func() {\n\t\t\tvar (\n\t\t\t\terr error\n\t\t\t)\n\n\t\t\tBeforeEach(func() {\n\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\tcol.ClusterServiceVersions = []v1alpha1.ClusterServiceVersion{*baseMultiVersionCSV}\n\t\t\t})\n\n\t\t\tAfterEach(func() {\n\t\t\t\tcol.ClusterServiceVersions = nil\n\t\t\t})\n\n\t\t\t// TODO: to verify conversion webhook specifically, this block has just the\n\t\t\t// tests to see if csv is being written cirrectly to io.Writer.\n\t\t\tIt(\"testing clustersevice version being written to io.Writer\", func() {\n\t\t\t\tg = Generator{\n\t\t\t\t\tOperatorName: operatorName,\n\t\t\t\t\tVersion:      zeroZeroOne,\n\t\t\t\t\tCollector:    col,\n\t\t\t\t}\n\t\t\t\topts := []Option{\n\t\t\t\t\tWithWriter(buf),\n\t\t\t\t}\n\t\t\t\tExpect(g.Generate(opts...)).ToNot(HaveOccurred())\n\t\t\t\tExpect(buf.String()).To(MatchYAML(multiVersionCSVStr))\n\t\t\t})\n\n\t\t})\n\n\t})\n})\n\nfunc collectManifestsFromFileHelper(col *collector.Manifests, path string) {\n\tf, err := os.Open(path)\n\tExpectWithOffset(1, err).ToNot(HaveOccurred())\n\tExpectWithOffset(1, col.UpdateFromReader(f)).ToNot(HaveOccurred())\n\tExpectWithOffset(1, f.Close()).Should(Succeed())\n}\n\nfunc initTestCSVsHelper() {\n\tvar err error\n\tpath := filepath.Join(csvBasesDir, \"memcached-operator.clusterserviceversion.yaml\")\n\tbaseCSV, baseCSVStr, err = getCSVFromFile(path)\n\tExpectWithOffset(1, err).ToNot(HaveOccurred())\n\tpath = filepath.Join(csvBasesDir, \"with-ui-metadata.clusterserviceversion.yaml\")\n\tbaseCSVUIMeta, baseCSVUIMetaStr, err = getCSVFromFile(path)\n\tExpectWithOffset(1, err).ToNot(HaveOccurred())\n\tpath = filepath.Join(csvNewLayoutBundleDir, \"memcached-operator.clusterserviceversion.yaml\")\n\tnewCSV, _, err = getCSVFromFile(path)\n\tExpectWithOffset(1, err).ToNot(HaveOccurred())\n\tpath = filepath.Join(csvNewLayoutBundleDir, \"with-ui-metadata.clusterserviceversion.yaml\")\n\tnewCSVUIMeta, newCSVUIMetaStr, err = getCSVFromFile(path)\n\tnewCSVUIMetaStr = strings.ReplaceAll(newCSVUIMetaStr, \"2022-11-08T16:44:38Z\", time.Now().UTC().Format(time.RFC3339))\n\tExpectWithOffset(1, err).ToNot(HaveOccurred())\n}\n\nfunc initTestMultiVersionCSVHelper() {\n\tvar err error\n\tpath := filepath.Join(csvBasesDir, \"memcached-operator-multiVersion.yaml\")\n\tbaseMultiVersionCSV, _, err = getCSVFromFile(path)\n\tExpectWithOffset(1, err).NotTo(HaveOccurred())\n\n\tpath = filepath.Join(csvNewLayoutBundleDir, \"memcached-operator-multiVersion.yaml\")\n\t_, multiVersionCSVStr, err = getCSVFromFile(path)\n\tmultiVersionCSVStr = strings.ReplaceAll(multiVersionCSVStr, \"2022-11-08T16:44:38Z\", time.Now().UTC().Format(time.RFC3339))\n\tExpectWithOffset(1, err).ToNot(HaveOccurred())\n}\n\nfunc readFileHelper(path string) string {\n\tb, err := os.ReadFile(path)\n\tExpectWithOffset(1, err).ToNot(HaveOccurred())\n\treturn string(b)\n}\n\nfunc modifyCSVDepImageHelper(tag string) func(csv *v1alpha1.ClusterServiceVersion) {\n\treturn func(csv *v1alpha1.ClusterServiceVersion) {\n\t\tdepSpecs := csv.Spec.InstallStrategy.StrategySpec.DeploymentSpecs\n\t\tExpectWithOffset(2, depSpecs).ToNot(BeEmpty())\n\t\tmodifyDepImageHelper(&depSpecs[0].Spec, tag)\n\t}\n}\n\nfunc modifyDepImageHelper(depSpec *appsv1.DeploymentSpec, tag string) {\n\tcontainers := depSpec.Template.Spec.Containers\n\tExpectWithOffset(1, containers).ToNot(BeEmpty())\n\tcontainers[0].Image = tag\n}\n\nfunc getCSVFromFile(path string) (*v1alpha1.ClusterServiceVersion, string, error) {\n\tb, err := os.ReadFile(path)\n\tif err != nil {\n\t\treturn nil, \"\", err\n\t}\n\tcsv := &v1alpha1.ClusterServiceVersion{}\n\tif err = yaml.Unmarshal(b, csv); err == nil {\n\t\t// Any updates applied to a CSV object will create non-nil slice type fields,\n\t\t// which cause comparison issues if their counterpart was only unmarshaled.\n\t\tif csv.Spec.InstallStrategy.StrategySpec.Permissions == nil {\n\t\t\tcsv.Spec.InstallStrategy.StrategySpec.Permissions = []v1alpha1.StrategyDeploymentPermissions{}\n\t\t}\n\t\tif csv.Spec.InstallStrategy.StrategySpec.ClusterPermissions == nil {\n\t\t\tcsv.Spec.InstallStrategy.StrategySpec.ClusterPermissions = []v1alpha1.StrategyDeploymentPermissions{}\n\t\t}\n\t\tif csv.Spec.InstallStrategy.StrategySpec.DeploymentSpecs == nil {\n\t\t\tcsv.Spec.InstallStrategy.StrategySpec.DeploymentSpecs = []v1alpha1.StrategyDeploymentSpec{}\n\t\t}\n\t\tif csv.Spec.WebhookDefinitions == nil {\n\t\t\tcsv.Spec.WebhookDefinitions = []v1alpha1.WebhookDescription{}\n\t\t}\n\t}\n\treturn csv, string(b), err\n}\n\nfunc updateCSV(csv *v1alpha1.ClusterServiceVersion,\n\topts ...func(*v1alpha1.ClusterServiceVersion)) *v1alpha1.ClusterServiceVersion {\n\n\tupdated := csv.DeepCopy()\n\tupdated.Annotations[\"createdAt\"] = time.Now().UTC().Format(time.RFC3339)\n\tfor _, opt := range opts {\n\t\topt(updated)\n\t}\n\treturn updated\n}\n\nfunc upgradeCSV(csv *v1alpha1.ClusterServiceVersion, name, version string) *v1alpha1.ClusterServiceVersion {\n\tupgraded := csv.DeepCopy()\n\n\t// Update CSV name and upgrade version.\n\tupgraded.SetName(genutil.MakeCSVName(name, version))\n\tupgraded.Spec.Version = operatorversion.OperatorVersion{Version: semver.MustParse(version)}\n\tupgraded.Annotations[\"createdAt\"] = time.Now().UTC().Format(time.RFC3339)\n\n\treturn upgraded\n}\n\nfunc containsConversionWebhookDefinition(whdef []v1alpha1.WebhookDescription) bool {\n\tfor _, def := range whdef {\n\t\tif def.Type == v1alpha1.ConversionWebhook {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "internal/generate/clusterserviceversion/clusterserviceversion_updaters.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage clusterserviceversion\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"sort\"\n\t\"strings\"\n\t\"time\"\n\n\toperatorsv1alpha1 \"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\t\"github.com/operator-framework/api/pkg/validation\"\n\t\"github.com/operator-framework/operator-registry/pkg/registry\"\n\tlog \"github.com/sirupsen/logrus\"\n\tadmissionregv1 \"k8s.io/api/admissionregistration/v1\"\n\tappsv1 \"k8s.io/api/apps/v1\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\trbacv1 \"k8s.io/api/rbac/v1\"\n\tapiextv1 \"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/generate/collector\"\n\t\"github.com/operator-framework/operator-sdk/internal/util/k8sutil\"\n)\n\n// ApplyTo applies relevant manifests in c to csv, sorts the applied updates,\n// and validates the result.\nfunc ApplyTo(c *collector.Manifests, csv *operatorsv1alpha1.ClusterServiceVersion, extraSAs []string) error {\n\t// Apply manifests to the CSV object.\n\tif err := apply(c, csv, extraSAs); err != nil {\n\t\treturn err\n\t}\n\n\t// Set fields required by namespaced operators. This is a no-op for cluster-scoped operators.\n\tsetNamespacedFields(csv)\n\n\treturn validate(csv)\n}\n\n// apply applies relevant manifests in c to csv.\nfunc apply(c *collector.Manifests, csv *operatorsv1alpha1.ClusterServiceVersion, extraSAs []string) error {\n\tstrategy := getCSVInstallStrategy(csv)\n\tswitch strategy.StrategyName {\n\tcase operatorsv1alpha1.InstallStrategyNameDeployment:\n\t\tinPerms, inCPerms, _ := c.SplitCSVPermissionsObjects(extraSAs)\n\t\tapplyRoles(c, inPerms, &strategy.StrategySpec, extraSAs)\n\t\tapplyClusterRoles(c, inCPerms, &strategy.StrategySpec, extraSAs)\n\t\tapplyDeployments(c, &strategy.StrategySpec)\n\t}\n\tcsv.Spec.InstallStrategy = strategy\n\n\t// Update createdAt timestamp annotation since the CSV has been updated.\n\tcsv.Annotations[\"createdAt\"] = time.Now().UTC().Format(time.RFC3339)\n\n\tapplyCustomResourceDefinitions(c, csv)\n\tif err := applyCustomResources(c, csv); err != nil {\n\t\treturn fmt.Errorf(\"error applying Custom Resource examples to CSV %s: %v\", csv.GetName(), err)\n\t}\n\tapplyWebhooks(c, csv)\n\treturn nil\n}\n\n// Get install strategy from csv.\nfunc getCSVInstallStrategy(csv *operatorsv1alpha1.ClusterServiceVersion) operatorsv1alpha1.NamedInstallStrategy {\n\t// Default to a deployment strategy if none found.\n\tif csv.Spec.InstallStrategy.StrategyName == \"\" {\n\t\tcsv.Spec.InstallStrategy.StrategyName = operatorsv1alpha1.InstallStrategyNameDeployment\n\t}\n\treturn csv.Spec.InstallStrategy\n}\n\n// This service account exists in every namespace as the default.\nconst defaultServiceAccountName = \"default\"\n\n// applyRoles applies Roles to strategy's permissions field by combining Roles bound to ServiceAccounts\n// into one set of permissions.\nfunc applyRoles(c *collector.Manifests, objs []client.Object, strategy *operatorsv1alpha1.StrategyDetailsDeployment, extraSAs []string) { //nolint:dupl\n\troleSet := make(map[string]rbacv1.Role)\n\tcRoleSet := make(map[string]rbacv1.ClusterRole)\n\tfor i := range objs {\n\t\tswitch t := objs[i].(type) {\n\t\tcase *rbacv1.Role:\n\t\t\troleSet[t.GetName()] = *t\n\t\tcase *rbacv1.ClusterRole:\n\t\t\tcRoleSet[t.GetName()] = *t\n\t\t}\n\t}\n\n\t// Collect all role and cluster role names by their corresponding service accounts via bindings. This lets us\n\t// look up all service accounts a role is bound to and create one set of permissions per service account.\n\tsaToPermissions := initPermissionSet(c.Deployments, extraSAs)\n\tfor _, binding := range c.RoleBindings {\n\t\tfor _, subject := range binding.Subjects {\n\t\t\tperm, hasSA := saToPermissions[subject.Name]\n\t\t\tif subject.Kind != \"ServiceAccount\" || !hasSA {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tvar (\n\t\t\t\trules   []rbacv1.PolicyRule\n\t\t\t\thasRole bool\n\t\t\t)\n\t\t\tswitch binding.RoleRef.Kind {\n\t\t\tcase \"Role\":\n\t\t\t\trole, has := roleSet[binding.RoleRef.Name]\n\t\t\t\trules = role.Rules\n\t\t\t\thasRole = has\n\t\t\tcase \"ClusterRole\":\n\t\t\t\trole, has := cRoleSet[binding.RoleRef.Name]\n\t\t\t\trules = role.Rules\n\t\t\t\thasRole = has\n\t\t\tdefault:\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif hasRole {\n\t\t\t\tperm.Rules = append(perm.Rules, rules...)\n\t\t\t\tsaToPermissions[subject.Name] = perm\n\t\t\t}\n\t\t}\n\t}\n\n\t// Apply relevant roles to each service account.\n\tperms := []operatorsv1alpha1.StrategyDeploymentPermissions{}\n\tfor _, perm := range saToPermissions {\n\t\tif len(perm.Rules) != 0 {\n\t\t\tperms = append(perms, perm)\n\t\t}\n\t}\n\tsort.Slice(perms, func(i, j int) bool {\n\t\treturn perms[i].ServiceAccountName < perms[j].ServiceAccountName\n\t})\n\tstrategy.Permissions = perms\n}\n\n// applyClusterRoles applies ClusterRoles to strategy's clusterPermissions field by combining ClusterRoles\n// bound to ServiceAccounts into one set of clusterPermissions.\nfunc applyClusterRoles(c *collector.Manifests, objs []client.Object, strategy *operatorsv1alpha1.StrategyDetailsDeployment, extraSAs []string) { //nolint:dupl\n\troleSet := make(map[string]rbacv1.ClusterRole)\n\tfor i := range objs {\n\t\tswitch t := objs[i].(type) {\n\t\tcase *rbacv1.ClusterRole:\n\t\t\troleSet[t.GetName()] = *t\n\t\t}\n\t}\n\n\t// Collect all role names by their corresponding service accounts via bindings. This lets us\n\t// look up all service accounts a role is bound to and create one set of permissions per service account.\n\tsaToPermissions := initPermissionSet(c.Deployments, extraSAs)\n\tfor _, binding := range c.ClusterRoleBindings {\n\t\tfor _, subject := range binding.Subjects {\n\t\t\tperm, hasSA := saToPermissions[subject.Name]\n\t\t\tif !hasSA || subject.Kind != \"ServiceAccount\" {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif role, hasRole := roleSet[binding.RoleRef.Name]; hasRole {\n\t\t\t\tperm.Rules = append(perm.Rules, role.Rules...)\n\t\t\t\tsaToPermissions[subject.Name] = perm\n\t\t\t}\n\t\t}\n\t}\n\n\t// Apply relevant roles to each service account.\n\tperms := []operatorsv1alpha1.StrategyDeploymentPermissions{}\n\tfor _, perm := range saToPermissions {\n\t\tif len(perm.Rules) != 0 {\n\t\t\tperms = append(perms, perm)\n\t\t}\n\t}\n\tsort.Slice(perms, func(i, j int) bool {\n\t\treturn perms[i].ServiceAccountName < perms[j].ServiceAccountName\n\t})\n\tstrategy.ClusterPermissions = perms\n}\n\n// initPermissionSet initializes a map of ServiceAccount name to permissions, which are empty.\nfunc initPermissionSet(deps []appsv1.Deployment, extraSAs []string) map[string]operatorsv1alpha1.StrategyDeploymentPermissions {\n\tsaToPermissions := make(map[string]operatorsv1alpha1.StrategyDeploymentPermissions)\n\tfor _, dep := range deps {\n\t\tsaName := dep.Spec.Template.Spec.ServiceAccountName\n\t\tif saName == \"\" {\n\t\t\tsaName = defaultServiceAccountName\n\t\t}\n\t\tsaToPermissions[saName] = operatorsv1alpha1.StrategyDeploymentPermissions{ServiceAccountName: saName}\n\t}\n\tfor _, extraSA := range extraSAs {\n\t\tsaToPermissions[extraSA] = operatorsv1alpha1.StrategyDeploymentPermissions{ServiceAccountName: extraSA}\n\t}\n\treturn saToPermissions\n}\n\n// applyDeployments updates strategy's deployments with the Deployments\n// in the collector.\nfunc applyDeployments(c *collector.Manifests, strategy *operatorsv1alpha1.StrategyDetailsDeployment) {\n\tdepSpecs := []operatorsv1alpha1.StrategyDeploymentSpec{}\n\tfor _, dep := range c.Deployments {\n\t\tdepSpecs = append(depSpecs, operatorsv1alpha1.StrategyDeploymentSpec{\n\t\t\tName:  dep.GetName(),\n\t\t\tSpec:  dep.Spec,\n\t\t\tLabel: dep.Labels,\n\t\t})\n\t}\n\tstrategy.DeploymentSpecs = depSpecs\n}\n\nconst (\n\t// WatchNamespaceEnv is a constant for internal use.\n\tWatchNamespaceEnv = \"WATCH_NAMESPACE\"\n\t// TargetNamespacesRef references the target namespaces a CSV is installed in.\n\t// This is required by legacy project Deployments.\n\tTargetNamespacesRef = \"metadata.annotations['olm.targetNamespaces']\"\n)\n\n// setNamespacedFields sets static fields in a CSV required by namespaced\n// operators.\nfunc setNamespacedFields(csv *operatorsv1alpha1.ClusterServiceVersion) {\n\tfor _, dep := range csv.Spec.InstallStrategy.StrategySpec.DeploymentSpecs {\n\t\t// Set WATCH_NAMESPACE if it exists in a deployment spec..\n\t\tenvVar := newFieldRefEnvVar(WatchNamespaceEnv, TargetNamespacesRef)\n\t\tsetContainerEnvVarIfExists(&dep.Spec, envVar)\n\t}\n}\n\n// setContainerEnvVarIfExists overwrites all references to ev.Name with ev.\nfunc setContainerEnvVarIfExists(spec *appsv1.DeploymentSpec, ev corev1.EnvVar) {\n\tfor _, c := range spec.Template.Spec.Containers {\n\t\tfor i := 0; i < len(c.Env); i++ {\n\t\t\tif c.Env[i].Name == ev.Name {\n\t\t\t\tc.Env[i] = ev\n\t\t\t}\n\t\t}\n\t}\n}\n\n// newFieldRefEnvVar creates a new environment variable referencing fieldPath.\nfunc newFieldRefEnvVar(name, fieldPath string) corev1.EnvVar {\n\treturn corev1.EnvVar{\n\t\tName: name,\n\t\tValueFrom: &corev1.EnvVarSource{\n\t\t\tFieldRef: &corev1.ObjectFieldSelector{\n\t\t\t\tFieldPath: fieldPath,\n\t\t\t},\n\t\t},\n\t}\n}\n\n// applyCustomResourceDefinitions updates csv's customresourcedefinitions.owned\n// with CustomResourceDefinitions in the collector.\n// customresourcedefinitions.required are left as-is, since they are\n// manually-defined values.\nfunc applyCustomResourceDefinitions(c *collector.Manifests, csv *operatorsv1alpha1.ClusterServiceVersion) {\n\townedDescs := []operatorsv1alpha1.CRDDescription{}\n\tdescMap := map[registry.DefinitionKey]operatorsv1alpha1.CRDDescription{}\n\tfor _, owned := range csv.Spec.CustomResourceDefinitions.Owned {\n\t\tdefKey := registry.DefinitionKey{\n\t\t\tName:    owned.Name,\n\t\t\tVersion: owned.Version,\n\t\t\tKind:    owned.Kind,\n\t\t}\n\t\tdescMap[defKey] = owned\n\t}\n\n\tvar defKeys []registry.DefinitionKey\n\tv1crdKeys := k8sutil.DefinitionsForV1CustomResourceDefinitions(c.V1CustomResourceDefinitions...)\n\tdefKeys = append(defKeys, v1crdKeys...)\n\tv1beta1crdKeys := k8sutil.DefinitionsForV1beta1CustomResourceDefinitions(c.V1beta1CustomResourceDefinitions...)\n\tdefKeys = append(defKeys, v1beta1crdKeys...)\n\t// crdDescriptions don't have a 'group' field.\n\tfor i := 0; i < len(defKeys); i++ {\n\t\tdefKeys[i].Group = \"\"\n\t}\n\n\tfor _, defKey := range defKeys {\n\t\tif owned, ownedExists := descMap[defKey]; ownedExists {\n\t\t\townedDescs = append(ownedDescs, owned)\n\t\t} else {\n\t\t\townedDescs = append(ownedDescs, operatorsv1alpha1.CRDDescription{\n\t\t\t\tName:    defKey.Name,\n\t\t\t\tVersion: defKey.Version,\n\t\t\t\tKind:    defKey.Kind,\n\t\t\t})\n\t\t}\n\t}\n\n\tcsv.Spec.CustomResourceDefinitions.Owned = ownedDescs\n}\n\n// applyWebhooks updates csv's webhookDefinitions with any mutating and validating webhooks in the collector.\nfunc applyWebhooks(c *collector.Manifests, csv *operatorsv1alpha1.ClusterServiceVersion) {\n\twebhookDescriptions := []operatorsv1alpha1.WebhookDescription{}\n\n\tfor _, webhook := range c.ValidatingWebhooks {\n\t\tvar validatingServiceName string\n\t\tdepName, svc := findMatchingDeploymentAndServiceForWebhook(c, webhook.ClientConfig)\n\n\t\tif svc != nil {\n\t\t\tvalidatingServiceName = svc.GetName()\n\t\t}\n\n\t\tif validatingServiceName == \"\" && depName == \"\" {\n\t\t\tlog.Infof(\"No service found for validating webhook %q\", webhook.Name)\n\t\t} else if depName == \"\" {\n\t\t\tlog.Infof(\"No deployment is selected by service %q for validating webhook %q\", validatingServiceName, webhook.Name)\n\t\t}\n\t\twebhookDescriptions = append(webhookDescriptions, validatingToWebhookDescription(webhook, depName, svc))\n\t}\n\tfor _, webhook := range c.MutatingWebhooks {\n\t\tvar mutatingServiceName string\n\t\tdepName, svc := findMatchingDeploymentAndServiceForWebhook(c, webhook.ClientConfig)\n\n\t\tif svc != nil {\n\t\t\tmutatingServiceName = svc.GetName()\n\t\t}\n\n\t\tif mutatingServiceName == \"\" && depName == \"\" {\n\t\t\tlog.Infof(\"No service found for mutating webhook %q\", webhook.Name)\n\t\t} else if depName == \"\" {\n\t\t\tlog.Infof(\"No deployment is selected by service %q for mutating webhook %q\", mutatingServiceName, webhook.Name)\n\t\t}\n\t\twebhookDescriptions = append(webhookDescriptions, mutatingToWebhookDescription(webhook, depName, svc))\n\t}\n\n\tfor _, svc := range c.Services {\n\t\tcrdToConfigMap := getConvWebhookCRDNamesAndConfig(c, svc.GetName())\n\n\t\tif len(crdToConfigMap) != 0 {\n\t\t\tdepName := findMatchingDepNameFromService(c, &svc)\n\t\t\tdes := conversionToWebhookDescription(crdToConfigMap, depName, &svc)\n\t\t\twebhookDescriptions = append(webhookDescriptions, des...)\n\t\t}\n\t}\n\t// Sorts the WebhookDescriptions based on natural order of webhookDescriptions Type\n\tsort.Slice(webhookDescriptions, func(i, j int) bool {\n\t\treturn webhookDescriptions[i].GenerateName < webhookDescriptions[j].GenerateName\n\t})\n\tcsv.Spec.WebhookDefinitions = webhookDescriptions\n}\n\n// conversionToWebhookDescription takes in a map of {crdNames, apiextv.WebhookConversion} and groups\n// all the crds with same port and path. It then creates a webhook description for each unique combination of\n// port and path.\n// For example: if we have the following map: {crd1:[portX+pathX], crd2: [portX+pathX], crd3: [portY:partY]},\n// we will create 2 webhook descriptions: one with [portX+pathX]:[crd1, crd2] and the other with [portY:pathY]:[crd3]\nfunc conversionToWebhookDescription(crdToConfig map[string]apiextv1.WebhookConversion, depName string, ws *corev1.Service) []operatorsv1alpha1.WebhookDescription {\n\tdes := make([]operatorsv1alpha1.WebhookDescription, 0)\n\n\t// this is a map of serviceportAndPath configs, and the respective CRDs.\n\twebhookDescriptions := crdGroups(crdToConfig)\n\n\tfor serviceConfig, crds := range webhookDescriptions {\n\t\t// we need this to get the conversionReviewVersions.\n\t\t// here, we assume all crds having same servicePortAndPath config will have\n\t\t// same conversion review versions.\n\t\tconfig, ok := crdToConfig[crds[0]]\n\t\tif !ok {\n\t\t\tlog.Infof(\"Webhook config for CRD %q not found\", crds[0])\n\t\t\tcontinue\n\t\t}\n\n\t\tdescription := operatorsv1alpha1.WebhookDescription{\n\t\t\tType:                    operatorsv1alpha1.ConversionWebhook,\n\t\t\tConversionCRDs:          crds,\n\t\t\tAdmissionReviewVersions: config.ConversionReviewVersions,\n\t\t\tWebhookPath:             &serviceConfig.Path,\n\t\t\tDeploymentName:          depName,\n\t\t\tGenerateName:            getGenerateName(crds),\n\t\t\tSideEffects: func() *admissionregv1.SideEffectClass {\n\t\t\t\tseNone := admissionregv1.SideEffectClassNone\n\t\t\t\treturn &seNone\n\t\t\t}(),\n\t\t}\n\n\t\tif len(description.AdmissionReviewVersions) == 0 {\n\t\t\tlog.Infof(\"ConversionReviewVersion not found for the deployment %q\", depName)\n\t\t}\n\n\t\tvar webhookServiceRefPort int32 = 443\n\n\t\tif serviceConfig.Port != nil {\n\t\t\twebhookServiceRefPort = *serviceConfig.Port\n\t\t}\n\n\t\tif ws != nil {\n\t\t\tfor _, port := range ws.Spec.Ports {\n\t\t\t\tif webhookServiceRefPort == port.Port {\n\t\t\t\t\tdescription.ContainerPort = port.Port\n\t\t\t\t\tdescription.TargetPort = &port.TargetPort\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif description.DeploymentName == \"\" {\n\t\t\tif config.ClientConfig.Service != nil {\n\t\t\t\tdescription.DeploymentName = strings.TrimSuffix(config.ClientConfig.Service.Name, \"-service\")\n\t\t\t}\n\t\t}\n\n\t\tdescription.WebhookPath = &serviceConfig.Path\n\t\tdes = append(des, description)\n\t}\n\n\treturn des\n}\n\n// serviceportPath is refers to the group of webhook service and\n// path names and port.\ntype serviceportPath struct {\n\tPort *int32\n\tPath string\n}\n\n// crdGroups groups the crds with similar service port and name. It returns a map of serviceportPath\n// and the corresponding crd names.\nfunc crdGroups(crdToConfig map[string]apiextv1.WebhookConversion) map[serviceportPath][]string {\n\n\tuniqueConfig := make(map[serviceportPath][]string)\n\n\tfor crdName, config := range crdToConfig {\n\t\tserviceportPath := serviceportPath{\n\t\t\tPort: config.ClientConfig.Service.Port,\n\t\t\tPath: *config.ClientConfig.Service.Path,\n\t\t}\n\n\t\tuniqueConfig[serviceportPath] = append(uniqueConfig[serviceportPath], crdName)\n\t}\n\n\treturn uniqueConfig\n}\n\nfunc getConvWebhookCRDNamesAndConfig(c *collector.Manifests, serviceName string) map[string]apiextv1.WebhookConversion {\n\tif serviceName == \"\" {\n\t\treturn nil\n\t}\n\n\tcrdToConfig := make(map[string]apiextv1.WebhookConversion)\n\n\tfor _, crd := range c.V1CustomResourceDefinitions {\n\t\tif crd.Spec.Conversion != nil {\n\t\t\twhConv := crd.Spec.Conversion.Webhook\n\t\t\tif whConv != nil && whConv.ClientConfig != nil && whConv.ClientConfig.Service != nil {\n\t\t\t\tif whConv.ClientConfig.Service.Name == serviceName {\n\t\t\t\t\tcrdToConfig[crd.GetName()] = *whConv\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfor _, crd := range c.V1beta1CustomResourceDefinitions {\n\t\twhConv := crd.Spec.Conversion\n\t\tif whConv != nil && whConv.WebhookClientConfig != nil && whConv.WebhookClientConfig.Service != nil {\n\t\t\tif whConv.WebhookClientConfig.Service.Name == serviceName {\n\t\t\t\tv1whConv := apiextv1.WebhookConversion{\n\t\t\t\t\tClientConfig:             &apiextv1.WebhookClientConfig{Service: &apiextv1.ServiceReference{}},\n\t\t\t\t\tConversionReviewVersions: crd.Spec.Conversion.ConversionReviewVersions,\n\t\t\t\t}\n\t\t\t\tif path := whConv.WebhookClientConfig.Service.Path; path != nil {\n\t\t\t\t\tv1whConv.ClientConfig.Service.Path = new(string)\n\t\t\t\t\t*v1whConv.ClientConfig.Service.Path = *path\n\t\t\t\t}\n\t\t\t\tcrdToConfig[crd.GetName()] = v1whConv\n\t\t\t}\n\t\t}\n\t}\n\treturn crdToConfig\n}\n\n// The default AdmissionReviewVersions set in a CSV if not set in the source webhook.\nvar defaultAdmissionReviewVersions = []string{\"v1beta1\"}\n\n// validatingToWebhookDescription transforms webhook into a WebhookDescription.\nfunc validatingToWebhookDescription(webhook admissionregv1.ValidatingWebhook, depName string, ws *corev1.Service) operatorsv1alpha1.WebhookDescription {\n\tdescription := operatorsv1alpha1.WebhookDescription{\n\t\tType:                    operatorsv1alpha1.ValidatingAdmissionWebhook,\n\t\tGenerateName:            webhook.Name,\n\t\tRules:                   webhook.Rules,\n\t\tFailurePolicy:           webhook.FailurePolicy,\n\t\tMatchPolicy:             webhook.MatchPolicy,\n\t\tObjectSelector:          webhook.ObjectSelector,\n\t\tSideEffects:             webhook.SideEffects,\n\t\tTimeoutSeconds:          webhook.TimeoutSeconds,\n\t\tAdmissionReviewVersions: webhook.AdmissionReviewVersions,\n\t}\n\tif len(description.AdmissionReviewVersions) == 0 {\n\t\tdescription.AdmissionReviewVersions = defaultAdmissionReviewVersions\n\t}\n\tif description.SideEffects == nil {\n\t\tseNone := admissionregv1.SideEffectClassNone\n\t\tdescription.SideEffects = &seNone\n\t}\n\n\tif serviceRef := webhook.ClientConfig.Service; serviceRef != nil {\n\t\tvar webhookServiceRefPort int32 = 443\n\t\tif serviceRef.Port != nil {\n\t\t\twebhookServiceRefPort = *serviceRef.Port\n\t\t}\n\t\tif ws != nil {\n\t\t\tfor _, port := range ws.Spec.Ports {\n\t\t\t\tif webhookServiceRefPort == port.Port {\n\t\t\t\t\tdescription.ContainerPort = port.Port\n\t\t\t\t\tdescription.TargetPort = &port.TargetPort\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tdescription.DeploymentName = depName\n\t\tif description.DeploymentName == \"\" {\n\t\t\tdescription.DeploymentName = strings.TrimSuffix(serviceRef.Name, \"-service\")\n\t\t}\n\t\tdescription.WebhookPath = serviceRef.Path\n\t}\n\treturn description\n}\n\n// mutatingToWebhookDescription transforms webhook into a WebhookDescription.\nfunc mutatingToWebhookDescription(webhook admissionregv1.MutatingWebhook, depName string, ws *corev1.Service) operatorsv1alpha1.WebhookDescription {\n\tdescription := operatorsv1alpha1.WebhookDescription{\n\t\tType:                    operatorsv1alpha1.MutatingAdmissionWebhook,\n\t\tGenerateName:            webhook.Name,\n\t\tRules:                   webhook.Rules,\n\t\tFailurePolicy:           webhook.FailurePolicy,\n\t\tMatchPolicy:             webhook.MatchPolicy,\n\t\tObjectSelector:          webhook.ObjectSelector,\n\t\tSideEffects:             webhook.SideEffects,\n\t\tTimeoutSeconds:          webhook.TimeoutSeconds,\n\t\tAdmissionReviewVersions: webhook.AdmissionReviewVersions,\n\t\tReinvocationPolicy:      webhook.ReinvocationPolicy,\n\t}\n\tif len(description.AdmissionReviewVersions) == 0 {\n\t\tdescription.AdmissionReviewVersions = defaultAdmissionReviewVersions\n\t}\n\tif description.SideEffects == nil {\n\t\tseNone := admissionregv1.SideEffectClassNone\n\t\tdescription.SideEffects = &seNone\n\t}\n\n\tif serviceRef := webhook.ClientConfig.Service; serviceRef != nil {\n\t\tvar webhookServiceRefPort int32 = 443\n\t\tif serviceRef.Port != nil {\n\t\t\twebhookServiceRefPort = *serviceRef.Port\n\t\t}\n\t\tif ws != nil {\n\t\t\tfor _, port := range ws.Spec.Ports {\n\t\t\t\tif webhookServiceRefPort == port.Port {\n\t\t\t\t\tdescription.ContainerPort = port.Port\n\t\t\t\t\tdescription.TargetPort = &port.TargetPort\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tdescription.DeploymentName = depName\n\t\tif description.DeploymentName == \"\" {\n\t\t\tdescription.DeploymentName = strings.TrimSuffix(serviceRef.Name, \"-service\")\n\t\t}\n\t\tdescription.WebhookPath = serviceRef.Path\n\t}\n\treturn description\n}\n\n// findMatchingDeploymentAndServiceForWebhook matches a Service to a webhook's client config (if it uses a service)\n// and uses that service to find the deployment name.\nfunc findMatchingDeploymentAndServiceForWebhook(c *collector.Manifests, wcc admissionregv1.WebhookClientConfig) (depName string, ws *corev1.Service) {\n\t// Return if a service reference is not specified, since a URL will be in that case.\n\tif wcc.Service == nil {\n\t\treturn depName, ws\n\t}\n\n\t// Find the matching service, if any. The webhook server may be externally managed\n\t// if no service is created by the operator.\n\tfor i, service := range c.Services {\n\t\tif service.GetName() == wcc.Service.Name {\n\t\t\tws = &c.Services[i]\n\t\t\tbreak\n\t\t}\n\t}\n\tif ws == nil {\n\t\treturn depName, ws\n\t}\n\n\t// Only ExternalName-type services cannot have selectors.\n\tif ws.Spec.Type == corev1.ServiceTypeExternalName {\n\t\treturn depName, ws\n\t}\n\n\t// If a selector does not exist, there is either an Endpoint or EndpointSlice object accompanying\n\t// the service so it should not be added to the CSV.\n\tif len(ws.Spec.Selector) == 0 {\n\t\treturn depName, ws\n\t}\n\n\tdepName = findMatchingDepNameFromService(c, ws)\n\n\treturn depName, ws\n}\n\n// findMatchingDepNameFromService matches the provided service to a deployment by comparing label selectors (if\n// Service uses label selectors).\nfunc findMatchingDepNameFromService(c *collector.Manifests, ws *corev1.Service) (depName string) {\n\t// Match service against pod labels, in which the webhook server will be running\n\tfor _, dep := range c.Deployments {\n\t\tpodTemplateLabels := dep.Spec.Template.GetLabels()\n\t\tif len(podTemplateLabels) == 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\tdepName = dep.GetName()\n\t\t// Check that all labels match.\n\t\tfor key, serviceValue := range ws.Spec.Selector {\n\t\t\tif podTemplateValue, hasKey := podTemplateLabels[key]; !hasKey || podTemplateValue != serviceValue {\n\t\t\t\tdepName = \"\"\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif depName != \"\" {\n\t\t\tbreak\n\t\t}\n\t}\n\treturn depName\n}\n\n// applyCustomResources updates csv's \"alm-examples\" annotation with the\n// Custom Resources in the collector.\nfunc applyCustomResources(c *collector.Manifests, csv *operatorsv1alpha1.ClusterServiceVersion) error {\n\texamples := []json.RawMessage{}\n\tfor _, cr := range c.CustomResources {\n\t\tcrBytes, err := cr.MarshalJSON()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\texamples = append(examples, json.RawMessage(crBytes))\n\t}\n\n\texamplesJSON, err := json.MarshalIndent(examples, \"\", \"  \")\n\tif err != nil {\n\t\treturn err\n\t}\n\tif csv.GetAnnotations() == nil {\n\t\tcsv.SetAnnotations(make(map[string]string))\n\t}\n\tcsv.GetAnnotations()[\"alm-examples\"] = string(examplesJSON)\n\n\treturn nil\n}\n\n// validate will validate csv using the api validation library.\n// More info: https://github.com/operator-framework/api\nfunc validate(csv *operatorsv1alpha1.ClusterServiceVersion) error {\n\tif csv == nil {\n\t\treturn errors.New(\"empty ClusterServiceVersion\")\n\t}\n\n\thasErrors := false\n\tresults := validation.ClusterServiceVersionValidator.Validate(csv)\n\tfor _, r := range results {\n\t\tfor _, w := range r.Warnings {\n\t\t\tlog.Warnf(\"ClusterServiceVersion validation: [%s] %s\", w.Type, w.Detail)\n\t\t}\n\t\tfor _, e := range r.Errors {\n\t\t\tlog.Errorf(\"ClusterServiceVersion validation: [%s] %s\", e.Type, e.Detail)\n\t\t}\n\t\tif r.HasError() {\n\t\t\thasErrors = true\n\t\t}\n\t}\n\tif hasErrors {\n\t\treturn errors.New(\"invalid generated ClusterServiceVersion\")\n\t}\n\n\treturn nil\n}\n\n// generateName takes in a list of crds, and returns a conversion webhook generator name.\nfunc getGenerateName(crds []string) string {\n\tsort.Strings(crds)\n\tjoinedResourceNames := strings.Builder{}\n\n\tfor _, name := range crds {\n\t\tif name != \"\" {\n\t\t\tjoinedResourceNames.WriteString(strings.Split(name, \".\")[0])\n\t\t}\n\t}\n\treturn fmt.Sprintf(\"c%s.kb.io\", joinedResourceNames.String())\n}\n"
  },
  {
    "path": "internal/generate/clusterserviceversion/clusterserviceversion_updaters_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage clusterserviceversion\n\nimport (\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\toperatorsv1alpha1 \"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\tadmissionregv1 \"k8s.io/api/admissionregistration/v1\"\n\tappsv1 \"k8s.io/api/apps/v1\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\trbacv1 \"k8s.io/api/rbac/v1\"\n\tapiextv1 \"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1\"\n\tapiextv1beta1 \"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1\"\n\t\"k8s.io/apimachinery/pkg/labels\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/generate/collector\"\n)\n\nvar _ = Describe(\"apply functions\", func() {\n\tvar (\n\t\tc        *collector.Manifests\n\t\tstrategy *operatorsv1alpha1.StrategyDetailsDeployment\n\t)\n\n\tDescribe(\"applyDeployments\", func() {\n\t\tconst (\n\t\t\tdepName = \"dep-1\"\n\t\t)\n\n\t\tBeforeEach(func() {\n\t\t\tc = &collector.Manifests{}\n\t\t\tstrategy = &operatorsv1alpha1.StrategyDetailsDeployment{}\n\t\t})\n\n\t\tContext(\"collector contains Deployments\", func() {\n\t\t\tIt(\"applies the deployment labels\", func() {\n\t\t\t\tlabels := labels.Set{}\n\t\t\t\tlabels[\"foo\"] = \"bar\"\n\n\t\t\t\tc.Deployments = []appsv1.Deployment{newDeploymentWithLabels(depName, labels)}\n\t\t\t\tapplyDeployments(c, strategy)\n\t\t\t\tExpect(strategy.DeploymentSpecs).To(HaveLen(1))\n\t\t\t\tExpect(strategy.DeploymentSpecs[0].Label).To(Equal(labels))\n\t\t\t})\n\t\t})\n\t})\n\n\tDescribe(\"apply{Cluster}Roles\", func() {\n\t\tconst (\n\t\t\tdepName1   = \"dep-1\"\n\t\t\tsaName1    = \"service-account-1\"\n\t\t\troleName1  = \"role-1\"\n\t\t\tcRoleName1 = \"cluster-role-1\"\n\t\t)\n\n\t\tBeforeEach(func() {\n\t\t\tc = &collector.Manifests{}\n\t\t\tstrategy = &operatorsv1alpha1.StrategyDetailsDeployment{}\n\t\t})\n\n\t\tContext(\"collector contains {Cluster}Roles\", func() {\n\t\t\tIt(\"adds one Role's rules to the CSV deployment strategy\", func() {\n\t\t\t\tc.Deployments = []appsv1.Deployment{newDeploymentWithServiceAccount(depName1, saName1)}\n\t\t\t\tc.ServiceAccounts = []corev1.ServiceAccount{newServiceAccount(saName1)}\n\t\t\t\trules := []rbacv1.PolicyRule{{Verbs: []string{\"create\"}}}\n\t\t\t\tperms := []client.Object{newRole(roleName1, rules...)}\n\t\t\t\tc.RoleBindings = []rbacv1.RoleBinding{newRoleBinding(\"role-binding\", newRoleRef(roleName1), newServiceAccountSubject(saName1))}\n\t\t\t\tapplyRoles(c, perms, strategy, nil)\n\t\t\t\tExpect(strategy.Permissions).To(Equal([]operatorsv1alpha1.StrategyDeploymentPermissions{\n\t\t\t\t\t{ServiceAccountName: saName1, Rules: rules},\n\t\t\t\t}))\n\t\t\t})\n\t\t\tIt(\"adds one ClusterRole's rules to the CSV deployment strategy\", func() {\n\t\t\t\tc.Deployments = []appsv1.Deployment{newDeploymentWithServiceAccount(depName1, saName1)}\n\t\t\t\tc.ServiceAccounts = []corev1.ServiceAccount{newServiceAccount(saName1)}\n\t\t\t\trules := []rbacv1.PolicyRule{{Verbs: []string{\"create\"}}}\n\t\t\t\tperms := []client.Object{newClusterRole(cRoleName1, rules...)}\n\t\t\t\tc.ClusterRoleBindings = []rbacv1.ClusterRoleBinding{newClusterRoleBinding(\"cluster-role-binding\", newClusterRoleRef(cRoleName1), newServiceAccountSubject(saName1))}\n\t\t\t\tapplyClusterRoles(c, perms, strategy, nil)\n\t\t\t\tExpect(strategy.ClusterPermissions).To(Equal([]operatorsv1alpha1.StrategyDeploymentPermissions{\n\t\t\t\t\t{ServiceAccountName: saName1, Rules: rules},\n\t\t\t\t}))\n\t\t\t})\n\t\t\tIt(\"adds multiple bound {Cluster}Roles to the CSV deployment strategy with extra service account\", func() {\n\t\t\t\troleName2, roleName3 := \"role-2\", \"role-3\"\n\t\t\t\tcRoleName2, cRoleName3 := \"cluster-role-2\", \"cluster-role-3\"\n\t\t\t\textraSAName := \"service-account-extra\"\n\t\t\t\tc.Deployments = []appsv1.Deployment{newDeploymentWithServiceAccount(depName1, saName1)}\n\t\t\t\tc.ServiceAccounts = []corev1.ServiceAccount{\n\t\t\t\t\tnewServiceAccount(saName1),\n\t\t\t\t\tnewServiceAccount(extraSAName),\n\t\t\t\t}\n\t\t\t\trules := []rbacv1.PolicyRule{{Verbs: []string{\"create\"}}}\n\t\t\t\trole3Rules := []rbacv1.PolicyRule{{APIGroups: []string{\"my.group\"}, Verbs: []string{\"update\"}}}\n\t\t\t\tcRole3Rules := []rbacv1.PolicyRule{{APIGroups: []string{\"my.group\"}, Verbs: []string{\"list\", \"watch\"}}}\n\t\t\t\tperms := []client.Object{\n\t\t\t\t\tnewRole(roleName1, rules...),\n\t\t\t\t\tnewRole(roleName2, rules...),\n\t\t\t\t\tnewRole(roleName3, role3Rules...),\n\t\t\t\t\tnewClusterRole(cRoleName1, rules...),\n\t\t\t\t\tnewClusterRole(cRoleName2, rules...),\n\t\t\t\t}\n\t\t\t\tcperms := []client.Object{\n\t\t\t\t\tnewClusterRole(cRoleName1, rules...),\n\t\t\t\t\tnewClusterRole(cRoleName3, cRole3Rules...),\n\t\t\t\t}\n\t\t\t\tc.RoleBindings = []rbacv1.RoleBinding{\n\t\t\t\t\tnewRoleBinding(\"role-binding\", newRoleRef(roleName1), newServiceAccountSubject(saName1)),\n\t\t\t\t\tnewRoleBinding(\"role-binding-2\", newRoleRef(roleName2), newServiceAccountSubject(extraSAName)),\n\t\t\t\t\tnewRoleBinding(\"role-binding-3\", newClusterRoleRef(cRoleName3), newServiceAccountSubject(extraSAName)),\n\t\t\t\t}\n\t\t\t\tc.ClusterRoleBindings = []rbacv1.ClusterRoleBinding{\n\t\t\t\t\tnewClusterRoleBinding(\"cluster-role-binding\", newClusterRoleRef(cRoleName1), newServiceAccountSubject(saName1)),\n\t\t\t\t\tnewClusterRoleBinding(\"cluster-role-binding-2\", newClusterRoleRef(cRoleName2), newServiceAccountSubject(extraSAName)),\n\t\t\t\t\tnewClusterRoleBinding(\"cluster-role-binding-3\", newClusterRoleRef(cRoleName3), newServiceAccountSubject(extraSAName)),\n\t\t\t\t}\n\t\t\t\tapplyRoles(c, perms, strategy, []string{extraSAName})\n\t\t\t\tapplyClusterRoles(c, cperms, strategy, []string{extraSAName})\n\t\t\t\tExpect(strategy.Permissions).To(Equal([]operatorsv1alpha1.StrategyDeploymentPermissions{\n\t\t\t\t\t{ServiceAccountName: saName1, Rules: rules},\n\t\t\t\t\t{ServiceAccountName: extraSAName, Rules: rules},\n\t\t\t\t}))\n\t\t\t\tExpect(strategy.ClusterPermissions).To(Equal([]operatorsv1alpha1.StrategyDeploymentPermissions{\n\t\t\t\t\t{ServiceAccountName: saName1, Rules: rules},\n\t\t\t\t\t{ServiceAccountName: extraSAName, Rules: cRole3Rules},\n\t\t\t\t}))\n\t\t\t})\n\t\t})\n\n\t\tContext(\"collector contains no {Cluster}Roles\", func() {\n\t\t\tIt(\"adds no Permissions to the CSV deployment strategy\", func() {\n\t\t\t\tc.Deployments = []appsv1.Deployment{newDeploymentWithServiceAccount(depName1, saName1)}\n\t\t\t\tc.ServiceAccounts = []corev1.ServiceAccount{newServiceAccount(saName1)}\n\t\t\t\tc.RoleBindings = []rbacv1.RoleBinding{newRoleBinding(\"role-binding\", newRoleRef(roleName1), newServiceAccountSubject(saName1))}\n\t\t\t\tapplyRoles(c, nil, strategy, nil)\n\t\t\t\tExpect(strategy.Permissions).To(Equal([]operatorsv1alpha1.StrategyDeploymentPermissions{}))\n\t\t\t})\n\t\t\tIt(\"adds no ClusterPermissions to the CSV deployment strategy\", func() {\n\t\t\t\tc.Deployments = []appsv1.Deployment{newDeploymentWithServiceAccount(depName1, saName1)}\n\t\t\t\tc.ServiceAccounts = []corev1.ServiceAccount{newServiceAccount(saName1)}\n\t\t\t\tc.ClusterRoleBindings = []rbacv1.ClusterRoleBinding{newClusterRoleBinding(\"cluster-role-binding\", newClusterRoleRef(cRoleName1), newServiceAccountSubject(saName1))}\n\t\t\t\tapplyClusterRoles(c, nil, strategy, nil)\n\t\t\t\tExpect(strategy.ClusterPermissions).To(Equal([]operatorsv1alpha1.StrategyDeploymentPermissions{}))\n\t\t\t})\n\t\t})\n\t})\n})\n\nvar _ = Describe(\"applyCustomResourceDefinitions\", func() {\n\tvar c *collector.Manifests\n\n\tcsv := operatorsv1alpha1.ClusterServiceVersion{\n\t\tSpec: operatorsv1alpha1.ClusterServiceVersionSpec{\n\t\t\tCustomResourceDefinitions: operatorsv1alpha1.CustomResourceDefinitions{\n\t\t\t\tOwned: []operatorsv1alpha1.CRDDescription{\n\t\t\t\t\t{\n\t\t\t\t\t\tName:    \"test1\",\n\t\t\t\t\t\tVersion: \"v1\",\n\t\t\t\t\t\tKind:    \"Memcached\",\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tName:    \"test1\",\n\t\t\t\t\t\tVersion: \"v1beta1\",\n\t\t\t\t\t\tKind:    \"Memcached\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tIt(\"should add all CRDs present in collector and specified in CSV\", func() {\n\t\tc = &collector.Manifests{}\n\t\tcrd1 := apiextv1.CustomResourceDefinition{\n\t\t\tSpec: apiextv1.CustomResourceDefinitionSpec{\n\t\t\t\tGroup: \"Test\",\n\t\t\t\tNames: apiextv1.CustomResourceDefinitionNames{\n\t\t\t\t\tKind: \"Memcached\",\n\t\t\t\t},\n\t\t\t\tVersions: []apiextv1.CustomResourceDefinitionVersion{\n\t\t\t\t\t{\n\t\t\t\t\t\tName:   \"v1\",\n\t\t\t\t\t\tServed: true,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tName:   \"v1beta1\",\n\t\t\t\t\t\tServed: true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}}\n\t\tcrd1.SetName(\"test1\")\n\n\t\tc.V1CustomResourceDefinitions = []apiextv1.CustomResourceDefinition{crd1}\n\n\t\tapplyCustomResourceDefinitions(c, &csv)\n\n\t\tBy(\"test if csv has the required owned crds applied\")\n\t\townedDes := csv.Spec.CustomResourceDefinitions.Owned\n\t\tExpect(len(ownedDes)).To(BeEquivalentTo(2))\n\t\tExpect(ownedDes).To(ContainElements(operatorsv1alpha1.CRDDescription{\n\t\t\tName:    \"test1\",\n\t\t\tVersion: \"v1\",\n\t\t\tKind:    \"Memcached\",\n\t\t}, operatorsv1alpha1.CRDDescription{\n\t\t\tName:    \"test1\",\n\t\t\tVersion: \"v1beta1\",\n\t\t\tKind:    \"Memcached\",\n\t\t}))\n\t})\n\n\tIt(\"should not add unserved v1CRDs\", func() {\n\t\tc = &collector.Manifests{}\n\t\tcrd1 := apiextv1.CustomResourceDefinition{\n\t\t\tSpec: apiextv1.CustomResourceDefinitionSpec{\n\t\t\t\tGroup: \"Test\",\n\t\t\t\tNames: apiextv1.CustomResourceDefinitionNames{\n\t\t\t\t\tKind: \"Memcached\",\n\t\t\t\t},\n\t\t\t\tVersions: []apiextv1.CustomResourceDefinitionVersion{\n\t\t\t\t\t{\n\t\t\t\t\t\tName:   \"v1\",\n\t\t\t\t\t\tServed: true,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tName:   \"v1beta1\",\n\t\t\t\t\t\tServed: false,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}}\n\t\tcrd1.SetName(\"test1\")\n\n\t\tc.V1CustomResourceDefinitions = []apiextv1.CustomResourceDefinition{crd1}\n\n\t\tapplyCustomResourceDefinitions(c, &csv)\n\n\t\tBy(\"test if deprecated crds are not added\")\n\t\townedDes := csv.Spec.CustomResourceDefinitions.Owned\n\t\tExpect(len(ownedDes)).To(BeEquivalentTo(1))\n\t\tExpect(ownedDes).To(ContainElement(operatorsv1alpha1.CRDDescription{\n\t\t\tName:    \"test1\",\n\t\t\tVersion: \"v1\",\n\t\t\tKind:    \"Memcached\",\n\t\t}))\n\t})\n\n\tIt(\"should not add unserved v1beta1CRDs\", func() {\n\t\tc = &collector.Manifests{}\n\n\t\tcrd1 := apiextv1beta1.CustomResourceDefinition{\n\t\t\tSpec: apiextv1beta1.CustomResourceDefinitionSpec{\n\t\t\t\tGroup: \"Test\",\n\t\t\t\tNames: apiextv1beta1.CustomResourceDefinitionNames{\n\t\t\t\t\tKind: \"Memcached\",\n\t\t\t\t},\n\t\t\t\tVersions: []apiextv1beta1.CustomResourceDefinitionVersion{\n\t\t\t\t\t{\n\t\t\t\t\t\tName:   \"v2\",\n\t\t\t\t\t\tServed: true,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tName:   \"v1beta1\",\n\t\t\t\t\t\tServed: false,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\n\t\tcrd1.SetName(\"test1\")\n\n\t\tc.V1beta1CustomResourceDefinitions = []apiextv1beta1.CustomResourceDefinition{crd1}\n\n\t\tapplyCustomResourceDefinitions(c, &csv)\n\n\t\tBy(\"test if deprecated crds are not added\")\n\t\townedDes := csv.Spec.CustomResourceDefinitions.Owned\n\t\tExpect(len(ownedDes)).To(BeEquivalentTo(1))\n\t\tExpect(ownedDes).To(ContainElement(operatorsv1alpha1.CRDDescription{\n\t\t\tName:    \"test1\",\n\t\t\tVersion: \"v2\",\n\t\t\tKind:    \"Memcached\",\n\t\t}))\n\t})\n})\n\nvar _ = Describe(\"findMatchingDeploymentAndServiceForWebhook\", func() {\n\n\tvar (\n\t\tc   *collector.Manifests\n\t\twcc admissionregv1.WebhookClientConfig\n\n\t\tdepName1     = \"dep-name-1\"\n\t\tdepName2     = \"dep-name-2\"\n\t\tserviceName1 = \"service-name-1\"\n\t\tserviceName2 = \"service-name-2\"\n\t)\n\n\tBeforeEach(func() {\n\t\tc = &collector.Manifests{}\n\t\twcc = admissionregv1.WebhookClientConfig{}\n\t\twcc.Service = &admissionregv1.ServiceReference{}\n\t})\n\n\tContext(\"webhook config has a matching service name\", func() {\n\t\tIt(\"parsing one deployment and one service with one label, it will returns the first service and deployment\", func() {\n\t\t\tlabels := map[string]string{\"operator-name\": \"test-operator\"}\n\t\t\tc.Deployments = []appsv1.Deployment{newDeployment(depName1, labels)}\n\t\t\tc.Services = []corev1.Service{newService(serviceName1, labels)}\n\t\t\twcc.Service.Name = serviceName1\n\t\t\tdepName, service := findMatchingDeploymentAndServiceForWebhook(c, wcc)\n\t\t\tExpect(depName).To(Equal(depName1))\n\t\t\tExpect(service.GetName()).To(Equal(serviceName1))\n\t\t})\n\n\t\tIt(\"parsing two deployments and two services with non-intersecting labels, it will returns the first service and deployment\", func() {\n\t\t\tlabels1 := map[string]string{\"operator-name\": \"test-operator\"}\n\t\t\tlabels2 := map[string]string{\"foo\": \"bar\"}\n\t\t\tc.Deployments = []appsv1.Deployment{\n\t\t\t\tnewDeployment(depName1, labels1),\n\t\t\t\tnewDeployment(depName2, labels2),\n\t\t\t}\n\t\t\tc.Services = []corev1.Service{\n\t\t\t\tnewService(serviceName1, labels1),\n\t\t\t\tnewService(serviceName2, labels2),\n\t\t\t}\n\t\t\twcc.Service.Name = serviceName1\n\t\t\tdepName, service := findMatchingDeploymentAndServiceForWebhook(c, wcc)\n\t\t\tExpect(depName).To(Equal(depName1))\n\t\t\tExpect(service.GetName()).To(Equal(serviceName1))\n\t\t})\n\n\t\tIt(\"parsing two deployments and two services with a label subset, it will returns the first service and second deployment\", func() {\n\t\t\tlabels1 := map[string]string{\"operator-name\": \"test-operator\"}\n\t\t\tlabels2 := map[string]string{\"operator-name\": \"test-operator\", \"foo\": \"bar\"}\n\t\t\tc.Deployments = []appsv1.Deployment{\n\t\t\t\tnewDeployment(depName2, labels2),\n\t\t\t\tnewDeployment(depName1, labels1),\n\t\t\t}\n\t\t\tc.Services = []corev1.Service{newService(serviceName1, labels1)}\n\t\t\twcc.Service.Name = serviceName1\n\t\t\tdepName, service := findMatchingDeploymentAndServiceForWebhook(c, wcc)\n\t\t\tExpect(depName).To(Equal(depName2))\n\t\t\tExpect(service.GetName()).To(Equal(serviceName1))\n\t\t})\n\t})\n\n\tContext(\"webhook config does not have a matching service\", func() {\n\t\tIt(\"parsing one deployment and one service with one label, it will returns neither service nor deployment name\", func() {\n\t\t\tlabels := map[string]string{\"operator-name\": \"test-operator\"}\n\t\t\tc.Deployments = []appsv1.Deployment{newDeployment(depName1, labels)}\n\t\t\tc.Services = []corev1.Service{newService(serviceName1, labels)}\n\t\t\twcc.Service.Name = serviceName2\n\t\t\tdepName, service := findMatchingDeploymentAndServiceForWebhook(c, wcc)\n\t\t\tExpect(depName).To(BeEmpty())\n\t\t\tExpect(service).To(BeNil())\n\t\t})\n\t})\n\n\tContext(\"webhook config has a matching service but labels do not match\", func() {\n\t\tIt(\"parsing one deployment and one service with one label, it will returns the first service and no deployment\", func() {\n\t\t\tlabels1 := map[string]string{\"operator-name\": \"test-operator\"}\n\t\t\tlabels2 := map[string]string{\"foo\": \"bar\"}\n\t\t\tc.Deployments = []appsv1.Deployment{newDeployment(depName1, labels1)}\n\t\t\tc.Services = []corev1.Service{newService(serviceName1, labels2)}\n\t\t\twcc.Service.Name = serviceName1\n\t\t\tdepName, service := findMatchingDeploymentAndServiceForWebhook(c, wcc)\n\t\t\tExpect(depName).To(BeEmpty())\n\t\t\tExpect(service.GetName()).To(Equal(serviceName1))\n\t\t})\n\n\t\tIt(\"parsing one deployment and one service with two intersecting labels, it will returns the first service and no deployment\", func() {\n\t\t\tlabels1 := map[string]string{\"operator-name\": \"test-operator\", \"foo\": \"bar\"}\n\t\t\tlabels2 := map[string]string{\"foo\": \"bar\", \"baz\": \"bat\"}\n\t\t\tc.Deployments = []appsv1.Deployment{newDeployment(depName1, labels1)}\n\t\t\tc.Services = []corev1.Service{newService(serviceName1, labels2)}\n\t\t\twcc.Service.Name = serviceName1\n\t\t\tdepName, service := findMatchingDeploymentAndServiceForWebhook(c, wcc)\n\t\t\tExpect(depName).To(BeEmpty())\n\t\t\tExpect(service.GetName()).To(Equal(serviceName1))\n\t\t})\n\t})\n\n\tContext(\"crdGroups\", func() {\n\t\tpath1 := \"/whPath\"\n\t\tport1 := new(int32)\n\t\t*port1 = 2311\n\t\tcrdToConfigPath := map[string]apiextv1.WebhookConversion{\n\t\t\t\"crd-test-1\": {\n\t\t\t\tClientConfig: &apiextv1.WebhookClientConfig{\n\t\t\t\t\tService: &apiextv1.ServiceReference{\n\t\t\t\t\t\tPath: &path1,\n\t\t\t\t\t\tPort: port1,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\n\t\t\t\"crd-test-2\": {\n\t\t\t\tClientConfig: &apiextv1.WebhookClientConfig{\n\t\t\t\t\tService: &apiextv1.ServiceReference{\n\t\t\t\t\t\tPath: &path1,\n\t\t\t\t\t\tPort: port1,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\n\t\tval := crdGroups(crdToConfigPath)\n\n\t\tExpect(len(val)).To(BeEquivalentTo(1))\n\n\t\ttest := serviceportPath{\n\t\t\tPort: port1,\n\t\t\tPath: path1,\n\t\t}\n\n\t\tg := val[test]\n\n\t\tExpect(g).NotTo(BeNil())\n\t\tExpect(len(g)).To(BeEquivalentTo(2))\n\t\tExpect(g).To(ContainElement(\"crd-test-2\"))\n\t\tExpect(g).To(ContainElement(\"crd-test-1\"))\n\n\t})\n\n})\n\nfunc newDeployment(name string, podLabels map[string]string) (dep appsv1.Deployment) {\n\tdep.SetGroupVersionKind(appsv1.SchemeGroupVersion.WithKind(\"Deployment\"))\n\tdep.SetName(name)\n\tdep.Spec.Template.SetLabels(podLabels)\n\treturn dep\n}\n\nfunc newService(name string, labels map[string]string) (s corev1.Service) {\n\ts.SetGroupVersionKind(corev1.SchemeGroupVersion.WithKind(\"Service\"))\n\ts.SetName(name)\n\ts.Spec.Selector = labels\n\treturn s\n}\n\n//nolint:unparam\nfunc newServiceAccount(name string) (s corev1.ServiceAccount) {\n\ts.SetGroupVersionKind(corev1.SchemeGroupVersion.WithKind(\"ServiceAccount\"))\n\ts.SetName(name)\n\treturn s\n}\n\n//nolint:unparam\nfunc newDeploymentWithServiceAccount(name, saName string) (d appsv1.Deployment) {\n\td = newDeployment(name, nil)\n\td.Spec.Template.Spec.ServiceAccountName = saName\n\treturn d\n}\n\n// newDeploymentWithLabels returns a deployment with the given labels\nfunc newDeploymentWithLabels(name string, labels labels.Set) appsv1.Deployment {\n\td := newDeployment(name, nil)\n\td.Labels = labels\n\treturn d\n}\n\nfunc newRole(name string, rules ...rbacv1.PolicyRule) (r *rbacv1.Role) {\n\tr = &rbacv1.Role{}\n\tr.SetGroupVersionKind(rbacv1.SchemeGroupVersion.WithKind(\"Role\"))\n\tr.SetName(name)\n\tr.Rules = rules\n\treturn r\n}\n\nfunc newClusterRole(name string, rules ...rbacv1.PolicyRule) (r *rbacv1.ClusterRole) {\n\tr = &rbacv1.ClusterRole{}\n\tr.SetGroupVersionKind(rbacv1.SchemeGroupVersion.WithKind(\"ClusterRole\"))\n\tr.SetName(name)\n\tr.Rules = rules\n\treturn r\n}\n\nfunc newRoleBinding(name string, ref rbacv1.RoleRef, subjects ...rbacv1.Subject) (r rbacv1.RoleBinding) {\n\tr.SetGroupVersionKind(rbacv1.SchemeGroupVersion.WithKind(\"RoleBinding\"))\n\tr.SetName(name)\n\tr.RoleRef = ref\n\tr.Subjects = subjects\n\treturn r\n}\n\nfunc newClusterRoleBinding(name string, ref rbacv1.RoleRef, subjects ...rbacv1.Subject) (r rbacv1.ClusterRoleBinding) {\n\tr.SetGroupVersionKind(rbacv1.SchemeGroupVersion.WithKind(\"ClusterRoleBinding\"))\n\tr.SetName(name)\n\tr.RoleRef = ref\n\tr.Subjects = subjects\n\treturn r\n}\n\nfunc newRef(name, kind, apiGroup string) (s rbacv1.RoleRef) {\n\ts.Name = name\n\ts.Kind = kind\n\ts.APIGroup = apiGroup\n\treturn s\n}\n\nfunc newRoleRef(name string) (s rbacv1.RoleRef) {\n\treturn newRef(name, \"Role\", rbacv1.SchemeGroupVersion.Group)\n}\n\nfunc newClusterRoleRef(name string) (s rbacv1.RoleRef) {\n\treturn newRef(name, \"ClusterRole\", rbacv1.SchemeGroupVersion.Group)\n}\n\nfunc newSubject(name, kind string) (s rbacv1.Subject) {\n\ts.Name = name\n\ts.Kind = kind\n\treturn s\n}\n\n//nolint:unparam\nfunc newServiceAccountSubject(name string) rbacv1.Subject {\n\treturn newSubject(name, \"ServiceAccount\")\n}\n"
  },
  {
    "path": "internal/generate/collector/clusterserviceversion.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage collector\n\nimport (\n\trbacv1 \"k8s.io/api/rbac/v1\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client\"\n)\n\n// TODO(estroz): there's a significant amount of code dupliation here, a byproduct of Go's type system.\n// However at least a few bits can be refactored so each method is smaller.\n\nconst (\n\t// This service account exists in every namespace as the default.\n\tdefaultServiceAccountName = \"default\"\n\n\tserviceAccountKind = \"ServiceAccount\"\n\troleKind           = \"Role\"\n\tcRoleKind          = \"ClusterRole\"\n)\n\n// SplitCSVPermissionsObjects splits Roles and ClusterRoles bound to ServiceAccounts in Deployments and extraSA's.\n// Roles and ClusterRoles bound to RoleBindings associated with ServiceAccounts are added to inPerms.\n// ClusterRoles bound to ClusterRoleBindings associated with ServiceAccounts are added to inCPerms.\n// All Roles and ClusterRoles not bound to a relevant ServiceAccount, and bindings without a relevant ServiceAccount,\n// are added to out. Any bindings with some associations, but with non-associations, are added to out unmodified.\nfunc (c *Manifests) SplitCSVPermissionsObjects(extraSAs []string) (inPerms, inCPerms, out []client.Object) {\n\t// Create a set of ServiceAccount names to match against below.\n\tcsvSAs := make(map[string]struct{})\n\tfor _, dep := range c.Deployments {\n\t\tsaName := dep.Spec.Template.Spec.ServiceAccountName\n\t\tif saName == \"\" {\n\t\t\tsaName = defaultServiceAccountName\n\t\t}\n\t\tcsvSAs[saName] = struct{}{}\n\t}\n\tfor _, extraSA := range extraSAs {\n\t\tcsvSAs[extraSA] = struct{}{}\n\t}\n\n\t// Construct sets for lookups.\n\troleMap := make(map[string]*rbacv1.Role, len(c.Roles))\n\troleNameMap := make(map[string]struct{}, len(c.Roles))\n\tfor i, r := range c.Roles {\n\t\troleMap[r.GetName()] = &c.Roles[i]\n\t\troleNameMap[r.GetName()] = struct{}{}\n\t}\n\tcRoleMap := make(map[string]*rbacv1.ClusterRole, len(c.ClusterRoles))\n\tcRoleNameMap := make(map[string]struct{}, len(c.ClusterRoles))\n\tfor i, r := range c.ClusterRoles {\n\t\tcRoleMap[r.GetName()] = &c.ClusterRoles[i]\n\t\tcRoleNameMap[r.GetName()] = struct{}{}\n\t}\n\tpRoleBindings := make(partialBindings, len(c.RoleBindings))\n\troleBindingMap := make(map[string]*rbacv1.RoleBinding, len(c.RoleBindings))\n\tfor i, binding := range c.RoleBindings {\n\t\tpRoleBindings[i].Name = binding.GetName()\n\t\tpRoleBindings[i].RoleRef = binding.RoleRef\n\t\tpRoleBindings[i].Subjects = make([]rbacv1.Subject, len(binding.Subjects))\n\t\tcopy(pRoleBindings[i].Subjects, binding.Subjects)\n\t\troleBindingMap[binding.GetName()] = &c.RoleBindings[i]\n\t}\n\tpCRoleBindings := make(partialBindings, len(c.ClusterRoleBindings))\n\tcRoleBindingMap := make(map[string]*rbacv1.ClusterRoleBinding, len(c.ClusterRoleBindings))\n\tfor i, binding := range c.ClusterRoleBindings {\n\t\tpCRoleBindings[i].Name = binding.GetName()\n\t\tpCRoleBindings[i].RoleRef = binding.RoleRef\n\t\tpCRoleBindings[i].Subjects = make([]rbacv1.Subject, len(binding.Subjects))\n\t\tcopy(pCRoleBindings[i].Subjects, binding.Subjects)\n\t\tcRoleBindingMap[binding.GetName()] = &c.ClusterRoleBindings[i]\n\t}\n\n\t// getRolesBoundToPartialBindings will remove\n\t// bound Subjects from partial bindings to easily find concrete bindings that bind non-CSV RBAC.\n\t// Those with no Subjects left will be removed from the partial binding lists; their concrete counterparts should\n\t// be added to out.\n\tinRoleNames := pRoleBindings.getRolesBoundToPartialBindings(roleKind, roleNameMap, csvSAs)\n\tinCRoleNamesNScope := pRoleBindings.getRolesBoundToPartialBindings(cRoleKind, cRoleNameMap, csvSAs)\n\tinCRoleNamesCScope := pCRoleBindings.getRolesBoundToPartialBindings(cRoleKind, cRoleNameMap, csvSAs)\n\n\t// Add {Cluster}Roles bound to a ServiceAccount to either namespace- or cluster-scoped permission sets.\n\tfor _, roleName := range inRoleNames {\n\t\tinPerms = append(inPerms, roleMap[roleName])\n\t\tdelete(roleMap, roleName)\n\t}\n\tfor _, roleName := range inCRoleNamesNScope {\n\t\tinPerms = append(inPerms, cRoleMap[roleName])\n\t}\n\tfor _, roleName := range inCRoleNamesCScope {\n\t\tinCPerms = append(inCPerms, cRoleMap[roleName])\n\t}\n\t// Delete afterwards so both namespace- and cluster-scoped ClusterRoles can be added.\n\tfor _, roleName := range append(inCRoleNamesNScope, inCRoleNamesCScope...) {\n\t\tdelete(cRoleMap, roleName)\n\t}\n\n\t// Add all {Cluster}Roles not used above and all remaining bindings to out.\n\tfor _, role := range roleMap {\n\t\tout = append(out, role)\n\t}\n\tfor _, role := range cRoleMap {\n\t\tout = append(out, role)\n\t}\n\tfor _, pBinding := range pRoleBindings {\n\t\tout = append(out, roleBindingMap[pBinding.Name])\n\t}\n\tfor _, pBinding := range pCRoleBindings {\n\t\tout = append(out, cRoleBindingMap[pBinding.Name])\n\t}\n\n\t// All ServiceAccounts not in the CSV should be in out.\n\tfor i := range c.ServiceAccounts {\n\t\tsa := c.ServiceAccounts[i]\n\t\tif _, csvHasSA := csvSAs[sa.Name]; !csvHasSA {\n\t\t\tout = append(out, &sa)\n\t\t}\n\t}\n\n\treturn inPerms, inCPerms, out\n}\n\n// partialBinding is a \"generic\" binding.\ntype partialBinding struct {\n\tName     string\n\tRoleRef  rbacv1.RoleRef\n\tSubjects []rbacv1.Subject\n}\n\ntype partialBindings []partialBinding\n\n// getRolesBoundToPartialBindings returns a list of role names for type refKind (one of Role, ClusterRole) in roleNameMap\n// that are bound to a binding in pBindings with a ServiceAccount subject with a name in saNames.\nfunc (pBindings *partialBindings) getRolesBoundToPartialBindings(refKind string, roleNameMap, saNames map[string]struct{}) (inNames []string) {\n\n\tfor i := 0; i < len(*pBindings); i++ {\n\t\tbinding := (*pBindings)[i]\n\t\tref := binding.RoleRef\n\t\t_, hasRoleName := roleNameMap[ref.Name]\n\t\tif !hasRoleName || ref.Kind != refKind || !acceptRefGroup(ref.APIGroup) {\n\t\t\tcontinue\n\t\t}\n\t\taddRole := false\n\t\tfor j := 0; j < len(binding.Subjects); j++ {\n\t\t\tsubject := binding.Subjects[j]\n\t\t\tif _, hasSA := saNames[subject.Name]; hasSA && subject.Kind == serviceAccountKind {\n\t\t\t\taddRole = true\n\t\t\t\tbinding.Subjects = append(binding.Subjects[:j], binding.Subjects[j+1:]...)\n\t\t\t\tj--\n\t\t\t}\n\t\t}\n\t\t// At least one ServiceAccount of this binding in saNames was found, so add the role's name.\n\t\tif addRole {\n\t\t\tinNames = append(inNames, ref.Name)\n\t\t}\n\t\tif len(binding.Subjects) == 0 && len(*pBindings) > 0 {\n\t\t\t*pBindings = append((*pBindings)[:i], (*pBindings)[i+1:]...)\n\t\t\ti--\n\t\t}\n\t}\n\n\treturn inNames\n}\n\nfunc acceptRefGroup(apiGroup string) bool {\n\treturn apiGroup == \"\" || apiGroup == rbacv1.SchemeGroupVersion.Group\n}\n"
  },
  {
    "path": "internal/generate/collector/clusterserviceversion_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n//nolint:dupl\npackage collector\n\nimport (\n\t\"sort\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\tappsv1 \"k8s.io/api/apps/v1\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\trbacv1 \"k8s.io/api/rbac/v1\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client\"\n)\n\nvar _ = Describe(\"SplitCSVPermissionsObjects\", func() {\n\tvar c *Manifests\n\tvar inPerm, inCPerm, out []client.Object\n\n\tBeforeEach(func() {\n\t\tc = &Manifests{}\n\t})\n\n\tIt(\"returns empty lists for an empty Manifests\", func() {\n\t\tc.Roles = []rbacv1.Role{}\n\t\tinPerm, inCPerm, out = c.SplitCSVPermissionsObjects(nil)\n\t\tExpect(inPerm).To(BeEmpty())\n\t\tExpect(inCPerm).To(BeEmpty())\n\t\tExpect(out).To(BeEmpty())\n\t})\n\n\tIt(\"splitting 1 Role no RoleBinding\", func() {\n\t\tc.Roles = []rbacv1.Role{newRole(\"my-role\")}\n\t\tinPerm, inCPerm, out = c.SplitCSVPermissionsObjects(nil)\n\t\tExpect(inPerm).To(BeEmpty())\n\t\tExpect(inCPerm).To(BeEmpty())\n\t\tExpect(out).To(HaveLen(1))\n\t\tExpect(getRoleNames(out)).To(Equal([]string{\"my-role\"}))\n\t})\n\n\tIt(\"splitting 1 Role 1 RoleBinding with 1 Subject not containing Deployment serviceAccountName\", func() {\n\t\tc.Deployments = []appsv1.Deployment{newDeploymentWithServiceAccount(\"my-dep-account\")}\n\t\tc.Roles = []rbacv1.Role{newRole(\"my-role\")}\n\t\tc.RoleBindings = []rbacv1.RoleBinding{\n\t\t\tnewRoleBinding(\"my-role-binding\", newRoleRef(\"my-role\"), newServiceAccountSubject(\"my-other-account\")),\n\t\t}\n\t\tinPerm, inCPerm, out = c.SplitCSVPermissionsObjects(nil)\n\t\tExpect(inPerm).To(BeEmpty())\n\t\tExpect(inCPerm).To(BeEmpty())\n\t\tExpect(out).To(HaveLen(2))\n\t\tExpect(getRoleNames(out)).To(Equal([]string{\"my-role\"}))\n\t\tExpect(getRoleBindingNames(out)).To(Equal([]string{\"my-role-binding\"}))\n\t})\n\n\tIt(\"splitting 1 ClusterRole 1 RoleBinding with 1 Subject not containing Deployment serviceAccountName\", func() {\n\t\tc.Deployments = []appsv1.Deployment{newDeploymentWithServiceAccount(\"my-dep-account\")}\n\t\tc.ClusterRoles = []rbacv1.ClusterRole{newClusterRole(\"my-role\")}\n\t\tc.RoleBindings = []rbacv1.RoleBinding{\n\t\t\tnewRoleBinding(\"my-role-binding\", newClusterRoleRef(\"my-role\"), newServiceAccountSubject(\"my-other-account\")),\n\t\t}\n\t\tinPerm, inCPerm, out = c.SplitCSVPermissionsObjects(nil)\n\t\tExpect(inPerm).To(BeEmpty())\n\t\tExpect(inCPerm).To(BeEmpty())\n\t\tExpect(out).To(HaveLen(2))\n\t\tExpect(getClusterRoleNames(out)).To(Equal([]string{\"my-role\"}))\n\t\tExpect(getRoleBindingNames(out)).To(Equal([]string{\"my-role-binding\"}))\n\t})\n\n\tIt(\"splitting 1 Role 1 ClusterRole 1 RoleBinding with 1 Subject not containing Deployment serviceAccountName\", func() {\n\t\tc.Deployments = []appsv1.Deployment{newDeploymentWithServiceAccount(\"my-dep-account\")}\n\t\tc.Roles = []rbacv1.Role{newRole(\"my-role\")}\n\t\tc.ClusterRoles = []rbacv1.ClusterRole{newClusterRole(\"my-role\")}\n\t\tc.RoleBindings = []rbacv1.RoleBinding{\n\t\t\tnewRoleBinding(\"my-role-binding-1\", newRoleRef(\"my-role\"), newServiceAccountSubject(\"my-other-account\")),\n\t\t\tnewRoleBinding(\"my-role-binding-2\", newClusterRoleRef(\"my-role\"), newServiceAccountSubject(\"my-other-account\")),\n\t\t}\n\t\tinPerm, inCPerm, out = c.SplitCSVPermissionsObjects(nil)\n\t\tExpect(inPerm).To(BeEmpty())\n\t\tExpect(inCPerm).To(BeEmpty())\n\t\tExpect(out).To(HaveLen(4))\n\t\tExpect(getRoleNames(out)).To(Equal([]string{\"my-role\"}))\n\t\tExpect(getClusterRoleNames(out)).To(Equal([]string{\"my-role\"}))\n\t\tExpect(getRoleBindingNames(out)).To(Equal([]string{\"my-role-binding-1\", \"my-role-binding-2\"}))\n\t})\n\n\tIt(\"splitting 1 Role 1 RoleBinding with 1 Subject containing a Deployment serviceAccountName\", func() {\n\t\tc.Deployments = []appsv1.Deployment{newDeploymentWithServiceAccount(\"my-dep-account\")}\n\t\tc.Roles = []rbacv1.Role{newRole(\"my-role\")}\n\t\tc.RoleBindings = []rbacv1.RoleBinding{\n\t\t\tnewRoleBinding(\"my-role-binding\", newRoleRef(\"my-role\"), newServiceAccountSubject(\"my-dep-account\")),\n\t\t}\n\t\tinPerm, inCPerm, out = c.SplitCSVPermissionsObjects(nil)\n\t\tExpect(inPerm).To(HaveLen(1))\n\t\tExpect(getRoleNames(inPerm)).To(Equal([]string{\"my-role\"}))\n\t\tExpect(inCPerm).To(BeEmpty())\n\t\tExpect(out).To(BeEmpty())\n\t})\n\n\tIt(\"splitting 1 ClusterRole 1 RoleBinding with 1 Subject containing a Deployment serviceAccountName\", func() {\n\t\tc.Deployments = []appsv1.Deployment{newDeploymentWithServiceAccount(\"my-dep-account\")}\n\t\tc.ClusterRoles = []rbacv1.ClusterRole{newClusterRole(\"my-role\")}\n\t\tc.RoleBindings = []rbacv1.RoleBinding{\n\t\t\tnewRoleBinding(\"my-role-binding\", newClusterRoleRef(\"my-role\"), newServiceAccountSubject(\"my-dep-account\")),\n\t\t}\n\t\tinPerm, inCPerm, out = c.SplitCSVPermissionsObjects(nil)\n\t\tExpect(inPerm).To(HaveLen(1))\n\t\tExpect(getClusterRoleNames(inPerm)).To(Equal([]string{\"my-role\"}))\n\t\tExpect(inCPerm).To(BeEmpty())\n\t\tExpect(out).To(BeEmpty())\n\t})\n\n\tIt(\"splitting 1 Role 1 ClusterRole 1 RoleBinding with 1 Subject containing a Deployment serviceAccountName\", func() {\n\t\tc.Deployments = []appsv1.Deployment{newDeploymentWithServiceAccount(\"my-dep-account\")}\n\t\tc.Roles = []rbacv1.Role{newRole(\"my-role\")}\n\t\tc.ClusterRoles = []rbacv1.ClusterRole{newClusterRole(\"my-role\")}\n\t\tc.RoleBindings = []rbacv1.RoleBinding{\n\t\t\tnewRoleBinding(\"my-role-binding-1\", newRoleRef(\"my-role\"), newServiceAccountSubject(\"my-dep-account\")),\n\t\t\tnewRoleBinding(\"my-role-binding-2\", newClusterRoleRef(\"my-role\"), newServiceAccountSubject(\"my-dep-account\")),\n\t\t}\n\t\tinPerm, inCPerm, out = c.SplitCSVPermissionsObjects(nil)\n\t\tExpect(inPerm).To(HaveLen(2))\n\t\tExpect(getRoleNames(inPerm)).To(Equal([]string{\"my-role\"}))\n\t\tExpect(getClusterRoleNames(inPerm)).To(Equal([]string{\"my-role\"}))\n\t\tExpect(inCPerm).To(BeEmpty())\n\t\tExpect(out).To(BeEmpty())\n\t})\n\n\tIt(\"splitting 1 Role 1 ClusterRole 1 RoleBinding with 2 Subjects containing a Deployment serviceAccountName\", func() {\n\t\tc.Deployments = []appsv1.Deployment{newDeploymentWithServiceAccount(\"my-dep-account\")}\n\t\tc.Roles = []rbacv1.Role{newRole(\"my-role\")}\n\t\tc.ClusterRoles = []rbacv1.ClusterRole{newClusterRole(\"my-role\")}\n\t\tc.RoleBindings = []rbacv1.RoleBinding{\n\t\t\tnewRoleBinding(\"my-role-binding-1\", newRoleRef(\"my-role\"), newServiceAccountSubject(\"my-other-account\"), newServiceAccountSubject(\"my-dep-account\")),\n\t\t\tnewRoleBinding(\"my-role-binding-2\", newClusterRoleRef(\"my-role\"), newServiceAccountSubject(\"my-dep-account\")),\n\t\t}\n\t\tinPerm, inCPerm, out = c.SplitCSVPermissionsObjects(nil)\n\t\tExpect(inPerm).To(HaveLen(2))\n\t\tExpect(getRoleNames(inPerm)).To(Equal([]string{\"my-role\"}))\n\t\tExpect(getClusterRoleNames(inPerm)).To(Equal([]string{\"my-role\"}))\n\t\tExpect(out).To(HaveLen(1))\n\t\tExpect(getRoleBindingNames(out)).To(Equal([]string{\"my-role-binding-1\"}))\n\t})\n\n\tContext(\"multiple relationship RBAC\", func() {\n\t\tdepSA, extraSA := \"my-dep-account\", \"my-other-account\"\n\t\troleName1, roleName2 := \"my-role-1\", \"my-role-2\"\n\t\tbindingName1, bindingName2, bindingName3 := \"my-role-binding-1\", \"my-role-binding-2\", \"my-role-binding-3\"\n\n\t\tcomplexTestSetup := func() {\n\t\t\tc.Deployments = []appsv1.Deployment{newDeploymentWithServiceAccount(depSA)}\n\t\t\tc.ServiceAccounts = []corev1.ServiceAccount{\n\t\t\t\tnewServiceAccount(depSA),\n\t\t\t\tnewServiceAccount(extraSA),\n\t\t\t}\n\t\t\trole1, role2 := newRole(roleName1), newRole(roleName2)\n\t\t\tc.Roles = []rbacv1.Role{role1, role2}\n\t\t\t// Use the same names as for Roles to make sure Kind is respected\n\t\t\tcRole1, cRole2 := newClusterRole(roleName1), newClusterRole(roleName2)\n\t\t\tc.ClusterRoles = []rbacv1.ClusterRole{cRole1, cRole2}\n\n\t\t\t// Binds role 1 to depSA,extraSA, role 2 to extraSA, and clusterrole 1 to depSA.\n\t\t\tc.RoleBindings = []rbacv1.RoleBinding{\n\t\t\t\tnewRoleBinding(bindingName1,\n\t\t\t\t\tnewRoleRef(role1.Name),\n\t\t\t\t\tnewServiceAccountSubject(depSA), newServiceAccountSubject(extraSA)),\n\t\t\t\tnewRoleBinding(bindingName2,\n\t\t\t\t\tnewRoleRef(role2.Name),\n\t\t\t\t\tnewServiceAccountSubject(extraSA)),\n\t\t\t\tnewRoleBinding(bindingName3,\n\t\t\t\t\tnewClusterRoleRef(cRole1.Name),\n\t\t\t\t\tnewServiceAccountSubject(depSA)),\n\t\t\t}\n\n\t\t\t// Binds clusterrole 1 to depSA and clusterrole 2 to extraSA.\n\t\t\tc.ClusterRoleBindings = []rbacv1.ClusterRoleBinding{\n\t\t\t\tnewClusterRoleBinding(bindingName1,\n\t\t\t\t\tnewClusterRoleRef(cRole1.Name),\n\t\t\t\t\tnewServiceAccountSubject(depSA)),\n\t\t\t\tnewClusterRoleBinding(bindingName2,\n\t\t\t\t\tnewClusterRoleRef(cRole2.Name),\n\t\t\t\t\tnewServiceAccountSubject(extraSA)),\n\t\t\t}\n\t\t}\n\n\t\tIt(\"contains a Deployment serviceAccountName only\", func() {\n\t\t\tcomplexTestSetup()\n\t\t\tinPerm, inCPerm, out = c.SplitCSVPermissionsObjects(nil)\n\t\t\tExpect(inPerm).To(HaveLen(2))\n\t\t\tExpect(getRoleNames(inPerm)).To(Equal([]string{roleName1}))\n\t\t\tExpect(getClusterRoleNames(inPerm)).To(Equal([]string{roleName1}))\n\t\t\tExpect(inCPerm).To(HaveLen(1))\n\t\t\tExpect(getClusterRoleNames(inCPerm)).To(Equal([]string{roleName1}))\n\t\t\tExpect(out).To(HaveLen(6))\n\t\t\tExpect(getRoleNames(out)).To(Equal([]string{roleName2}))\n\t\t\tExpect(getClusterRoleNames(out)).To(Equal([]string{roleName2}))\n\t\t\tExpect(getRoleBindingNames(out)).To(Equal([]string{bindingName1, bindingName2}))\n\t\t\tExpect(getClusterRoleBindingNames(out)).To(Equal([]string{bindingName2}))\n\t\t\tExpect(getServiceAccountNames(out)).To(Equal([]string{extraSA}))\n\t\t})\n\n\t\tIt(\"contains a Deployment serviceAccountName and extra ServiceAccount\", func() {\n\t\t\tcomplexTestSetup()\n\t\t\tinPerm, inCPerm, out = c.SplitCSVPermissionsObjects([]string{extraSA})\n\t\t\tExpect(inPerm).To(HaveLen(3))\n\t\t\tExpect(getRoleNames(inPerm)).To(Equal([]string{roleName1, roleName2}))\n\t\t\tExpect(getClusterRoleNames(inPerm)).To(Equal([]string{roleName1}))\n\t\t\tExpect(inCPerm).To(HaveLen(2))\n\t\t\tExpect(getClusterRoleNames(inCPerm)).To(Equal([]string{roleName1, roleName2}))\n\t\t\tExpect(out).To(BeEmpty())\n\t\t})\n\t})\n})\n\nfunc getRoleNames(objs []client.Object) []string {\n\treturn getNamesForKind(\"Role\", objs)\n}\n\nfunc getRoleBindingNames(objs []client.Object) []string {\n\treturn getNamesForKind(\"RoleBinding\", objs)\n}\n\nfunc getClusterRoleNames(objs []client.Object) []string {\n\treturn getNamesForKind(\"ClusterRole\", objs)\n}\n\nfunc getClusterRoleBindingNames(objs []client.Object) []string {\n\treturn getNamesForKind(\"ClusterRoleBinding\", objs)\n}\n\nfunc getServiceAccountNames(objs []client.Object) []string {\n\treturn getNamesForKind(\"ServiceAccount\", objs)\n}\n\nfunc getNamesForKind(kind string, objs []client.Object) (names []string) {\n\tfor _, obj := range objs {\n\t\tif obj.GetObjectKind().GroupVersionKind().Kind == kind {\n\t\t\tnames = append(names, obj.GetName())\n\t\t}\n\t}\n\tsort.Strings(names)\n\treturn\n}\n\nfunc newDeploymentWithServiceAccount(name string) (d appsv1.Deployment) {\n\td.Spec.Template.Spec.ServiceAccountName = name\n\treturn d\n}\n\nfunc newRole(name string) (r rbacv1.Role) {\n\tr.SetGroupVersionKind(rbacv1.SchemeGroupVersion.WithKind(\"Role\"))\n\tr.SetName(name)\n\treturn r\n}\n\nfunc newClusterRole(name string) (r rbacv1.ClusterRole) {\n\tr.SetGroupVersionKind(rbacv1.SchemeGroupVersion.WithKind(\"ClusterRole\"))\n\tr.SetName(name)\n\treturn r\n}\n\nfunc newRoleBinding(name string, ref rbacv1.RoleRef, subjects ...rbacv1.Subject) (r rbacv1.RoleBinding) {\n\tr.SetGroupVersionKind(rbacv1.SchemeGroupVersion.WithKind(\"RoleBinding\"))\n\tr.SetName(name)\n\tr.RoleRef = ref\n\tr.Subjects = subjects\n\treturn r\n}\n\nfunc newClusterRoleBinding(name string, ref rbacv1.RoleRef, subjects ...rbacv1.Subject) (r rbacv1.ClusterRoleBinding) {\n\tr.SetGroupVersionKind(rbacv1.SchemeGroupVersion.WithKind(\"ClusterRoleBinding\"))\n\tr.SetName(name)\n\tr.RoleRef = ref\n\tr.Subjects = subjects\n\treturn r\n}\n\nfunc newRef(name, kind, apiGroup string) (s rbacv1.RoleRef) {\n\ts.Name = name\n\ts.Kind = kind\n\ts.APIGroup = apiGroup\n\treturn s\n}\n\nfunc newRoleRef(name string) (s rbacv1.RoleRef) {\n\treturn newRef(name, \"Role\", rbacv1.SchemeGroupVersion.Group)\n}\n\nfunc newClusterRoleRef(name string) (s rbacv1.RoleRef) {\n\treturn newRef(name, \"ClusterRole\", rbacv1.SchemeGroupVersion.Group)\n}\n\nfunc newSubject(name, kind string) (s rbacv1.Subject) {\n\ts.Name = name\n\ts.Kind = kind\n\treturn s\n}\n\nfunc newServiceAccountSubject(name string) (s rbacv1.Subject) {\n\treturn newSubject(name, \"ServiceAccount\")\n}\n\nfunc newServiceAccount(name string) (sa corev1.ServiceAccount) {\n\tsa.SetGroupVersionKind(corev1.SchemeGroupVersion.WithKind(\"ServiceAccount\"))\n\tsa.Name = name\n\treturn sa\n}\n"
  },
  {
    "path": "internal/generate/collector/collector_suite_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage collector\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nfunc TestCollector(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"Collector Suite\")\n}\n"
  },
  {
    "path": "internal/generate/collector/filter.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage collector\n\nimport (\n\t\"crypto/sha256\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/util/k8sutil\"\n\tadmissionregv1 \"k8s.io/api/admissionregistration/v1\"\n\tappsv1 \"k8s.io/api/apps/v1\"\n\trbacv1 \"k8s.io/api/rbac/v1\"\n\tapiextv1 \"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1\"\n\tapiextv1beta1 \"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1\"\n\t\"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured\"\n\t\"k8s.io/apimachinery/pkg/runtime/schema\"\n)\n\n// filter applies filtering rules to certain manifest types in a collection.\nfunc (c *Manifests) filter() {\n\tc.filterCustomResources()\n}\n\n// filterCustomResources filters \"other\" objects, which contain likely\n// Custom Resources corresponding to a CustomResourceDefinition, by GVK.\nfunc (c *Manifests) filterCustomResources() {\n\tcrdGVKSet := make(map[schema.GroupVersionKind]struct{})\n\tv1crdGVKs := k8sutil.GVKsForV1CustomResourceDefinitions(c.V1CustomResourceDefinitions...)\n\tv1beta1crdGVKs := k8sutil.GVKsForV1beta1CustomResourceDefinitions(c.V1beta1CustomResourceDefinitions...)\n\tfor _, gvk := range append(v1crdGVKs, v1beta1crdGVKs...) {\n\t\tcrdGVKSet[gvk] = struct{}{}\n\t}\n\n\tcustomResources := []unstructured.Unstructured{}\n\tfor _, other := range c.Others {\n\t\tif _, gvkMatches := crdGVKSet[other.GroupVersionKind()]; gvkMatches {\n\t\t\tcustomResources = append(customResources, other)\n\t\t}\n\t}\n\tc.CustomResources = customResources\n}\n\n// deduplicate removes duplicate objects from the collection, since we are\n// collecting an arbitrary list of manifests.\nfunc (c *Manifests) deduplicate() error {\n\thashes := make(map[string]struct{})\n\n\troles := []rbacv1.Role{}\n\tfor _, role := range c.Roles {\n\t\thasHash, err := addToHashes(&role, hashes)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif !hasHash {\n\t\t\troles = append(roles, role)\n\t\t}\n\t}\n\tc.Roles = roles\n\n\tclusterRoles := []rbacv1.ClusterRole{}\n\tfor _, clusterRole := range c.ClusterRoles {\n\t\thasHash, err := addToHashes(&clusterRole, hashes)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif !hasHash {\n\t\t\tclusterRoles = append(clusterRoles, clusterRole)\n\t\t}\n\t}\n\tc.ClusterRoles = clusterRoles\n\n\tdeps := []appsv1.Deployment{}\n\tfor _, dep := range c.Deployments {\n\t\thasHash, err := addToHashes(&dep, hashes)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif !hasHash {\n\t\t\tdeps = append(deps, dep)\n\t\t}\n\t}\n\tc.Deployments = deps\n\n\tv1crds := []apiextv1.CustomResourceDefinition{}\n\tfor _, crd := range c.V1CustomResourceDefinitions {\n\t\thasHash, err := addToHashes(&crd, hashes)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif !hasHash {\n\t\t\tv1crds = append(v1crds, crd)\n\t\t}\n\t}\n\tc.V1CustomResourceDefinitions = v1crds\n\n\tv1beta1crds := []apiextv1beta1.CustomResourceDefinition{}\n\tfor _, crd := range c.V1beta1CustomResourceDefinitions {\n\t\thasHash, err := addToHashes(&crd, hashes)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif !hasHash {\n\t\t\tv1beta1crds = append(v1beta1crds, crd)\n\t\t}\n\t}\n\tc.V1beta1CustomResourceDefinitions = v1beta1crds\n\n\tvalidatingWebhooks := []admissionregv1.ValidatingWebhook{}\n\tfor _, webhook := range c.ValidatingWebhooks {\n\t\thasHash, err := addToHashes(&webhook, hashes)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif !hasHash {\n\t\t\tvalidatingWebhooks = append(validatingWebhooks, webhook)\n\t\t}\n\t}\n\tc.ValidatingWebhooks = validatingWebhooks\n\n\tmutatingWebhooks := []admissionregv1.MutatingWebhook{}\n\tfor _, webhook := range c.MutatingWebhooks {\n\t\thasHash, err := addToHashes(&webhook, hashes)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif !hasHash {\n\t\t\tmutatingWebhooks = append(mutatingWebhooks, webhook)\n\t\t}\n\t}\n\tc.MutatingWebhooks = mutatingWebhooks\n\n\tcrs := []unstructured.Unstructured{}\n\tfor _, cr := range c.CustomResources {\n\t\tb, err := cr.MarshalJSON()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\thash := hashContents(b)\n\t\tif _, hasHash := hashes[hash]; !hasHash {\n\t\t\tcrs = append(crs, cr)\n\t\t\thashes[hash] = struct{}{}\n\t\t}\n\t}\n\tc.CustomResources = crs\n\n\treturn nil\n}\n\n// marshaller is an interface used to generalize hashing for deduplication.\ntype marshaller interface {\n\tMarshal() ([]byte, error)\n}\n\n// addToHashes calls m.Marshal(), hashes the returned bytes, and adds the\n// hash to hashes if it does not exist. addToHashes returns true if m's hash\n// was not in hashes.\nfunc addToHashes(m marshaller, hashes map[string]struct{}) (bool, error) {\n\tb, err := m.Marshal()\n\tif err != nil {\n\t\treturn false, err\n\t}\n\thash := hashContents(b)\n\t_, hasHash := hashes[hash]\n\tif !hasHash {\n\t\thashes[hash] = struct{}{}\n\t}\n\treturn hasHash, nil\n}\n\n// hashContents creates a sha256 md5 digest of b's bytes.\nfunc hashContents(b []byte) string {\n\th := sha256.New()\n\t_, _ = h.Write(b)\n\treturn string(h.Sum(nil))\n}\n"
  },
  {
    "path": "internal/generate/collector/manifests.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage collector\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\n\tscorecardv1alpha3 \"github.com/operator-framework/api/pkg/apis/scorecard/v1alpha3\"\n\toperatorsv1alpha1 \"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\tlog \"github.com/sirupsen/logrus\"\n\tadmissionregv1 \"k8s.io/api/admissionregistration/v1\"\n\tappsv1 \"k8s.io/api/apps/v1\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\trbacv1 \"k8s.io/api/rbac/v1\"\n\tapiextv1 \"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1\"\n\tapiextv1beta1 \"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1\"\n\t\"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured\"\n\t\"sigs.k8s.io/yaml\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/util/k8sutil\"\n)\n\n// Manifests holds a collector of all manifests relevant to CSV updates.\ntype Manifests struct {\n\tClusterServiceVersions           []operatorsv1alpha1.ClusterServiceVersion\n\tRoles                            []rbacv1.Role\n\tClusterRoles                     []rbacv1.ClusterRole\n\tRoleBindings                     []rbacv1.RoleBinding\n\tClusterRoleBindings              []rbacv1.ClusterRoleBinding\n\tDeployments                      []appsv1.Deployment\n\tServiceAccounts                  []corev1.ServiceAccount\n\tServices                         []corev1.Service\n\tV1CustomResourceDefinitions      []apiextv1.CustomResourceDefinition\n\tV1beta1CustomResourceDefinitions []apiextv1beta1.CustomResourceDefinition\n\tValidatingWebhooks               []admissionregv1.ValidatingWebhook\n\tMutatingWebhooks                 []admissionregv1.MutatingWebhook\n\tCustomResources                  []unstructured.Unstructured\n\tScorecardConfig                  scorecardv1alpha3.Configuration\n\n\tOthers []unstructured.Unstructured\n}\n\nvar (\n\tcsvGK                  = operatorsv1alpha1.SchemeGroupVersion.WithKind(\"ClusterServiceVersion\").GroupKind()\n\troleGK                 = rbacv1.SchemeGroupVersion.WithKind(\"Role\").GroupKind()\n\tclusterRoleGK          = rbacv1.SchemeGroupVersion.WithKind(\"ClusterRole\").GroupKind()\n\troleBindingGK          = rbacv1.SchemeGroupVersion.WithKind(\"RoleBinding\").GroupKind()\n\tclusterRoleBindingGK   = rbacv1.SchemeGroupVersion.WithKind(\"ClusterRoleBinding\").GroupKind()\n\tserviceAccountGK       = corev1.SchemeGroupVersion.WithKind(\"ServiceAccount\").GroupKind()\n\tserviceGK              = corev1.SchemeGroupVersion.WithKind(\"Service\").GroupKind()\n\tdeploymentGK           = appsv1.SchemeGroupVersion.WithKind(\"Deployment\").GroupKind()\n\tcrdGK                  = apiextv1.SchemeGroupVersion.WithKind(\"CustomResourceDefinition\").GroupKind()\n\tvalidatingWebhookCfgGK = admissionregv1.SchemeGroupVersion.WithKind(\"ValidatingWebhookConfiguration\").GroupKind()\n\tmutatingWebhookCfgGK   = admissionregv1.SchemeGroupVersion.WithKind(\"MutatingWebhookConfiguration\").GroupKind()\n\tv1alpha3ScorecardCfgGK = scorecardv1alpha3.GroupVersion.WithKind(\"Configuration\").GroupKind()\n)\n\n// UpdateFromDirs adds CustomResourceDefinitions found in crdsDir, and all other CSV-relevant manifests\n// from deployDir, to their respective fields in a Manifests, then filters and deduplicates them.\n// All other objects are added to Manifests.Others.\nfunc (c *Manifests) UpdateFromDirs(deployDir, crdsDir string) error {\n\t// Collect all manifests in paths.\n\terr := filepath.Walk(deployDir, func(path string, info os.FileInfo, err error) error {\n\t\tif err != nil || info.IsDir() {\n\t\t\treturn err\n\t\t}\n\n\t\tb, err := os.ReadFile(path)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn c.updateFromReader(bytes.NewBuffer(b))\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error collecting manifests from directory %s: %v\", deployDir, err)\n\t}\n\n\t// Add CRDs from input.\n\tif isDirExist(crdsDir) {\n\t\tc.V1CustomResourceDefinitions, c.V1beta1CustomResourceDefinitions, err = k8sutil.GetCustomResourceDefinitions(crdsDir)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error adding CustomResourceDefinitions to manifest collector: %v\", err)\n\t\t}\n\t}\n\n\t// Filter manifests based on data collected.\n\tc.filter()\n\n\t// Remove duplicate manifests.\n\tif err := c.deduplicate(); err != nil {\n\t\treturn fmt.Errorf(\"error removing duplicate manifests: %v\", err)\n\t}\n\n\treturn nil\n}\n\n// UpdateFromDir adds all CSV-relevant manifests from dir to their respective fields in a Manifests,\n// then filters and deduplicates them. All other objects are added to Manifests.Others.\nfunc (c *Manifests) UpdateFromDir(dir string) error {\n\treturn c.UpdateFromDirs(dir, \"\")\n}\n\n// UpdateFromReader adds Roles, ClusterRoles, Deployments, CustomResourceDefinitions,\n// and Custom Resources found in r to their respective fields in a Manifests, then\n// filters and deduplicates them. All other objects are added to Manifests.Others.\nfunc (c *Manifests) UpdateFromReader(r io.Reader) error {\n\t// Bundle contents.\n\tif err := c.updateFromReader(r); err != nil {\n\t\treturn err\n\t}\n\n\t// Filter manifests based on data collected.\n\tc.filter()\n\n\t// Remove duplicate manifests.\n\tif err := c.deduplicate(); err != nil {\n\t\treturn fmt.Errorf(\"error removing duplicate manifests: %v\", err)\n\t}\n\n\treturn nil\n}\n\nfunc (c *Manifests) updateFromReader(r io.Reader) error {\n\tscanner := k8sutil.NewYAMLScanner(r)\n\tfor scanner.Scan() {\n\t\tmanifest := scanner.Bytes()\n\t\ttypeMeta, err := k8sutil.GetTypeMetaFromBytes(manifest)\n\t\tif err != nil {\n\t\t\tlog.Debug(\"No TypeMeta found, skipping manifest\")\n\t\t\tcontinue\n\t\t}\n\n\t\tgvk := typeMeta.GroupVersionKind()\n\t\tswitch gvk.GroupKind() {\n\t\tcase csvGK:\n\t\t\terr = c.addClusterServiceVersions(manifest)\n\t\tcase roleGK:\n\t\t\terr = c.addRoles(manifest)\n\t\tcase clusterRoleGK:\n\t\t\terr = c.addClusterRoles(manifest)\n\t\tcase roleBindingGK:\n\t\t\terr = c.addRoleBindings(manifest)\n\t\tcase clusterRoleBindingGK:\n\t\t\terr = c.addClusterRoleBindings(manifest)\n\t\tcase serviceAccountGK:\n\t\t\terr = c.addServiceAccounts(manifest)\n\t\tcase serviceGK:\n\t\t\terr = c.addServices(manifest)\n\t\tcase deploymentGK:\n\t\t\terr = c.addDeployments(manifest)\n\t\tcase crdGK:\n\t\t\terr = c.addCustomResourceDefinitions(gvk.Version, manifest)\n\t\tcase validatingWebhookCfgGK:\n\t\t\terr = c.addValidatingWebhookConfigurations(manifest)\n\t\tcase mutatingWebhookCfgGK:\n\t\t\terr = c.addMutatingWebhookConfigurations(manifest)\n\t\tcase v1alpha3ScorecardCfgGK:\n\t\t\terr = c.addScorecardConfig(manifest)\n\t\tdefault:\n\t\t\terr = c.addOthers(manifest)\n\t\t}\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error adding %s to manifest collector: %v\", gvk, err)\n\t\t}\n\t}\n\tif err := scanner.Err(); err != nil {\n\t\treturn fmt.Errorf(\"error collecting manifests from reader: %v\", err)\n\t}\n\n\treturn nil\n}\n\n// addClusterServiceVersions assumes all manifest data in rawManifests are ClusterServiceVersions\n// and adds them to the collector.\nfunc (c *Manifests) addClusterServiceVersions(rawManifests ...[]byte) error {\n\tfor _, rawManifest := range rawManifests {\n\t\tcsv := operatorsv1alpha1.ClusterServiceVersion{}\n\t\tif err := yaml.Unmarshal(rawManifest, &csv); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tc.ClusterServiceVersions = append(c.ClusterServiceVersions, csv)\n\t}\n\treturn nil\n}\n\n// addRoles assumes all manifest data in rawManifests are Roles and adds them\n// to the collector.\nfunc (c *Manifests) addRoles(rawManifests ...[]byte) error {\n\tfor _, rawManifest := range rawManifests {\n\t\trole := rbacv1.Role{}\n\t\tif err := yaml.Unmarshal(rawManifest, &role); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tc.Roles = append(c.Roles, role)\n\t}\n\treturn nil\n}\n\n// addClusterRoles assumes all manifest data in rawManifests are ClusterRoles\n// and adds them to the collector.\nfunc (c *Manifests) addClusterRoles(rawManifests ...[]byte) error {\n\tfor _, rawManifest := range rawManifests {\n\t\trole := rbacv1.ClusterRole{}\n\t\tif err := yaml.Unmarshal(rawManifest, &role); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tc.ClusterRoles = append(c.ClusterRoles, role)\n\t}\n\treturn nil\n}\n\n// addRoleBindings assumes all manifest data in rawManifests are RoleBindings and adds them to the collector.\nfunc (c *Manifests) addRoleBindings(rawManifests ...[]byte) error {\n\tfor _, rawManifest := range rawManifests {\n\t\tbinding := rbacv1.RoleBinding{}\n\t\tif err := yaml.Unmarshal(rawManifest, &binding); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tc.RoleBindings = append(c.RoleBindings, binding)\n\t}\n\treturn nil\n}\n\n// addClusterRoleBindings assumes all manifest data in rawManifests are ClusterRoleBindings and adds them to the collector.\nfunc (c *Manifests) addClusterRoleBindings(rawManifests ...[]byte) error {\n\tfor _, rawManifest := range rawManifests {\n\t\tbinding := rbacv1.ClusterRoleBinding{}\n\t\tif err := yaml.Unmarshal(rawManifest, &binding); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tc.ClusterRoleBindings = append(c.ClusterRoleBindings, binding)\n\t}\n\treturn nil\n}\n\n// addServiceAccounts assumes all manifest data in rawManifests are ServiceAccounts and adds them to the collector.\nfunc (c *Manifests) addServiceAccounts(rawManifests ...[]byte) error {\n\tfor _, rawManifest := range rawManifests {\n\t\tsa := corev1.ServiceAccount{}\n\t\tif err := yaml.Unmarshal(rawManifest, &sa); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tc.ServiceAccounts = append(c.ServiceAccounts, sa)\n\t}\n\treturn nil\n}\n\n// addServices assumes all manifest data in rawManifests are Services and adds them to the collector.\nfunc (c *Manifests) addServices(rawManifests ...[]byte) error {\n\tfor _, rawManifest := range rawManifests {\n\t\ts := corev1.Service{}\n\t\tif err := yaml.Unmarshal(rawManifest, &s); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tc.Services = append(c.Services, s)\n\t}\n\treturn nil\n}\n\n// addDeployments assumes all manifest data in rawManifests are Deployments\n// and adds them to the collector.\nfunc (c *Manifests) addDeployments(rawManifests ...[]byte) error {\n\tfor _, rawManifest := range rawManifests {\n\t\tdep := appsv1.Deployment{}\n\t\tif err := yaml.Unmarshal(rawManifest, &dep); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tc.Deployments = append(c.Deployments, dep)\n\t}\n\treturn nil\n}\n\n// addCustomResourceDefinitions assumes all manifest data in rawManifests are\n// CustomResourceDefinitions and adds them to the collector. version determines\n// which CustomResourceDefinition type is used for all manifests in rawManifests.\nfunc (c *Manifests) addCustomResourceDefinitions(version string, rawManifests ...[]byte) (err error) {\n\tfor _, rawManifest := range rawManifests {\n\t\tswitch version {\n\t\tcase apiextv1.SchemeGroupVersion.Version:\n\t\t\tcrd := apiextv1.CustomResourceDefinition{}\n\t\t\tif err := yaml.Unmarshal(rawManifest, &crd); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tc.V1CustomResourceDefinitions = append(c.V1CustomResourceDefinitions, crd)\n\t\tcase apiextv1beta1.SchemeGroupVersion.Version:\n\t\t\tcrd := apiextv1beta1.CustomResourceDefinition{}\n\t\t\tif err := yaml.Unmarshal(rawManifest, &crd); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tc.V1beta1CustomResourceDefinitions = append(c.V1beta1CustomResourceDefinitions, crd)\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"unrecognized CustomResourceDefinition version %q\", version)\n\t\t}\n\t}\n\treturn nil\n}\n\n// addValidatingWebhookConfigurations assumes all manifest data in rawManifests\n// are ValidatingWebhookConfigurations and adds their webhooks to the collector.\nfunc (c *Manifests) addValidatingWebhookConfigurations(rawManifests ...[]byte) error {\n\tfor _, rawManifest := range rawManifests {\n\t\twebhookConfig := admissionregv1.ValidatingWebhookConfiguration{}\n\t\tif err := yaml.Unmarshal(rawManifest, &webhookConfig); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tc.ValidatingWebhooks = append(c.ValidatingWebhooks, webhookConfig.Webhooks...)\n\t}\n\treturn nil\n}\n\n// addMutatingWebhookConfigurations assumes all manifest data in rawManifests\n// are MutatingWebhookConfigurations and adds their webhooks to the collector.\nfunc (c *Manifests) addMutatingWebhookConfigurations(rawManifests ...[]byte) error {\n\tfor _, rawManifest := range rawManifests {\n\t\twebhookConfig := admissionregv1.MutatingWebhookConfiguration{}\n\t\tif err := yaml.Unmarshal(rawManifest, &webhookConfig); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tc.MutatingWebhooks = append(c.MutatingWebhooks, webhookConfig.Webhooks...)\n\t}\n\treturn nil\n}\n\n// addScorecardConfig assumes manifest data in rawManifests is a ScorecardConfigs and adds it to the collector.\n// If a config has already been found, addScorecardConfig will return an error.\nfunc (c *Manifests) addScorecardConfig(rawManifest []byte) error {\n\tcfg := scorecardv1alpha3.Configuration{}\n\tif err := yaml.Unmarshal(rawManifest, &cfg); err != nil {\n\t\treturn err\n\t}\n\tif c.ScorecardConfig.Metadata.Name != \"\" {\n\t\treturn errors.New(\"duplicate scorecard configurations in collector input\")\n\t}\n\tc.ScorecardConfig = cfg\n\treturn nil\n}\n\n// addOthers assumes all manifest data in rawManifests are able to be\n// unmarshalled into an Unstructured object and adds them to the collector.\nfunc (c *Manifests) addOthers(rawManifests ...[]byte) error {\n\tfor _, rawManifest := range rawManifests {\n\t\tu := unstructured.Unstructured{}\n\t\tif err := yaml.Unmarshal(rawManifest, &u); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tc.Others = append(c.Others, u)\n\t}\n\treturn nil\n}\n\n// isDirExist returns true if dir exists on disk.\nfunc isDirExist(dir string) bool {\n\tif dir == \"\" {\n\t\treturn false\n\t}\n\tinfo, err := os.Stat(dir)\n\treturn (err == nil && info.IsDir()) || os.IsExist(err)\n}\n"
  },
  {
    "path": "internal/generate/internal/genutil.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage genutil\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\n\t\"sigs.k8s.io/yaml\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/util/k8sutil\"\n)\n\n// InternalError wraps errors that are development issues and unrelated to user\n// input.\ntype InternalError string\n\nfunc (e InternalError) Error() string {\n\treturn fmt.Sprintf(\"internal error: %s\", string(e))\n}\n\n// MakeCSVName returns a ClusterServiceVersion's name.\nfunc MakeCSVName(name, version string) string {\n\treturn fmt.Sprintf(\"%s.v%s\", name, version)\n}\n\n// File wraps os.File. Use this type when generating files that may already\n// exist on disk and should be overwritten.\ntype File struct {\n\t*os.File\n}\n\n// Open first creates dir then opens <dir>/<fileName> for reading and writing,\n// creating the file if it does not exist.\nfunc Open(dir, fileName string) (*File, error) {\n\tif err := os.MkdirAll(dir, 0755); err != nil {\n\t\treturn nil, err\n\t}\n\tf, err := os.OpenFile(filepath.Join(dir, fileName), os.O_RDWR|os.O_CREATE, 0666)\n\treturn &File{f}, err\n}\n\n// WriteObject writes a k8s object to w.\nfunc WriteObject(w io.Writer, obj any) error {\n\tb, err := k8sutil.GetObjectBytes(obj, yaml.Marshal)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// todo: remove it when the OLM starts to support https://github.com/operator-framework/api/pull/100\n\tconst cleanup = \"cleanup:\\n    enabled: false\\n  \"\n\tb = bytes.ReplaceAll(b, []byte(cleanup), []byte(\"\"))\n\n\treturn write(w, b)\n}\n\n// WriteObject writes any object to w.\nfunc WriteYAML(w io.Writer, obj any) error {\n\tb, err := yaml.Marshal(obj)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn write(w, b)\n}\n\n// write writes b to w. If w is a File, its contents will be cleared and w\n// will be closed following the write.\nfunc write(w io.Writer, b []byte) error {\n\tif f, isFile := w.(*File); isFile {\n\t\tif err := f.Truncate(0); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tdefer func() {\n\t\t\t_ = f.Close()\n\t\t}()\n\t}\n\t_, err := w.Write(b)\n\treturn err\n}\n\n// IsExist returns true if path exists on disk.\nfunc IsExist(path string) bool {\n\tif path == \"\" {\n\t\treturn false\n\t}\n\t_, err := os.Stat(path)\n\treturn err == nil || errors.Is(err, os.ErrExist)\n}\n\n// IsNotExist returns true if path does not exist on disk.\nfunc IsNotExist(path string) bool {\n\tif path == \"\" {\n\t\treturn true\n\t}\n\t_, err := os.Stat(path)\n\treturn err != nil && errors.Is(err, os.ErrNotExist)\n}\n"
  },
  {
    "path": "internal/generate/packagemanifest/packagemanifest.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage packagemanifest\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sort\"\n\n\tapimanifests \"github.com/operator-framework/api/pkg/manifests\"\n\t\"github.com/operator-framework/api/pkg/validation\"\n\tlog \"github.com/sirupsen/logrus\"\n\t\"sigs.k8s.io/yaml\"\n\n\tgenutil \"github.com/operator-framework/operator-sdk/internal/generate/internal\"\n)\n\nconst (\n\t// File extension for all PackageManifests written by Generator.\n\tpackageManifestFileExt = \".package.yaml\"\n)\n\n// generator is an implementation of the Generator interface\ntype generator struct{}\n\n// NewGenerator returns a new generator object\nfunc NewGenerator() Generator {\n\treturn generator{}\n}\n\n// Generator is an interface that specifies the Generate methods\n// to generate and write various package manifests\n//\n//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . Generator\ntype Generator interface {\n\tGenerate(operatorName, version, outputDir string, opts Options) error\n}\n\n// PackageManifest configures the PackageManifest that GetBase() returns.\ntype PackageManifest struct {\n\tPackageName string\n\tBasePath    string\n}\n\nvar (\n\t// User-facing errors.\n\n\t// ErrNoVersion if no version # has been provided\n\tErrNoVersion = errors.New(\"version must be set\")\n\n\t// Internal errors.\n\n\t// ErrNoOpName if the operator name has not been set\n\tErrNoOpName = genutil.InternalError(\"operator name must be set\")\n\t// ErrNoOutputDir if the directory to write the package manifest to has not been set\n\tErrNoOutputDir = genutil.InternalError(\"output directory must be set\")\n)\n\ntype Options struct {\n\t// BaseDir is a directory to look for an existing base package manifest\n\t// to update.\n\tBaseDir string\n\t// ChannelName is operator's PackageManifest channel. If a new PackageManifest is generated\n\t// or ChannelName is the only channel in the generated PackageManifest,\n\t// this channel will be set to the PackageManifest's default.\n\tChannelName string\n\t// IsDefaultChannel determines whether ChannelName should be the default channel in the\n\t// generated PackageManifest. If true, ChannelName will be the PackageManifest's default channel.\n\t// Setting this field is only necessary when more than one channel exists.\n\tIsDefaultChannel bool\n}\n\n// Generate configures the Generator with opts then runs it.\nfunc (g generator) Generate(operatorName, version, outputDir string, opts Options) error {\n\tif operatorName == \"\" {\n\t\treturn ErrNoOpName\n\t}\n\tif version == \"\" {\n\t\treturn ErrNoVersion\n\t}\n\tif outputDir == \"\" {\n\t\treturn ErrNoOutputDir\n\t}\n\n\tpkg, err := g.generate(operatorName, version, opts)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\toutputWriter, err := genutil.Open(outputDir, makePkgManFileName(operatorName))\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn genutil.WriteYAML(outputWriter, pkg)\n}\n\n// generate takes the input and generates the populated package manifest object\nfunc (g generator) generate(operatorName, version string, opts Options) (*apimanifests.PackageManifest, error) {\n\tb := PackageManifest{\n\t\tPackageName: operatorName,\n\t}\n\tif opts.BaseDir != \"\" {\n\t\tbasePath := filepath.Join(opts.BaseDir, makePkgManFileName(operatorName))\n\t\tif genutil.IsNotExist(basePath) {\n\t\t\tbasePath = \"\"\n\t\t}\n\t\tb.BasePath = basePath\n\t}\n\tbase, err := b.GetBase()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error getting PackageManifest base: %v\", err)\n\t}\n\n\tcsvName := genutil.MakeCSVName(operatorName, version)\n\tif opts.ChannelName != \"\" {\n\t\tsetChannels(base, opts.ChannelName, csvName)\n\t\tsortChannelsByName(base)\n\t\tif opts.IsDefaultChannel || len(base.Channels) == 1 {\n\t\t\tbase.DefaultChannelName = opts.ChannelName\n\t\t}\n\t} else if len(base.Channels) == 0 {\n\t\tsetChannels(base, \"alpha\", csvName)\n\t\tbase.DefaultChannelName = \"alpha\"\n\t}\n\n\tif err = validatePackageManifest(base); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn base, nil\n}\n\n// makePkgManFileName will return the file name of a PackageManifest.\nfunc makePkgManFileName(operatorName string) string {\n\treturn operatorName + packageManifestFileExt\n}\n\n// sortChannelsByName sorts pkg.Channels by each element's name.\nfunc sortChannelsByName(pkg *apimanifests.PackageManifest) {\n\tsort.Slice(pkg.Channels, func(i int, j int) bool {\n\t\treturn pkg.Channels[i].Name < pkg.Channels[j].Name\n\t})\n}\n\n// validatePackageManifest will validate pkg and log warnings and errors.\n// If a validation error is encountered, an error is returned.\nfunc validatePackageManifest(pkg *apimanifests.PackageManifest) error {\n\tif pkg == nil {\n\t\treturn errors.New(\"empty PackageManifest\")\n\t}\n\n\thasErrors := false\n\tresults := validation.PackageManifestValidator.Validate(pkg)\n\tfor _, r := range results {\n\t\tfor _, e := range r.Errors {\n\t\t\tlog.Errorf(\"PackageManifest validation: [%s] %s\", e.Type, e.Detail)\n\t\t}\n\t\tfor _, w := range r.Warnings {\n\t\t\tlog.Warnf(\"PackageManifest validation: [%s] %s\", w.Type, w.Detail)\n\t\t}\n\t\tif r.HasError() {\n\t\t\thasErrors = true\n\t\t}\n\t}\n\n\tif hasErrors {\n\t\treturn errors.New(\"invalid generated PackageManifest\")\n\t}\n\n\treturn nil\n}\n\n// setChannels checks for duplicate channels in pkg and sets the default channel if possible.\nfunc setChannels(pkg *apimanifests.PackageManifest, channelName, csvName string) {\n\tchannelIdx := -1\n\tfor i, channel := range pkg.Channels {\n\t\tif channel.Name == channelName {\n\t\t\tpkg.Channels[i].CurrentCSVName = csvName\n\t\t\tchannelIdx = i\n\t\t\tbreak\n\t\t}\n\t}\n\tif channelIdx == -1 {\n\t\tpkg.Channels = append(pkg.Channels, apimanifests.PackageChannel{\n\t\t\tName:           channelName,\n\t\t\tCurrentCSVName: csvName,\n\t\t})\n\t}\n}\n\n// GetBase returns a base PackageManifest, populated either with default\n// values or, if b.BasePath is set, bytes from disk.\nfunc (b PackageManifest) GetBase() (base *apimanifests.PackageManifest, err error) {\n\tif b.BasePath != \"\" {\n\t\tif base, err = readPackageManifestBase(b.BasePath); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error reading existing PackageManifest base %s: %v\", b.BasePath, err)\n\t\t}\n\t} else {\n\t\tbase = b.makeNewBase()\n\t}\n\n\treturn base, nil\n}\n\n// makeNewBase returns a base makeNewBase to modify.\nfunc (b PackageManifest) makeNewBase() *apimanifests.PackageManifest {\n\treturn &apimanifests.PackageManifest{\n\t\tPackageName: b.PackageName,\n\t}\n}\n\n// readPackageManifestBase returns the PackageManifest base at path.\n// If no base is found, readPackageManifestBase returns an error.\nfunc readPackageManifestBase(path string) (*apimanifests.PackageManifest, error) {\n\tb, err := os.ReadFile(path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tpkg := &apimanifests.PackageManifest{}\n\tif err := yaml.Unmarshal(b, pkg); err != nil {\n\t\treturn nil, fmt.Errorf(\"error unmarshalling PackageManifest from %s: %w\", path, err)\n\t}\n\tif pkg.PackageName == \"\" {\n\t\treturn nil, fmt.Errorf(\"no PackageManifest in %s\", path)\n\t}\n\treturn pkg, nil\n}\n"
  },
  {
    "path": "internal/generate/packagemanifest/packagemanifest_suite_test.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage packagemanifest_test\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nfunc TestGenerate(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"Generate Suite\")\n}\n"
  },
  {
    "path": "internal/generate/packagemanifest/packagemanifest_test.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage packagemanifest_test\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\t\"github.com/operator-framework/operator-sdk/internal/generate/packagemanifest\"\n)\n\nvar _ = Describe(\"A package manifest generator\", func() {\n\tvar (\n\t\ttestDataDir string\n\t)\n\tBeforeEach(func() {\n\t\ttestDataDir = filepath.Join(\"..\", \"testdata\")\n\t})\n\tDescribe(\"Generate\", func() {\n\t\tvar (\n\t\t\tg                                    packagemanifest.Generator\n\t\t\tblankOpts                            packagemanifest.Options\n\t\t\toperatorName                         string\n\t\t\toutputDir                            string\n\t\t\tpkgManFilename                       string\n\t\t\tpkgManDefault                        string\n\t\t\tpkgManOneChannel                     string\n\t\t\tpkgManUpdatedOneChannel              string\n\t\t\tpkgManUpdatedSecondChannel           string\n\t\t\tpkgManUpdatedSecondChannelNewDefault string\n\t\t)\n\t\tBeforeEach(func() {\n\t\t\tg = packagemanifest.NewGenerator()\n\t\t\toperatorName = \"memcached-operator\"\n\t\t\tblankOpts = packagemanifest.Options{}\n\t\t\tpkgManFilename = operatorName + \".package.yaml\"\n\t\t\toutputDir = os.TempDir()\n\t\t\tpkgManDefault = `channels:\n- currentCSV: memcached-operator.v0.0.1\n  name: alpha\ndefaultChannel: alpha\npackageName: memcached-operator\n`\n\t\t\tpkgManOneChannel = `channels:\n- currentCSV: memcached-operator.v0.0.1\n  name: stable\ndefaultChannel: stable\npackageName: memcached-operator\n`\n\t\t\tpkgManUpdatedOneChannel = `channels:\n- currentCSV: memcached-operator.v0.0.2\n  name: alpha\ndefaultChannel: alpha\npackageName: memcached-operator\n`\n\t\t\tpkgManUpdatedSecondChannel = `channels:\n- currentCSV: memcached-operator.v0.0.1\n  name: alpha\n- currentCSV: memcached-operator.v0.0.2\n  name: stable\ndefaultChannel: alpha\npackageName: memcached-operator\n`\n\t\t\tpkgManUpdatedSecondChannelNewDefault = `channels:\n- currentCSV: memcached-operator.v0.0.1\n  name: alpha\n- currentCSV: memcached-operator.v0.0.2\n  name: stable\ndefaultChannel: stable\npackageName: memcached-operator\n`\n\t\t})\n\t\tContext(\"when writing a new package manifest\", func() {\n\t\t\tIt(\"writes a package manifest\", func() {\n\t\t\t\terr := g.Generate(operatorName, \"0.0.1\", outputDir, blankOpts)\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t\tfile, err := os.ReadFile(outputDir + string(os.PathSeparator) + pkgManFilename)\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t\tExpect(string(file)).To(Equal(pkgManDefault))\n\t\t\t})\n\t\t\tIt(\"writes a package manifest with a non-default channel\", func() {\n\t\t\t\topts := packagemanifest.Options{\n\t\t\t\t\tChannelName: \"stable\",\n\t\t\t\t}\n\n\t\t\t\terr := g.Generate(operatorName, \"0.0.1\", outputDir, opts)\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t\tfile, err := os.ReadFile(outputDir + string(os.PathSeparator) + pkgManFilename)\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t\tExpect(string(file)).To(Equal(pkgManOneChannel))\n\t\t\t})\n\t\t})\n\t\tContext(\"when updating an existing package manifest\", func() {\n\t\t\tIt(\"creates a new package manifest if provided an existing packagemanifest that doesn't exist\", func() {\n\t\t\t\topts := packagemanifest.Options{\n\t\t\t\t\tBaseDir:     \"testpotato\",\n\t\t\t\t\tChannelName: \"stable\",\n\t\t\t\t}\n\n\t\t\t\terr := g.Generate(operatorName, \"0.0.1\", outputDir, opts)\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t\tfile, err := os.ReadFile(outputDir + string(os.PathSeparator) + pkgManFilename)\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t\tExpect(string(file)).To(Equal(pkgManOneChannel))\n\t\t\t})\n\t\t\tIt(\"updates an existing package manifest with a updated channel\", func() {\n\t\t\t\topts := packagemanifest.Options{\n\t\t\t\t\tBaseDir:     testDataDir,\n\t\t\t\t\tChannelName: \"alpha\",\n\t\t\t\t}\n\n\t\t\t\terr := g.Generate(operatorName, \"0.0.2\", outputDir, opts)\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t\tfile, err := os.ReadFile(outputDir + string(os.PathSeparator) + pkgManFilename)\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t\tExpect(string(file)).To(Equal(pkgManUpdatedOneChannel))\n\t\t\t})\n\t\t\tIt(\"updates an existing package manifest with a new channel\", func() {\n\t\t\t\topts := packagemanifest.Options{\n\t\t\t\t\tBaseDir:     testDataDir,\n\t\t\t\t\tChannelName: \"stable\",\n\t\t\t\t}\n\n\t\t\t\terr := g.Generate(operatorName, \"0.0.2\", outputDir, opts)\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t\tfile, err := os.ReadFile(outputDir + string(os.PathSeparator) + pkgManFilename)\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t\tExpect(string(file)).To(Equal(pkgManUpdatedSecondChannel))\n\t\t\t})\n\t\t\tIt(\"updates an existing package manifest with a new channel and an updated default channel\", func() {\n\t\t\t\topts := packagemanifest.Options{\n\t\t\t\t\tBaseDir:          testDataDir,\n\t\t\t\t\tChannelName:      \"stable\",\n\t\t\t\t\tIsDefaultChannel: true,\n\t\t\t\t}\n\n\t\t\t\terr := g.Generate(operatorName, \"0.0.2\", outputDir, opts)\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t\tfile, err := os.ReadFile(outputDir + string(os.PathSeparator) + pkgManFilename)\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t\tExpect(string(file)).To(Equal(pkgManUpdatedSecondChannelNewDefault))\n\t\t\t})\n\t\t})\n\t\tContext(\"when incorrect params are provided\", func() {\n\t\t\tIt(\"fails if no operator name is specified\", func() {\n\t\t\t\terr := g.Generate(\"\", \"\", \"\", blankOpts)\n\t\t\t\tExpect(err).To(HaveOccurred())\n\t\t\t\tExpect(err.Error()).To(ContainSubstring(packagemanifest.ErrNoOpName.Error()))\n\t\t\t})\n\t\t\tIt(\"fails if no version is specified\", func() {\n\t\t\t\terr := g.Generate(operatorName, \"\", \"\", blankOpts)\n\t\t\t\tExpect(err).To(HaveOccurred())\n\t\t\t\tExpect(err.Error()).To(ContainSubstring(packagemanifest.ErrNoVersion.Error()))\n\t\t\t})\n\t\t\tIt(\"fails if no output directory is set\", func() {\n\t\t\t\terr := g.Generate(operatorName, \"0.0.1\", \"\", blankOpts)\n\t\t\t\tExpect(err).To(HaveOccurred())\n\t\t\t\tExpect(err.Error()).To(ContainSubstring(packagemanifest.ErrNoOutputDir.Error()))\n\t\t\t})\n\t\t})\n\t})\n\tDescribe(\"GetBase\", func() {\n\t\tvar (\n\t\t\tb packagemanifest.PackageManifest\n\t\t)\n\t\tBeforeEach(func() {\n\t\t\tb = packagemanifest.PackageManifest{}\n\t\t})\n\t\tIt(\"returns a new blank packagemanifest\", func() {\n\t\t\tb.PackageName = \"sweetsop\"\n\n\t\t\tpm, err := b.GetBase()\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\tExpect(pm).NotTo(BeNil())\n\t\t\tExpect(pm.PackageName).To(Equal(b.PackageName))\n\t\t})\n\t\tIt(\"reads an existing packagemanifest from disk\", func() {\n\t\t\tb.BasePath = filepath.Join(testDataDir, \"memcached-operator.package.yaml\")\n\n\t\t\tpm, err := b.GetBase()\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\tExpect(pm).NotTo(BeNil())\n\t\t\tExpect(pm.PackageName).To(Equal(\"memcached-operator\"))\n\t\t\tExpect(pm.Channels).To(HaveLen(1))\n\t\t\tExpect(pm.Channels[0].Name).To(Equal(\"alpha\"))\n\t\t\tExpect(pm.Channels[0].CurrentCSVName).To(Equal(\"memcached-operator.v0.0.1\"))\n\t\t\tExpect(pm.DefaultChannelName).To(Equal(\"alpha\"))\n\t\t})\n\t\tIt(\"fails if provided a non-existent base path\", func() {\n\t\t\tb.BasePath = \"not-a-real-thing.yaml\"\n\n\t\t\tpm, err := b.GetBase()\n\t\t\tExpect(pm).To(BeNil())\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t\tExpect(err.Error()).To(ContainSubstring(\"error reading existing\"))\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "internal/generate/packagemanifest/packagemanifestfakes/fake_generator.go",
    "content": "// Code generated by counterfeiter. DO NOT EDIT.\npackage packagemanifestfakes\n\nimport (\n\t\"sync\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/generate/packagemanifest\"\n)\n\ntype FakeGenerator struct {\n\tGenerateStub        func(string, string, string, packagemanifest.Options) error\n\tgenerateMutex       sync.RWMutex\n\tgenerateArgsForCall []struct {\n\t\targ1 string\n\t\targ2 string\n\t\targ3 string\n\t\targ4 packagemanifest.Options\n\t}\n\tgenerateReturns struct {\n\t\tresult1 error\n\t}\n\tgenerateReturnsOnCall map[int]struct {\n\t\tresult1 error\n\t}\n\tinvocations      map[string][][]interface{}\n\tinvocationsMutex sync.RWMutex\n}\n\nfunc (fake *FakeGenerator) Generate(arg1 string, arg2 string, arg3 string, arg4 packagemanifest.Options) error {\n\tfake.generateMutex.Lock()\n\tret, specificReturn := fake.generateReturnsOnCall[len(fake.generateArgsForCall)]\n\tfake.generateArgsForCall = append(fake.generateArgsForCall, struct {\n\t\targ1 string\n\t\targ2 string\n\t\targ3 string\n\t\targ4 packagemanifest.Options\n\t}{arg1, arg2, arg3, arg4})\n\tstub := fake.GenerateStub\n\tfakeReturns := fake.generateReturns\n\tfake.recordInvocation(\"Generate\", []interface{}{arg1, arg2, arg3, arg4})\n\tfake.generateMutex.Unlock()\n\tif stub != nil {\n\t\treturn stub(arg1, arg2, arg3, arg4)\n\t}\n\tif specificReturn {\n\t\treturn ret.result1\n\t}\n\treturn fakeReturns.result1\n}\n\nfunc (fake *FakeGenerator) GenerateCallCount() int {\n\tfake.generateMutex.RLock()\n\tdefer fake.generateMutex.RUnlock()\n\treturn len(fake.generateArgsForCall)\n}\n\nfunc (fake *FakeGenerator) GenerateCalls(stub func(string, string, string, packagemanifest.Options) error) {\n\tfake.generateMutex.Lock()\n\tdefer fake.generateMutex.Unlock()\n\tfake.GenerateStub = stub\n}\n\nfunc (fake *FakeGenerator) GenerateArgsForCall(i int) (string, string, string, packagemanifest.Options) {\n\tfake.generateMutex.RLock()\n\tdefer fake.generateMutex.RUnlock()\n\targsForCall := fake.generateArgsForCall[i]\n\treturn argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4\n}\n\nfunc (fake *FakeGenerator) GenerateReturns(result1 error) {\n\tfake.generateMutex.Lock()\n\tdefer fake.generateMutex.Unlock()\n\tfake.GenerateStub = nil\n\tfake.generateReturns = struct {\n\t\tresult1 error\n\t}{result1}\n}\n\nfunc (fake *FakeGenerator) GenerateReturnsOnCall(i int, result1 error) {\n\tfake.generateMutex.Lock()\n\tdefer fake.generateMutex.Unlock()\n\tfake.GenerateStub = nil\n\tif fake.generateReturnsOnCall == nil {\n\t\tfake.generateReturnsOnCall = make(map[int]struct {\n\t\t\tresult1 error\n\t\t})\n\t}\n\tfake.generateReturnsOnCall[i] = struct {\n\t\tresult1 error\n\t}{result1}\n}\n\nfunc (fake *FakeGenerator) Invocations() map[string][][]interface{} {\n\tfake.invocationsMutex.RLock()\n\tdefer fake.invocationsMutex.RUnlock()\n\tcopiedInvocations := map[string][][]interface{}{}\n\tfor key, value := range fake.invocations {\n\t\tcopiedInvocations[key] = value\n\t}\n\treturn copiedInvocations\n}\n\nfunc (fake *FakeGenerator) recordInvocation(key string, args []interface{}) {\n\tfake.invocationsMutex.Lock()\n\tdefer fake.invocationsMutex.Unlock()\n\tif fake.invocations == nil {\n\t\tfake.invocations = map[string][][]interface{}{}\n\t}\n\tif fake.invocations[key] == nil {\n\t\tfake.invocations[key] = [][]interface{}{}\n\t}\n\tfake.invocations[key] = append(fake.invocations[key], args)\n}\n\nvar _ packagemanifest.Generator = new(FakeGenerator)\n"
  },
  {
    "path": "internal/generate/testdata/clusterserviceversions/bases/memcached-operator-multiVersion.yaml",
    "content": "apiVersion: operators.coreos.com/v1alpha1\nkind: ClusterServiceVersion\nmetadata:\n  annotations:\n    alm-examples: '[]'\n    capabilities: Basic Install\n  name: memcached-operator.v0.0.0\n  namespace: placeholder\nspec:\n  apiservicedefinitions: {}\n  customresourcedefinitions:\n    owned:\n    - description: Memcached is the Schema for the memcacheds API\n      displayName: Memcached\n      kind: Memcached1\n      name: memcacheds1.cache1.example.com\n      version: v1alpha1\n    - description: Memcached is the Schema for the memcacheds API\n      displayName: Memcached\n      kind: Memcached1\n      name: memcacheds1.cache1.example.com\n      version: v1\n    - description: Memcached is the Schema for the memcacheds API\n      displayName: Memcached\n      kind: Memcached\n      name: memcacheds.cache.example.com\n      version: v1\n    - description: Memcached is the Schema for the memcacheds API\n      displayName: Memcached\n      kind: Memcached\n      name: memcacheds.cache.example.com\n      version: v1alpha1\n  description: Memcached Operator description. TODO.\n  displayName: Memcached Operator\n  icon:\n  - base64data: \"\"\n    mediatype: \"\"\n  install:\n    spec:\n      deployments: null\n    strategy: \"\"\n  installModes:\n  - supported: false\n    type: OwnNamespace\n  - supported: false\n    type: SingleNamespace\n  - supported: false\n    type: MultiNamespace\n  - supported: true\n    type: AllNamespaces\n  keywords:\n  - memcached-operator\n  links:\n  - name: Memcached Operator\n    url: https://memcached-operator.domain\n  maintainers:\n  - email: your@email.com\n    name: Maintainer Name\n  maturity: alpha\n  provider:\n    name: Provider Name\n    url: https://your.domain\n  version: 0.0.0\n\n"
  },
  {
    "path": "internal/generate/testdata/clusterserviceversions/bases/memcached-operator.clusterserviceversion.yaml",
    "content": "apiVersion: operators.coreos.com/v1alpha1\nkind: ClusterServiceVersion\nmetadata:\n  name: memcached-operator.v0.0.0\n  namespace: placeholder\n  annotations:\n    alm-examples: |-\n      [\n        {\n          \"apiVersion\": \"cache.example.com/v1alpha1\",\n          \"kind\": \"Memcached\",\n          \"metadata\": {\n            \"name\": \"memcached-sample\"\n          },\n          \"spec\": {\n            \"foo\": \"bar\"\n          }\n        }\n      ]\nspec:\n  apiservicedefinitions: {}\n  customresourcedefinitions: {}\n  # displayName is a required field.\n  displayName: Memcached Operator\n  install:\n    spec:\n      deployments: null\n    strategy: \"\"\n  installModes:\n  - supported: false\n    type: OwnNamespace\n  - supported: false\n    type: SingleNamespace\n  - supported: false\n    type: MultiNamespace\n  - supported: true\n    type: AllNamespaces\n  version: 0.0.0\n"
  },
  {
    "path": "internal/generate/testdata/clusterserviceversions/bases/with-ui-metadata.clusterserviceversion.yaml",
    "content": "apiVersion: operators.coreos.com/v1alpha1\nkind: ClusterServiceVersion\nmetadata:\n  annotations:\n    alm-examples: '[]'\n    capabilities: Basic Install\n  name: memcached-operator.v0.0.0\n  namespace: placeholder\nspec:\n  apiservicedefinitions: {}\n  customresourcedefinitions:\n    owned:\n    - description: Memcached is the Schema for the memcacheds API\n      displayName: Memcached App Display Name\n      kind: Memcached\n      name: memcacheds.cache.example.com\n      specDescriptors:\n      - description: List of Providers\n        displayName: Providers\n        path: providers\n      - description: Foo represents the Foo provider\n        displayName: Foo Provider\n        path: providers[0].foo\n      - description: CredentialsSecret is a reference to a secret containing authentication details for the Foo server\n        displayName: Secret Containing the Credentials\n        path: providers[0].foo.credentialsSecret\n        x-descriptors:\n        - urn:alm:descriptor:io.kubernetes:Secret\n      - description: Key represents the specific key to reference from the secret\n        displayName: Key within the secret\n        path: providers[0].foo.credentialsSecret.key\n        x-descriptors:\n        - urn:alm:descriptor:com.tectonic.ui:advanced\n        - urn:alm:descriptor:com.tectonic.ui:text\n      - description: Name represents the name of the secret\n        displayName: Name of the secret\n        path: providers[0].foo.credentialsSecret.name\n        x-descriptors:\n        - urn:alm:descriptor:com.tectonic.ui:advanced\n        - urn:alm:descriptor:com.tectonic.ui:text\n      - description: Namespace represents the namespace containing the secret\n        displayName: Namespace containing the secret\n        path: providers[0].foo.credentialsSecret.namespace\n        x-descriptors:\n        - urn:alm:descriptor:com.tectonic.ui:advanced\n        - urn:alm:descriptor:com.tectonic.ui:text\n      - description: Size is the size of the memcached deployment\n        displayName: Size\n        path: size\n      statusDescriptors:\n      - description: Nodes are the names of the memcached pods\n        displayName: Nodes\n        path: nodes\n      version: v1alpha1\n  description: Memcached Operator description. TODO.\n  displayName: Memcached Operator\n  icon:\n  - base64data: \"\"\n    mediatype: \"\"\n  install:\n    spec:\n      deployments: null\n    strategy: \"\"\n  installModes:\n  - supported: false\n    type: OwnNamespace\n  - supported: false\n    type: SingleNamespace\n  - supported: false\n    type: MultiNamespace\n  - supported: true\n    type: AllNamespaces\n  keywords:\n  - memcached-operator\n  links:\n  - name: Memcached Operator\n    url: https://memcached-operator.domain\n  maintainers:\n  - email: your@email.com\n    name: Maintainer Name\n  maturity: alpha\n  provider:\n    name: Provider Name\n    url: https://your.domain\n  version: 0.0.0\n"
  },
  {
    "path": "internal/generate/testdata/clusterserviceversions/output/memcached-operator-multiVersion.yaml",
    "content": "apiVersion: operators.coreos.com/v1alpha1\nkind: ClusterServiceVersion\nmetadata:\n  annotations:\n    alm-examples: |-\n      [\n        {\n          \"apiVersion\": \"cache.example.com/v1\",\n          \"kind\": \"Memcached\",\n          \"metadata\": {\n            \"name\": \"memcached-sample\"\n          },\n          \"spec\": {\n            \"foo\": \"bar\"\n          }\n        }\n      ]\n    capabilities: Basic Install\n    createdAt: \"2022-11-08T16:44:38Z\"\n  name: memcached-operator.v0.0.1\n  namespace: placeholder\nspec:\n  apiservicedefinitions: {}\n  customresourcedefinitions:\n    owned:\n    - description: Memcached is the Schema for the memcacheds API\n      displayName: Memcached\n      kind: Memcached\n      name: memcacheds.cache.example.com\n      version: v1\n    - description: Memcached is the Schema for the memcacheds API\n      displayName: Memcached\n      kind: Memcached\n      name: memcacheds.cache.example.com\n      version: v1alpha1\n  description: Memcached Operator description. TODO.\n  displayName: Memcached Operator\n  icon:\n  - base64data: \"\"\n    mediatype: \"\"\n  install:\n    spec:\n      clusterPermissions:\n      - rules:\n        - apiGroups:\n          - apps\n          resources:\n          - deployments\n          verbs:\n          - create\n          - delete\n          - get\n          - list\n          - patch\n          - update\n          - watch\n        - apiGroups:\n          - cache.example.com\n          resources:\n          - memcacheds\n          verbs:\n          - create\n          - delete\n          - get\n          - list\n          - patch\n          - update\n          - watch\n        - apiGroups:\n          - cache.example.com\n          resources:\n          - memcacheds/finalizers\n          verbs:\n          - update\n        - apiGroups:\n          - cache.example.com\n          resources:\n          - memcacheds/status\n          verbs:\n          - get\n          - patch\n          - update\n        - apiGroups:\n          - \"\"\n          resources:\n          - pods\n          verbs:\n          - get\n          - list\n          - watch\n        - apiGroups:\n          - authentication.k8s.io\n          resources:\n          - tokenreviews\n          verbs:\n          - create\n        - apiGroups:\n          - authorization.k8s.io\n          resources:\n          - subjectaccessreviews\n          verbs:\n          - create\n        serviceAccountName: default\n      deployments:\n      - name: memcached-operator-controller-manager\n        label:\n          control-plane: controller-manager\n        spec:\n          replicas: 1\n          selector:\n            matchLabels:\n              control-plane: controller-manager\n          strategy: {}\n          template:\n            metadata:\n              labels:\n                control-plane: controller-manager\n            spec:\n              containers:\n              - args:\n                - --secure-listen-address=0.0.0.0:8443\n                - --upstream=http://127.0.0.1:8080/\n                - --logtostderr=true\n                - --v=10\n                image: gcr.io/kubebuilder/kube-rbac-proxy:v0.8.0\n                name: kube-rbac-proxy\n                ports:\n                - containerPort: 8443\n                  name: https\n                resources: {}\n              - args:\n                - --health-probe-bind-address=:8081\n                - --metrics-bind-address=127.0.0.1:8080\n                - --leader-elect\n                command:\n                - /manager\n                image: controller:latest\n                livenessProbe:\n                  httpGet:\n                    path: /healthz\n                    port: 8081\n                  initialDelaySeconds: 15\n                  periodSeconds: 20\n                name: manager\n                ports:\n                - containerPort: 9443\n                  name: webhook-server\n                  protocol: TCP\n                readinessProbe:\n                  httpGet:\n                    path: /readyz\n                    port: 8081\n                  initialDelaySeconds: 5\n                  periodSeconds: 10\n                resources:\n                  limits:\n                    cpu: 100m\n                    memory: 30Mi\n                  requests:\n                    cpu: 100m\n                    memory: 20Mi\n                securityContext: {}\n              securityContext:\n                runAsNonRoot: true\n              terminationGracePeriodSeconds: 10\n      permissions:\n      - rules:\n        - apiGroups:\n          - \"\"\n          - coordination.k8s.io\n          resources:\n          - configmaps\n          - leases\n          verbs:\n          - get\n          - list\n          - watch\n          - create\n          - update\n          - patch\n          - delete\n        - apiGroups:\n          - \"\"\n          resources:\n          - events\n          verbs:\n          - create\n          - patch\n        serviceAccountName: default\n    strategy: deployment\n  installModes:\n  - supported: false\n    type: OwnNamespace\n  - supported: false\n    type: SingleNamespace\n  - supported: false\n    type: MultiNamespace\n  - supported: true\n    type: AllNamespaces\n  keywords:\n  - memcached-operator\n  links:\n  - name: Memcached Operator\n    url: https://memcached-operator.domain\n  maintainers:\n  - email: your@email.com\n    name: Maintainer Name\n  maturity: alpha\n  provider:\n    name: Provider Name\n    url: https://your.domain\n  version: 0.0.1\n  webhookdefinitions:\n  - admissionReviewVersions: null\n    containerPort: 443\n    conversionCRDs:\n    - memcacheds.cache.example.com\n    deploymentName: memcached-operator-controller-manager\n    generateName: cmemcacheds.kb.io\n    sideEffects: None\n    targetPort: 9443\n    type: ConversionWebhook\n    webhookPath: /convert\n  - admissionReviewVersions:\n    - v1\n    - v1beta1\n    containerPort: 443\n    deploymentName: memcached-operator-controller-manager\n    failurePolicy: Fail\n    generateName: mmemcached.kb.io\n    rules:\n    - apiGroups:\n      - cache.example.com\n      apiVersions:\n      - v1alpha1\n      operations:\n      - CREATE\n      - UPDATE\n      resources:\n      - memcacheds\n    sideEffects: None\n    targetPort: 9443\n    type: MutatingAdmissionWebhook\n    webhookPath: /mutate-cache-example-com-v1alpha1-memcached\n  - admissionReviewVersions:\n    - v1\n    - v1beta1\n    containerPort: 443\n    deploymentName: memcached-operator-controller-manager\n    failurePolicy: Fail\n    generateName: vmemcached.kb.io\n    rules:\n    - apiGroups:\n      - cache.example.com\n      apiVersions:\n      - v1alpha1\n      operations:\n      - CREATE\n      - UPDATE\n      resources:\n      - memcacheds\n    sideEffects: None\n    targetPort: 9443\n    type: ValidatingAdmissionWebhook\n    webhookPath: /validate-cache-example-com-v1alpha1-memcached\n"
  },
  {
    "path": "internal/generate/testdata/clusterserviceversions/output/memcached-operator.clusterserviceversion.yaml",
    "content": "apiVersion: operators.coreos.com/v1alpha1\nkind: ClusterServiceVersion\nmetadata:\n  annotations:\n    alm-examples: |-\n      [\n        {\n          \"apiVersion\": \"cache.example.com/v1alpha1\",\n          \"kind\": \"Memcached\",\n          \"metadata\": {\n            \"name\": \"memcached-sample\"\n          },\n          \"spec\": {\n            \"foo\": \"bar\"\n          }\n        }\n      ]\n  name: memcached-operator.v0.0.1\n  namespace: placeholder\nspec:\n  apiservicedefinitions: {}\n  customresourcedefinitions:\n    owned:\n    - kind: Memcached\n      name: memcacheds.cache.example.com\n      version: v1alpha1\n  displayName: Memcached Operator\n  install:\n    spec:\n      clusterPermissions:\n      - rules:\n        - apiGroups:\n          - cache.example.com\n          resources:\n          - memcacheds\n          verbs:\n          - create\n          - delete\n          - get\n          - list\n          - patch\n          - update\n          - watch\n        - apiGroups:\n          - cache.example.com\n          resources:\n          - memcacheds/status\n          verbs:\n          - get\n          - patch\n          - update\n        - apiGroups:\n          - authentication.k8s.io\n          resources:\n          - tokenreviews\n          verbs:\n          - create\n        - apiGroups:\n          - authorization.k8s.io\n          resources:\n          - subjectaccessreviews\n          verbs:\n          - create\n        serviceAccountName: default\n      deployments:\n      - name: memcached-operator-controller-manager\n        label:\n          control-plane: controller-manager\n        spec:\n          replicas: 1\n          selector:\n            matchLabels:\n              control-plane: controller-manager\n          strategy: {}\n          template:\n            metadata:\n              labels:\n                control-plane: controller-manager\n            spec:\n              containers:\n              - args:\n                - --secure-listen-address=0.0.0.0:8443\n                - --upstream=http://127.0.0.1:8080/\n                - --logtostderr=true\n                - --v=10\n                image: gcr.io/kubebuilder/kube-rbac-proxy:v0.8.0\n                name: kube-rbac-proxy\n                ports:\n                - containerPort: 8443\n                  name: https\n                resources: {}\n              - args:\n                - --metrics-addr=127.0.0.1:8080\n                - --enable-leader-election\n                command:\n                - /manager\n                image: controller:latest\n                name: manager\n                ports:\n                - containerPort: 9443\n                  name: webhook-server\n                  protocol: TCP\n                resources:\n                  limits:\n                    cpu: 100m\n                    memory: 30Mi\n                  requests:\n                    cpu: 100m\n                    memory: 20Mi\n                volumeMounts:\n                - mountPath: /tmp/k8s-webhook-server/serving-certs\n                  name: cert\n                  readOnly: true\n              terminationGracePeriodSeconds: 10\n              volumes:\n              - name: cert\n                secret:\n                  defaultMode: 420\n                  secretName: webhook-server-cert\n      permissions:\n      - rules:\n        - apiGroups:\n          - \"\"\n          resources:\n          - configmaps\n          verbs:\n          - get\n          - list\n          - watch\n          - create\n          - update\n          - patch\n          - delete\n        - apiGroups:\n          - \"\"\n          resources:\n          - configmaps/status\n          verbs:\n          - get\n          - update\n          - patch\n        - apiGroups:\n          - \"\"\n          resources:\n          - events\n          verbs:\n          - create\n          - patch\n        serviceAccountName: default\n    strategy: deployment\n  installModes:\n  - supported: false\n    type: OwnNamespace\n  - supported: false\n    type: SingleNamespace\n  - supported: false\n    type: MultiNamespace\n  - supported: true\n    type: AllNamespaces\n  version: 0.0.1\n  webhookdefinitions:\n  - admissionReviewVersions:\n    - v1beta1\n    containerPort: 443\n    conversionCRDs:\n    - memcacheds.cache.example.com\n    deploymentName: memcached-operator-controller-manager\n    generateName: cmemcacheds.kb.io\n    sideEffects: None\n    targetPort: 9443\n    type: ConversionWebhook\n    webhookPath: /convert\n  - admissionReviewVersions:\n    - v1beta1\n    containerPort: 443\n    deploymentName: memcached-operator-controller-manager\n    failurePolicy: Fail\n    generateName: mmemcached.kb.io\n    rules:\n    - apiGroups:\n      - cache.example.com\n      apiVersions:\n      - v1alpha1\n      operations:\n      - CREATE\n      - UPDATE\n      resources:\n      - memcacheds\n    sideEffects: None\n    targetPort: 9443\n    type: MutatingAdmissionWebhook\n    webhookPath: /mutate-cache-my-domain-v1alpha1-memcached\n  - admissionReviewVersions:\n    - v1beta1\n    containerPort: 443\n    deploymentName: memcached-operator-controller-manager\n    failurePolicy: Fail\n    generateName: vmemcached.kb.io\n    rules:\n    - apiGroups:\n      - cache.example.com\n      apiVersions:\n      - v1alpha1\n      operations:\n      - CREATE\n      - UPDATE\n      resources:\n      - memcacheds\n    sideEffects: None\n    targetPort: 9443\n    type: ValidatingAdmissionWebhook\n    webhookPath: /validate-cache-my-domain-v1alpha1-memcached\n"
  },
  {
    "path": "internal/generate/testdata/clusterserviceversions/output/with-ui-metadata.clusterserviceversion.yaml",
    "content": "apiVersion: operators.coreos.com/v1alpha1\nkind: ClusterServiceVersion\nmetadata:\n  annotations:\n    alm-examples: |-\n      [\n        {\n          \"apiVersion\": \"cache.example.com/v1alpha1\",\n          \"kind\": \"Memcached\",\n          \"metadata\": {\n            \"name\": \"memcached-sample\"\n          },\n          \"spec\": {\n            \"foo\": \"bar\"\n          }\n        }\n      ]\n    capabilities: Basic Install\n    createdAt: \"2022-11-08T16:44:38Z\"\n  name: memcached-operator.v0.0.1\n  namespace: placeholder\nspec:\n  apiservicedefinitions: {}\n  customresourcedefinitions:\n    owned:\n    - description: Memcached is the Schema for the memcacheds API\n      displayName: Memcached App Display Name\n      kind: Memcached\n      name: memcacheds.cache.example.com\n      specDescriptors:\n      - description: List of Providers\n        displayName: Providers\n        path: providers\n      - description: Foo represents the Foo provider\n        displayName: Foo Provider\n        path: providers[0].foo\n      - description: CredentialsSecret is a reference to a secret containing authentication details for the Foo server\n        displayName: Secret Containing the Credentials\n        path: providers[0].foo.credentialsSecret\n        x-descriptors:\n        - urn:alm:descriptor:io.kubernetes:Secret\n      - description: Key represents the specific key to reference from the secret\n        displayName: Key within the secret\n        path: providers[0].foo.credentialsSecret.key\n        x-descriptors:\n        - urn:alm:descriptor:com.tectonic.ui:advanced\n        - urn:alm:descriptor:com.tectonic.ui:text\n      - description: Name represents the name of the secret\n        displayName: Name of the secret\n        path: providers[0].foo.credentialsSecret.name\n        x-descriptors:\n        - urn:alm:descriptor:com.tectonic.ui:advanced\n        - urn:alm:descriptor:com.tectonic.ui:text\n      - description: Namespace represents the namespace containing the secret\n        displayName: Namespace containing the secret\n        path: providers[0].foo.credentialsSecret.namespace\n        x-descriptors:\n        - urn:alm:descriptor:com.tectonic.ui:advanced\n        - urn:alm:descriptor:com.tectonic.ui:text\n      - description: Size is the size of the memcached deployment\n        displayName: Size\n        path: size\n      statusDescriptors:\n      - description: Nodes are the names of the memcached pods\n        displayName: Nodes\n        path: nodes\n      version: v1alpha1\n  description: Memcached Operator description. TODO.\n  displayName: Memcached Operator\n  icon:\n  - base64data: \"\"\n    mediatype: \"\"\n  install:\n    spec:\n      clusterPermissions:\n      - rules:\n        - apiGroups:\n          - cache.example.com\n          resources:\n          - memcacheds\n          verbs:\n          - create\n          - delete\n          - get\n          - list\n          - patch\n          - update\n          - watch\n        - apiGroups:\n          - cache.example.com\n          resources:\n          - memcacheds/status\n          verbs:\n          - get\n          - patch\n          - update\n        - apiGroups:\n          - authentication.k8s.io\n          resources:\n          - tokenreviews\n          verbs:\n          - create\n        - apiGroups:\n          - authorization.k8s.io\n          resources:\n          - subjectaccessreviews\n          verbs:\n          - create\n        serviceAccountName: default\n      deployments:\n      - name: memcached-operator-controller-manager\n        label:\n          control-plane: controller-manager\n        spec:\n          replicas: 1\n          selector:\n            matchLabels:\n              control-plane: controller-manager\n          strategy: {}\n          template:\n            metadata:\n              labels:\n                control-plane: controller-manager\n            spec:\n              containers:\n              - args:\n                - --secure-listen-address=0.0.0.0:8443\n                - --upstream=http://127.0.0.1:8080/\n                - --logtostderr=true\n                - --v=10\n                image: gcr.io/kubebuilder/kube-rbac-proxy:v0.8.0\n                name: kube-rbac-proxy\n                ports:\n                - containerPort: 8443\n                  name: https\n                resources: {}\n              - args:\n                - --metrics-addr=127.0.0.1:8080\n                - --enable-leader-election\n                command:\n                - /manager\n                image: controller:latest\n                name: manager\n                ports:\n                - containerPort: 9443\n                  name: webhook-server\n                  protocol: TCP\n                resources:\n                  limits:\n                    cpu: 100m\n                    memory: 30Mi\n                  requests:\n                    cpu: 100m\n                    memory: 20Mi\n                volumeMounts:\n                - mountPath: /tmp/k8s-webhook-server/serving-certs\n                  name: cert\n                  readOnly: true\n              terminationGracePeriodSeconds: 10\n              volumes:\n              - name: cert\n                secret:\n                  defaultMode: 420\n                  secretName: webhook-server-cert\n      permissions:\n      - rules:\n        - apiGroups:\n          - \"\"\n          resources:\n          - configmaps\n          verbs:\n          - get\n          - list\n          - watch\n          - create\n          - update\n          - patch\n          - delete\n        - apiGroups:\n          - \"\"\n          resources:\n          - configmaps/status\n          verbs:\n          - get\n          - update\n          - patch\n        - apiGroups:\n          - \"\"\n          resources:\n          - events\n          verbs:\n          - create\n          - patch\n        serviceAccountName: default\n    strategy: deployment\n  installModes:\n  - supported: false\n    type: OwnNamespace\n  - supported: false\n    type: SingleNamespace\n  - supported: false\n    type: MultiNamespace\n  - supported: true\n    type: AllNamespaces\n  keywords:\n  - memcached-operator\n  links:\n  - name: Memcached Operator\n    url: https://memcached-operator.domain\n  maintainers:\n  - email: your@email.com\n    name: Maintainer Name\n  maturity: alpha\n  provider:\n    name: Provider Name\n    url: https://your.domain\n  version: 0.0.1\n  webhookdefinitions:\n  - admissionReviewVersions:\n    - v1beta1\n    containerPort: 443\n    conversionCRDs:\n    - memcacheds.cache.example.com\n    deploymentName: memcached-operator-controller-manager\n    generateName: cmemcacheds.kb.io\n    sideEffects: None\n    targetPort: 9443\n    type: ConversionWebhook\n    webhookPath: /convert\n  - admissionReviewVersions:\n    - v1beta1\n    containerPort: 443\n    deploymentName: memcached-operator-controller-manager\n    failurePolicy: Fail\n    generateName: mmemcached.kb.io\n    rules:\n    - apiGroups:\n      - cache.example.com\n      apiVersions:\n      - v1alpha1\n      operations:\n      - CREATE\n      - UPDATE\n      resources:\n      - memcacheds\n    sideEffects: None\n    targetPort: 9443\n    type: MutatingAdmissionWebhook\n    webhookPath: /mutate-cache-my-domain-v1alpha1-memcached\n  - admissionReviewVersions:\n    - v1beta1\n    containerPort: 443\n    deploymentName: memcached-operator-controller-manager\n    failurePolicy: Fail\n    generateName: vmemcached.kb.io\n    rules:\n    - apiGroups:\n      - cache.example.com\n      apiVersions:\n      - v1alpha1\n      operations:\n      - CREATE\n      - UPDATE\n      resources:\n      - memcacheds\n    sideEffects: None\n    targetPort: 9443\n    type: ValidatingAdmissionWebhook\n    webhookPath: /validate-cache-my-domain-v1alpha1-memcached\n"
  },
  {
    "path": "internal/generate/testdata/go/PROJECT",
    "content": "domain: example.com\nprojectName: memcached-operator\nrepo: github.com/example/memcached-operator\nresources:\n- group: cache\n  kind: Memcached\n  version: v1alpha1\nversion: 3-alpha\n"
  },
  {
    "path": "internal/generate/testdata/go/api/shared/doc.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage shared\n"
  },
  {
    "path": "internal/generate/testdata/go/api/shared/memcached_types.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage shared\n\nimport (\n\tv1 \"k8s.io/api/core/v1\"\n)\n\n// UsefulType is a type shared between APIs.\ntype UsefulType struct {\n\t// +operator-sdk:csv:customresourcedefinitions:type=spec\n\tContainers []v1.Container `json:\"containers\"`\n}\n"
  },
  {
    "path": "internal/generate/testdata/go/api/v1alpha1/doc.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Package v1alpha1 contains API Schema definitions for the cache v1alpha1 API group\n// +k8s:deepcopy-gen=package,register\n// +groupName=cache.example.com\npackage v1alpha1\n"
  },
  {
    "path": "internal/generate/testdata/go/api/v1alpha1/memcached_types.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage v1alpha1\n\nimport (\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/generate/testdata/go/api/shared\"\n)\n\n// MemcachedSpec defines the desired state of Memcached\ntype MemcachedSpec struct {\n\t// Size is the size of the memcached deployment\n\t//+operator-sdk:csv:customresourcedefinitions:type=spec\n\tSize int32 `json:\"size\"`\n\n\t// List of Providers\n\t//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName=\"Providers\"\n\tProviders []Provider `json:\"providers,omitempty\"`\n\n\t// A useful shared type.\n\tUseful shared.UsefulType `json:\",inline\"`\n}\n\n// Provider represents the container for a single provider\ntype Provider struct {\n\t// Foo represents the Foo provider\n\t//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName=\"Foo Provider\"\n\tFoo *FooProvider `json:\"foo,omitempty\"`\n}\n\n// FooProvider represents integration with Foo\ntype FooProvider struct {\n\t// CredentialsSecret is a reference to a secret containing authentication details for the Foo server\n\t//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName=\"Secret Containing the Credentials\",xDescriptors=\"urn:alm:descriptor:io.kubernetes:Secret\"\n\t//+kubebuilder:validation:Required\n\tCredentialsSecret *SecretRef `json:\"credentialsSecret\"`\n}\n\n// SecretRef represents a reference to an item within a Secret\ntype SecretRef struct {\n\t// Name represents the name of the secret\n\t//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName=\"Name of the secret\",xDescriptors={\"urn:alm:descriptor:com.tectonic.ui:advanced\",\"urn:alm:descriptor:com.tectonic.ui:text\"}\n\tName string `json:\"name\"`\n\n\t// Namespace represents the namespace containing the secret\n\t//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName=\"Namespace containing the secret\",xDescriptors={\"urn:alm:descriptor:com.tectonic.ui:advanced\",\"urn:alm:descriptor:com.tectonic.ui:text\"}\n\tNamespace string `json:\"namespace\"`\n\n\t// Key represents the specific key to reference from the secret\n\t//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName=\"Key within the secret\",xDescriptors={\"urn:alm:descriptor:com.tectonic.ui:advanced\",\"urn:alm:descriptor:com.tectonic.ui:text\"}\n\tKey string `json:\"key,omitempty\"`\n}\n\n// MemcachedStatus defines the observed state of Memcached\ntype MemcachedStatus struct {\n\t// Nodes are the names of the memcached pods\n\t//+operator-sdk:csv:customresourcedefinitions:type=status\n\tNodes []string `json:\"nodes\"`\n}\n\n// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n\n// Memcached is the Schema for the memcacheds API\n//+kubebuilder:subresource:status\n//+kubebuilder:resource:path=memcacheds,scope=Namespaced\n//+kubebuilder:storageversion\n//+operator-sdk:csv:customresourcedefinitions:displayName=\"Memcached App Display Name\"\ntype Memcached struct {\n\tmetav1.TypeMeta   `json:\",inline\"`\n\tmetav1.ObjectMeta `json:\"metadata,omitempty\"`\n\n\tSpec   MemcachedSpec   `json:\"spec,omitempty\"`\n\tStatus MemcachedStatus `json:\"status,omitempty\"`\n}\n\n// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n\n// MemcachedList contains a list of Memcached\ntype MemcachedList struct {\n\tmetav1.TypeMeta `json:\",inline\"`\n\tmetav1.ListMeta `json:\"metadata,omitempty\"`\n\tItems           []Memcached `json:\"items\"`\n}\n"
  },
  {
    "path": "internal/generate/testdata/go/api/v1alpha2/doc.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Package v1alpha2 contains API Schema definitions for the cache v1alpha2 API group\n// +k8s:deepcopy-gen=package,register\n// +groupName=cache.example.com\npackage v1alpha2\n"
  },
  {
    "path": "internal/generate/testdata/go/api/v1alpha2/dummy_types.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage v1alpha2\n\nimport (\n\tv1 \"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\n\t// Has the same name as a different import in memcached_types.go to test duplicate package names.\n\tfoo \"github.com/operator-framework/operator-sdk/internal/generate/testdata/go/api/shared\"\n)\n\n// +k8s:deepcopy-gen=false\n// +k8s:openapi-gen=false\ntype NoKindSpec struct {\n\t// Not included in anything, no kind type\n\t//+operator-sdk:csv:customresourcedefinitions:type=spec\n\t//+operator-sdk:csv:customresourcedefinitions:type=status\n\tSize int32 `json:\"size\"`\n\t// Not included in anything, no kind type\n\tBoss Hog `json:\"hog\"`\n}\n\n// +k8s:deepcopy-gen=false\n// +k8s:openapi-gen=false\ntype NoKindStatus struct {\n\t// Not included in anything, no kind type\n\t//+operator-sdk:csv:customresourcedefinitions:type=spec\n\t//+operator-sdk:csv:customresourcedefinitions:type=status\n\tNodes []string `json:\"nodes\"`\n}\n\n// +k8s:deepcopy-gen=false\n// +k8s:openapi-gen=false\ntype DummySpec struct {\n\t// Should be in spec\n\t//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName=\"dummy-size\",xDescriptors=\"urn:alm:descriptor:com.tectonic.ui:podCount\"\n\tSize int32 `json:\"size\"`\n\t// Should be in spec, but should not have array index in path\n\t//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName=\"Wheels\",xDescriptors=\"urn:alm:descriptor:com.tectonic.ui:text\"\n\tWheels []Wheel `json:\"wheels\"`\n\t// A useful shared type.\n\tUseful foo.UsefulType `json:\"useful\"`\n\t// +operator-sdk:csv:customresourcedefinitions:type=spec\n\tSideCar v1.Container `json:\"sideCar\"`\n}\n\n// +k8s:deepcopy-gen=false\n// +k8s:openapi-gen=false\ntype DummyStatus struct {\n\t// Should be in status but not spec, since DummyStatus isn't in DummySpec\n\t//+operator-sdk:csv:customresourcedefinitions:type=spec\n\t//+operator-sdk:csv:customresourcedefinitions:type=status\n\tNodes []string `json:\"nodes\"`\n\t// Not included in status but children should be\n\tBoss Hog `json:\"hog\"`\n}\n\n// +k8s:deepcopy-gen=false\n// +k8s:openapi-gen=false\ntype OtherDummyStatus struct {\n\t// Should be in status but not spec, since this isn't a spec type\n\t//+operator-sdk:csv:customresourcedefinitions:type=spec\n\t//+operator-sdk:csv:customresourcedefinitions:type=status\n\tNothing string `json:\"nothing\"`\n}\n\n// Dummy is the Schema for the dummy API\n// +k8s:deepcopy-gen=false\n// +k8s:openapi-gen=false\n//+kubebuilder:subresource:status\n//+kubebuilder:resource:path=dummys,scope=Namespaced\n//+operator-sdk:csv:customresourcedefinitions:displayName=\"Dummy App\"\n//+operator-sdk:csv:customresourcedefinitions:resources={{Deployment,v1,\"dummy-deployment\"},{ReplicaSet,v1beta2,\"dummy-replicaset\"},{Pod,v1,\"dummy-pod\"}}\ntype Dummy struct {\n\tmetav1.TypeMeta   `json:\",inline\"`\n\tmetav1.ObjectMeta `json:\"metadata,omitempty\"`\n\n\tSpec   DummySpec   `json:\"spec,omitempty\"`\n\tStatus DummyStatus `json:\"status,omitempty\"`\n}\n\n// OtherDummy is the Schema for the other dummy API\n// +k8s:deepcopy-gen=false\n// +k8s:openapi-gen=false\n//+operator-sdk:csv:customresourcedefinitions:displayName=\"Other Dummy App\"\n//+operator-sdk:csv:customresourcedefinitions:resources={{Service,v1,\"other-dummy-service\"},{Pod,v1,\"other-dummy-pod\"}}\ntype OtherDummy struct {\n\tmetav1.TypeMeta   `json:\",inline\"`\n\tmetav1.ObjectMeta `json:\"metadata,omitempty\"`\n\n\tSpec   Hog              `json:\"spec,omitempty\"`\n\tStatus OtherDummyStatus `json:\"status,omitempty\"`\n}\n\n// DummyList contains a list of Dummy\n// +k8s:deepcopy-gen=false\n// +k8s:openapi-gen=false\ntype DummyList struct {\n\tmetav1.TypeMeta `json:\",inline\"`\n\tmetav1.ListMeta `json:\"metadata,omitempty\"`\n\tItems           []Dummy `json:\"items\"`\n}\n"
  },
  {
    "path": "internal/generate/testdata/go/api/v1alpha2/memcached_types.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage v1alpha2\n\nimport (\n\t// Has the same name as a different import in dummy_types.go to test duplicate package names.\n\tfoo \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n)\n\n// MemcachedSpec defines the desired state of Memcached\ntype MemcachedSpec struct {\n\t// Size is the size of the memcached deployment\n\t//+operator-sdk:csv:customresourcedefinitions:type=spec\n\tSize int32 `json:\"size\"`\n}\n\n// MemcachedStatus defines the observed state of Memcached\ntype MemcachedStatus struct {\n\t// Nodes are the names of the memcached pods\n\t//+operator-sdk:csv:customresourcedefinitions:type=status\n\tNodes []string `json:\"nodes\"`\n}\n\n// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n\n// Memcached is the Schema for the memcacheds API\n//+kubebuilder:subresource:status\n//+kubebuilder:resource:path=memcacheds,scope=Namespaced\n//+kubebuilder:storageversion\n//+operator-sdk:csv:customresourcedefinitions:displayName=\"Memcached App\"\ntype Memcached struct {\n\tfoo.TypeMeta   `json:\",inline\"`\n\tfoo.ObjectMeta `json:\"metadata,omitempty\"`\n\n\tSpec   MemcachedSpec   `json:\"spec,omitempty\"`\n\tStatus MemcachedStatus `json:\"status,omitempty\"`\n}\n\n// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n\n// MemcachedList contains a list of Memcached\ntype MemcachedList struct {\n\tfoo.TypeMeta `json:\",inline\"`\n\tfoo.ListMeta `json:\"metadata,omitempty\"`\n\tItems        []Memcached `json:\"items\"`\n}\n"
  },
  {
    "path": "internal/generate/testdata/go/api/v1alpha2/memcachedrs_types.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage v1alpha2\n\nimport (\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n)\n\n// MemcachedRSSpec defines the desired state of MemcachedRS\ntype MemcachedRSSpec struct {\n\t//+operator-sdk:csv:customresourcedefinitions:type=spec\n\tNumNodes int32 `json:\"numNodes\"`\n}\n\n// MemcachedRSStatus defines the observed state of MemcachedRS\ntype MemcachedRSStatus struct {\n\t//+operator-sdk:csv:customresourcedefinitions:type=status\n\tNodeList []string `json:\"nodeList\"`\n}\n\n// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n\n// MemcachedRS is the Schema for the memcachedrs API\n//+kubebuilder:subresource:status\n//+kubebuilder:resource:path=memcachedrs,scope=Namespaced\n//+kubebuilder:storageversion\n//+operator-sdk:csv:customresourcedefinitions:displayName=\"MemcachedRS App\"\ntype MemcachedRS struct {\n\tmetav1.TypeMeta   `json:\",inline\"`\n\tmetav1.ObjectMeta `json:\"metadata,omitempty\"`\n\n\tSpec   MemcachedRSSpec   `json:\"spec,omitempty\"`\n\tStatus MemcachedRSStatus `json:\"status,omitempty\"`\n}\n\n// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n\n// MemcachedRSList contains a list of MemcachedRS\ntype MemcachedRSList struct {\n\tmetav1.TypeMeta `json:\",inline\"`\n\tmetav1.ListMeta `json:\"metadata,omitempty\"`\n\tItems           []MemcachedRS `json:\"items\"`\n}\n"
  },
  {
    "path": "internal/generate/testdata/go/api/v1alpha2/motorcycle_types.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage v1alpha2\n\n// +k8s:deepcopy-gen=false\n// +k8s:openapi-gen=false\ntype Hog struct {\n\t// Should be in status but not spec, since Hog isn't in DummySpec\n\t// +operator-sdk:csv:customresourcedefinitions:type=spec\n\t// +operator-sdk:csv:customresourcedefinitions:type=status,displayName=\"boss-hog-engine\"\n\tEngine Engine `json:\"engine\"`\n\t// Not in spec or status, no boolean annotation\n\t// +operator-sdk:csv:customresourcedefinitions:displayName=\"doesnt-matter\"\n\tBrand string `json:\"brand\"`\n\t// Not in spec or status\n\tHelmet string `json:\"helmet\"`\n\t// Fields should be inlined\n\t// +operator-sdk:csv:customresourcedefinitions:type=spec\n\t// +operator-sdk:csv:customresourcedefinitions:type=status\n\tInlined InlinedComponent `json:\",inline\"`\n\t// Fields should be inlined\n\tInlinedComponent `json:\",inline\"`\n\t// Should be ignored\n\t// +operator-sdk:csv:customresourcedefinitions:type=spec\n\t// +operator-sdk:csv:customresourcedefinitions:type=status\n\tIgnored IgnoredComponent `json:\"-\"`\n\t// Should be ignored, but exported children should not be\n\tnotExported `json:\",inline\"`\n}\n\ntype notExported struct {\n\t// +operator-sdk:csv:customresourcedefinitions:type=spec\n\t// +operator-sdk:csv:customresourcedefinitions:type=status\n\tPublic string `json:\"foo\"`\n\t// +operator-sdk:csv:customresourcedefinitions:type=spec\n\t// +operator-sdk:csv:customresourcedefinitions:type=status\n\tprivate string `json:\"-\"`\n}\n\n// +k8s:deepcopy-gen=false\n// +k8s:openapi-gen=false\ntype Engine struct {\n\t// Should not be included, no annotations.\n\tPistons []string `json:\"pistons\"`\n}\n\n// +k8s:deepcopy-gen=false\n// +k8s:openapi-gen=false\ntype Wheel struct {\n\t// Type should be in spec with path equal to wheels[0].type\n\t// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName=\"Wheel Type\",xDescriptors=\"urn:alm:descriptor:com.tectonic.ui:arrayFieldGroup:wheels\" ; \"urn:alm:descriptor:com.tectonic.ui:text\"\n\tType string `json:\"type\"`\n}\n\n// +k8s:deepcopy-gen=false\n// +k8s:openapi-gen=false\ntype InlinedComponent struct {\n\t// +operator-sdk:csv:customresourcedefinitions:type=spec\n\t// +operator-sdk:csv:customresourcedefinitions:type=status\n\tSeatMaterial string `json:\"seatMaterial\"`\n}\n\n// +k8s:deepcopy-gen=false\n// +k8s:openapi-gen=false\ntype IgnoredComponent struct {\n\t// +operator-sdk:csv:customresourcedefinitions:type=spec\n\t// +operator-sdk:csv:customresourcedefinitions:type=status\n\tTrunkSpace string `json:\"trunkSpace\"`\n}\n"
  },
  {
    "path": "internal/generate/testdata/go/static/basic.multiversion.operator.yaml",
    "content": "apiVersion: v1\nkind: Namespace\nmetadata:\n  labels:\n    control-plane: controller-manager\n  name: memcached-operator-system\n---\napiVersion: apiextensions.k8s.io/v1\nkind: CustomResourceDefinition\nmetadata:\n  annotations:\n    cert-manager.io/inject-ca-from: memcached-operator-system/memcached-operator-serving-cert\n    controller-gen.kubebuilder.io/version: v0.4.1\n  creationTimestamp: null\n  name: memcacheds.cache.example.com\nspec:\n  conversion:\n    strategy: Webhook\n    webhook:\n      clientConfig:\n        service:\n          name: memcached-operator-webhook-service\n          namespace: memcached-operator-system\n          path: /convert\n      conversionReviewVersions: null\n  group: cache.example.com\n  names:\n    kind: Memcached\n    listKind: MemcachedList\n    plural: memcacheds\n    singular: memcached\n  scope: Namespaced\n  versions:\n  - name: v1\n    schema:\n      openAPIV3Schema:\n        description: Memcached is the Schema for the memcacheds API\n        properties:\n          apiVersion:\n            description: 'APIVersion defines the versioned schema of this representation\n              of an object. Servers should convert recognized schemas to the latest\n              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'\n            type: string\n          kind:\n            description: 'Kind is a string value representing the REST resource this\n              object represents. Servers may infer this from the endpoint the client\n              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'\n            type: string\n          metadata:\n            type: object\n          spec:\n            description: MemcachedSpec defines the desired state of Memcached\n            properties:\n              foo:\n                description: Foo is an example field of Memcached. Edit memcached_types.go\n                  to remove/update\n                type: string\n              schedule:\n                description: describes a Cron schedule.\n                properties:\n                  dayOfMonth:\n                    description: specifies the day of the month during which the job\n                      executes.\n                    type: string\n                  dayOfWeek:\n                    description: specifies the day of the week during which the job\n                      executes.\n                    type: string\n                  hour:\n                    description: specifies the hour during which the job executes.\n                    type: string\n                  minute:\n                    description: specifies the minute during which the job executes.\n                    type: string\n                  month:\n                    description: specifies the month during which the job executes.\n                    type: string\n                type: object\n              size:\n                format: int32\n                type: integer\n            required:\n            - schedule\n            - size\n            type: object\n          status:\n            description: MemcachedStatus defines the observed state of Memcached\n            properties:\n              nodes:\n                description: 'INSERT ADDITIONAL STATUS FIELD - define observed state\n                  of cluster Important: Run \"make\" to regenerate code after modifying\n                  this file'\n                items:\n                  type: string\n                type: array\n            required:\n            - nodes\n            type: object\n        type: object\n    served: true\n    storage: false\n    subresources:\n      status: {}\n  - name: v1alpha1\n    schema:\n      openAPIV3Schema:\n        description: Memcached is the Schema for the memcacheds API\n        properties:\n          apiVersion:\n            description: 'APIVersion defines the versioned schema of this representation\n              of an object. Servers should convert recognized schemas to the latest\n              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'\n            type: string\n          kind:\n            description: 'Kind is a string value representing the REST resource this\n              object represents. Servers may infer this from the endpoint the client\n              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'\n            type: string\n          metadata:\n            type: object\n          spec:\n            description: MemcachedSpec defines the desired state of Memcached\n            properties:\n              foo:\n                description: Foo is an example field of Memcached. Edit memcached_types.go\n                  to remove/update\n                type: string\n              schedule:\n                type: string\n              size:\n                description: Size defines the number of Memcached instances\n                format: int32\n                type: integer\n            required:\n            - schedule\n            type: object\n          status:\n            description: MemcachedStatus defines the observed state of Memcached\n            properties:\n              nodes:\n                description: Nodes store the name of the pods which are running Memcached\n                  instances\n                items:\n                  type: string\n                type: array\n            type: object\n        type: object\n    served: true\n    storage: true\n    subresources:\n      status: {}\nstatus:\n  acceptedNames:\n    kind: \"\"\n    plural: \"\"\n  conditions: []\n  storedVersions: []\n---\napiVersion: admissionregistration.k8s.io/v1\nkind: MutatingWebhookConfiguration\nmetadata:\n  creationTimestamp: null\n  name: memcached-operator-mutating-webhook-configuration\nwebhooks:\n- admissionReviewVersions:\n  - v1\n  - v1beta1\n  clientConfig:\n    service:\n      name: memcached-operator-webhook-service\n      namespace: memcached-operator-system\n      path: /mutate-cache-example-com-v1alpha1-memcached\n  failurePolicy: Fail\n  name: mmemcached.kb.io\n  rules:\n  - apiGroups:\n    - cache.example.com\n    apiVersions:\n    - v1alpha1\n    operations:\n    - CREATE\n    - UPDATE\n    resources:\n    - memcacheds\n  sideEffects: None\n---\n# permissions to do leader election.\napiVersion: rbac.authorization.k8s.io/v1\nkind: Role\nmetadata:\n  name: memcached-operator-leader-election-role\n  namespace: memcached-operator-system\nrules:\n- apiGroups:\n  - \"\"\n  - coordination.k8s.io\n  resources:\n  - configmaps\n  - leases\n  verbs:\n  - get\n  - list\n  - watch\n  - create\n  - update\n  - patch\n  - delete\n- apiGroups:\n  - \"\"\n  resources:\n  - events\n  verbs:\n  - create\n  - patch\n---\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  creationTimestamp: null\n  name: memcached-operator-manager-role\nrules:\n- apiGroups:\n  - apps\n  resources:\n  - deployments\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds/finalizers\n  verbs:\n  - update\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds/status\n  verbs:\n  - get\n  - patch\n  - update\n- apiGroups:\n  - \"\"\n  resources:\n  - pods\n  verbs:\n  - get\n  - list\n  - watch\n---\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  name: memcached-operator-proxy-role\nrules:\n- apiGroups: [\"authentication.k8s.io\"]\n  resources:\n  - tokenreviews\n  verbs: [\"create\"]\n- apiGroups: [\"authorization.k8s.io\"]\n  resources:\n  - subjectaccessreviews\n  verbs: [\"create\"]\n---\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  name: memcached-operator-metrics-reader\nrules:\n- nonResourceURLs: [\"/metrics\"]\n  verbs: [\"get\"]\n---\napiVersion: rbac.authorization.k8s.io/v1\nkind: RoleBinding\nmetadata:\n  name: memcached-operator-leader-election-rolebinding\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: Role\n  name: memcached-operator-leader-election-role\nsubjects:\n- kind: ServiceAccount\n  name: default\n  namespace: memcached-operator-system\n---\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: default\n  namespace: memcached-operator-system\n---\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n  name: memcached-operator-manager-rolebinding\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: memcached-operator-manager-role\nsubjects:\n- kind: ServiceAccount\n  name: default\n  namespace: memcached-operator-system\n---\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n  name: memcached-operator-proxy-rolebinding\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: memcached-operator-proxy-role\nsubjects:\n- kind: ServiceAccount\n  name: default\n  namespace: memcached-operator-system\n---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    control-plane: memcached-operator-controller-manager\n  name: memcached-operator-controller-manager-metrics-service\n  namespace: memcached-operator-system\nspec:\n  ports:\n  - name: https\n    port: 8443\n    targetPort: https\n  selector:\n    control-plane: controller-manager\n---\napiVersion: v1\nkind: Service\nmetadata:\n  name: memcached-operator-webhook-service\n  namespace: memcached-operator-system\nspec:\n  ports:\n  - port: 443\n    targetPort: 9443\n  selector:\n    control-plane: controller-manager\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    control-plane: controller-manager\n  name: memcached-operator-controller-manager\n  namespace: memcached-operator-system\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      control-plane: controller-manager\n  template:\n    metadata:\n      labels:\n        control-plane: controller-manager\n    spec:\n      containers:\n      - args:\n        - --secure-listen-address=0.0.0.0:8443\n        - --upstream=http://127.0.0.1:8080/\n        - --logtostderr=true\n        - --v=10\n        image: gcr.io/kubebuilder/kube-rbac-proxy:v0.8.0\n        name: kube-rbac-proxy\n        ports:\n        - containerPort: 8443\n          name: https\n      - args:\n        - --health-probe-bind-address=:8081\n        - --metrics-bind-address=127.0.0.1:8080\n        - --leader-elect\n        command:\n        - /manager\n        image: controller:latest\n        livenessProbe:\n          httpGet:\n            path: /healthz\n            port: 8081\n          initialDelaySeconds: 15\n          periodSeconds: 20\n        name: manager\n        ports:\n        - containerPort: 9443\n          name: webhook-server\n          protocol: TCP\n        readinessProbe:\n          httpGet:\n            path: /readyz\n            port: 8081\n          initialDelaySeconds: 5\n          periodSeconds: 10  \n        resources:\n          limits:\n            cpu: 100m\n            memory: 30Mi\n          requests:\n            cpu: 100m\n            memory: 20Mi\n        securityContext:\n          allowPrivateEscalation: false\n      securityContext:\n         runAsNonRoot: true\n      terminationGracePeriodSeconds: 10\n---\napiVersion: cache.example.com/v1\nkind: Memcached\nmetadata:\n  name: memcached-sample\nspec:\n  # TODO(user): Add fields here\n  foo: bar\n---\napiVersion: admissionregistration.k8s.io/v1\nkind: ValidatingWebhookConfiguration\nmetadata:\n  creationTimestamp: null\n  name: memcached-operator-validating-webhook-configuration\nwebhooks:\n- admissionReviewVersions:\n  - v1\n  - v1beta1\n  clientConfig:\n    service:\n      name: memcached-operator-webhook-service\n      namespace: memcached-operator-system\n      path: /validate-cache-example-com-v1alpha1-memcached\n  failurePolicy: Fail\n  name: vmemcached.kb.io\n  rules:\n  - apiGroups:\n    - cache.example.com\n    apiVersions:\n    - v1alpha1\n    operations:\n    - CREATE\n    - UPDATE\n    resources:\n    - memcacheds\n  sideEffects: None"
  },
  {
    "path": "internal/generate/testdata/go/static/basic.operator.yaml",
    "content": "apiVersion: v1\nkind: Namespace\nmetadata:\n  labels:\n    control-plane: controller-manager\n  name: memcached-operator-system\n---\napiVersion: apiextensions.k8s.io/v1beta1\nkind: CustomResourceDefinition\nmetadata:\n  annotations:\n    controller-gen.kubebuilder.io/version: v0.3.0\n  creationTimestamp: null\n  name: memcacheds.cache.example.com\nspec:\n  conversion:\n      strategy: Webhook\n      webhookClientConfig:\n        caBundle: Cg==\n        service:\n          name: memcached-operator-webhook-service\n          namespace: memcached-operator-system\n          path: /convert\n      conversionReviewVersions:\n      - v1beta1\n  group: cache.example.com\n  names:\n    kind: Memcached\n    listKind: MemcachedList\n    plural: memcacheds\n    singular: memcached\n  scope: Namespaced\n  subresources:\n    status: {}\n  validation:\n    openAPIV3Schema:\n      description: Memcached is the Schema for the memcacheds API\n      properties:\n        apiVersion:\n          description: 'APIVersion defines the versioned schema of this representation\n            of an object. Servers should convert recognized schemas to the latest\n            internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'\n          type: string\n        kind:\n          description: 'Kind is a string value representing the REST resource this\n            object represents. Servers may infer this from the endpoint the client\n            submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'\n          type: string\n        metadata:\n          type: object\n        spec:\n          description: MemcachedSpec defines the desired state of Memcached\n          properties:\n            foo:\n              description: Foo is an example field of Memcached. Edit Memcached_types.go\n                to remove/update\n              type: string\n          type: object\n        status:\n          description: MemcachedStatus defines the observed state of Memcached\n          type: object\n      type: object\n  version: v1alpha1\n  versions:\n  - name: v1alpha1\n    served: true\n    storage: true\nstatus:\n  acceptedNames:\n    kind: \"\"\n    plural: \"\"\n  conditions: []\n  storedVersions: []\n---\napiVersion: admissionregistration.k8s.io/v1beta1\nkind: MutatingWebhookConfiguration\nmetadata:\n  creationTimestamp: null\n  name: memcached-operator-mutating-webhook-configuration\nwebhooks:\n- clientConfig:\n    caBundle: Cg==\n    service:\n      name: memcached-operator-webhook-service\n      namespace: memcached-operator-system\n      path: /mutate-cache-my-domain-v1alpha1-memcached\n  failurePolicy: Fail\n  name: mmemcached.kb.io\n  rules:\n  - apiGroups:\n    - cache.example.com\n    apiVersions:\n    - v1alpha1\n    operations:\n    - CREATE\n    - UPDATE\n    resources:\n    - memcacheds\n---\napiVersion: rbac.authorization.k8s.io/v1\nkind: Role\nmetadata:\n  name: memcached-operator-leader-election-role\n  namespace: memcached-operator-system\nrules:\n- apiGroups:\n  - \"\"\n  resources:\n  - configmaps\n  verbs:\n  - get\n  - list\n  - watch\n  - create\n  - update\n  - patch\n  - delete\n- apiGroups:\n  - \"\"\n  resources:\n  - configmaps/status\n  verbs:\n  - get\n  - update\n  - patch\n- apiGroups:\n  - \"\"\n  resources:\n  - events\n  verbs:\n  - create\n  - patch\n---\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  creationTimestamp: null\n  name: memcached-operator-manager-role\nrules:\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds/status\n  verbs:\n  - get\n  - patch\n  - update\n---\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  name: memcached-operator-proxy-role\nrules:\n- apiGroups:\n  - authentication.k8s.io\n  resources:\n  - tokenreviews\n  verbs:\n  - create\n- apiGroups:\n  - authorization.k8s.io\n  resources:\n  - subjectaccessreviews\n  verbs:\n  - create\n---\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  name: memcached-operator-metrics-reader\nrules:\n- nonResourceURLs:\n  - /metrics\n  verbs:\n  - get\n---\napiVersion: rbac.authorization.k8s.io/v1\nkind: RoleBinding\nmetadata:\n  name: memcached-operator-leader-election-rolebinding\n  namespace: memcached-operator-system\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: Role\n  name: memcached-operator-leader-election-role\nsubjects:\n- kind: ServiceAccount\n  name: default\n  namespace: memcached-operator-system\n---\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n  name: memcached-operator-manager-rolebinding\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: memcached-operator-manager-role\nsubjects:\n- kind: ServiceAccount\n  name: default\n  namespace: memcached-operator-system\n---\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n  name: memcached-operator-proxy-rolebinding\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: memcached-operator-proxy-role\nsubjects:\n- kind: ServiceAccount\n  name: default\n  namespace: memcached-operator-system\n---\napiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    control-plane: controller-manager\n  name: memcached-operator-controller-manager-metrics-service\n  namespace: memcached-operator-system\nspec:\n  ports:\n  - name: https\n    port: 8443\n    targetPort: https\n  selector:\n    control-plane: controller-manager\n---\napiVersion: v1\nkind: Service\nmetadata:\n  name: memcached-operator-webhook-service\n  namespace: memcached-operator-system\nspec:\n  ports:\n  - port: 443\n    targetPort: 9443\n  selector:\n    control-plane: controller-manager\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  labels:\n    control-plane: controller-manager\n  name: memcached-operator-controller-manager\n  namespace: memcached-operator-system\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      control-plane: controller-manager\n  template:\n    metadata:\n      labels:\n        control-plane: controller-manager\n    spec:\n      containers:\n      - args:\n        - --secure-listen-address=0.0.0.0:8443\n        - --upstream=http://127.0.0.1:8080/\n        - --logtostderr=true\n        - --v=10\n        image: gcr.io/kubebuilder/kube-rbac-proxy:v0.8.0\n        name: kube-rbac-proxy\n        ports:\n        - containerPort: 8443\n          name: https\n      - args:\n        - --metrics-addr=127.0.0.1:8080\n        - --enable-leader-election\n        command:\n        - /manager\n        image: controller:latest\n        name: manager\n        ports:\n        - containerPort: 9443\n          name: webhook-server\n          protocol: TCP\n        resources:\n          limits:\n            cpu: 100m\n            memory: 30Mi\n          requests:\n            cpu: 100m\n            memory: 20Mi\n        volumeMounts:\n        - mountPath: /tmp/k8s-webhook-server/serving-certs\n          name: cert\n          readOnly: true\n      terminationGracePeriodSeconds: 10\n      volumes:\n      - name: cert\n        secret:\n          defaultMode: 420\n          secretName: webhook-server-cert\n---\napiVersion: cache.example.com/v1alpha1\nkind: Memcached\nmetadata:\n  name: memcached-sample\nspec:\n  foo: bar\n---\napiVersion: admissionregistration.k8s.io/v1beta1\nkind: ValidatingWebhookConfiguration\nmetadata:\n  creationTimestamp: null\n  name: memcached-operator-validating-webhook-configuration\nwebhooks:\n- clientConfig:\n    caBundle: Cg==\n    service:\n      name: memcached-operator-webhook-service\n      namespace: memcached-operator-system\n      path: /validate-cache-my-domain-v1alpha1-memcached\n  failurePolicy: Fail\n  name: vmemcached.kb.io\n  rules:\n  - apiGroups:\n    - cache.example.com\n    apiVersions:\n    - v1alpha1\n    operations:\n    - CREATE\n    - UPDATE\n    resources:\n    - memcacheds\n"
  },
  {
    "path": "internal/generate/testdata/memcached-operator.package.yaml",
    "content": "channels:\n- currentCSV: memcached-operator.v0.0.1\n  name: alpha\ndefaultChannel: alpha\npackageName: memcached-operator\n"
  },
  {
    "path": "internal/helm/client/actionconfig.go",
    "content": "/*\nCopyright 2020 The Operator-SDK Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage client\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"sync\"\n\n\t\"k8s.io/client-go/kubernetes\"\n\n\t\"github.com/go-logr/logr\"\n\t\"helm.sh/helm/v3/pkg/action\"\n\t\"helm.sh/helm/v3/pkg/kube\"\n\t\"helm.sh/helm/v3/pkg/storage\"\n\t\"helm.sh/helm/v3/pkg/storage/driver\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\t\"k8s.io/apimachinery/pkg/api/meta\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\tv1 \"k8s.io/client-go/kubernetes/typed/core/v1\"\n\t\"k8s.io/client-go/rest\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client\"\n)\n\ntype ActionConfigGetter interface {\n\tActionConfigFor(obj client.Object) (*action.Configuration, error)\n}\n\nfunc NewActionConfigGetter(cfg *rest.Config, rm meta.RESTMapper, log logr.Logger) (ActionConfigGetter, error) {\n\trcg := newRESTClientGetter(cfg, rm, \"\")\n\t// Setup the debug log function that Helm will use\n\tdebugLog := func(format string, v ...any) {\n\t\tif log.Enabled() {\n\t\t\tlog.V(1).Info(fmt.Sprintf(format, v...))\n\t\t}\n\t}\n\n\tkc := kube.New(rcg)\n\tkc.Log = debugLog\n\n\tkcs, err := kc.Factory.KubernetesClientSet()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"creating kubernetes client set: %w\", err)\n\t}\n\n\treturn &actionConfigGetter{\n\t\tkubeClient:          kc,\n\t\tkubeClientSet:       kcs,\n\t\tdebugLog:            debugLog,\n\t\trestClientGetter:    rcg.restClientGetter,\n\t\twatchedSecrets:      map[string]*WatchedSecrets{},\n\t\twatchedSecretsMutex: &sync.Mutex{},\n\t}, nil\n}\n\nvar _ ActionConfigGetter = &actionConfigGetter{}\n\ntype actionConfigGetter struct {\n\tkubeClient          *kube.Client\n\tkubeClientSet       kubernetes.Interface\n\tdebugLog            func(string, ...any)\n\trestClientGetter    *restClientGetter\n\twatchedSecrets      map[string]*WatchedSecrets\n\twatchedSecretsMutex *sync.Mutex\n}\n\n// Creates a new watcher for each namespace to not require cluster-wide secret access\nfunc (acg *actionConfigGetter) getWatchedSecretsForNamespace(namespace string) *WatchedSecrets {\n\tacg.watchedSecretsMutex.Lock()\n\tif _, found := acg.watchedSecrets[namespace]; !found {\n\t\tacg.watchedSecrets[namespace] = NewWatchedSecrets(acg.kubeClientSet, namespace)\n\t\tacg.watchedSecrets[namespace].Run()\n\t}\n\tacg.watchedSecretsMutex.Unlock()\n\treturn acg.watchedSecrets[namespace]\n}\n\nfunc (acg *actionConfigGetter) ActionConfigFor(obj client.Object) (*action.Configuration, error) {\n\twatchedSecrets := acg.getWatchedSecretsForNamespace(obj.GetNamespace())\n\townerRef := metav1.NewControllerRef(obj, obj.GetObjectKind().GroupVersionKind())\n\td := driver.NewSecrets(&ownerRefSecretClient{\n\t\tSecretInterface: watchedSecrets,\n\t\trefs:            []metav1.OwnerReference{*ownerRef},\n\t})\n\n\t// Also, use the debug log for the storage driver\n\td.Log = acg.debugLog\n\n\t// Initialize the storage backend\n\ts := storage.Init(d)\n\n\tkubeClient := *acg.kubeClient\n\tkubeClient.Namespace = obj.GetNamespace()\n\n\townerRefClient, err := NewOwnerRefInjectingClient(&kubeClient, acg.restClientGetter.restMapper, obj)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"could not create owner reference injecting client: %w\", err)\n\t}\n\n\treturn &action.Configuration{\n\t\tRESTClientGetter: acg.restClientGetter.ForNamespace(obj.GetNamespace()),\n\t\tReleases:         s,\n\t\tKubeClient:       ownerRefClient,\n\t\tLog:              acg.debugLog,\n\t}, nil\n}\n\nvar _ v1.SecretInterface = &ownerRefSecretClient{}\n\ntype ownerRefSecretClient struct {\n\tv1.SecretInterface\n\trefs []metav1.OwnerReference\n}\n\nfunc (c *ownerRefSecretClient) Create(ctx context.Context, in *corev1.Secret, opts metav1.CreateOptions) (*corev1.Secret, error) {\n\tin.OwnerReferences = append(in.OwnerReferences, c.refs...)\n\treturn c.SecretInterface.Create(ctx, in, opts)\n}\n\nfunc (c *ownerRefSecretClient) Update(ctx context.Context, in *corev1.Secret, opts metav1.UpdateOptions) (*corev1.Secret, error) {\n\tin.OwnerReferences = append(in.OwnerReferences, c.refs...)\n\treturn c.SecretInterface.Update(ctx, in, opts)\n}\n"
  },
  {
    "path": "internal/helm/client/client.go",
    "content": "// Copyright 2018 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage client\n\nimport (\n\t\"errors\"\n\t\"io\"\n\t\"strings\"\n\n\t\"github.com/operator-framework/operator-lib/handler\"\n\t\"github.com/operator-framework/operator-sdk/internal/util/k8sutil\"\n\t\"helm.sh/helm/v3/pkg/kube\"\n\t\"k8s.io/apimachinery/pkg/api/meta\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\t\"k8s.io/cli-runtime/pkg/resource\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client\"\n)\n\nvar _ kube.Interface = &ownerRefInjectingClient{}\n\nfunc NewOwnerRefInjectingClient(base kube.Interface, restMapper meta.RESTMapper,\n\tobj client.Object) (kube.Interface, error) {\n\n\tif obj != nil {\n\t\tif obj.GetObjectKind() != nil {\n\t\t\tif obj.GetObjectKind().GroupVersionKind().Empty() || obj.GetName() == \"\" || obj.GetUID() == \"\" {\n\t\t\t\tvar err = errors.New(\"owner resource is invalid\")\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\t}\n\treturn &ownerRefInjectingClient{\n\t\tInterface:  base,\n\t\trestMapper: restMapper,\n\t\towner:      obj,\n\t}, nil\n}\n\ntype ownerRefInjectingClient struct {\n\tkube.Interface\n\trestMapper meta.RESTMapper\n\towner      client.Object\n}\n\nfunc (c *ownerRefInjectingClient) Build(reader io.Reader, validate bool) (kube.ResourceList, error) {\n\tresourceList, err := c.Interface.Build(reader, validate)\n\tif err != nil {\n\t\treturn resourceList, err\n\t}\n\terr = resourceList.Visit(func(r *resource.Info, err error) error {\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tobjMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(r.Object)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tu := &unstructured.Unstructured{Object: objMap}\n\t\tuseOwnerRef, err := k8sutil.SupportsOwnerReference(c.restMapper, c.owner, u, \"\")\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// If the resource contains the Helm resource-policy keep annotation, then do not add\n\t\t// the owner reference. So when the CR is deleted, Kubernetes won't GCs the resource.\n\t\tif useOwnerRef && !containsResourcePolicyKeep(u.GetAnnotations()) {\n\t\t\townerRef := metav1.NewControllerRef(c.owner, c.owner.GetObjectKind().GroupVersionKind())\n\t\t\tu.SetOwnerReferences([]metav1.OwnerReference{*ownerRef})\n\t\t} else {\n\t\t\terr := handler.SetOwnerAnnotations(c.owner, u)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn resourceList, nil\n}\n\nfunc containsResourcePolicyKeep(annotations map[string]string) bool {\n\tif annotations == nil {\n\t\treturn false\n\t}\n\tresourcePolicyType, ok := annotations[kube.ResourcePolicyAnno]\n\tif !ok {\n\t\treturn false\n\t}\n\tresourcePolicyType = strings.ToLower(strings.TrimSpace(resourcePolicyType))\n\treturn resourcePolicyType == kube.KeepPolicy\n}\n\ntype labelInjectingClient struct {\n\tkube.Interface\n\tlabels map[string]string\n}\n\nfunc NewLabelInjectingClient(base kube.Interface, labels map[string]string) kube.Interface {\n\treturn &labelInjectingClient{\n\t\tInterface: base,\n\t\tlabels:    labels,\n\t}\n}\n\nfunc (c *labelInjectingClient) Build(reader io.Reader, validate bool) (kube.ResourceList, error) {\n\tresourceList, err := c.Interface.Build(reader, validate)\n\tif err != nil {\n\t\treturn resourceList, err\n\t}\n\terr = resourceList.Visit(func(r *resource.Info, err error) error {\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tobjMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(r.Object)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tu := &unstructured.Unstructured{Object: objMap}\n\t\tlabels := u.GetLabels()\n\t\tif labels == nil {\n\t\t\tlabels = map[string]string{}\n\t\t}\n\t\tfor k, v := range c.labels {\n\t\t\tlabels[k] = v\n\t\t}\n\t\tu.SetLabels(labels)\n\t\treturn nil\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn resourceList, nil\n}\n"
  },
  {
    "path": "internal/helm/client/client_test.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage client\n\nimport (\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"helm.sh/helm/v3/pkg/kube\"\n)\n\nfunc TestContainsResourcePolicyKeep(t *testing.T) {\n\ttests := []struct {\n\t\tinput       map[string]string\n\t\texpectedVal bool\n\t\texpectedOut string\n\t\tname        string\n\t}{\n\t\t{\n\t\t\tinput: map[string]string{\n\t\t\t\tkube.ResourcePolicyAnno: kube.KeepPolicy,\n\t\t\t},\n\t\t\texpectedVal: true,\n\t\t\tname:        \"base case true\",\n\t\t},\n\t\t{\n\t\t\tinput: map[string]string{\n\t\t\t\t\"not-\" + kube.ResourcePolicyAnno: kube.KeepPolicy,\n\t\t\t},\n\t\t\texpectedVal: false,\n\t\t\tname:        \"base case annotation false\",\n\t\t},\n\t\t{\n\t\t\tinput: map[string]string{\n\t\t\t\tkube.ResourcePolicyAnno: \"not-\" + kube.KeepPolicy,\n\t\t\t},\n\t\t\texpectedVal: false,\n\t\t\tname:        \"base case value false\",\n\t\t},\n\t\t{\n\t\t\tinput: map[string]string{\n\t\t\t\tkube.ResourcePolicyAnno: strings.ToUpper(kube.KeepPolicy),\n\t\t\t},\n\t\t\texpectedVal: true,\n\t\t\tname:        \"true with upper case\",\n\t\t},\n\t\t{\n\t\t\tinput: map[string]string{\n\t\t\t\tkube.ResourcePolicyAnno: \" \" + kube.KeepPolicy + \"  \",\n\t\t\t},\n\t\t\texpectedVal: true,\n\t\t\tname:        \"true with spaces\",\n\t\t},\n\t\t{\n\t\t\tinput: map[string]string{\n\t\t\t\tkube.ResourcePolicyAnno: \" \" + strings.ToUpper(kube.KeepPolicy) + \"  \",\n\t\t\t},\n\t\t\texpectedVal: true,\n\t\t\tname:        \"true with upper case and spaces\",\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tassert.Equal(t, test.expectedVal, containsResourcePolicyKeep(test.input), test.name)\n\t}\n}\n"
  },
  {
    "path": "internal/helm/client/doc.go",
    "content": "// Copyright 2018 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Package client provides helper functions for API clients used by the helm\n// operator.\npackage client\n"
  },
  {
    "path": "internal/helm/client/restclientgetter.go",
    "content": "/*\nCopyright 2020 The Operator-SDK Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage client\n\nimport (\n\t\"sync\"\n\n\t\"k8s.io/apimachinery/pkg/api/meta\"\n\t\"k8s.io/cli-runtime/pkg/genericclioptions\"\n\t\"k8s.io/client-go/discovery\"\n\tcached \"k8s.io/client-go/discovery/cached\"\n\t\"k8s.io/client-go/rest\"\n\t\"k8s.io/client-go/tools/clientcmd\"\n\tclientcmdapi \"k8s.io/client-go/tools/clientcmd/api\"\n)\n\nfunc newRESTClientGetter(cfg *rest.Config, rm meta.RESTMapper, ns string) *namespacedRCG {\n\treturn &namespacedRCG{\n\t\trestClientGetter: &restClientGetter{\n\t\t\trestConfig: cfg,\n\t\t\trestMapper: rm,\n\t\t},\n\t\tnamespaceConfig: namespaceClientConfig{ns},\n\t}\n}\n\ntype restClientGetter struct {\n\trestConfig *rest.Config\n\trestMapper meta.RESTMapper\n\n\tsetupDiscoveryClient  sync.Once\n\tcachedDiscoveryClient discovery.CachedDiscoveryInterface\n}\n\nfunc (c *restClientGetter) ToRESTConfig() (*rest.Config, error) {\n\treturn rest.CopyConfig(c.restConfig), nil\n}\n\nfunc (c *restClientGetter) ToDiscoveryClient() (discovery.CachedDiscoveryInterface, error) {\n\tvar (\n\t\tdc  discovery.DiscoveryInterface\n\t\terr error\n\t)\n\tc.setupDiscoveryClient.Do(func() {\n\t\tdc, err = discovery.NewDiscoveryClientForConfig(c.restConfig)\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t\tc.cachedDiscoveryClient = cached.NewMemCacheClient(dc)\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn c.cachedDiscoveryClient, nil\n}\n\nfunc (c *restClientGetter) ToRESTMapper() (meta.RESTMapper, error) {\n\treturn c.restMapper, nil\n}\n\nfunc (c *restClientGetter) ForNamespace(ns string) genericclioptions.RESTClientGetter {\n\treturn &namespacedRCG{\n\t\trestClientGetter: c,\n\t\tnamespaceConfig:  namespaceClientConfig{namespace: ns},\n\t}\n}\n\nvar _ genericclioptions.RESTClientGetter = &namespacedRCG{}\n\ntype namespacedRCG struct {\n\t*restClientGetter\n\tnamespaceConfig namespaceClientConfig\n}\n\nfunc (c *namespacedRCG) ToRawKubeConfigLoader() clientcmd.ClientConfig {\n\treturn c.namespaceConfig\n}\n\nvar _ clientcmd.ClientConfig = &namespaceClientConfig{}\n\ntype namespaceClientConfig struct {\n\tnamespace string\n}\n\nfunc (c namespaceClientConfig) RawConfig() (clientcmdapi.Config, error) {\n\treturn clientcmdapi.Config{}, nil\n}\n\nfunc (c namespaceClientConfig) ClientConfig() (*rest.Config, error) {\n\treturn nil, nil\n}\n\nfunc (c namespaceClientConfig) Namespace() (string, bool, error) {\n\treturn c.namespace, false, nil\n}\n\nfunc (c namespaceClientConfig) ConfigAccess() clientcmd.ConfigAccess {\n\treturn nil\n}\n"
  },
  {
    "path": "internal/helm/client/secrets_watch.go",
    "content": "/*\nCopyright 2020 The Operator-SDK Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage client\n\nimport (\n\t\"context\"\n\t\"time\"\n\n\t\"k8s.io/apimachinery/pkg/selection\"\n\n\tcorev1 \"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/labels\"\n\t\"k8s.io/apimachinery/pkg/types\"\n\t\"k8s.io/apimachinery/pkg/util/wait\"\n\t\"k8s.io/apimachinery/pkg/watch\"\n\tapplyconfv1 \"k8s.io/client-go/applyconfigurations/core/v1\"\n\t\"k8s.io/client-go/informers\"\n\t\"k8s.io/client-go/kubernetes\"\n\ttypedcorev1 \"k8s.io/client-go/kubernetes/typed/core/v1\"\n\tlisterscorev1 \"k8s.io/client-go/listers/core/v1\"\n\tlogf \"sigs.k8s.io/controller-runtime/pkg/log\"\n)\n\nvar log = logf.Log.WithName(\"helm.watchedsecrets\")\n\nconst helmSecretsLabelKey = \"owner\"\nconst helmSecretsLabelValue = \"helm\"\n\n// Wraps the kubernetes SecretInterface\n// Helm queries its own secrets multiple times per reconciliation. To reduce the number of lists going to the apiserver\n// we instead use an informer to watch the changes on secrets.\ntype WatchedSecrets struct {\n\tinner           typedcorev1.SecretInterface\n\tinformerFactory informers.SharedInformerFactory\n\tinformerLister  listerscorev1.SecretNamespaceLister\n}\n\nfunc (w *WatchedSecrets) Create(ctx context.Context, secret *corev1.Secret, opts metav1.CreateOptions) (*corev1.Secret, error) {\n\treturn w.inner.Create(ctx, secret, opts)\n}\n\nfunc (w *WatchedSecrets) Update(ctx context.Context, secret *corev1.Secret, opts metav1.UpdateOptions) (*corev1.Secret, error) {\n\treturn w.inner.Update(ctx, secret, opts)\n}\n\nfunc (w *WatchedSecrets) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error {\n\treturn w.inner.Delete(ctx, name, opts)\n}\n\nfunc (w *WatchedSecrets) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error {\n\treturn w.inner.DeleteCollection(ctx, opts, listOpts)\n}\n\nfunc (w *WatchedSecrets) Get(ctx context.Context, name string, opts metav1.GetOptions) (*corev1.Secret, error) {\n\treturn w.inner.Get(ctx, name, opts)\n}\n\nfunc (w *WatchedSecrets) List(ctx context.Context, opts metav1.ListOptions) (*corev1.SecretList, error) {\n\tlabelSelector, err := labels.Parse(opts.LabelSelector)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\townerLabelSelector, hasOwnerLabelSelector := labelSelector.RequiresExactMatch(helmSecretsLabelKey)\n\n\t// The informer interface only offers to filter secrets with a labelSelector\n\t// We are only watching secrets with label owner=helm.\n\t// Currently (helm v3.10.3) this List function is only being called in `storage/driver/secrets.go` with a\n\t// labelSelector, meaning this case should never be executed. But we are able to fallback to the normal List\n\t// implementation.\n\tif hasListOptionsOtherThanLabelSelector(opts) || !hasOwnerLabelSelector || ownerLabelSelector != helmSecretsLabelValue {\n\t\tlog.Info(\"Cannot use informer to list secrets\", \"listOptions\", opts)\n\t\treturn w.inner.List(ctx, opts)\n\t}\n\n\tsecrets, err := w.informerLister.List(labelSelector)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tsecretList := &corev1.SecretList{\n\t\tTypeMeta: metav1.TypeMeta{},\n\t\tListMeta: metav1.ListMeta{},\n\t\tItems:    make([]corev1.Secret, len(secrets)),\n\t}\n\tfor i, sec := range secrets {\n\t\tsecretList.Items[i] = *sec\n\t}\n\n\treturn secretList, nil\n}\n\nfunc hasListOptionsOtherThanLabelSelector(opts metav1.ListOptions) bool {\n\tempty := metav1.ListOptions{}\n\n\tprovidedWithoutLabelSelector := opts\n\tprovidedWithoutLabelSelector.LabelSelector = \"\"\n\n\treturn empty != providedWithoutLabelSelector\n}\n\nfunc (w *WatchedSecrets) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) {\n\treturn w.inner.Watch(ctx, opts)\n}\n\nfunc (w *WatchedSecrets) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, _ ...string) (result *corev1.Secret, err error) {\n\treturn w.inner.Patch(ctx, name, pt, data, opts)\n}\n\nfunc (w *WatchedSecrets) Apply(ctx context.Context, secret *applyconfv1.SecretApplyConfiguration, opts metav1.ApplyOptions) (result *corev1.Secret, err error) {\n\treturn w.inner.Apply(ctx, secret, opts)\n}\n\nvar _ typedcorev1.SecretInterface = &WatchedSecrets{}\n\nfunc NewWatchedSecrets(clientSet kubernetes.Interface, namespace string) *WatchedSecrets {\n\tlog.V(2).Info(\"Get secrets client\", \"namespace\", namespace)\n\n\thelmListOptionsTweaker := func(options *metav1.ListOptions) {\n\t\tlabelSelector, err := labels.Parse(options.LabelSelector)\n\t\tif err != nil {\n\t\t\tlog.Info(\"Could not parse labelSelector\", \"labelSelector\", options.LabelSelector)\n\t\t\tpanic(\"could not parse labelSelector\")\n\t\t}\n\n\t\townerLabelSelector, hasOwnerLabelSelector := labelSelector.RequiresExactMatch(helmSecretsLabelKey)\n\n\t\tif !hasOwnerLabelSelector || ownerLabelSelector != helmSecretsLabelValue {\n\t\t\thelmRequirement, _ := labels.NewRequirement(\n\t\t\t\t\"owner\", selection.Equals, []string{helmSecretsLabelValue},\n\t\t\t)\n\t\t\tlabelSelectorWithOwner := labelSelector.Add(*helmRequirement)\n\t\t\toptions.LabelSelector = labelSelectorWithOwner.String()\n\t\t}\n\t}\n\n\tinformerFactory := informers.NewSharedInformerFactoryWithOptions(clientSet, time.Second*30, informers.WithNamespace(namespace), informers.WithTweakListOptions(helmListOptionsTweaker))\n\tsecretsInformer := informerFactory.Core().V1().Secrets()\n\n\tinformerSecretsLister := secretsInformer.Lister().Secrets(namespace)\n\n\treturn &WatchedSecrets{\n\t\tinner:           clientSet.CoreV1().Secrets(namespace),\n\t\tinformerFactory: informerFactory,\n\t\tinformerLister:  informerSecretsLister,\n\t}\n}\n\nfunc (w *WatchedSecrets) Run() {\n\tw.informerFactory.Start(wait.NeverStop)\n\t_ = w.informerFactory.WaitForCacheSync(wait.NeverStop)\n}\n"
  },
  {
    "path": "internal/helm/controller/controller.go",
    "content": "// Copyright 2018 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage controller\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\trpb \"helm.sh/helm/v3/pkg/release\"\n\t\"helm.sh/helm/v3/pkg/releaseutil\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\t\"k8s.io/apimachinery/pkg/runtime/schema\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client\"\n\t\"sigs.k8s.io/controller-runtime/pkg/controller\"\n\tcrthandler \"sigs.k8s.io/controller-runtime/pkg/handler\"\n\tlogf \"sigs.k8s.io/controller-runtime/pkg/log\"\n\t\"sigs.k8s.io/controller-runtime/pkg/manager\"\n\t\"sigs.k8s.io/controller-runtime/pkg/source\"\n\t\"sigs.k8s.io/yaml\"\n\n\tlibhandler \"github.com/operator-framework/operator-lib/handler\"\n\t\"github.com/operator-framework/operator-lib/predicate\"\n\t\"github.com/operator-framework/operator-sdk/internal/helm/release\"\n\t\"github.com/operator-framework/operator-sdk/internal/util/k8sutil\"\n)\n\nvar log = logf.Log.WithName(\"helm.controller\")\n\n// WatchOptions contains the necessary values to create a new controller that\n// manages helm releases in a particular namespace based on a GVK watch.\ntype WatchOptions struct {\n\tGVK                     schema.GroupVersionKind\n\tManagerFactory          release.ManagerFactory\n\tReconcilePeriod         time.Duration\n\tWatchDependentResources bool\n\tOverrideValues          map[string]string\n\tSuppressOverrideValues  bool\n\tMaxConcurrentReconciles int\n\tSelector                metav1.LabelSelector\n\tDryRunOption            string\n}\n\n// Add creates a new helm operator controller and adds it to the manager\nfunc Add(mgr manager.Manager, options WatchOptions) error {\n\tcontrollerName := fmt.Sprintf(\"%v-controller\", strings.ToLower(options.GVK.Kind))\n\n\tr := &HelmOperatorReconciler{\n\t\tClient:                 mgr.GetClient(),\n\t\tEventRecorder:          mgr.GetEventRecorderFor(controllerName),\n\t\tGVK:                    options.GVK,\n\t\tManagerFactory:         options.ManagerFactory,\n\t\tReconcilePeriod:        options.ReconcilePeriod,\n\t\tOverrideValues:         options.OverrideValues,\n\t\tSuppressOverrideValues: options.SuppressOverrideValues,\n\t\tDryRunOption:           options.DryRunOption,\n\t}\n\n\tc, err := controller.New(controllerName, mgr, controller.Options{\n\t\tReconciler:              r,\n\t\tMaxConcurrentReconciles: options.MaxConcurrentReconciles,\n\t})\n\tif err != nil {\n\t\treturn err\n\t}\n\n\to := &unstructured.Unstructured{}\n\to.SetGroupVersionKind(options.GVK)\n\n\tif err := c.Watch(source.Kind(mgr.GetCache(), client.Object(o), &libhandler.InstrumentedEnqueueRequestForObject[client.Object]{})); err != nil {\n\t\treturn err\n\t}\n\n\tif options.WatchDependentResources {\n\t\twatchDependentResources(mgr, r, c)\n\t}\n\n\tlog.Info(\"Watching resource\", \"apiVersion\", options.GVK.GroupVersion(), \"kind\",\n\t\toptions.GVK.Kind, \"reconcilePeriod\", options.ReconcilePeriod.String())\n\treturn nil\n}\n\n// watchDependentResources adds a release hook function to the HelmOperatorReconciler\n// that adds watches for resources in released Helm charts.\nfunc watchDependentResources(mgr manager.Manager, r *HelmOperatorReconciler, c controller.Controller) {\n\tvar m sync.RWMutex\n\twatches := map[schema.GroupVersionKind]struct{}{}\n\treleaseHook := func(release *rpb.Release) error {\n\t\towner := &unstructured.Unstructured{}\n\t\towner.SetGroupVersionKind(r.GVK)\n\t\towner.SetNamespace(release.Namespace)\n\t\tresources := releaseutil.SplitManifests(release.Manifest)\n\t\tfor _, resource := range resources {\n\t\t\tvar u unstructured.Unstructured\n\t\t\tif err := yaml.Unmarshal([]byte(resource), &u); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tgvk := u.GroupVersionKind()\n\t\t\tif gvk.Empty() {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tvar setWatchOnResource = func(dependent runtime.Object) error {\n\t\t\t\tunstructuredObj := dependent.(*unstructured.Unstructured)\n\t\t\t\tgvkDependent := unstructuredObj.GroupVersionKind()\n\t\t\t\tif gvkDependent.Empty() {\n\t\t\t\t\treturn nil\n\t\t\t\t}\n\n\t\t\t\tm.RLock()\n\t\t\t\t_, ok := watches[gvkDependent]\n\t\t\t\tm.RUnlock()\n\t\t\t\tif ok {\n\t\t\t\t\treturn nil\n\t\t\t\t}\n\n\t\t\t\trestMapper := mgr.GetRESTMapper()\n\t\t\t\tuseOwnerRef, err := k8sutil.SupportsOwnerReference(restMapper, owner, dependent, \"\")\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\n\t\t\t\tif useOwnerRef { // Setup watch using owner references.\n\t\t\t\t\terr = c.Watch(\n\t\t\t\t\t\tsource.Kind(\n\t\t\t\t\t\t\tmgr.GetCache(),\n\t\t\t\t\t\t\tclient.Object(unstructuredObj),\n\t\t\t\t\t\t\tcrthandler.TypedEnqueueRequestForOwner[client.Object](mgr.GetScheme(), mgr.GetRESTMapper(), owner, crthandler.OnlyControllerOwner()),\n\t\t\t\t\t\t\tpredicate.DependentPredicate{}))\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t} else { // Setup watch using annotations.\n\t\t\t\t\terr = c.Watch(\n\t\t\t\t\t\tsource.Kind(\n\t\t\t\t\t\t\tmgr.GetCache(),\n\t\t\t\t\t\t\tclient.Object(unstructuredObj),\n\t\t\t\t\t\t\t&libhandler.EnqueueRequestForAnnotation[client.Object]{Type: gvkDependent.GroupKind()},\n\t\t\t\t\t\t\tpredicate.DependentPredicate{}))\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tm.Lock()\n\t\t\t\twatches[gvkDependent] = struct{}{}\n\t\t\t\tm.Unlock()\n\t\t\t\tlog.Info(\"Watching dependent resource\", \"ownerApiVersion\", r.GVK.GroupVersion(),\n\t\t\t\t\t\"ownerKind\", r.GVK.Kind, \"apiVersion\", gvkDependent.GroupVersion(), \"kind\", gvkDependent.Kind)\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\t// List is not actually a resource and therefore cannot have a\n\t\t\t// watch on it. The watch will be on the kinds listed in the list\n\t\t\t// and will therefore need to be handled individually.\n\t\t\tlistGVK := schema.GroupVersionKind{Group: \"\", Version: \"v1\", Kind: \"List\"}\n\t\t\tif gvk == listGVK {\n\t\t\t\terrListItem := u.EachListItem(func(obj runtime.Object) error {\n\t\t\t\t\treturn setWatchOnResource(obj)\n\t\t\t\t})\n\t\t\t\tif errListItem != nil {\n\t\t\t\t\treturn errListItem\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\terr := setWatchOnResource(&u)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n\tr.releaseHook = releaseHook\n}\n"
  },
  {
    "path": "internal/helm/controller/doc.go",
    "content": "// Copyright 2018 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Package controller provides functions for creating and registering a Helm\n// controller with a `controller-runtime` manager. It also provides a Helm\n// reconciler implementation that can be used to create a Helm-based operator.\npackage controller\n"
  },
  {
    "path": "internal/helm/controller/reconcile.go",
    "content": "// Copyright 2018 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage controller\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\trpb \"helm.sh/helm/v3/pkg/release\"\n\t\"helm.sh/helm/v3/pkg/storage/driver\"\n\tapierrors \"k8s.io/apimachinery/pkg/api/errors\"\n\t\"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured\"\n\t\"k8s.io/apimachinery/pkg/runtime/schema\"\n\t\"k8s.io/apimachinery/pkg/util/wait\"\n\t\"k8s.io/client-go/tools/record\"\n\t\"k8s.io/client-go/util/retry\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client\"\n\t\"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil\"\n\t\"sigs.k8s.io/controller-runtime/pkg/reconcile\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/helm/internal/diff\"\n\t\"github.com/operator-framework/operator-sdk/internal/helm/internal/types\"\n\t\"github.com/operator-framework/operator-sdk/internal/helm/release\"\n)\n\n// blank assignment to verify that HelmOperatorReconciler implements reconcile.Reconciler\nvar _ reconcile.Reconciler = &HelmOperatorReconciler{}\n\n// ReleaseHookFunc defines a function signature for release hooks.\ntype ReleaseHookFunc func(*rpb.Release) error\n\n// HelmOperatorReconciler reconciles custom resources as Helm releases.\ntype HelmOperatorReconciler struct {\n\tClient                 client.Client\n\tEventRecorder          record.EventRecorder\n\tGVK                    schema.GroupVersionKind\n\tManagerFactory         release.ManagerFactory\n\tReconcilePeriod        time.Duration\n\tOverrideValues         map[string]string\n\tSuppressOverrideValues bool\n\treleaseHook            ReleaseHookFunc\n\tDryRunOption           string\n}\n\nconst (\n\t// uninstallFinalizer is added to CRs so they are cleaned up after uninstalling a release.\n\tuninstallFinalizer = \"helm.sdk.operatorframework.io/uninstall-release\"\n\t// Deprecated: use uninstallFinalizer. This will be removed in operator-sdk v2.0.0.\n\tuninstallFinalizerLegacy = \"uninstall-helm-release\"\n\n\thelmUpgradeForceAnnotation    = \"helm.sdk.operatorframework.io/upgrade-force\"\n\thelmRollbackForceAnnotation   = \"helm.sdk.operatorframework.io/rollback-force\"\n\thelmUninstallWaitAnnotation   = \"helm.sdk.operatorframework.io/uninstall-wait\"\n\thelmReconcilePeriodAnnotation = \"helm.sdk.operatorframework.io/reconcile-period\"\n)\n\n// Reconcile reconciles the requested resource by installing, updating, or\n// uninstalling a Helm release based on the resource's current state. If no\n// release changes are necessary, Reconcile will create or patch the underlying\n// resources to match the expected release manifest.\n\nfunc (r HelmOperatorReconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) { //nolint:gocyclo\n\to := &unstructured.Unstructured{}\n\to.SetGroupVersionKind(r.GVK)\n\to.SetNamespace(request.Namespace)\n\to.SetName(request.Name)\n\tlog := log.WithValues(\n\t\t\"namespace\", o.GetNamespace(),\n\t\t\"name\", o.GetName(),\n\t\t\"apiVersion\", o.GetAPIVersion(),\n\t\t\"kind\", o.GetKind(),\n\t)\n\tlog.V(1).Info(\"Reconciling\")\n\n\terr := r.Client.Get(ctx, request.NamespacedName, o)\n\tif apierrors.IsNotFound(err) {\n\t\treturn reconcile.Result{}, nil\n\t}\n\tif err != nil {\n\t\tlog.Error(err, \"Failed to lookup resource\")\n\t\treturn reconcile.Result{}, err\n\t}\n\n\tmanager, err := r.ManagerFactory.NewManager(o, r.OverrideValues, r.DryRunOption)\n\tif err != nil {\n\t\tlog.Error(err, \"Failed to get release manager\")\n\t\treturn reconcile.Result{}, err\n\t}\n\n\tstatus := types.StatusFor(o)\n\toriginalStatus := types.StatusFor(o.DeepCopy())\n\tlog = log.WithValues(\"release\", manager.ReleaseName())\n\n\treconcileResult := reconcile.Result{RequeueAfter: r.ReconcilePeriod}\n\t// Determine the correct reconcile period based on the existing value in the reconciler and the\n\t// annotations in the custom resource. If a reconcile period is specified in the custom resource\n\t// annotations, this value will take precedence over the existing reconcile period value\n\t// (which came from either the command-line flag or the watches.yaml file).\n\tfinalReconcilePeriod, err := determineReconcilePeriod(r.ReconcilePeriod, o)\n\tif err != nil {\n\t\tlog.Error(err, \"Error: unable to parse reconcile period from the custom resource's annotations\")\n\t\treturn reconcile.Result{}, err\n\t}\n\treconcileResult.RequeueAfter = finalReconcilePeriod\n\n\tif o.GetDeletionTimestamp() != nil {\n\t\tif !controllerutil.ContainsFinalizer(o, uninstallFinalizer) && !controllerutil.ContainsFinalizer(o, uninstallFinalizerLegacy) {\n\n\t\t\tlog.Info(\"Resource is terminated, skipping reconciliation\")\n\t\t\treturn reconcile.Result{}, nil\n\t\t}\n\n\t\tuninstalledRelease, err := manager.UninstallRelease()\n\t\tif err != nil && !errors.Is(err, driver.ErrReleaseNotFound) {\n\t\t\tlog.Error(err, \"Failed to uninstall release\")\n\t\t\tstatus.SetCondition(types.HelmAppCondition{\n\t\t\t\tType:    types.ConditionReleaseFailed,\n\t\t\t\tStatus:  types.StatusTrue,\n\t\t\t\tReason:  types.ReasonUninstallError,\n\t\t\t\tMessage: err.Error(),\n\t\t\t})\n\t\t\tif err := r.updateResourceStatus(ctx, o, status); err != nil {\n\t\t\t\tlog.Error(err, \"Failed to update status after uninstall release failure\")\n\t\t\t}\n\t\t\treturn reconcile.Result{}, err\n\t\t}\n\t\tstatus.RemoveCondition(types.ConditionReleaseFailed)\n\n\t\twait := hasAnnotation(helmUninstallWaitAnnotation, o)\n\t\tif errors.Is(err, driver.ErrReleaseNotFound) {\n\t\t\tlog.Info(\"Release not found\")\n\t\t} else {\n\t\t\tlog.Info(\"Uninstalled release\")\n\t\t\tif log.V(1).Enabled() && uninstalledRelease != nil {\n\t\t\t\tfmt.Println(diff.Generate(uninstalledRelease.Manifest, \"\"))\n\t\t\t}\n\t\t\tif !wait {\n\t\t\t\tstatus.SetCondition(types.HelmAppCondition{\n\t\t\t\t\tType:   types.ConditionDeployed,\n\t\t\t\t\tStatus: types.StatusFalse,\n\t\t\t\t\tReason: types.ReasonUninstallSuccessful,\n\t\t\t\t})\n\t\t\t\tstatus.DeployedRelease = nil\n\t\t\t}\n\t\t}\n\t\tif wait {\n\t\t\tstatus.SetCondition(types.HelmAppCondition{\n\t\t\t\tType:    types.ConditionDeployed,\n\t\t\t\tStatus:  types.StatusFalse,\n\t\t\t\tReason:  types.ReasonUninstallSuccessful,\n\t\t\t\tMessage: \"Waiting until all resources are deleted.\",\n\t\t\t})\n\t\t}\n\t\tif err := r.updateResourceStatus(ctx, o, status); err != nil {\n\t\t\tlog.Info(\"Failed to update CR status\")\n\t\t\treturn reconcile.Result{}, err\n\t\t}\n\n\t\tif wait && status.DeployedRelease != nil && status.DeployedRelease.Manifest != \"\" {\n\t\t\tlog.Info(\"Uninstall wait\")\n\t\t\tisAllResourcesDeleted, err := manager.CleanupRelease(status.DeployedRelease.Manifest)\n\t\t\tif err != nil {\n\t\t\t\tlog.Error(err, \"Failed to cleanup release\")\n\t\t\t\tstatus.SetCondition(types.HelmAppCondition{\n\t\t\t\t\tType:    types.ConditionReleaseFailed,\n\t\t\t\t\tStatus:  types.StatusTrue,\n\t\t\t\t\tReason:  types.ReasonUninstallError,\n\t\t\t\t\tMessage: err.Error(),\n\t\t\t\t})\n\t\t\t\t_ = r.updateResourceStatus(ctx, o, status)\n\t\t\t\treturn reconcile.Result{}, err\n\t\t\t}\n\t\t\tif !isAllResourcesDeleted {\n\t\t\t\tlog.Info(\"Waiting until all resources are deleted\")\n\t\t\t\treturn reconcileResult, nil\n\t\t\t}\n\t\t\tstatus.RemoveCondition(types.ConditionReleaseFailed)\n\t\t}\n\n\t\tlog.Info(\"Removing finalizer\")\n\t\tcontrollerutil.RemoveFinalizer(o, uninstallFinalizer)\n\t\tcontrollerutil.RemoveFinalizer(o, uninstallFinalizerLegacy)\n\t\tif err := r.updateResource(ctx, o); err != nil {\n\t\t\tlog.Info(\"Failed to remove CR uninstall finalizer\")\n\t\t\treturn reconcile.Result{}, err\n\t\t}\n\n\t\t// Since the client is hitting a cache, waiting for the\n\t\t// deletion here will guarantee that the next reconciliation\n\t\t// will see that the CR has been deleted and that there's\n\t\t// nothing left to do.\n\t\tif err := r.waitForDeletion(ctx, o); err != nil {\n\t\t\tlog.Info(\"Failed waiting for CR deletion\")\n\t\t\treturn reconcile.Result{}, err\n\t\t}\n\n\t\treturn reconcile.Result{}, nil\n\t}\n\n\tstatus.SetCondition(types.HelmAppCondition{\n\t\tType:   types.ConditionInitialized,\n\t\tStatus: types.StatusTrue,\n\t})\n\n\tif err := manager.Sync(); err != nil {\n\t\tlog.Error(err, \"Failed to sync release\")\n\t\tstatus.SetCondition(types.HelmAppCondition{\n\t\t\tType:    types.ConditionIrreconcilable,\n\t\t\tStatus:  types.StatusTrue,\n\t\t\tReason:  types.ReasonReconcileError,\n\t\t\tMessage: err.Error(),\n\t\t})\n\t\tif err := r.updateResourceStatus(ctx, o, status); err != nil {\n\t\t\tlog.Error(err, \"Failed to update status after sync release failure\")\n\t\t}\n\t\treturn reconcile.Result{}, err\n\t}\n\tstatus.RemoveCondition(types.ConditionIrreconcilable)\n\n\tif !manager.IsInstalled() {\n\t\tfor k, v := range r.OverrideValues {\n\t\t\tif r.SuppressOverrideValues {\n\t\t\t\tv = \"****\"\n\t\t\t}\n\t\t\tr.EventRecorder.Eventf(o, \"Warning\", \"OverrideValuesInUse\",\n\t\t\t\t\"Chart value %q overridden to %q by operator's watches.yaml\", k, v)\n\t\t}\n\t\tinstalledRelease, err := manager.InstallRelease()\n\t\tif err != nil {\n\t\t\tlog.Error(err, \"Release failed\")\n\t\t\tstatus.SetCondition(types.HelmAppCondition{\n\t\t\t\tType:    types.ConditionReleaseFailed,\n\t\t\t\tStatus:  types.StatusTrue,\n\t\t\t\tReason:  types.ReasonInstallError,\n\t\t\t\tMessage: err.Error(),\n\t\t\t})\n\t\t\tif err := r.updateResourceStatus(ctx, o, status); err != nil {\n\t\t\t\tlog.Error(err, \"Failed to update status after install release failure\")\n\t\t\t}\n\t\t\treturn reconcile.Result{}, err\n\t\t}\n\t\tstatus.RemoveCondition(types.ConditionReleaseFailed)\n\n\t\tlog.V(1).Info(\"Adding finalizer\", \"finalizer\", uninstallFinalizer)\n\t\tcontrollerutil.AddFinalizer(o, uninstallFinalizer)\n\t\tif err := r.updateResource(ctx, o); err != nil {\n\t\t\tlog.Info(\"Failed to add CR uninstall finalizer\")\n\t\t\treturn reconcile.Result{}, err\n\t\t}\n\n\t\tif r.releaseHook != nil {\n\t\t\tif err := r.releaseHook(installedRelease); err != nil {\n\t\t\t\tlog.Error(err, \"Failed to run release hook\")\n\t\t\t\treturn reconcile.Result{}, err\n\t\t\t}\n\t\t}\n\n\t\tlog.Info(\"Installed release\")\n\t\tif log.V(1).Enabled() {\n\t\t\tfmt.Println(diff.Generate(\"\", installedRelease.Manifest))\n\t\t}\n\t\tlog.V(1).Info(\"Config values\", \"values\", installedRelease.Config)\n\t\tmessage := \"\"\n\t\tif installedRelease.Info != nil {\n\t\t\tmessage = installedRelease.Info.Notes\n\t\t}\n\t\tstatus.SetCondition(types.HelmAppCondition{\n\t\t\tType:    types.ConditionDeployed,\n\t\t\tStatus:  types.StatusTrue,\n\t\t\tReason:  types.ReasonInstallSuccessful,\n\t\t\tMessage: message,\n\t\t})\n\t\tstatus.DeployedRelease = &types.HelmAppRelease{\n\t\t\tName:     installedRelease.Name,\n\t\t\tManifest: installedRelease.Manifest,\n\t\t}\n\t\terr = r.updateResourceStatus(ctx, o, status)\n\t\treturn reconcileResult, err\n\t}\n\n\tif !controllerutil.ContainsFinalizer(o, uninstallFinalizer) && !controllerutil.ContainsFinalizer(o, uninstallFinalizerLegacy) {\n\n\t\tlog.V(1).Info(\"Adding finalizer\", \"finalizer\", uninstallFinalizer)\n\t\tcontrollerutil.AddFinalizer(o, uninstallFinalizer)\n\t\tif err := r.updateResource(ctx, o); err != nil {\n\t\t\tlog.Info(\"Failed to add CR uninstall finalizer\")\n\t\t\treturn reconcile.Result{}, err\n\t\t}\n\t}\n\n\tif manager.IsUpgradeRequired() {\n\t\tfor k, v := range r.OverrideValues {\n\t\t\tif r.SuppressOverrideValues {\n\t\t\t\tv = \"****\"\n\t\t\t}\n\t\t\tr.EventRecorder.Eventf(o, \"Warning\", \"OverrideValuesInUse\",\n\t\t\t\t\"Chart value %q overridden to %q by operator's watches.yaml\", k, v)\n\t\t}\n\t\tforce := hasAnnotation(helmUpgradeForceAnnotation, o)\n\n\t\tpreviousRelease, upgradedRelease, err := manager.UpgradeRelease(release.ForceUpgrade(force))\n\t\tif err != nil {\n\t\t\tif errors.Is(err, release.ErrUpgradeFailed) {\n\t\t\t\t// the forceRollback variable takes the value of the annotation,\n\t\t\t\t// \"helm.sdk.operatorframework.io/rollback-force\".\n\t\t\t\t// The default value for the annotation is true\n\t\t\t\tforceRollback := readBoolAnnotationWithDefault(o, helmRollbackForceAnnotation, true)\n\t\t\t\tif err := manager.RollBack(release.ForceRollback(forceRollback)); err != nil {\n\t\t\t\t\tlog.Error(err, \"Error rolling back release\")\n\t\t\t\t}\n\t\t\t}\n\t\t\tlog.Error(err, \"Release failed\")\n\t\t\tstatus.SetCondition(types.HelmAppCondition{\n\t\t\t\tType:    types.ConditionReleaseFailed,\n\t\t\t\tStatus:  types.StatusTrue,\n\t\t\t\tReason:  types.ReasonUpgradeError,\n\t\t\t\tMessage: err.Error(),\n\t\t\t})\n\t\t\tif err := r.updateResourceStatus(ctx, o, status); err != nil {\n\t\t\t\tlog.Error(err, \"Failed to update status after sync release failure\")\n\t\t\t}\n\t\t\treturn reconcile.Result{}, err\n\t\t}\n\t\tstatus.RemoveCondition(types.ConditionReleaseFailed)\n\n\t\tif r.releaseHook != nil {\n\t\t\tif err := r.releaseHook(upgradedRelease); err != nil {\n\t\t\t\tlog.Error(err, \"Failed to run release hook\")\n\t\t\t\treturn reconcile.Result{}, err\n\t\t\t}\n\t\t}\n\n\t\tlog.Info(\"Upgraded release\", \"force\", force)\n\t\tif log.V(1).Enabled() {\n\t\t\tfmt.Println(diff.Generate(previousRelease.Manifest, upgradedRelease.Manifest))\n\t\t}\n\t\tlog.V(1).Info(\"Config values\", \"values\", upgradedRelease.Config)\n\t\tmessage := \"\"\n\t\tif upgradedRelease.Info != nil {\n\t\t\tmessage = upgradedRelease.Info.Notes\n\t\t}\n\t\tstatus.SetCondition(types.HelmAppCondition{\n\t\t\tType:    types.ConditionDeployed,\n\t\t\tStatus:  types.StatusTrue,\n\t\t\tReason:  types.ReasonUpgradeSuccessful,\n\t\t\tMessage: message,\n\t\t})\n\t\tstatus.DeployedRelease = &types.HelmAppRelease{\n\t\t\tName:     upgradedRelease.Name,\n\t\t\tManifest: upgradedRelease.Manifest,\n\t\t}\n\t\terr = r.updateResourceStatus(ctx, o, status)\n\t\treturn reconcileResult, err\n\t}\n\n\t// If a change is made to the CR spec that causes a release failure, a\n\t// ConditionReleaseFailed is added to the status conditions. If that change\n\t// is then reverted to its previous state, the operator will stop\n\t// attempting the release and will resume reconciling. In this case, we\n\t// need to remove the ConditionReleaseFailed because the failing release is\n\t// no longer being attempted.\n\tstatus.RemoveCondition(types.ConditionReleaseFailed)\n\n\texpectedRelease, err := manager.ReconcileRelease(ctx)\n\tif err != nil {\n\t\tlog.Error(err, \"Failed to reconcile release\")\n\t\tstatus.SetCondition(types.HelmAppCondition{\n\t\t\tType:    types.ConditionIrreconcilable,\n\t\t\tStatus:  types.StatusTrue,\n\t\t\tReason:  types.ReasonReconcileError,\n\t\t\tMessage: err.Error(),\n\t\t})\n\t\tif err := r.updateResourceStatus(ctx, o, status); err != nil {\n\t\t\tlog.Error(err, \"Failed to update status after reconcile release failure\")\n\t\t}\n\t\treturn reconcile.Result{}, err\n\t}\n\tstatus.RemoveCondition(types.ConditionIrreconcilable)\n\n\tif r.releaseHook != nil {\n\t\tif err := r.releaseHook(expectedRelease); err != nil {\n\t\t\tlog.Error(err, \"Failed to run release hook\")\n\t\t\treturn reconcile.Result{}, err\n\t\t}\n\t}\n\n\tlog.Info(\"Reconciled release\")\n\treason := types.ReasonUpgradeSuccessful\n\tif expectedRelease.Version == 1 {\n\t\treason = types.ReasonInstallSuccessful\n\t}\n\tmessage := \"\"\n\tif expectedRelease.Info != nil {\n\t\tmessage = expectedRelease.Info.Notes\n\t}\n\tstatus.SetCondition(types.HelmAppCondition{\n\t\tType:    types.ConditionDeployed,\n\t\tStatus:  types.StatusTrue,\n\t\tReason:  reason,\n\t\tMessage: message,\n\t})\n\tstatus.DeployedRelease = &types.HelmAppRelease{\n\t\tName:     expectedRelease.Name,\n\t\tManifest: expectedRelease.Manifest,\n\t}\n\n\tif !reflect.DeepEqual(status, originalStatus) {\n\t\terr = r.updateResourceStatus(ctx, o, status)\n\t}\n\n\treturn reconcileResult, err\n}\n\n// returns the reconcile period that will be set to the RequeueAfter field in the reconciler. If any period\n// is specified in the custom resource's annotations, this will be returned. If not, the existing reconcile period\n// will be returned. An error will be thrown if the custom resource time period is not in proper format.\nfunc determineReconcilePeriod(currentPeriod time.Duration, o *unstructured.Unstructured) (time.Duration, error) {\n\t// If custom resource annotations are present, they will take precedence over the command-line flag\n\tif annot, exists := o.UnstructuredContent()[\"metadata\"].(map[string]any)[\"annotations\"]; exists {\n\t\tif timeDuration, present := annot.(map[string]any)[helmReconcilePeriodAnnotation]; present {\n\t\t\tannotationsPeriod, err := time.ParseDuration(timeDuration.(string))\n\t\t\tif err != nil {\n\t\t\t\treturn currentPeriod, err // First return value does not matter, since err != nil\n\t\t\t}\n\t\t\treturn annotationsPeriod, nil\n\t\t}\n\t}\n\treturn currentPeriod, nil\n}\n\n// returns the boolean representation of the annotation string\n// will return false if annotation is not set\nfunc hasAnnotation(anno string, o *unstructured.Unstructured) bool {\n\tboolStr := o.GetAnnotations()[anno]\n\tif boolStr == \"\" {\n\t\treturn false\n\t}\n\tvalue := false\n\tif i, err := strconv.ParseBool(boolStr); err != nil {\n\t\tlog.Info(\"Could not parse annotation as a boolean\",\n\t\t\t\"annotation\", anno, \"value informed\", boolStr)\n\t} else {\n\t\tvalue = i\n\t}\n\treturn value\n}\n\nfunc readBoolAnnotationWithDefault(obj *unstructured.Unstructured, annotation string, fallback bool) bool {\n\tval, ok := obj.GetAnnotations()[annotation]\n\tif !ok {\n\t\treturn fallback\n\t}\n\tr, err := strconv.ParseBool(val)\n\tif err != nil {\n\t\tlog.Error(\n\t\t\tfmt.Errorf(\"%s\", strings.ToLower(err.Error())), \"error parsing annotation\", \"annotation\", annotation)\n\t\treturn fallback\n\t}\n\n\treturn r\n}\n\nfunc (r HelmOperatorReconciler) updateResource(ctx context.Context, o client.Object) error {\n\treturn retry.RetryOnConflict(retry.DefaultBackoff, func() error {\n\t\treturn r.Client.Update(ctx, o)\n\t})\n}\n\nfunc (r HelmOperatorReconciler) updateResourceStatus(ctx context.Context, o *unstructured.Unstructured, status *types.HelmAppStatus) error {\n\treturn retry.RetryOnConflict(retry.DefaultBackoff, func() error {\n\t\to.Object[\"status\"] = status\n\t\treturn r.Client.Status().Update(ctx, o)\n\t})\n}\n\nfunc (r HelmOperatorReconciler) waitForDeletion(ctx context.Context, o client.Object) error {\n\tkey := client.ObjectKeyFromObject(o)\n\n\ttctx, cancel := context.WithTimeout(ctx, time.Second*5)\n\tdefer cancel()\n\treturn wait.PollUntilContextCancel(tctx, time.Millisecond*10, false, func(pctx context.Context) (bool, error) {\n\t\terr := r.Client.Get(pctx, key, o)\n\t\tif apierrors.IsNotFound(err) {\n\t\t\treturn true, nil\n\t\t}\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\t\treturn false, nil\n\t})\n}\n"
  },
  {
    "path": "internal/helm/controller/reconcile_test.go",
    "content": "// Copyright 2018 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage controller\n\nimport (\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured\"\n)\n\nfunc TestDetermineReconcilePeriod(t *testing.T) {\n\ttestPeriod1, _ := time.ParseDuration(\"10s\")\n\tobj1 := &unstructured.Unstructured{\n\t\tObject: map[string]any{\n\t\t\t\"metadata\": map[string]any{\n\t\t\t\t\"annotations\": map[string]any{\n\t\t\t\t\t\"name\":                        \"test-obj-1\",\n\t\t\t\t\thelmReconcilePeriodAnnotation: \"3s\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\texpected1, _ := time.ParseDuration(\"3s\")\n\tfinalPeriod1, err := determineReconcilePeriod(testPeriod1, obj1)\n\tassert.Equal(t, nil, err, \"Verify that no error is returned on parsing the time period\")\n\tassert.Equal(t, expected1, finalPeriod1, \"Verify that the annotations period takes precedence\")\n\n\ttestPeriod2, _ := time.ParseDuration(\"1h3m4s\")\n\tobj2 := &unstructured.Unstructured{\n\t\tObject: map[string]any{\n\t\t\t\"metadata\": map[string]any{\n\t\t\t\t\"annotations\": map[string]any{\n\t\t\t\t\t\"name\": \"test-obj-2\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\texpected2, _ := time.ParseDuration(\"1h3m4s\")\n\tfinalPeriod2, err := determineReconcilePeriod(testPeriod2, obj2)\n\tassert.Equal(t, nil, err, \"Verify that no error is returned on parsing the time period\")\n\tassert.Equal(t, expected2, finalPeriod2, \"Verify that when no time period is present under the CR's annotations, the original time period value gets used\")\n\n\ttestPeriod3, _ := time.ParseDuration(\"5m15s\")\n\tobj3 := &unstructured.Unstructured{\n\t\tObject: map[string]any{\n\t\t\t\"metadata\": map[string]any{\n\t\t\t\t\"annotations\": map[string]any{\n\t\t\t\t\t\"name\":                        \"test-obj-3\",\n\t\t\t\t\thelmReconcilePeriodAnnotation: \"4x\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\tfinalPeriod3, err := determineReconcilePeriod(testPeriod3, obj3)\n\texpected3, _ := time.ParseDuration(\"5m15s\")\n\tassert.NotEqual(t, nil, err, \"Verify that error is thrown when invalid time period is passed in the CR annotations\")\n\tassert.Equal(t, expected3, finalPeriod3, \"Verify that when a faulty time period is present under the CR's annotations, the original time period value gets used\")\n}\n\nfunc TestHasAnnotation(t *testing.T) {\n\tupgradeForceTests := []struct {\n\t\tinput       map[string]any\n\t\texpectedVal bool\n\t\texpectedOut string\n\t\tname        string\n\t}{\n\t\t{\n\t\t\tinput: map[string]any{\n\t\t\t\t\"helm.sdk.operatorframework.io/upgrade-force\": \"True\",\n\t\t\t},\n\t\t\texpectedVal: true,\n\t\t\tname:        \"upgrade force base case true\",\n\t\t},\n\t\t{\n\t\t\tinput: map[string]any{\n\t\t\t\t\"helm.sdk.operatorframework.io/upgrade-force\": \"False\",\n\t\t\t},\n\t\t\texpectedVal: false,\n\t\t\tname:        \"upgrade force base case false\",\n\t\t},\n\t\t{\n\t\t\tinput: map[string]any{\n\t\t\t\t\"helm.sdk.operatorframework.io/upgrade-force\": \"1\",\n\t\t\t},\n\t\t\texpectedVal: true,\n\t\t\tname:        \"upgrade force true as int\",\n\t\t},\n\t\t{\n\t\t\tinput: map[string]any{\n\t\t\t\t\"helm.sdk.operatorframework.io/upgrade-force\": \"0\",\n\t\t\t},\n\t\t\texpectedVal: false,\n\t\t\tname:        \"upgrade force false as int\",\n\t\t},\n\t\t{\n\t\t\tinput: map[string]any{\n\t\t\t\t\"helm.sdk.operatorframework.io/wrong-annotation\": \"true\",\n\t\t\t},\n\t\t\texpectedVal: false,\n\t\t\tname:        \"upgrade force annotation not set\",\n\t\t},\n\t\t{\n\t\t\tinput: map[string]any{\n\t\t\t\t\"helm.sdk.operatorframework.io/upgrade-force\": \"invalid\",\n\t\t\t},\n\t\t\texpectedVal: false,\n\t\t\tname:        \"upgrade force invalid value\",\n\t\t},\n\t}\n\n\tfor _, test := range upgradeForceTests {\n\t\tassert.Equal(t, test.expectedVal, hasAnnotation(helmUpgradeForceAnnotation, annotations(test.input)), test.name)\n\t}\n\n\tuninstallWaitTests := []struct {\n\t\tinput       map[string]any\n\t\texpectedVal bool\n\t\texpectedOut string\n\t\tname        string\n\t}{\n\t\t{\n\t\t\tinput: map[string]any{\n\t\t\t\t\"helm.sdk.operatorframework.io/uninstall-wait\": \"True\",\n\t\t\t},\n\t\t\texpectedVal: true,\n\t\t\tname:        \"uninstall wait base case true\",\n\t\t},\n\t\t{\n\t\t\tinput: map[string]any{\n\t\t\t\t\"helm.sdk.operatorframework.io/uninstall-wait\": \"False\",\n\t\t\t},\n\t\t\texpectedVal: false,\n\t\t\tname:        \"uninstall wait base case false\",\n\t\t},\n\t\t{\n\t\t\tinput: map[string]any{\n\t\t\t\t\"helm.sdk.operatorframework.io/uninstall-wait\": \"1\",\n\t\t\t},\n\t\t\texpectedVal: true,\n\t\t\tname:        \"uninstall wait true as int\",\n\t\t},\n\t\t{\n\t\t\tinput: map[string]any{\n\t\t\t\t\"helm.sdk.operatorframework.io/uninstall-wait\": \"0\",\n\t\t\t},\n\t\t\texpectedVal: false,\n\t\t\tname:        \"uninstall wait false as int\",\n\t\t},\n\t\t{\n\t\t\tinput: map[string]any{\n\t\t\t\t\"helm.sdk.operatorframework.io/wrong-annotation\": \"true\",\n\t\t\t},\n\t\t\texpectedVal: false,\n\t\t\tname:        \"uninstall wait annotation not set\",\n\t\t},\n\t\t{\n\t\t\tinput: map[string]any{\n\t\t\t\t\"helm.sdk.operatorframework.io/uninstall-wait\": \"invalid\",\n\t\t\t},\n\t\t\texpectedVal: false,\n\t\t\tname:        \"uninstall wait invalid value\",\n\t\t},\n\t}\n\n\tfor _, test := range uninstallWaitTests {\n\t\tassert.Equal(t, test.expectedVal, hasAnnotation(helmUninstallWaitAnnotation, annotations(test.input)), test.name)\n\t}\n}\n\nfunc annotations(m map[string]any) *unstructured.Unstructured {\n\treturn &unstructured.Unstructured{\n\t\tObject: map[string]any{\n\t\t\t\"metadata\": map[string]any{\n\t\t\t\t\"annotations\": m,\n\t\t\t},\n\t\t},\n\t}\n}\n\nfunc Test_readBoolAnnotationWithDefault(t *testing.T) {\n\tobjBuilder := func(anno map[string]string) *unstructured.Unstructured {\n\t\tobject := &unstructured.Unstructured{}\n\t\tobject.SetAnnotations(anno)\n\t\treturn object\n\t}\n\n\ttype args struct {\n\t\tobj        *unstructured.Unstructured\n\t\tannotation string\n\t\tfallback   bool\n\t}\n\n\ttests := []struct {\n\t\tname string\n\t\targs args\n\t\twant bool\n\t}{\n\t\t{\n\t\t\tname: \"Should return value of annotation read\",\n\t\t\targs: args{\n\t\t\t\tobj: objBuilder(map[string]string{\n\t\t\t\t\t\"helm.sdk.operatorframework.io/rollback-force\": \"false\",\n\t\t\t\t}),\n\t\t\t\tannotation: \"helm.sdk.operatorframework.io/rollback-force\",\n\t\t\t\tfallback:   true,\n\t\t\t},\n\t\t\twant: false,\n\t\t},\n\t\t{\n\t\t\tname: \"Should return fallback when annotation is not present\",\n\t\t\targs: args{\n\t\t\t\tobj: objBuilder(map[string]string{\n\t\t\t\t\t\"helm.sdk.operatorframework.io/upgrade-force\": \"true\",\n\t\t\t\t}),\n\t\t\t\tannotation: \"helm.sdk.operatorframework.io/rollback-force\",\n\t\t\t\tfallback:   false,\n\t\t\t},\n\t\t\twant: false,\n\t\t},\n\t\t{\n\t\t\tname: \"Should return fallback when errors while parsing bool value\",\n\t\t\targs: args{\n\t\t\t\tobj: objBuilder(map[string]string{\n\t\t\t\t\t\"helm.sdk.operatorframework.io/rollback-force\": \"force\",\n\t\t\t\t}),\n\t\t\t\tannotation: \"helm.sdk.operatorframework.io/rollback-force\",\n\t\t\t\tfallback:   true,\n\t\t\t},\n\t\t\twant: true,\n\t\t},\n\t}\n\tfor _, tc := range tests {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tif got := readBoolAnnotationWithDefault(tc.args.obj, tc.args.annotation, tc.args.fallback); got != tc.want {\n\t\t\t\tassert.Equal(t, tc.want, got, \"readBoolAnnotationWithDefault() function\")\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "internal/helm/flags/flag.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage flags\n\nimport (\n\t\"crypto/tls\"\n\t\"runtime\"\n\t\"time\"\n\n\t\"github.com/spf13/pflag\"\n\t\"k8s.io/client-go/tools/leaderelection/resourcelock\"\n\t\"sigs.k8s.io/controller-runtime/pkg/manager\"\n\t\"sigs.k8s.io/controller-runtime/pkg/metrics/filters\"\n\t\"sigs.k8s.io/controller-runtime/pkg/webhook\"\n)\n\n// Flags - Options to be used by a helm operator\ntype Flags struct {\n\tReconcilePeriod         time.Duration\n\tWatchesFile             string\n\tMetricsBindAddress      string\n\tLeaderElection          bool\n\tLeaderElectionID        string\n\tLeaderElectionNamespace string\n\tMaxConcurrentReconciles int\n\tProbeAddr               string\n\tSuppressOverrideValues  bool\n\tEnableHTTP2             bool\n\tSecureMetrics           bool\n\tMetricsRequireRBAC      bool\n\n\t// If not nil, used to deduce which flags were set in the CLI.\n\tflagSet *pflag.FlagSet\n}\n\n// AddTo - Add the helm operator flags to the flagset\nfunc (f *Flags) AddTo(flagSet *pflag.FlagSet) {\n\t// Store flagset internally to be used for lookups later.\n\tf.flagSet = flagSet\n\n\t// Helm flags.\n\tflagSet.StringVar(&f.WatchesFile,\n\t\t\"watches-file\",\n\t\t\"./watches.yaml\",\n\t\t\"Path to the watches file to use\",\n\t)\n\n\t// Controller flags.\n\tflagSet.DurationVar(&f.ReconcilePeriod,\n\t\t\"reconcile-period\",\n\t\ttime.Minute,\n\t\t\"Default reconcile period for controllers\",\n\t)\n\tflagSet.IntVar(&f.MaxConcurrentReconciles,\n\t\t\"max-concurrent-reconciles\",\n\t\truntime.NumCPU(),\n\t\t\"Maximum number of concurrent reconciles for controllers.\",\n\t)\n\n\t_ = flagSet.MarkDeprecated(\"config\",\n\t\t`controller-runtime has deprecated the ComponentConfig package \nand as such, the ability to load the configuation from a file. Since the helm operator relies on controller-runtime\nthis flag will be removed when upgrading to a version of controller-runtime where the ComponentConfig package has been removed.\nsee https://github.com/kubernetes-sigs/controller-runtime/issues/895 for more information.`)\n\n\t// TODO(2.0.0): remove\n\tflagSet.StringVar(&f.MetricsBindAddress,\n\t\t\"metrics-addr\",\n\t\t\":8080\",\n\t\t\"The address the metric endpoint binds to\",\n\t)\n\t_ = flagSet.MarkDeprecated(\"metrics-addr\", \"use --metrics-bind-address instead\")\n\tflagSet.StringVar(&f.MetricsBindAddress,\n\t\t\"metrics-bind-address\",\n\t\t\":8080\",\n\t\t\"The address the metric endpoint binds to\",\n\t)\n\t// TODO(2.0.0): for Go/Helm the port used is: 8081\n\t// update it to keep the project aligned to the other\n\tflagSet.StringVar(&f.ProbeAddr,\n\t\t\"health-probe-bind-address\",\n\t\t\":8081\",\n\t\t\"The address the probe endpoint binds to.\",\n\t)\n\t// TODO(2.0.0): remove\n\tflagSet.BoolVar(&f.LeaderElection,\n\t\t\"enable-leader-election\",\n\t\tfalse,\n\t\t\"Enable leader election for controller manager. Enabling this will\"+\n\t\t\t\" ensure there is only one active controller manager.\",\n\t)\n\t_ = flagSet.MarkDeprecated(\"enable-leader-election\", \"use --leader-elect instead.\")\n\tflagSet.BoolVar(&f.LeaderElection,\n\t\t\"leader-elect\",\n\t\tfalse,\n\t\t\"Enable leader election for controller manager. Enabling this will\"+\n\t\t\t\" ensure there is only one active controller manager.\",\n\t)\n\tflagSet.StringVar(&f.LeaderElectionID,\n\t\t\"leader-election-id\",\n\t\t\"\",\n\t\t\"Name of the configmap that is used for holding the leader lock.\",\n\t)\n\tflagSet.StringVar(&f.LeaderElectionNamespace,\n\t\t\"leader-election-namespace\",\n\t\t\"\",\n\t\t\"Namespace in which to create the leader election configmap for\"+\n\t\t\t\" holding the leader lock (required if running locally with leader\"+\n\t\t\t\" election enabled).\",\n\t)\n\tflagSet.BoolVar(&f.SuppressOverrideValues,\n\t\t\"suppress-override-values\",\n\t\tfalse,\n\t\t\"Silences the override-value for OverrideValuesInUse events\",\n\t)\n\tflagSet.BoolVar(&f.EnableHTTP2,\n\t\t\"enable-http2\",\n\t\tfalse,\n\t\t\"enables HTTP/2 on the webhook and metrics servers\",\n\t)\n\tflagSet.BoolVar(&f.SecureMetrics,\n\t\t\"metrics-secure\",\n\t\tfalse,\n\t\t\"enables secure serving of the metrics endpoint\",\n\t)\n\tflagSet.BoolVar(&f.MetricsRequireRBAC,\n\t\t\"metrics-require-rbac\",\n\t\tfalse,\n\t\t\"enables protection of the metrics endpoint with RBAC-based authn/authz.\"+\n\t\t\t\"see https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.18.4/pkg/metrics/filters#WithAuthenticationAndAuthorization for more info\")\n}\n\n// ToManagerOptions uses the flag set in f to configure options.\n// Values of options take precedence over flag defaults,\n// as values are assume to have been explicitly set.\nfunc (f *Flags) ToManagerOptions(options manager.Options) manager.Options {\n\t// Alias FlagSet.Changed so options are still updated when fields are empty.\n\tchanged := func(flagName string) bool {\n\t\treturn f.flagSet.Changed(flagName)\n\t}\n\tif f.flagSet == nil {\n\t\t//nolint:golint\n\t\tchanged = func(_ string) bool { return false }\n\t}\n\n\t// TODO(2.0.0): remove metrics-addr\n\tif changed(\"metrics-bind-address\") || changed(\"metrics-addr\") || options.Metrics.BindAddress == \"\" {\n\t\toptions.Metrics.BindAddress = f.MetricsBindAddress\n\t}\n\tif changed(\"health-probe-bind-address\") || options.HealthProbeBindAddress == \"\" {\n\t\toptions.HealthProbeBindAddress = f.ProbeAddr\n\t}\n\t// TODO(2.0.0): remove enable-leader-election\n\tif changed(\"leader-elect\") || changed(\"enable-leader-election\") || !options.LeaderElection {\n\t\toptions.LeaderElection = f.LeaderElection\n\t}\n\tif changed(\"leader-election-id\") || options.LeaderElectionID == \"\" {\n\t\toptions.LeaderElectionID = f.LeaderElectionID\n\t}\n\tif changed(\"leader-election-namespace\") || options.LeaderElectionNamespace == \"\" {\n\t\toptions.LeaderElectionNamespace = f.LeaderElectionNamespace\n\t}\n\tif options.LeaderElectionResourceLock == \"\" {\n\t\toptions.LeaderElectionResourceLock = resourcelock.LeasesResourceLock\n\t}\n\n\tdisableHTTP2 := func(c *tls.Config) {\n\t\tc.NextProtos = []string{\"http/1.1\"}\n\t}\n\tif !f.EnableHTTP2 {\n\t\toptions.WebhookServer = webhook.NewServer(webhook.Options{\n\t\t\tTLSOpts: []func(*tls.Config){disableHTTP2},\n\t\t})\n\t\toptions.Metrics.TLSOpts = append(options.Metrics.TLSOpts, disableHTTP2)\n\t}\n\toptions.Metrics.SecureServing = f.SecureMetrics\n\n\tif f.MetricsRequireRBAC {\n\t\t// FilterProvider is used to protect the metrics endpoint with authn/authz.\n\t\t// These configurations ensure that only authorized users and service accounts\n\t\t// can access the metrics endpoint. The RBAC are configured in 'config/rbac/kustomization.yaml'. More info:\n\t\t// https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.18.4/pkg/metrics/filters#WithAuthenticationAndAuthorization\n\t\toptions.Metrics.FilterProvider = filters.WithAuthenticationAndAuthorization\n\t}\n\n\treturn options\n}\n"
  },
  {
    "path": "internal/helm/flags/flag_test.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage flags_test\n\nimport (\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\t\"github.com/spf13/pflag\"\n\t\"sigs.k8s.io/controller-runtime/pkg/manager\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/helm/flags\"\n)\n\nvar _ = Describe(\"Flags\", func() {\n\tDescribe(\"ToManagerOptions\", func() {\n\t\tvar (\n\t\t\tf       *flags.Flags\n\t\t\tflagSet *pflag.FlagSet\n\t\t\toptions manager.Options\n\t\t)\n\t\tBeforeEach(func() {\n\t\t\tf = &flags.Flags{}\n\t\t\tflagSet = pflag.NewFlagSet(\"test\", pflag.ExitOnError)\n\t\t\tf.AddTo(flagSet)\n\t\t})\n\n\t\tWhen(\"the flag is set\", func() {\n\t\t\tIt(\"uses the flag value when corresponding option value is empty\", func() {\n\t\t\t\texpOptionValue := \":5678\"\n\t\t\t\toptions.Metrics.BindAddress = \"\"\n\t\t\t\tparseArgs(flagSet, \"--metrics-bind-address\", expOptionValue)\n\t\t\t\tExpect(f.ToManagerOptions(options).Metrics.BindAddress).To(Equal(expOptionValue))\n\t\t\t})\n\t\t\tIt(\"uses the flag value when corresponding option value is not empty\", func() {\n\t\t\t\texpOptionValue := \":5678\"\n\t\t\t\toptions.Metrics.BindAddress = \":1234\"\n\t\t\t\tparseArgs(flagSet, \"--metrics-bind-address\", expOptionValue)\n\t\t\t\tExpect(f.ToManagerOptions(options).Metrics.BindAddress).To(Equal(expOptionValue))\n\t\t\t})\n\t\t})\n\t\tWhen(\"the flag is not set\", func() {\n\t\t\tIt(\"uses the default flag value when corresponding option value is empty\", func() {\n\t\t\t\texpOptionValue := \":8080\"\n\t\t\t\toptions.Metrics.BindAddress = \"\"\n\t\t\t\tparseArgs(flagSet)\n\t\t\t\tExpect(f.ToManagerOptions(options).Metrics.BindAddress).To(Equal(expOptionValue))\n\t\t\t})\n\t\t\tIt(\"uses the option value when corresponding option value is not empty\", func() {\n\t\t\t\texpOptionValue := \":1234\"\n\t\t\t\toptions.Metrics.BindAddress = expOptionValue\n\t\t\t\tparseArgs(flagSet)\n\t\t\t\tExpect(f.ToManagerOptions(options).Metrics.BindAddress).To(Equal(expOptionValue))\n\t\t\t})\n\t\t})\n\t})\n})\n\nfunc parseArgs(fs *pflag.FlagSet, extraArgs ...string) {\n\tExpect(fs.Parse(extraArgs)).To(Succeed())\n}\n"
  },
  {
    "path": "internal/helm/flags/suite_test.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage flags_test\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nfunc TestFlags(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"Flags Suite\")\n}\n"
  },
  {
    "path": "internal/helm/internal/diff/diff.go",
    "content": "// Copyright 2018 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage diff\n\nimport (\n\t\"bytes\"\n\t\"regexp\"\n\t\"strings\"\n\n\t\"github.com/sergi/go-diff/diffmatchpatch\"\n)\n\n// Generate generates a diff between a and b, in color.\nfunc Generate(a, b string) string {\n\tdmp := diffmatchpatch.New()\n\n\twSrc, wDst, warray := dmp.DiffLinesToRunes(a, b)\n\tdiffs := dmp.DiffMainRunes(wSrc, wDst, false)\n\tdiffs = dmp.DiffCharsToLines(diffs, warray)\n\tvar buff bytes.Buffer\n\tfor _, diff := range diffs {\n\t\ttext := diff.Text\n\n\t\tswitch diff.Type {\n\t\tcase diffmatchpatch.DiffInsert:\n\t\t\t_, _ = buff.WriteString(\"\\x1b[32m\")\n\t\t\t_, _ = buff.WriteString(prefixLines(text, \"+\"))\n\t\t\t_, _ = buff.WriteString(\"\\x1b[0m\")\n\t\tcase diffmatchpatch.DiffDelete:\n\t\t\t_, _ = buff.WriteString(\"\\x1b[31m\")\n\t\t\t_, _ = buff.WriteString(prefixLines(text, \"-\"))\n\t\t\t_, _ = buff.WriteString(\"\\x1b[0m\")\n\t\tcase diffmatchpatch.DiffEqual:\n\t\t\t_, _ = buff.WriteString(prefixLines(text, \" \"))\n\t\t}\n\t}\n\treturn buff.String()\n}\n\nfunc prefixLines(s, prefix string) string {\n\tvar buf bytes.Buffer\n\tlines := strings.Split(s, \"\\n\")\n\tls := regexp.MustCompile(\"^\")\n\tfor _, line := range lines[:len(lines)-1] {\n\t\tbuf.WriteString(ls.ReplaceAllString(line, prefix))\n\t\tbuf.WriteString(\"\\n\")\n\t}\n\treturn buf.String()\n}\n"
  },
  {
    "path": "internal/helm/internal/types/doc.go",
    "content": "// Copyright 2018 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Package types contains types used by various components of the Helm\n// operator\npackage types\n"
  },
  {
    "path": "internal/helm/internal/types/types.go",
    "content": "// Copyright 2018 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage types\n\nimport (\n\t\"encoding/json\"\n\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n)\n\ntype HelmAppList struct {\n\tmetav1.TypeMeta `json:\",inline\"`\n\tmetav1.ListMeta `json:\"metadata\"`\n\tItems           []HelmApp `json:\"items\"`\n}\n\ntype HelmApp struct {\n\tmetav1.TypeMeta   `json:\",inline\"`\n\tmetav1.ObjectMeta `json:\"metadata\"`\n\tSpec              HelmAppSpec   `json:\"spec\"`\n\tStatus            HelmAppStatus `json:\"status,omitempty\"`\n}\n\ntype HelmAppSpec map[string]any\n\ntype HelmAppConditionType string\ntype ConditionStatus string\ntype HelmAppConditionReason string\n\ntype HelmAppCondition struct {\n\tType    HelmAppConditionType   `json:\"type\"`\n\tStatus  ConditionStatus        `json:\"status\"`\n\tReason  HelmAppConditionReason `json:\"reason,omitempty\"`\n\tMessage string                 `json:\"message,omitempty\"`\n\n\tLastTransitionTime metav1.Time `json:\"lastTransitionTime,omitempty\"`\n}\n\ntype HelmAppRelease struct {\n\tName     string `json:\"name,omitempty\"`\n\tManifest string `json:\"manifest,omitempty\"`\n}\n\nconst (\n\tConditionInitialized    HelmAppConditionType = \"Initialized\"\n\tConditionDeployed       HelmAppConditionType = \"Deployed\"\n\tConditionReleaseFailed  HelmAppConditionType = \"ReleaseFailed\"\n\tConditionIrreconcilable HelmAppConditionType = \"Irreconcilable\"\n\n\tStatusTrue    ConditionStatus = \"True\"\n\tStatusFalse   ConditionStatus = \"False\"\n\tStatusUnknown ConditionStatus = \"Unknown\"\n\n\tReasonInstallSuccessful   HelmAppConditionReason = \"InstallSuccessful\"\n\tReasonUpgradeSuccessful   HelmAppConditionReason = \"UpgradeSuccessful\"\n\tReasonUninstallSuccessful HelmAppConditionReason = \"UninstallSuccessful\"\n\tReasonInstallError        HelmAppConditionReason = \"InstallError\"\n\tReasonUpgradeError        HelmAppConditionReason = \"UpgradeError\"\n\tReasonReconcileError      HelmAppConditionReason = \"ReconcileError\"\n\tReasonUninstallError      HelmAppConditionReason = \"UninstallError\"\n)\n\ntype HelmAppStatus struct {\n\tConditions      []HelmAppCondition `json:\"conditions\"`\n\tDeployedRelease *HelmAppRelease    `json:\"deployedRelease,omitempty\"`\n}\n\nfunc (s *HelmAppStatus) ToMap() (map[string]any, error) {\n\tvar out map[string]any\n\tjsonObj, err := json.Marshal(&s)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif err := json.Unmarshal(jsonObj, &out); err != nil {\n\t\treturn nil, err\n\t}\n\treturn out, nil\n}\n\n// SetCondition sets a condition on the status object. If the condition already\n// exists, it will be replaced. SetCondition does not update the resource in\n// the cluster.\nfunc (s *HelmAppStatus) SetCondition(condition HelmAppCondition) *HelmAppStatus {\n\tnow := metav1.Now()\n\tfor i := range s.Conditions {\n\t\tif s.Conditions[i].Type == condition.Type {\n\t\t\tif s.Conditions[i].Status != condition.Status {\n\t\t\t\tcondition.LastTransitionTime = now\n\t\t\t} else {\n\t\t\t\tcondition.LastTransitionTime = s.Conditions[i].LastTransitionTime\n\t\t\t}\n\t\t\ts.Conditions[i] = condition\n\t\t\treturn s\n\t\t}\n\t}\n\n\t// If the condition does not exist,\n\t// initialize the lastTransitionTime\n\tcondition.LastTransitionTime = now\n\ts.Conditions = append(s.Conditions, condition)\n\treturn s\n}\n\n// RemoveCondition removes the condition with the passed condition type from\n// the status object. If the condition is not already present, the returned\n// status object is returned unchanged. RemoveCondition does not update the\n// resource in the cluster.\nfunc (s *HelmAppStatus) RemoveCondition(conditionType HelmAppConditionType) *HelmAppStatus {\n\tfor i := range s.Conditions {\n\t\tif s.Conditions[i].Type == conditionType {\n\t\t\ts.Conditions = append(s.Conditions[:i], s.Conditions[i+1:]...)\n\t\t\treturn s\n\t\t}\n\t}\n\treturn s\n}\n\n// StatusFor safely returns a typed status block from a custom resource.\nfunc StatusFor(cr *unstructured.Unstructured) *HelmAppStatus {\n\tswitch s := cr.Object[\"status\"].(type) {\n\tcase *HelmAppStatus:\n\t\treturn s\n\tcase map[string]any:\n\t\tvar status *HelmAppStatus\n\t\tif err := runtime.DefaultUnstructuredConverter.FromUnstructured(s, &status); err != nil {\n\t\t\treturn &HelmAppStatus{}\n\t\t}\n\t\treturn status\n\tdefault:\n\t\treturn &HelmAppStatus{}\n\t}\n}\n"
  },
  {
    "path": "internal/helm/internal/types/types_test.go",
    "content": "// Copyright 2018 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage types\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured\"\n)\n\nconst (\n\ttestNamespaceName = \"helm-test\"\n)\n\nvar now = metav1.Now()\n\nfunc TestSetCondition(t *testing.T) {\n\tmessage := \"uninstall was successful\"\n\tnewStatus, err := newTestStatus().SetCondition(HelmAppCondition{\n\t\tType:    ConditionDeployed,\n\t\tStatus:  StatusFalse,\n\t\tReason:  ReasonUninstallSuccessful,\n\t\tMessage: message,\n\t}).ToMap()\n\tassert.NoError(t, err)\n\n\tresource := newTestResource()\n\tresource.Object[\"status\"] = newStatus\n\tactual := StatusFor(resource)\n\n\tassert.Equal(t, ConditionDeployed, actual.Conditions[0].Type)\n\tassert.Equal(t, StatusFalse, actual.Conditions[0].Status)\n\tassert.Equal(t, ReasonUninstallSuccessful, actual.Conditions[0].Reason)\n\tassert.Equal(t, message, actual.Conditions[0].Message)\n\tassert.NotEqual(t, metav1.Now(), actual.Conditions[0].LastTransitionTime)\n}\nfunc TestRemoveCondition(t *testing.T) {\n\tnewStatus, err := newTestStatus().RemoveCondition(ConditionDeployed).ToMap()\n\tassert.NoError(t, err)\n\n\tresource := newTestResource()\n\tresource.Object[\"status\"] = newStatus\n\tactual := StatusFor(resource)\n\n\tassert.Empty(t, actual.Conditions)\n}\n\nfunc TestStatusForEmpty(t *testing.T) {\n\tstatus := StatusFor(newTestResource())\n\n\tassert.Equal(t, &HelmAppStatus{}, status)\n}\n\nfunc TestStatusForFilled(t *testing.T) {\n\texpectedResource := newTestResource()\n\texpectedResource.Object[\"status\"] = newTestStatus()\n\tstatus := StatusFor(expectedResource)\n\n\tassert.EqualValues(t, newTestStatus(), status)\n}\n\nfunc TestStatusForFilledRaw(t *testing.T) {\n\texpectedResource := newTestResource()\n\texpectedResource.Object[\"status\"] = newTestStatusRaw()\n\tstatus := StatusFor(expectedResource)\n\n\tassert.Equal(t, ConditionDeployed, status.Conditions[0].Type)\n\tassert.Equal(t, StatusTrue, status.Conditions[0].Status)\n\tassert.Equal(t, ReasonInstallSuccessful, status.Conditions[0].Reason)\n\tassert.Equal(t, \"some message\", status.Conditions[0].Message)\n\tassert.NotEqual(t, metav1.Now(), status.Conditions[0].LastTransitionTime)\n\tassert.Equal(t, \"SomeRelease\", status.DeployedRelease.Name)\n}\n\nfunc newTestResource() *unstructured.Unstructured {\n\treturn &unstructured.Unstructured{\n\t\tObject: map[string]any{\n\t\t\t\"kind\":       \"Character\",\n\t\t\t\"apiVersion\": \"stable.nicolerenee.io\",\n\t\t\t\"metadata\": map[string]any{\n\t\t\t\t\"name\":      \"dory\",\n\t\t\t\t\"namespace\": testNamespaceName,\n\t\t\t},\n\t\t\t\"spec\": map[string]any{\n\t\t\t\t\"Name\": \"Dory\",\n\t\t\t\t\"From\": \"Finding Nemo\",\n\t\t\t\t\"By\":   \"Disney\",\n\t\t\t},\n\t\t},\n\t}\n}\n\nfunc newTestStatus() *HelmAppStatus {\n\treturn &HelmAppStatus{\n\t\tConditions: []HelmAppCondition{\n\t\t\t{\n\t\t\t\tType:               ConditionDeployed,\n\t\t\t\tStatus:             StatusTrue,\n\t\t\t\tReason:             ReasonInstallSuccessful,\n\t\t\t\tMessage:            \"some message\",\n\t\t\t\tLastTransitionTime: now,\n\t\t\t},\n\t\t},\n\t\tDeployedRelease: &HelmAppRelease{Name: \"SomeRelease\"},\n\t}\n}\n\nfunc newTestStatusRaw() map[string]any {\n\treturn map[string]any{\n\t\t\"conditions\": []map[string]any{\n\t\t\t{\n\t\t\t\t\"type\":               \"Deployed\",\n\t\t\t\t\"status\":             \"True\",\n\t\t\t\t\"reason\":             \"InstallSuccessful\",\n\t\t\t\t\"message\":            \"some message\",\n\t\t\t\t\"lastTransitionTime\": now.UTC(),\n\t\t\t},\n\t\t},\n\t\t\"deployedRelease\": map[string]any{\"name\": \"SomeRelease\"},\n\t}\n}\n"
  },
  {
    "path": "internal/helm/manifestutil/resource_policy.go",
    "content": "/*\nCopyright 2021 The Operator-SDK Authors.\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n    http://www.apache.org/licenses/LICENSE-2.0\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage manifestutil\n\nimport (\n\t\"strings\"\n\n\t\"helm.sh/helm/v3/pkg/kube\"\n\t\"helm.sh/helm/v3/pkg/releaseutil\"\n)\n\n// Source from https://github.com/helm/helm/blob/v3.4.2/pkg/action/resource_policy.go\nfunc FilterManifestsToKeep(manifests []releaseutil.Manifest) (keep, remaining []releaseutil.Manifest) {\n\tfor _, m := range manifests {\n\t\tif m.Head.Metadata == nil || m.Head.Metadata.Annotations == nil || len(m.Head.Metadata.Annotations) == 0 {\n\t\t\tremaining = append(remaining, m)\n\t\t\tcontinue\n\t\t}\n\n\t\tresourcePolicyType, ok := m.Head.Metadata.Annotations[kube.ResourcePolicyAnno]\n\t\tif !ok {\n\t\t\tremaining = append(remaining, m)\n\t\t\tcontinue\n\t\t}\n\n\t\tresourcePolicyType = strings.ToLower(strings.TrimSpace(resourcePolicyType))\n\t\tif resourcePolicyType == kube.KeepPolicy {\n\t\t\tkeep = append(keep, m)\n\t\t}\n\n\t}\n\treturn keep, remaining\n}\n"
  },
  {
    "path": "internal/helm/metrics/metrics.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage metrics\n\nimport (\n\t\"github.com/prometheus/client_golang/prometheus\"\n\n\tsdkVersion \"github.com/operator-framework/operator-sdk/internal/version\"\n)\n\nconst (\n\tsubsystem = \"helm_operator\"\n)\n\nvar (\n\tbuildInfo = prometheus.NewGauge(\n\t\tprometheus.GaugeOpts{\n\t\t\tSubsystem: subsystem,\n\t\t\tName:      \"build_info\",\n\t\t\tHelp:      \"Build information for the helm-operator binary\",\n\t\t\tConstLabels: map[string]string{\n\t\t\t\t\"commit\":  sdkVersion.GitCommit,\n\t\t\t\t\"version\": sdkVersion.Version,\n\t\t\t},\n\t\t},\n\t)\n)\n\nfunc RegisterBuildInfo(r prometheus.Registerer) {\n\tbuildInfo.Set(1)\n\tr.MustRegister(buildInfo)\n}\n"
  },
  {
    "path": "internal/helm/release/doc.go",
    "content": "// Copyright 2018 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Package release provides interfaces and default implementations for a Helm\n// release manager, which is used by the Helm controller and reconciler to\n// manage Helm releases in a cluster based on watched custom resources.\npackage release\n"
  },
  {
    "path": "internal/helm/release/manager.go",
    "content": "// Copyright 2018 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage release\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"strings\"\n\n\tjsonpatch \"gomodules.xyz/jsonpatch/v3\"\n\t\"helm.sh/helm/v3/pkg/action\"\n\tcpb \"helm.sh/helm/v3/pkg/chart\"\n\t\"helm.sh/helm/v3/pkg/kube\"\n\trpb \"helm.sh/helm/v3/pkg/release\"\n\t\"helm.sh/helm/v3/pkg/releaseutil\"\n\t\"helm.sh/helm/v3/pkg/storage\"\n\t\"helm.sh/helm/v3/pkg/storage/driver\"\n\tapiextv1 \"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1\"\n\tapiextv1beta1 \"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1\"\n\tapierrors \"k8s.io/apimachinery/pkg/api/errors\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\tapitypes \"k8s.io/apimachinery/pkg/types\"\n\tapiutilerrors \"k8s.io/apimachinery/pkg/util/errors\"\n\t\"k8s.io/apimachinery/pkg/util/strategicpatch\"\n\t\"k8s.io/cli-runtime/pkg/resource\"\n\t\"k8s.io/client-go/discovery\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/helm/internal/types\"\n\t\"github.com/operator-framework/operator-sdk/internal/helm/manifestutil\"\n)\n\n// Manager manages a Helm release. It can install, upgrade, reconcile,\n// and uninstall a release.\ntype Manager interface {\n\tReleaseName() string\n\tIsInstalled() bool\n\tIsUpgradeRequired() bool\n\tSync() error\n\tInstallRelease(...InstallOption) (*rpb.Release, error)\n\tUpgradeRelease(...UpgradeOption) (*rpb.Release, *rpb.Release, error)\n\tRollBack(...RollBackOption) error\n\tReconcileRelease(context.Context) (*rpb.Release, error)\n\tUninstallRelease(...UninstallOption) (*rpb.Release, error)\n\tCleanupRelease(string) (bool, error)\n}\n\ntype manager struct {\n\tactionConfig   *action.Configuration\n\tstorageBackend *storage.Storage\n\tkubeClient     kube.Interface\n\n\treleaseName string\n\tnamespace   string\n\n\tvalues map[string]any\n\tstatus *types.HelmAppStatus\n\n\tisInstalled       bool\n\tisUpgradeRequired bool\n\tdeployedRelease   *rpb.Release\n\tchart             *cpb.Chart\n\n\tdryRunOption string\n}\n\ntype InstallOption func(*action.Install) error\ntype UpgradeOption func(*action.Upgrade) error\ntype UninstallOption func(*action.Uninstall) error\ntype RollBackOption func(*action.Rollback) error\n\n// ReleaseName returns the name of the release.\nfunc (m manager) ReleaseName() string {\n\treturn m.releaseName\n}\n\nfunc (m manager) IsInstalled() bool {\n\treturn m.isInstalled\n}\n\nfunc (m manager) IsUpgradeRequired() bool {\n\treturn m.isUpgradeRequired\n}\n\n// Sync ensures the Helm storage backend is in sync with the status of the\n// custom resource.\nfunc (m *manager) Sync() error {\n\t// Get release history for this release name\n\treleases, err := m.storageBackend.History(m.releaseName)\n\tif err != nil && !notFoundErr(err) {\n\t\treturn fmt.Errorf(\"failed to retrieve release history: %w\", err)\n\t}\n\n\t// Cleanup non-deployed release versions. If all release versions are\n\t// non-deployed, this will ensure that failed installations are correctly\n\t// retried.\n\tfor _, rel := range releases {\n\t\tif rel.Info != nil && rel.Info.Status != rpb.StatusDeployed {\n\t\t\t_, err := m.storageBackend.Delete(rel.Name, rel.Version)\n\t\t\tif err != nil && !notFoundErr(err) {\n\t\t\t\treturn fmt.Errorf(\"failed to delete stale release version: %w\", err)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Load the most recently deployed release from the storage backend.\n\tdeployedRelease, err := m.getDeployedRelease()\n\tif errors.Is(err, driver.ErrReleaseNotFound) {\n\t\treturn nil\n\t}\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to get deployed release: %w\", err)\n\t}\n\tm.deployedRelease = deployedRelease\n\tm.isInstalled = true\n\n\t// Get the next candidate release to determine if an upgrade is necessary.\n\tcandidateRelease, err := m.getCandidateRelease(m.namespace, m.releaseName, m.chart, m.values)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to get candidate release: %w\", err)\n\t}\n\tif deployedRelease.Manifest != candidateRelease.Manifest {\n\t\tm.isUpgradeRequired = true\n\t}\n\n\treturn nil\n}\n\nfunc notFoundErr(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"not found\")\n}\n\nfunc (m manager) getDeployedRelease() (*rpb.Release, error) {\n\tdeployedRelease, err := m.storageBackend.Deployed(m.releaseName)\n\tif err != nil {\n\t\tif strings.Contains(err.Error(), \"has no deployed releases\") {\n\t\t\treturn nil, driver.ErrReleaseNotFound\n\t\t}\n\t\treturn nil, err\n\t}\n\treturn deployedRelease, nil\n}\n\nfunc (m manager) getCandidateRelease(namespace, name string, chart *cpb.Chart,\n\tvalues map[string]any) (*rpb.Release, error) {\n\tupgrade := action.NewUpgrade(m.actionConfig)\n\tupgrade.Namespace = namespace\n\tupgrade.DryRun = true\n\tupgrade.DryRunOption = m.dryRunOption\n\treturn upgrade.Run(name, chart, values)\n}\n\n// InstallRelease performs a Helm release install.\nfunc (m manager) InstallRelease(opts ...InstallOption) (*rpb.Release, error) {\n\tinstall := action.NewInstall(m.actionConfig)\n\tinstall.ReleaseName = m.releaseName\n\tinstall.Namespace = m.namespace\n\tfor _, o := range opts {\n\t\tif err := o(install); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to apply install option: %w\", err)\n\t\t}\n\t}\n\n\tinstalledRelease, err := install.Run(m.chart, m.values)\n\tif err != nil {\n\t\t// Workaround for helm/helm#3338\n\t\tif installedRelease != nil {\n\t\t\tuninstall := action.NewUninstall(m.actionConfig)\n\t\t\t_, uninstallErr := uninstall.Run(m.releaseName)\n\n\t\t\t// In certain cases, InstallRelease will return a partial release in\n\t\t\t// the response even when it doesn't record the release in its release\n\t\t\t// store (e.g. when there is an error rendering the release manifest).\n\t\t\t// In that case the rollback will fail with a not found error because\n\t\t\t// there was nothing to rollback.\n\t\t\t//\n\t\t\t// Only log a message about a rollback failure if the failure was caused\n\t\t\t// by something other than the release not being found.\n\t\t\tif uninstallErr != nil && !notFoundErr(uninstallErr) {\n\t\t\t\treturn nil, fmt.Errorf(\"failed installation (%s) and failed rollback: %w\", err, uninstallErr)\n\t\t\t}\n\t\t}\n\t\treturn nil, fmt.Errorf(\"failed to install release: %w\", err)\n\t}\n\treturn installedRelease, nil\n}\n\nfunc ForceUpgrade(force bool) UpgradeOption {\n\treturn func(u *action.Upgrade) error {\n\t\tu.Force = force\n\t\treturn nil\n\t}\n}\n\nvar ErrUpgradeFailed = errors.New(\"upgrade failed; rollback required\")\n\n// UpgradeRelease performs a Helm release upgrade.\nfunc (m manager) UpgradeRelease(opts ...UpgradeOption) (*rpb.Release, *rpb.Release, error) {\n\tupgrade := action.NewUpgrade(m.actionConfig)\n\tupgrade.Namespace = m.namespace\n\n\tfor _, o := range opts {\n\t\tif err := o(upgrade); err != nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"failed to apply upgrade option: %w\", err)\n\t\t}\n\t}\n\n\tupgradedRelease, err := upgrade.Run(m.releaseName, m.chart, m.values)\n\tif err != nil {\n\t\t// Workaround for helm/helm#3338\n\t\tif upgradedRelease != nil {\n\t\t\t// As of Helm 2.13, if UpgradeRelease returns a non-nil release, that\n\t\t\t// means the release was also recorded in the release store.\n\t\t\t// Therefore, we should perform the rollback when we have a non-nil\n\t\t\t// release. Any rollback error here would be unexpected, so always\n\t\t\t// log both the upgrade and rollback errors.\n\t\t\tfmt.Printf(\"release upgrade failed; %v\", err)\n\n\t\t\treturn nil, nil, ErrUpgradeFailed\n\t\t}\n\t\treturn nil, nil, fmt.Errorf(\"failed to upgrade release: %w\", err)\n\t}\n\treturn m.deployedRelease, upgradedRelease, err\n}\n\nfunc ForceRollback(force bool) RollBackOption {\n\treturn func(r *action.Rollback) error {\n\t\tr.Force = force\n\t\treturn nil\n\t}\n}\n\n// RollBack attempts to reverse any partially applied releases\nfunc (m manager) RollBack(opts ...RollBackOption) error {\n\trollback := action.NewRollback(m.actionConfig)\n\n\tfor _, fn := range opts {\n\t\tif err := fn(rollback); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to apply rollback option: %w\", err)\n\t\t}\n\t}\n\n\tif err := rollback.Run(m.releaseName); err != nil {\n\t\treturn fmt.Errorf(\"rollback failed: %w\", err)\n\t}\n\n\treturn nil\n}\n\n// ReconcileRelease creates or patches resources as necessary to match the\n// deployed release's manifest.\nfunc (m manager) ReconcileRelease(ctx context.Context) (*rpb.Release, error) {\n\terr := reconcileRelease(ctx, m.kubeClient, m.deployedRelease.Manifest)\n\treturn m.deployedRelease, err\n}\n\nfunc reconcileRelease(_ context.Context, kubeClient kube.Interface, expectedManifest string) error {\n\texpectedInfos, err := kubeClient.Build(bytes.NewBufferString(expectedManifest), false)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn expectedInfos.Visit(func(expected *resource.Info, err error) error {\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"visit error: %w\", err)\n\t\t}\n\n\t\thelper := resource.NewHelper(expected.Client, expected.Mapping)\n\t\texisting, err := helper.Get(expected.Namespace, expected.Name)\n\t\tif apierrors.IsNotFound(err) {\n\t\t\tif _, err := helper.Create(expected.Namespace, true, expected.Object); err != nil {\n\t\t\t\treturn fmt.Errorf(\"create error: %s\", err)\n\t\t\t}\n\t\t\treturn nil\n\t\t} else if err != nil {\n\t\t\treturn fmt.Errorf(\"could not get object: %w\", err)\n\t\t}\n\n\t\t// Replicate helm's patch creation, which will create a Three-Way-Merge patch for\n\t\t// native kubernetes Objects and fall back to a JSON merge patch for unstructured Objects such as CRDs\n\t\t// We also extend the JSON merge patch by ignoring \"remove\" operations for fields added by kubernetes\n\t\t// Reference in the helm source code:\n\t\t// https://github.com/helm/helm/blob/1c9b54ad7f62a5ce12f87c3ae55136ca20f09c98/pkg/kube/client.go#L392\n\t\tpatch, patchType, err := createPatch(existing, expected)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error creating patch: %w\", err)\n\t\t}\n\n\t\tif patch == nil {\n\t\t\t// nothing to do\n\t\t\treturn nil\n\t\t}\n\n\t\t_, err = helper.Patch(expected.Namespace, expected.Name, patchType, patch,\n\t\t\t&metav1.PatchOptions{})\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"patch error: %w\", err)\n\t\t}\n\t\treturn nil\n\t})\n}\n\nfunc createPatch(existing runtime.Object, expected *resource.Info) ([]byte, apitypes.PatchType, error) {\n\texistingJSON, err := json.Marshal(existing)\n\tif err != nil {\n\t\treturn nil, apitypes.StrategicMergePatchType, err\n\t}\n\texpectedJSON, err := json.Marshal(expected.Object)\n\tif err != nil {\n\t\treturn nil, apitypes.StrategicMergePatchType, err\n\t}\n\n\t// Get a versioned object\n\tversionedObject := kube.AsVersioned(expected)\n\n\t// Unstructured objects, such as CRDs, may not have an not registered error\n\t// returned from ConvertToVersion. Anything that's unstructured should\n\t// use the jsonpatch.CreateMergePatch. Strategic Merge Patch is not supported\n\t// on objects like CRDs.\n\t_, isUnstructured := versionedObject.(runtime.Unstructured)\n\n\t// On newer K8s versions, CRDs aren't unstructured but have a dedicated type\n\t_, isV1CRD := versionedObject.(*apiextv1.CustomResourceDefinition)\n\t_, isV1beta1CRD := versionedObject.(*apiextv1beta1.CustomResourceDefinition)\n\tisCRD := isV1CRD || isV1beta1CRD\n\n\tif isUnstructured || isCRD {\n\t\t// fall back to generic JSON merge patch\n\t\tpatch, err := createJSONMergePatch(existingJSON, expectedJSON)\n\t\treturn patch, apitypes.JSONPatchType, err\n\t}\n\n\tpatchMeta, err := strategicpatch.NewPatchMetaFromStruct(versionedObject)\n\tif err != nil {\n\t\treturn nil, apitypes.StrategicMergePatchType, err\n\t}\n\n\tpatch, err := strategicpatch.CreateThreeWayMergePatch(expectedJSON, expectedJSON, existingJSON, patchMeta, true)\n\tif err != nil {\n\t\treturn nil, apitypes.StrategicMergePatchType, err\n\t}\n\t// An empty patch could be in the form of \"{}\" which represents an empty map out of the 3-way merge;\n\t// filter them out here too to avoid sending the apiserver empty patch requests.\n\tif len(patch) == 0 || bytes.Equal(patch, []byte(\"{}\")) {\n\t\treturn nil, apitypes.StrategicMergePatchType, nil\n\t}\n\treturn patch, apitypes.StrategicMergePatchType, nil\n}\n\nfunc createJSONMergePatch(existingJSON, expectedJSON []byte) ([]byte, error) {\n\tops, err := jsonpatch.CreatePatch(existingJSON, expectedJSON)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// We ignore the \"remove\" operations from the full patch because they are\n\t// fields added by Kubernetes or by the user after the existing release\n\t// resource has been applied. The goal for this patch is to make sure that\n\t// the fields managed by the Helm chart are applied.\n\t// All \"add\" operations without a value (null) can be ignored\n\tpatchOps := make([]jsonpatch.JsonPatchOperation, 0)\n\tfor _, op := range ops {\n\t\tif op.Operation != \"remove\" && (op.Operation != \"add\" || op.Value != nil) {\n\t\t\tpatchOps = append(patchOps, op)\n\t\t}\n\t}\n\n\t// If there are no patch operations, return nil. Callers are expected\n\t// to check for a nil response and skip the patch operation to avoid\n\t// unnecessary chatter with the API server.\n\tif len(patchOps) == 0 {\n\t\treturn nil, nil\n\t}\n\n\treturn json.Marshal(patchOps)\n}\n\n// UninstallRelease performs a Helm release uninstall.\nfunc (m manager) UninstallRelease(opts ...UninstallOption) (*rpb.Release, error) {\n\tuninstall := action.NewUninstall(m.actionConfig)\n\tfor _, o := range opts {\n\t\tif err := o(uninstall); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to apply uninstall option: %w\", err)\n\t\t}\n\t}\n\tuninstallResponse, err := uninstall.Run(m.releaseName)\n\tif uninstallResponse == nil {\n\t\treturn nil, err\n\t}\n\treturn uninstallResponse.Release, err\n}\n\n// CleanupRelease deletes resources if they are not deleted already.\n// Return true if all the resources are deleted, false otherwise.\nfunc (m manager) CleanupRelease(manifest string) (bool, error) {\n\tdc, err := m.actionConfig.RESTClientGetter.ToDiscoveryClient()\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"failed to get Kubernetes discovery client: %w\", err)\n\t}\n\tapiVersions, err := action.GetVersionSet(dc)\n\tif err != nil && !discovery.IsGroupDiscoveryFailedError(err) {\n\t\treturn false, fmt.Errorf(\"failed to get apiVersions from Kubernetes: %w\", err)\n\t}\n\tmanifests := releaseutil.SplitManifests(manifest)\n\t_, files, err := releaseutil.SortManifests(manifests, apiVersions, releaseutil.UninstallOrder)\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"failed to sort manifests: %w\", err)\n\t}\n\t// do not delete resources that are annotated with the Helm resource policy 'keep'\n\t_, filesToDelete := manifestutil.FilterManifestsToKeep(files)\n\tvar builder strings.Builder\n\tfor _, file := range filesToDelete {\n\t\tbuilder.WriteString(\"\\n---\\n\" + file.Content)\n\t}\n\tresources, err := m.kubeClient.Build(strings.NewReader(builder.String()), false)\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"failed to build resources from manifests: %w\", err)\n\t}\n\tif len(resources) <= 0 {\n\t\treturn true, nil\n\t}\n\tfor _, resource := range resources {\n\t\terr = resource.Get()\n\t\tif err != nil {\n\t\t\tif apierrors.IsNotFound(err) {\n\t\t\t\tcontinue // resource is already delete, check the next one.\n\t\t\t}\n\t\t\treturn false, fmt.Errorf(\"failed to get resource: %w\", err)\n\t\t}\n\t\t// found at least one resource that is not deleted so just delete everything again.\n\t\t_, errs := m.kubeClient.Delete(resources)\n\t\tif len(errs) > 0 {\n\t\t\treturn false, fmt.Errorf(\"failed to delete resources: %v\", apiutilerrors.NewAggregate(errs))\n\t\t}\n\t\treturn false, nil\n\t}\n\treturn true, nil\n}\n"
  },
  {
    "path": "internal/helm/release/manager_factory.go",
    "content": "// Copyright 2018 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage release\n\nimport (\n\t\"fmt\"\n\n\t\"helm.sh/helm/v3/pkg/chart/loader\"\n\thelmrelease \"helm.sh/helm/v3/pkg/release\"\n\t\"helm.sh/helm/v3/pkg/storage\"\n\t\"helm.sh/helm/v3/pkg/strvals\"\n\t\"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured\"\n\tcrmanager \"sigs.k8s.io/controller-runtime/pkg/manager\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/helm/client\"\n\t\"github.com/operator-framework/operator-sdk/internal/helm/internal/types\"\n)\n\n// ManagerFactory creates Managers that are specific to custom resources. It is\n// used by the HelmOperatorReconciler during resource reconciliation, and it\n// improves decoupling between reconciliation logic and the Helm backend\n// components used to manage releases.\ntype ManagerFactory interface {\n\tNewManager(r *unstructured.Unstructured, overrideValues map[string]string, dryRunOption string) (Manager, error)\n}\n\ntype managerFactory struct {\n\tmgr      crmanager.Manager\n\tacg      client.ActionConfigGetter\n\tchartDir string\n}\n\n// NewManagerFactory returns a new Helm manager factory capable of installing and uninstalling releases.\nfunc NewManagerFactory(mgr crmanager.Manager, acg client.ActionConfigGetter, chartDir string) ManagerFactory {\n\treturn &managerFactory{mgr, acg, chartDir}\n}\n\nfunc (f managerFactory) NewManager(cr *unstructured.Unstructured, overrideValues map[string]string, dryRunOption string) (Manager, error) {\n\tactionConfig, err := f.acg.ActionConfigFor(cr)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get helm action config: %w\", err)\n\t}\n\n\tcrChart, err := loader.LoadDir(f.chartDir)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to load chart dir: %w\", err)\n\t}\n\n\tactionConfig.KubeClient = client.NewLabelInjectingClient(actionConfig.KubeClient, map[string]string{\n\t\t\"helm.sdk.operatorframework.io/chart\": crChart.Name(),\n\t})\n\n\treleaseName, err := getReleaseName(actionConfig.Releases, crChart.Name(), cr)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get helm release name: %w\", err)\n\t}\n\n\tcrValues, ok := cr.Object[\"spec\"].(map[string]any)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"failed to get spec: expected map[string]interface{}\")\n\t}\n\n\texpOverrides, err := parseOverrides(overrideValues)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse override values: %w\", err)\n\t}\n\tvalues := mergeMaps(crValues, expOverrides)\n\n\treturn &manager{\n\t\tactionConfig:   actionConfig,\n\t\tstorageBackend: actionConfig.Releases,\n\t\tkubeClient:     actionConfig.KubeClient,\n\n\t\treleaseName: releaseName,\n\t\tnamespace:   cr.GetNamespace(),\n\n\t\tchart:        crChart,\n\t\tvalues:       values,\n\t\tstatus:       types.StatusFor(cr),\n\t\tdryRunOption: dryRunOption,\n\t}, nil\n}\n\n// getReleaseName returns a release name for the CR.\n//\n// getReleaseName searches for a release using the CR name. If a release\n// cannot be found, or if it is found and was created by the chart managed\n// by this manager, the CR name is returned.\n//\n// If a release is found but it was created by another chart, that means we\n// have a release name collision, so return an error. This case is possible\n// because Kubernetes allows instances of different types to have the same name\n// in the same namespace.\n//\n// TODO(jlanford): As noted above, using the CR name as the release name raises\n//\n//\tthe possibility of collision. We should move this logic to a validating\n//\tadmission webhook so that the CR owner receives immediate feedback of the\n//\tcollision. As is, the only indication of collision will be in the CR status\n//\tand operator logs.\nfunc getReleaseName(storageBackend *storage.Storage, crChartName string,\n\tcr *unstructured.Unstructured) (string, error) {\n\t// If a release with the CR name does not exist, return the CR name.\n\treleaseName := cr.GetName()\n\thistory, exists, err := releaseHistory(storageBackend, releaseName)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tif !exists {\n\t\treturn releaseName, nil\n\t}\n\n\t// If a release name with the CR name exists, but the release's chart is\n\t// different than the chart managed by this operator, return an error\n\t// because something else created the existing release.\n\tif history[0].Chart == nil {\n\t\treturn \"\", fmt.Errorf(\"could not find chart metadata in release with name %q\", releaseName)\n\t}\n\texistingChartName := history[0].Chart.Name()\n\tif existingChartName != crChartName {\n\t\treturn \"\", fmt.Errorf(\"duplicate release name: found existing release with name %q for chart %q\",\n\t\t\treleaseName, existingChartName)\n\t}\n\n\treturn releaseName, nil\n}\n\nfunc releaseHistory(storageBackend *storage.Storage, releaseName string) ([]*helmrelease.Release, bool, error) {\n\treleaseHistory, err := storageBackend.History(releaseName)\n\tif err != nil {\n\t\tif notFoundErr(err) {\n\t\t\treturn nil, false, nil\n\t\t}\n\t\treturn nil, false, err\n\t}\n\treturn releaseHistory, len(releaseHistory) > 0, nil\n}\n\nfunc parseOverrides(in map[string]string) (map[string]any, error) {\n\tout := make(map[string]any)\n\tfor k, v := range in {\n\t\tval := fmt.Sprintf(\"%s=%s\", k, v)\n\t\tif err := strvals.ParseIntoString(val, out); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\treturn out, nil\n}\n\nfunc mergeMaps(a, b map[string]any) map[string]any {\n\tout := make(map[string]any, len(a))\n\tfor k, v := range a {\n\t\tout[k] = v\n\t}\n\tfor k, v := range b {\n\t\tif v, ok := v.(map[string]any); ok {\n\t\t\tif bv, ok := out[k]; ok {\n\t\t\t\tif bv, ok := bv.(map[string]any); ok {\n\t\t\t\t\tout[k] = mergeMaps(bv, v)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tout[k] = v\n\t}\n\treturn out\n}\n"
  },
  {
    "path": "internal/helm/release/manager_test.go",
    "content": "// Copyright 2018 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage release\n\nimport (\n\t\"testing\"\n\n\t\"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured\"\n\tapitypes \"k8s.io/apimachinery/pkg/types\"\n\t\"k8s.io/cli-runtime/pkg/resource\"\n\n\tappsv1 \"k8s.io/api/apps/v1\"\n\tv1 \"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n)\n\nfunc newTestUnstructured(containers []any) *unstructured.Unstructured {\n\treturn &unstructured.Unstructured{\n\t\tObject: map[string]any{\n\t\t\t\"kind\":       \"MyResource\",\n\t\t\t\"apiVersion\": \"myApi\",\n\t\t\t\"metadata\": map[string]any{\n\t\t\t\t\"name\":      \"test\",\n\t\t\t\t\"namespace\": \"ns\",\n\t\t\t},\n\t\t\t\"spec\": map[string]any{\n\t\t\t\t\"template\": map[string]any{\n\t\t\t\t\t\"spec\": map[string]any{\n\t\t\t\t\t\t\"containers\": containers,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n}\n\nfunc newTestDeployment(containers []v1.Container) *appsv1.Deployment {\n\treturn &appsv1.Deployment{\n\t\tTypeMeta:   metav1.TypeMeta{Kind: \"Deployment\", APIVersion: \"apps/v1\"},\n\t\tObjectMeta: metav1.ObjectMeta{Name: \"test\", Namespace: \"ns\"},\n\t\tSpec: appsv1.DeploymentSpec{\n\t\t\tTemplate: v1.PodTemplateSpec{\n\t\t\t\tSpec: v1.PodSpec{\n\t\t\t\t\tContainers: containers,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n}\n\nfunc TestManagerGenerateStrategicMergePatch(t *testing.T) {\n\n\ttests := []struct {\n\t\to1        runtime.Object\n\t\to2        runtime.Object\n\t\tpatch     string\n\t\tpatchType apitypes.PatchType\n\t}{\n\t\t{\n\t\t\to1: newTestUnstructured([]any{\n\t\t\t\tmap[string]any{\n\t\t\t\t\t\"name\": \"test1\",\n\t\t\t\t},\n\t\t\t\tmap[string]any{\n\t\t\t\t\t\"name\": \"test2\",\n\t\t\t\t},\n\t\t\t}),\n\t\t\to2: newTestUnstructured([]any{\n\t\t\t\tmap[string]any{\n\t\t\t\t\t\"name\": \"test1\",\n\t\t\t\t},\n\t\t\t}),\n\t\t\tpatch:     ``,\n\t\t\tpatchType: apitypes.JSONPatchType,\n\t\t},\n\t\t{\n\t\t\to1: newTestUnstructured([]any{\n\t\t\t\tmap[string]any{\n\t\t\t\t\t\"name\": \"test1\",\n\t\t\t\t},\n\t\t\t}),\n\t\t\to2: newTestUnstructured([]any{\n\t\t\t\tmap[string]any{\n\t\t\t\t\t\"name\": \"test1\",\n\t\t\t\t},\n\t\t\t\tmap[string]any{\n\t\t\t\t\t\"name\": \"test2\",\n\t\t\t\t},\n\t\t\t}),\n\t\t\tpatch:     `[{\"op\":\"add\",\"path\":\"/spec/template/spec/containers/1\",\"value\":{\"name\":\"test2\"}}]`,\n\t\t\tpatchType: apitypes.JSONPatchType,\n\t\t},\n\t\t{\n\t\t\to1: newTestUnstructured([]any{\n\t\t\t\tmap[string]any{\n\t\t\t\t\t\"name\": \"test1\",\n\t\t\t\t},\n\t\t\t}),\n\t\t\to2: newTestUnstructured([]any{\n\t\t\t\tmap[string]any{\n\t\t\t\t\t\"name\": \"test1\",\n\t\t\t\t\t\"test\": nil,\n\t\t\t\t},\n\t\t\t}),\n\t\t\tpatch:     ``,\n\t\t\tpatchType: apitypes.JSONPatchType,\n\t\t},\n\t\t{\n\t\t\to1: newTestUnstructured([]any{\n\t\t\t\tmap[string]any{\n\t\t\t\t\t\"name\": \"test1\",\n\t\t\t\t},\n\t\t\t}),\n\t\t\to2: newTestUnstructured([]any{\n\t\t\t\tmap[string]any{\n\t\t\t\t\t\"name\": \"test2\",\n\t\t\t\t},\n\t\t\t}),\n\t\t\tpatch:     `[{\"op\":\"replace\",\"path\":\"/spec/template/spec/containers/0/name\",\"value\":\"test2\"}]`,\n\t\t\tpatchType: apitypes.JSONPatchType,\n\t\t},\n\t\t{\n\t\t\to1: newTestDeployment([]v1.Container{\n\t\t\t\t{Name: \"test1\"},\n\t\t\t\t{Name: \"test2\"},\n\t\t\t}),\n\t\t\to2: newTestDeployment([]v1.Container{\n\t\t\t\t{Name: \"test1\"},\n\t\t\t}),\n\t\t\tpatch:     `{\"spec\":{\"template\":{\"spec\":{\"$setElementOrder/containers\":[{\"name\":\"test1\"}]}}}}`,\n\t\t\tpatchType: apitypes.StrategicMergePatchType,\n\t\t},\n\t\t{\n\t\t\to1: newTestDeployment([]v1.Container{\n\t\t\t\t{Name: \"test1\"},\n\t\t\t}),\n\t\t\to2: newTestDeployment([]v1.Container{\n\t\t\t\t{Name: \"test1\"},\n\t\t\t\t{Name: \"test2\"},\n\t\t\t}),\n\t\t\tpatch:     `{\"spec\":{\"template\":{\"spec\":{\"$setElementOrder/containers\":[{\"name\":\"test1\"},{\"name\":\"test2\"}],\"containers\":[{\"name\":\"test2\",\"resources\":{}}]}}}}`,\n\t\t\tpatchType: apitypes.StrategicMergePatchType,\n\t\t},\n\t\t{\n\t\t\to1: newTestDeployment([]v1.Container{\n\t\t\t\t{Name: \"test1\"},\n\t\t\t}),\n\t\t\to2: newTestDeployment([]v1.Container{\n\t\t\t\t{Name: \"test1\", LivenessProbe: nil},\n\t\t\t}),\n\t\t\tpatch:     ``,\n\t\t\tpatchType: apitypes.StrategicMergePatchType,\n\t\t},\n\t\t{\n\t\t\to1: newTestDeployment([]v1.Container{\n\t\t\t\t{Name: \"test1\"},\n\t\t\t}),\n\t\t\to2: newTestDeployment([]v1.Container{\n\t\t\t\t{Name: \"test2\"},\n\t\t\t}),\n\t\t\tpatch:     `{\"spec\":{\"template\":{\"spec\":{\"$setElementOrder/containers\":[{\"name\":\"test2\"}],\"containers\":[{\"name\":\"test2\",\"resources\":{}}]}}}}`,\n\t\t\tpatchType: apitypes.StrategicMergePatchType,\n\t\t},\n\t\t{\n\t\t\to1: &appsv1.Deployment{\n\t\t\t\tTypeMeta: metav1.TypeMeta{Kind: \"Deployment\", APIVersion: \"apps/v1\"},\n\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\tName:      \"test\",\n\t\t\t\t\tNamespace: \"ns\",\n\t\t\t\t\tAnnotations: map[string]string{\n\t\t\t\t\t\t\"testannotation\": \"testvalue\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tSpec: appsv1.DeploymentSpec{},\n\t\t\t},\n\t\t\to2: &appsv1.Deployment{\n\t\t\t\tTypeMeta: metav1.TypeMeta{Kind: \"Deployment\", APIVersion: \"apps/v1\"},\n\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\tName:      \"test\",\n\t\t\t\t\tNamespace: \"ns\",\n\t\t\t\t},\n\t\t\t\tSpec: appsv1.DeploymentSpec{},\n\t\t\t},\n\t\t\tpatch:     ``,\n\t\t\tpatchType: apitypes.StrategicMergePatchType,\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\n\t\to2Info := &resource.Info{\n\t\t\tObject: test.o2,\n\t\t}\n\n\t\tdiff, patchType, err := createPatch(test.o1, o2Info)\n\t\tassert.NoError(t, err)\n\t\tassert.Equal(t, test.patchType, patchType)\n\t\tassert.Equal(t, test.patch, string(diff))\n\t}\n}\n"
  },
  {
    "path": "internal/helm/watches/watches.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage watches\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"text/template\"\n\n\tsprig \"github.com/go-task/slim-sprig\"\n\t\"helm.sh/helm/v3/pkg/chartutil\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/runtime/schema\"\n\t\"sigs.k8s.io/yaml\"\n)\n\nconst WatchesFile = \"watches.yaml\"\n\n// Watch defines options for configuring a watch for a Helm-based\n// custom resource.\ntype Watch struct {\n\tschema.GroupVersionKind `json:\",inline\"`\n\tChartDir                string               `json:\"chart\"`\n\tWatchDependentResources *bool                `json:\"watchDependentResources,omitempty\"`\n\tOverrideValues          map[string]string    `json:\"overrideValues,omitempty\"`\n\tSelector                metav1.LabelSelector `json:\"selector\"`\n\tReconcilePeriod         metav1.Duration      `json:\"reconcilePeriod,omitempty\"`\n\tDryRunOption            string               `json:\"dryRunOption,omitempty\"`\n}\n\n// UnmarshalYAML unmarshals an individual watch from the Helm watches.yaml file\n// into a Watch struct.\n//\n// Deprecated: This function is no longer used internally to unmarshal\n// watches.yaml data. To ensure the correct defaults are applied when loading\n// watches.yaml, use Load() or LoadReader() instead of this function and/or\n// yaml.Unmarshal().\nfunc (w *Watch) UnmarshalYAML(unmarshal func(any) error) error {\n\t// by default, the operator will watch dependent resources\n\ttrueVal := true\n\tw.WatchDependentResources = &trueVal\n\n\t// hide watch data in plain struct to prevent unmarshal from calling\n\t// UnmarshalYAML again\n\ttype plain Watch\n\n\treturn unmarshal((*plain)(w))\n}\n\n// Load loads a slice of Watches from the watch file at `path`. For each entry\n// in the watches file, it verifies the configuration. If an error is\n// encountered loading the file or verifying the configuration, it will be\n// returned.\nfunc Load(path string) ([]Watch, error) {\n\tf, err := os.Open(path)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"could not open watches file: %w\", err)\n\t}\n\tw, err := LoadReader(f)\n\n\t// Make sure to close the file, regardless of the error returned by\n\t// LoadReader.\n\tif err := f.Close(); err != nil {\n\t\treturn nil, fmt.Errorf(\"could not close watches file: %w\", err)\n\t}\n\treturn w, err\n}\n\n// LoadReader loads a slice of Watches from the provided reader. For each entry\n// in the watches file, it verifies the configuration. If an error is\n// encountered reading or verifying the configuration, it will be returned.\nfunc LoadReader(reader io.Reader) ([]Watch, error) {\n\tb, err := io.ReadAll(reader)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\twatches := []Watch{}\n\terr = yaml.Unmarshal(b, &watches)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\twatchesMap := make(map[schema.GroupVersionKind]struct{})\n\tfor i, w := range watches {\n\t\tgvk := w.GroupVersionKind\n\n\t\tif err := verifyGVK(gvk); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"invalid GVK: %s: %w\", gvk, err)\n\t\t}\n\n\t\tif _, err := chartutil.IsChartDir(w.ChartDir); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"invalid chart directory %s: %w\", w.ChartDir, err)\n\t\t}\n\n\t\tif _, ok := watchesMap[gvk]; ok {\n\t\t\treturn nil, fmt.Errorf(\"duplicate GVK: %s\", gvk)\n\t\t}\n\t\twatchesMap[gvk] = struct{}{}\n\t\tif w.WatchDependentResources == nil {\n\t\t\ttrueVal := true\n\t\t\tw.WatchDependentResources = &trueVal\n\t\t}\n\t\tw.OverrideValues, err = expandOverrideValues(w.OverrideValues)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to expand override values: %v\", err)\n\t\t}\n\t\twatches[i] = w\n\t}\n\treturn watches, nil\n}\n\nfunc expandOverrideValues(in map[string]string) (map[string]string, error) {\n\tif in == nil {\n\t\treturn nil, nil\n\t}\n\tout := make(map[string]string)\n\tfor k, v := range in {\n\t\tenvV := os.ExpandEnv(v)\n\n\t\tv := &bytes.Buffer{}\n\t\ttmplV, err := template.New(k).Funcs(sprig.TxtFuncMap()).Parse(envV)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"invalid template string %q: %v\", envV, err)\n\t\t}\n\t\tif err := tmplV.Execute(v, nil); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to execute template %q: %v\", envV, err)\n\t\t}\n\t\tout[k] = v.String()\n\t}\n\treturn out, nil\n}\n\nfunc verifyGVK(gvk schema.GroupVersionKind) error {\n\t// A GVK without a group is valid. Certain scenarios may cause a GVK\n\t// without a group to fail in other ways later in the initialization\n\t// process.\n\tif gvk.Version == \"\" {\n\t\treturn errors.New(\"version must not be empty\")\n\t}\n\tif gvk.Kind == \"\" {\n\t\treturn errors.New(\"kind must not be empty\")\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "internal/helm/watches/watches_test.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage watches\n\nimport (\n\t\"bytes\"\n\t\"os\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"k8s.io/apimachinery/pkg/runtime/schema\"\n)\n\nfunc TestLoadReader(t *testing.T) {\n\ttrueVal, falseVal := true, false\n\ttestCases := []struct {\n\t\tname          string\n\t\tdata          string\n\t\tenv           map[string]string\n\t\texpectWatches []Watch\n\t\texpectErr     bool\n\t}{\n\t\t{\n\t\t\tname: \"valid\",\n\t\t\tdata: `---\n- group: mygroup\n  version: v1alpha1\n  kind: MyKind\n  chart: ../../../internal/plugins/helm/v1/chartutil/testdata/test-chart\n  watchDependentResources: false\n  overrideValues:\n    key: value\n`,\n\t\t\texpectWatches: []Watch{\n\t\t\t\t{\n\t\t\t\t\tGroupVersionKind:        schema.GroupVersionKind{Group: \"mygroup\", Version: \"v1alpha1\", Kind: \"MyKind\"},\n\t\t\t\t\tChartDir:                \"../../../internal/plugins/helm/v1/chartutil/testdata/test-chart\",\n\t\t\t\t\tWatchDependentResources: &falseVal,\n\t\t\t\t\tOverrideValues:          map[string]string{\"key\": \"value\"},\n\t\t\t\t},\n\t\t\t},\n\t\t\texpectErr: false,\n\t\t},\n\t\t{\n\t\t\tname: \"valid with override env expansion\",\n\t\t\tdata: `---\n- group: mygroup\n  version: v1alpha1\n  kind: MyKind\n  chart: ../../../internal/plugins/helm/v1/chartutil/testdata/test-chart\n  watchDependentResources: false\n  overrideValues:\n    key: $MY_VALUE\n`,\n\t\t\tenv: map[string]string{\"MY_VALUE\": \"value\"},\n\t\t\texpectWatches: []Watch{\n\t\t\t\t{\n\t\t\t\t\tGroupVersionKind:        schema.GroupVersionKind{Group: \"mygroup\", Version: \"v1alpha1\", Kind: \"MyKind\"},\n\t\t\t\t\tChartDir:                \"../../../internal/plugins/helm/v1/chartutil/testdata/test-chart\",\n\t\t\t\t\tWatchDependentResources: &falseVal,\n\t\t\t\t\tOverrideValues:          map[string]string{\"key\": \"value\"},\n\t\t\t\t},\n\t\t\t},\n\t\t\texpectErr: false,\n\t\t},\n\t\t{\n\t\t\tname: \"valid with override template expansion\",\n\t\t\tdata: `---\n- group: mygroup\n  version: v1alpha1\n  kind: MyKind\n  chart: ../../../internal/plugins/helm/v1/chartutil/testdata/test-chart\n  watchDependentResources: false\n  overrideValues:\n    repo: '{{ (\"$MY_IMAGE\" | split \":\")._0 }}'\n    tag: '{{ (\"$MY_IMAGE\" | split \":\")._1 }}'\n`,\n\t\t\tenv: map[string]string{\"MY_IMAGE\": \"quay.io/operator-framework/helm-operator:latest\"},\n\t\t\texpectWatches: []Watch{\n\t\t\t\t{\n\t\t\t\t\tGroupVersionKind:        schema.GroupVersionKind{Group: \"mygroup\", Version: \"v1alpha1\", Kind: \"MyKind\"},\n\t\t\t\t\tChartDir:                \"../../../internal/plugins/helm/v1/chartutil/testdata/test-chart\",\n\t\t\t\t\tWatchDependentResources: &falseVal,\n\t\t\t\t\tOverrideValues: map[string]string{\n\t\t\t\t\t\t\"repo\": \"quay.io/operator-framework/helm-operator\",\n\t\t\t\t\t\t\"tag\":  \"latest\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\texpectErr: false,\n\t\t},\n\t\t{\n\t\t\tname: \"valid with dry run option\",\n\t\t\tdata: `---\n- group: mygroup\n  version: v1alpha1\n  kind: MyKind\n  chart: ../../../internal/plugins/helm/v1/chartutil/testdata/test-chart\n  watchDependentResources: false\n  overrideValues:\n    key: $MY_VALUE\n  dryRunOption: server\n`,\n\t\t\tenv: map[string]string{\"MY_VALUE\": \"value\"},\n\t\t\texpectWatches: []Watch{\n\t\t\t\t{\n\t\t\t\t\tGroupVersionKind:        schema.GroupVersionKind{Group: \"mygroup\", Version: \"v1alpha1\", Kind: \"MyKind\"},\n\t\t\t\t\tChartDir:                \"../../../internal/plugins/helm/v1/chartutil/testdata/test-chart\",\n\t\t\t\t\tWatchDependentResources: &falseVal,\n\t\t\t\t\tOverrideValues:          map[string]string{\"key\": \"value\"},\n\t\t\t\t\tDryRunOption:            \"server\",\n\t\t\t\t},\n\t\t\t},\n\t\t\texpectErr: false,\n\t\t},\n\t\t{\n\t\t\tname: \"invalid with override template expansion\",\n\t\t\tdata: `---\n- group: mygroup\n  version: v1alpha1\n  kind: MyKind\n  chart: ../../../internal/plugins/helm/v1/chartutil/testdata/test-chart\n  watchDependentResources: false\n  overrideValues:\n    repo: '{{ (\"$MY_IMAGE\" | split \":\")._0 }}'\n    tag: '{{ (\"$MY_IMAGE\" | split \":\")._1'\n`,\n\t\t\tenv:       map[string]string{\"MY_IMAGE\": \"quay.io/operator-framework/helm-operator:latest\"},\n\t\t\texpectErr: true,\n\t\t},\n\t\t{\n\t\t\tname: \"multiple gvk\",\n\t\t\tdata: `---\n- group: mygroup\n  version: v1alpha1\n  kind: MyFirstKind\n  chart: ../../../internal/plugins/helm/v1/chartutil/testdata/test-chart\n- group: mygroup\n  version: v1alpha1\n  kind: MySecondKind\n  chart: ../../../internal/plugins/helm/v1/chartutil/testdata/test-chart\n`,\n\t\t\texpectWatches: []Watch{\n\t\t\t\t{\n\t\t\t\t\tGroupVersionKind:        schema.GroupVersionKind{Group: \"mygroup\", Version: \"v1alpha1\", Kind: \"MyFirstKind\"},\n\t\t\t\t\tChartDir:                \"../../../internal/plugins/helm/v1/chartutil/testdata/test-chart\",\n\t\t\t\t\tWatchDependentResources: &trueVal,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tGroupVersionKind:        schema.GroupVersionKind{Group: \"mygroup\", Version: \"v1alpha1\", Kind: \"MySecondKind\"},\n\t\t\t\t\tChartDir:                \"../../../internal/plugins/helm/v1/chartutil/testdata/test-chart\",\n\t\t\t\t\tWatchDependentResources: &trueVal,\n\t\t\t\t},\n\t\t\t},\n\t\t\texpectErr: false,\n\t\t},\n\t\t{\n\t\t\tname: \"duplicate gvk\",\n\t\t\tdata: `---\n- group: mygroup\n  version: v1alpha1\n  kind: MyKind\n  chart: ../../../internal/plugins/helm/v1/chartutil/testdata/test-chart\n- group: mygroup\n  version: v1alpha1\n  kind: MyKind\n  chart: ../../../internal/plugins/helm/v1/chartutil/testdata/test-chart\n`,\n\t\t\texpectErr: true,\n\t\t},\n\t\t{\n\t\t\tname: \"no version\",\n\t\t\tdata: `---\n- group: mygroup\n  kind: MyKind\n  chart: ../../../internal/plugins/helm/v1/chartutil/testdata/test-chart\n`,\n\t\t\texpectErr: true,\n\t\t},\n\t\t{\n\t\t\tname: \"no kind\",\n\t\t\tdata: `---\n- group: mygroup\n  version: v1alpha1\n  chart: ../../../internal/plugins/helm/v1/chartutil/testdata/test-chart\n`,\n\t\t\texpectErr: true,\n\t\t},\n\t\t{\n\t\t\tname: \"bad chart path\",\n\t\t\tdata: `---\n- group: mygroup\n  version: v1alpha1\n  kind: MyKind\n  chart: nonexistent/path/to/chart\n`,\n\t\t\texpectErr: true,\n\t\t},\n\t\t{\n\t\t\tname: \"invalid overrides\",\n\t\t\tdata: `---\n- group: mygroup\n  version: v1alpha1\n  kind: MyKind\n  chart: ../../../internal/plugins/helm/v1/chartutil/testdata/test-chart\n  overrideValues:\n    key1:\n\t\tkey2: value\n`,\n\t\t\texpectErr: true,\n\t\t},\n\t\t{\n\t\t\tname: \"invalid yaml\",\n\t\t\tdata: `---\nfoo: bar\n`,\n\t\t\texpectErr: true,\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tfor k, v := range tc.env {\n\t\t\t\tif err := os.Setenv(k, v); err != nil {\n\t\t\t\t\tt.Fatalf(\"Failed to set environment variable %q: %v\", k, err)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\twatchesData := bytes.NewBufferString(tc.data)\n\t\t\twatches, err := LoadReader(watchesData)\n\t\t\tif !tc.expectErr && err != nil {\n\t\t\t\tt.Fatalf(\"Expected no error; got error: %v\", err)\n\t\t\t} else if tc.expectErr && err == nil {\n\t\t\t\tt.Fatalf(\"Expected error; got no error\")\n\t\t\t}\n\t\t\tassert.Equal(t, tc.expectWatches, watches)\n\n\t\t\tfor k := range tc.env {\n\t\t\t\tif err := os.Unsetenv(k); err != nil {\n\t\t\t\t\tt.Fatalf(\"Failed to unset environment variable %q: %v\", k, err)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestLoad(t *testing.T) {\n\tfalseVal := false\n\ttestCases := []struct {\n\t\tname          string\n\t\tdata          string\n\t\tenv           map[string]string\n\t\texpectWatches []Watch\n\t\texpectErr     bool\n\t}{\n\t\t{\n\t\t\tname: \"valid\",\n\t\t\tdata: `---\n- group: mygroup\n  version: v1alpha1\n  kind: MyKind\n  chart: ../../../internal/plugins/helm/v1/chartutil/testdata/test-chart\n  watchDependentResources: false\n  overrideValues:\n    key: value\n`,\n\t\t\texpectWatches: []Watch{\n\t\t\t\t{\n\t\t\t\t\tGroupVersionKind:        schema.GroupVersionKind{Group: \"mygroup\", Version: \"v1alpha1\", Kind: \"MyKind\"},\n\t\t\t\t\tChartDir:                \"../../../internal/plugins/helm/v1/chartutil/testdata/test-chart\",\n\t\t\t\t\tWatchDependentResources: &falseVal,\n\t\t\t\t\tOverrideValues:          map[string]string{\"key\": \"value\"},\n\t\t\t\t},\n\t\t\t},\n\t\t\texpectErr: false,\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tfor k, v := range tc.env {\n\t\t\t\tif err := os.Setenv(k, v); err != nil {\n\t\t\t\t\tt.Fatalf(\"Failed to set environment variable %q: %v\", k, err)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tf, err := os.CreateTemp(\"\", \"osdk-test-load\")\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"Failed to create temporary watches file: %v\", err)\n\t\t\t}\n\t\t\tdefer removeFile(t, f)\n\t\t\tif _, err := f.WriteString(tc.data); err != nil {\n\t\t\t\tt.Fatalf(\"Failed to write temporary watches file: %v\", err)\n\t\t\t}\n\t\t\twatches, err := Load(f.Name())\n\t\t\tif !tc.expectErr && err != nil {\n\t\t\t\tt.Fatalf(\"Expected no error; got error: %v\", err)\n\t\t\t} else if tc.expectErr && err == nil {\n\t\t\t\tt.Fatalf(\"Expected error; got no error\")\n\t\t\t}\n\t\t\tassert.Equal(t, tc.expectWatches, watches)\n\n\t\t\tfor k := range tc.env {\n\t\t\t\tif err := os.Unsetenv(k); err != nil {\n\t\t\t\t\tt.Fatalf(\"Failed to unset environment variable %q: %v\", k, err)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\n// remove removes path from disk. Used in defer statements.\nfunc removeFile(t *testing.T, f *os.File) {\n\tif err := f.Close(); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif err := os.Remove(f.Name()); err != nil {\n\t\tt.Fatal(err)\n\t}\n}\n"
  },
  {
    "path": "internal/markers/markers.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage markers\n\nconst (\n\tPrefix = \"operator-sdk\"\n)\n"
  },
  {
    "path": "internal/olm/client/client.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Package olm provides an API to install, uninstall, and check the\n// status of an Operator Lifecycle Manager installation.\n// TODO: move to OLM repository?\npackage client\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/blang/semver/v4\"\n\tolmapiv1 \"github.com/operator-framework/api/pkg/operators/v1\"\n\tolmapiv1alpha1 \"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\tlog \"github.com/sirupsen/logrus\"\n\tappsv1 \"k8s.io/api/apps/v1\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\tapierrors \"k8s.io/apimachinery/pkg/api/errors\"\n\t\"k8s.io/apimachinery/pkg/api/meta\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/types\"\n\t\"k8s.io/apimachinery/pkg/util/wait\"\n\t\"k8s.io/client-go/kubernetes/scheme\"\n\t\"k8s.io/client-go/rest\"\n\tdeploymentutil \"k8s.io/kubectl/pkg/util/deployment\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client/apiutil\"\n)\n\nvar ErrOLMNotInstalled = errors.New(\"no existing installation found\")\n\nvar Scheme = scheme.Scheme\n\n// custom error struct to capture deployment errors\n// while verifying CSV installs.\ntype resourceError struct {\n\tname  string\n\tissue string\n}\ntype podError struct {\n\tresourceError\n}\ntype deploymentError struct {\n\tresourceError\n\tpodErrs podErrors\n}\ntype deploymentErrors []deploymentError\ntype podErrors []podError\n\nfunc (e deploymentErrors) Error() string {\n\tvar sb strings.Builder\n\tfor _, i := range e {\n\t\tsb.WriteString(fmt.Sprintf(\"deployment %s has error: %s\\n%s\", i.name, i.issue, i.podErrs.Error()))\n\t}\n\treturn sb.String()\n}\n\nfunc (e podErrors) Error() string {\n\tvar sb strings.Builder\n\tfor _, i := range e {\n\t\tsb.WriteString(fmt.Sprintf(\"\\tpod %s has error: %s\\n\", i.name, i.issue))\n\t}\n\treturn sb.String()\n}\n\nfunc init() {\n\tif err := olmapiv1alpha1.AddToScheme(Scheme); err != nil {\n\t\tlog.Fatalf(\"Failed to add OLM operator API v1alpha1 types to scheme: %v\", err)\n\t}\n}\n\ntype Client struct {\n\tKubeClient client.Client\n}\n\nfunc NewClientForConfig(cfg *rest.Config, httpClient *http.Client) (*Client, error) {\n\trm, err := apiutil.NewDynamicRESTMapper(cfg, httpClient)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create dynamic rest mapper: %v\", err)\n\t}\n\n\tif err := olmapiv1alpha1.AddToScheme(Scheme); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to add OLM API v1alpha1 types to scheme: %v\", err)\n\t}\n\n\tif err := olmapiv1.AddToScheme(Scheme); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to add OLM API v1 types to scheme: %v\", err)\n\t}\n\n\tcl, err := client.New(cfg, client.Options{\n\t\tScheme: Scheme,\n\t\tMapper: rm,\n\t})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create client: %v\", err)\n\t}\n\n\tc := &Client{\n\t\tKubeClient: cl,\n\t}\n\treturn c, nil\n}\n\nfunc (c Client) DoCreate(ctx context.Context, objs ...client.Object) error {\n\tfor _, obj := range objs {\n\t\tkind := obj.GetObjectKind().GroupVersionKind().Kind\n\t\tresourceName := getName(obj.GetNamespace(), obj.GetName())\n\n\t\tlog.Infof(\"  Creating %s %q\", kind, resourceName)\n\n\t\tif err := c.safeCreateOneResource(ctx, obj, kind, resourceName); err != nil {\n\t\t\tlog.Infof(\"  failed to create %s %q; %v\", kind, resourceName, err)\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\n// try to create resource until context is cancelled\n// or resource is created successfully\nfunc (c Client) safeCreateOneResource(ctx context.Context, obj client.Object, kind string, resourceName string) error {\n\terr := wait.PollUntilContextCancel(ctx, time.Second, false, func(ctx context.Context) (bool, error) {\n\t\terr := c.KubeClient.Create(ctx, obj)\n\t\tif err == nil || apierrors.IsAlreadyExists(err) {\n\t\t\tlog.Infof(\"  %s %q created\", kind, resourceName)\n\t\t\treturn true, nil\n\t\t}\n\n\t\tif meta.IsNoMatchError(err) {\n\t\t\tlog.Infof(\"    Failed to create %s %q. CRD is not ready yet. Retrying...\", kind, resourceName)\n\t\t\treturn false, nil\n\t\t}\n\n\t\treturn false, err\n\t})\n\n\tif err != nil && errors.Is(err, context.DeadlineExceeded) {\n\t\treturn fmt.Errorf(\"timeout\")\n\t}\n\n\treturn err\n}\n\nfunc (c Client) DoDelete(ctx context.Context, objs ...client.Object) error {\n\tfor _, obj := range objs {\n\t\tkind := obj.GetObjectKind().GroupVersionKind().Kind\n\t\tlog.Infof(\"  Deleting %s %q\", kind, getName(obj.GetNamespace(), obj.GetName()))\n\t\terr := c.KubeClient.Delete(ctx, obj, client.PropagationPolicy(metav1.DeletePropagationBackground))\n\t\tif err != nil {\n\t\t\tif !apierrors.IsNotFound(err) {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tlog.Infof(\"    %s %q does not exist\", kind, getName(obj.GetNamespace(), obj.GetName()))\n\t\t}\n\t\tkey := client.ObjectKeyFromObject(obj)\n\t\tif err := wait.PollUntilContextCancel(ctx, time.Millisecond*100, false, func(pctx context.Context) (bool, error) {\n\t\t\terr := c.KubeClient.Get(pctx, key, obj)\n\t\t\tif apierrors.IsNotFound(err) {\n\t\t\t\treturn true, nil\n\t\t\t} else if err != nil {\n\t\t\t\treturn false, err\n\t\t\t}\n\t\t\treturn false, nil\n\t\t}); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc getName(namespace, name string) string {\n\tif namespace != \"\" {\n\t\tname = fmt.Sprintf(\"%s/%s\", namespace, name)\n\t}\n\treturn name\n}\n\nfunc (c Client) DoRolloutWait(ctx context.Context, key types.NamespacedName) error {\n\tonceNotFound := sync.Once{}\n\tonceReplicasUpdated := sync.Once{}\n\toncePendingTermination := sync.Once{}\n\tonceNotAvailable := sync.Once{}\n\tonceSpecUpdate := sync.Once{}\n\n\trolloutComplete := func(pctx context.Context) (bool, error) {\n\t\tdeployment := appsv1.Deployment{}\n\t\terr := c.KubeClient.Get(pctx, key, &deployment)\n\t\tif err != nil {\n\t\t\tif apierrors.IsNotFound(err) {\n\t\t\t\tonceNotFound.Do(func() {\n\t\t\t\t\tlog.Printf(\"  Waiting for Deployment %q to appear\", key)\n\t\t\t\t})\n\t\t\t\treturn false, nil\n\t\t\t}\n\t\t\treturn false, err\n\t\t}\n\t\tif deployment.Generation <= deployment.Status.ObservedGeneration {\n\t\t\tcond := deploymentutil.GetDeploymentCondition(deployment.Status, appsv1.DeploymentProgressing)\n\t\t\tif cond != nil && cond.Reason == deploymentutil.TimedOutReason {\n\t\t\t\treturn false, errors.New(\"progress deadline exceeded\")\n\t\t\t}\n\t\t\tif deployment.Spec.Replicas != nil && deployment.Status.UpdatedReplicas < *deployment.Spec.Replicas {\n\t\t\t\tonceReplicasUpdated.Do(func() {\n\t\t\t\t\tlog.Printf(\n\t\t\t\t\t\t\"  Waiting for Deployment %q to rollout: %d out of %d new replicas have been updated\",\n\t\t\t\t\t\tkey, deployment.Status.UpdatedReplicas, *deployment.Spec.Replicas)\n\t\t\t\t})\n\t\t\t\treturn false, nil\n\t\t\t}\n\t\t\tif deployment.Status.Replicas > deployment.Status.UpdatedReplicas {\n\t\t\t\toncePendingTermination.Do(func() {\n\t\t\t\t\tlog.Printf(\"  Waiting for Deployment %q to rollout: %d old replicas are pending termination\",\n\t\t\t\t\t\tkey, deployment.Status.Replicas-deployment.Status.UpdatedReplicas)\n\t\t\t\t})\n\t\t\t\treturn false, nil\n\t\t\t}\n\t\t\tif deployment.Status.AvailableReplicas < deployment.Status.UpdatedReplicas {\n\t\t\t\tonceNotAvailable.Do(func() {\n\t\t\t\t\tlog.Printf(\"  Waiting for Deployment %q to rollout: %d of %d updated replicas are available\",\n\t\t\t\t\t\tkey, deployment.Status.AvailableReplicas, deployment.Status.UpdatedReplicas)\n\t\t\t\t})\n\t\t\t\treturn false, nil\n\t\t\t}\n\t\t\tlog.Printf(\"  Deployment %q successfully rolled out\", key)\n\t\t\treturn true, nil\n\t\t}\n\t\tonceSpecUpdate.Do(func() {\n\t\t\tlog.Printf(\"Waiting for Deployment %q to rollout: waiting for deployment spec update to be observed\",\n\t\t\t\tkey)\n\t\t})\n\t\treturn false, nil\n\t}\n\treturn wait.PollUntilContextCancel(ctx, time.Second, false, rolloutComplete)\n}\n\nfunc (c Client) DoCSVWait(ctx context.Context, key types.NamespacedName) error {\n\tvar (\n\t\tcurPhase olmapiv1alpha1.ClusterServiceVersionPhase\n\t\tnewPhase olmapiv1alpha1.ClusterServiceVersionPhase\n\t)\n\tonce := sync.Once{}\n\n\tcsv := olmapiv1alpha1.ClusterServiceVersion{}\n\tcsvPhaseSucceeded := func(pctx context.Context) (bool, error) {\n\t\terr := c.KubeClient.Get(pctx, key, &csv)\n\t\tif err != nil {\n\t\t\tif apierrors.IsNotFound(err) {\n\t\t\t\tonce.Do(func() {\n\t\t\t\t\tlog.Printf(\"  Waiting for ClusterServiceVersion %q to appear\", key)\n\t\t\t\t})\n\t\t\t\treturn false, nil\n\t\t\t}\n\t\t\treturn false, err\n\t\t}\n\t\tnewPhase = csv.Status.Phase\n\t\tif newPhase != curPhase {\n\t\t\tcurPhase = newPhase\n\t\t\tlog.Printf(\"  Found ClusterServiceVersion %q phase: %s\", key, curPhase)\n\t\t}\n\n\t\tswitch curPhase {\n\t\tcase olmapiv1alpha1.CSVPhaseFailed:\n\t\t\treturn false, fmt.Errorf(\"csv failed: reason: %q, message: %q\", csv.Status.Reason, csv.Status.Message)\n\t\tcase olmapiv1alpha1.CSVPhaseSucceeded:\n\t\t\treturn true, nil\n\t\tdefault:\n\t\t\treturn false, nil\n\t\t}\n\t}\n\n\terr := wait.PollUntilContextCancel(ctx, time.Second, false, csvPhaseSucceeded)\n\tif err != nil && errors.Is(err, context.DeadlineExceeded) {\n\t\tdepCheckErr := c.checkDeploymentErrors(ctx, key, csv)\n\t\tif depCheckErr != nil {\n\t\t\treturn depCheckErr\n\t\t}\n\t}\n\treturn err\n}\n\n// checkDeploymentErrors function loops through deployment specs of a given CSV, and prints reason\n// in case of failures, based on deployment condition.\nfunc (c Client) checkDeploymentErrors(ctx context.Context, key types.NamespacedName, csv olmapiv1alpha1.ClusterServiceVersion) error {\n\tdepErrs := deploymentErrors{}\n\tif key.Namespace == \"\" {\n\t\treturn fmt.Errorf(\"no namespace provided to get deployment failures\")\n\t}\n\tdep := &appsv1.Deployment{}\n\tfor _, ds := range csv.Spec.InstallStrategy.StrategySpec.DeploymentSpecs {\n\t\tdepKey := types.NamespacedName{\n\t\t\tNamespace: key.Namespace,\n\t\t\tName:      ds.Name,\n\t\t}\n\t\tdepSelectors := ds.Spec.Selector\n\t\tif err := c.KubeClient.Get(ctx, depKey, dep); err != nil {\n\t\t\tdepErrs = append(depErrs, deploymentError{\n\t\t\t\tresourceError: resourceError{\n\t\t\t\t\tname:  ds.Name,\n\t\t\t\t\tissue: err.Error(),\n\t\t\t\t},\n\t\t\t})\n\t\t\tcontinue\n\t\t}\n\t\tfor _, s := range dep.Status.Conditions {\n\t\t\tif s.Type == appsv1.DeploymentAvailable && s.Status != corev1.ConditionTrue {\n\t\t\t\tdepErr := deploymentError{\n\t\t\t\t\tresourceError: resourceError{\n\t\t\t\t\t\tname:  ds.Name,\n\t\t\t\t\t\tissue: s.Reason,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t\tpodErr := c.checkPodErrors(ctx, depSelectors, key)\n\t\t\t\tpodErrs := podErrors{}\n\t\t\t\tif errors.As(podErr, &podErrs) {\n\t\t\t\t\tdepErr.podErrs = append(depErr.podErrs, podErrs...)\n\t\t\t\t} else {\n\t\t\t\t\treturn podErr\n\t\t\t\t}\n\t\t\t\tdepErrs = append(depErrs, depErr)\n\t\t\t}\n\t\t}\n\t}\n\treturn depErrs\n}\n\n// checkPodErrors loops through pods, and returns pod errors if any.\nfunc (c Client) checkPodErrors(ctx context.Context, depSelectors *metav1.LabelSelector, key types.NamespacedName) error {\n\t// loop through pods and return specific error message.\n\tpodErr := podErrors{}\n\tpodList := &corev1.PodList{}\n\tpodLabelSelectors, err := metav1.LabelSelectorAsSelector(depSelectors)\n\tif err != nil {\n\t\treturn err\n\t}\n\toptions := client.ListOptions{\n\t\tLabelSelector: podLabelSelectors,\n\t\tNamespace:     key.Namespace,\n\t}\n\tif err := c.KubeClient.List(ctx, podList, &options); err != nil {\n\t\treturn fmt.Errorf(\"error getting Pods: %v\", err)\n\t}\n\tfor _, p := range podList.Items {\n\t\tfor _, cs := range p.Status.ContainerStatuses {\n\t\t\tif !cs.Ready {\n\t\t\t\tif cs.State.Waiting != nil {\n\t\t\t\t\tcontainerName := p.Name + \":\" + cs.Name\n\t\t\t\t\tpodErr = append(podErr, podError{\n\t\t\t\t\t\tresourceError{\n\t\t\t\t\t\t\tname:  containerName,\n\t\t\t\t\t\t\tissue: cs.State.Waiting.Message,\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn podErr\n}\n\n// GetInstalledVersion returns the OLM version installed in the namespace informed.\nfunc (c Client) GetInstalledVersion(ctx context.Context, namespace string) (string, error) {\n\topts := client.InNamespace(namespace)\n\tcsvs := &olmapiv1alpha1.ClusterServiceVersionList{}\n\tif err := c.KubeClient.List(ctx, csvs, opts); err != nil {\n\t\tif apierrors.IsNotFound(err) || meta.IsNoMatchError(err) {\n\t\t\treturn \"\", ErrOLMNotInstalled\n\t\t}\n\t\treturn \"\", fmt.Errorf(\"failed to list CSVs in namespace %q: %v\", namespace, err)\n\t}\n\tvar pkgServerCSV *olmapiv1alpha1.ClusterServiceVersion\n\tfor i := range csvs.Items {\n\t\tcsv := csvs.Items[i]\n\t\tname := csv.GetName()\n\t\t// Check old and new name possibilities.\n\t\tif name == pkgServerCSVNewName || strings.HasPrefix(name, pkgServerCSVOldNamePrefix) {\n\t\t\t// There is more than one version of OLM installed in the cluster,\n\t\t\t// so we can't resolve the version being used.\n\t\t\tif pkgServerCSV != nil {\n\t\t\t\treturn \"\", fmt.Errorf(\"more than one OLM (package server) version installed: %q and %q\",\n\t\t\t\t\tpkgServerCSV.GetName(), name)\n\t\t\t}\n\t\t\tpkgServerCSV = &csv\n\t\t}\n\t}\n\tif pkgServerCSV == nil {\n\t\treturn \"\", ErrOLMNotInstalled\n\t}\n\treturn getOLMVersionFromPackageServerCSV(pkgServerCSV)\n}\n\nconst (\n\t// Versions pre-0.11 have a versioned name.\n\tpkgServerCSVOldNamePrefix = \"packageserver.\"\n\t// Versions 0.11+ have a fixed name.\n\tpkgServerCSVNewName      = \"packageserver\"\n\tpkgServerOLMVersionLabel = \"olm.version\"\n)\n\nfunc getOLMVersionFromPackageServerCSV(csv *olmapiv1alpha1.ClusterServiceVersion) (string, error) {\n\t// Package server CSV's from OLM versions > 0.10.1 have a label containing\n\t// the OLM version.\n\tif labels := csv.GetLabels(); labels != nil {\n\t\tif ver, ok := labels[pkgServerOLMVersionLabel]; ok {\n\t\t\treturn ver, nil\n\t\t}\n\t}\n\t// Fall back to getting OLM version from package server CSV name. Versions\n\t// of OLM <= 0.10.1 are not labelled with pkgServerOLMVersionLabel.\n\tver := strings.TrimPrefix(csv.GetName(), pkgServerCSVOldNamePrefix)\n\t// OLM releases do not have a \"v\" prefix but CSV versions do.\n\tver = strings.TrimPrefix(ver, \"v\")\n\t// Check if a valid semver. Ignore non-nil errors as they are not related\n\t// to the reason OLM version can't be found.\n\tif _, err := semver.Parse(ver); err == nil {\n\t\treturn ver, nil\n\t}\n\treturn \"\", fmt.Errorf(\"no OLM version found in CSV %q spec\", csv.GetName())\n}\n"
  },
  {
    "path": "internal/olm/client/client_suite_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage client\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nfunc TestClient(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"check depErrors\")\n}\n"
  },
  {
    "path": "internal/olm/client/client_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage client\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"time\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\tolmapiv1alpha1 \"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\tappsv1 \"k8s.io/api/apps/v1\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\t\"k8s.io/apimachinery/pkg/api/meta\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\t\"k8s.io/apimachinery/pkg/runtime/schema\"\n\t\"k8s.io/apimachinery/pkg/types\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client/fake\"\n)\n\nvar _ = Describe(\"Client\", func() {\n\tDescribe(\"checkDeploymentErrors\", func() {\n\n\t\tvar (\n\t\t\tfakeClient client.Client\n\t\t\tcsv        olmapiv1alpha1.ClusterServiceVersion\n\t\t)\n\n\t\tBeforeEach(func() {\n\t\t\tcsv = olmapiv1alpha1.ClusterServiceVersion{\n\t\t\t\tSpec: olmapiv1alpha1.ClusterServiceVersionSpec{\n\t\t\t\t\tDisplayName: \"test-operator\",\n\t\t\t\t\tInstallStrategy: olmapiv1alpha1.NamedInstallStrategy{\n\t\t\t\t\t\tStrategySpec: olmapiv1alpha1.StrategyDetailsDeployment{\n\t\t\t\t\t\t\tDeploymentSpecs: []olmapiv1alpha1.StrategyDeploymentSpec{\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tName: \"dummy-operator\",\n\t\t\t\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\t\t\t\tSelector: &metav1.LabelSelector{\n\t\t\t\t\t\t\t\t\t\t\tMatchLabels: map[string]string{\n\t\t\t\t\t\t\t\t\t\t\t\t\"dummylabel\": \"dummyvalue\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tName: \"test-operator-controller-manager\",\n\t\t\t\t\t\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\t\t\t\t\t\tSelector: &metav1.LabelSelector{\n\t\t\t\t\t\t\t\t\t\t\tMatchLabels: map[string]string{\n\t\t\t\t\t\t\t\t\t\t\t\t\"control-plane\": \"controller-manager\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t})\n\t\tContext(\"with a valid csv\", func() {\n\t\t\tIt(\"check error string for pod errors\", func() {\n\t\t\t\tfakeClient = fake.NewClientBuilder().WithObjects(\n\t\t\t\t\t&corev1.Pod{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\t\t\tName:      \"test-operator-kc44t\",\n\t\t\t\t\t\t\tNamespace: \"test-operator-system\",\n\t\t\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\t\t\t\"control-plane\": \"controller-manager\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tStatus: corev1.PodStatus{\n\t\t\t\t\t\t\tContainerStatuses: []corev1.ContainerStatus{\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tName:  \"container1\",\n\t\t\t\t\t\t\t\t\tReady: false,\n\t\t\t\t\t\t\t\t\tState: corev1.ContainerState{\n\t\t\t\t\t\t\t\t\t\tWaiting: &corev1.ContainerStateWaiting{\n\t\t\t\t\t\t\t\t\t\t\tMessage: \"back-off 5m0s restarting failed container\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\t\t\tName:      \"test-operator-controller-manager\",\n\t\t\t\t\t\t\tNamespace: \"test-operator-system\",\n\t\t\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\t\t\t\"control-plane\": \"controller-manager\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tStatus: appsv1.DeploymentStatus{\n\t\t\t\t\t\t\tConditions: []appsv1.DeploymentCondition{\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tType:   \"Available\",\n\t\t\t\t\t\t\t\t\tStatus: \"False\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tType:   \"Progressing\",\n\t\t\t\t\t\t\t\t\tStatus: \"True\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t).Build()\n\t\t\t\tkey := types.NamespacedName{\n\t\t\t\t\tName:      \"test.operator\",\n\t\t\t\t\tNamespace: \"test-operator-system\",\n\t\t\t\t}\n\t\t\t\tolmclient := Client{KubeClient: fakeClient}\n\t\t\t\terr := olmclient.checkDeploymentErrors(context.TODO(), key, csv)\n\t\t\t\tExpect(err.Error()).To(ContainSubstring(\"back-off 5m0s restarting failed container\"))\n\t\t\t})\n\n\t\t\tIt(\"check error string for multiple pod failures\", func() {\n\t\t\t\tfakeClt := fake.NewClientBuilder().WithObjects(\n\t\t\t\t\t&corev1.Pod{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\t\t\tName:      \"test-operator-jjj\",\n\t\t\t\t\t\t\tNamespace: \"test-operator-system\",\n\t\t\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\t\t\t\"control-plane\": \"controller-manager\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tStatus: corev1.PodStatus{\n\t\t\t\t\t\t\tContainerStatuses: []corev1.ContainerStatus{\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tName:  \"container1\",\n\t\t\t\t\t\t\t\t\tReady: false,\n\t\t\t\t\t\t\t\t\tState: corev1.ContainerState{\n\t\t\t\t\t\t\t\t\t\tWaiting: &corev1.ContainerStateWaiting{\n\t\t\t\t\t\t\t\t\t\t\tMessage: \"Restarting container\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t&corev1.Pod{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\t\t\tName:      \"test-operator-kkk\",\n\t\t\t\t\t\t\tNamespace: \"test-operator-system\",\n\t\t\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\t\t\t\"control-plane\": \"controller-manager\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tStatus: corev1.PodStatus{\n\t\t\t\t\t\t\tContainerStatuses: []corev1.ContainerStatus{\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tName:  \"container2\",\n\t\t\t\t\t\t\t\t\tReady: false,\n\t\t\t\t\t\t\t\t\tState: corev1.ContainerState{\n\t\t\t\t\t\t\t\t\t\tWaiting: &corev1.ContainerStateWaiting{\n\t\t\t\t\t\t\t\t\t\t\tMessage: \"ImageErrPull\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\t\t\tName:      \"test-operator-controller-manager\",\n\t\t\t\t\t\t\tNamespace: \"test-operator-system\",\n\t\t\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\t\t\t\"control-plane\": \"controller-manager\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tStatus: appsv1.DeploymentStatus{\n\t\t\t\t\t\t\tConditions: []appsv1.DeploymentCondition{\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tType:   \"Available\",\n\t\t\t\t\t\t\t\t\tStatus: \"False\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tType:   \"Progressing\",\n\t\t\t\t\t\t\t\t\tStatus: \"True\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t).Build()\n\t\t\t\tkey := types.NamespacedName{\n\t\t\t\t\tName:      \"test.operator\",\n\t\t\t\t\tNamespace: \"test-operator-system\",\n\t\t\t\t}\n\t\t\t\tolmclient := Client{KubeClient: fakeClt}\n\t\t\t\terr := olmclient.checkDeploymentErrors(context.TODO(), key, csv)\n\t\t\t\tExpect(err.Error()).To(ContainSubstring(\"ImageErrPull\"))\n\t\t\t\tExpect(err.Error()).To(ContainSubstring(\"Restarting container\"))\n\t\t\t})\n\n\t\t\tIt(\"check error string for deployment errors,when no pods exist\", func() {\n\t\t\t\tfakeClient = fake.NewClientBuilder().WithObjects(\n\t\t\t\t\t&appsv1.Deployment{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\t\t\tName:      \"test-operator-controller-manager\",\n\t\t\t\t\t\t\tNamespace: \"test-operator-system\",\n\t\t\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\t\t\t\"control-plane\": \"controller-manager\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tStatus: appsv1.DeploymentStatus{\n\t\t\t\t\t\t\tConditions: []appsv1.DeploymentCondition{\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tType:   \"Available\",\n\t\t\t\t\t\t\t\t\tStatus: \"False\",\n\t\t\t\t\t\t\t\t\tReason: \"Pods not available\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t).Build()\n\t\t\t\tkey := types.NamespacedName{\n\t\t\t\t\tName:      \"test-operator\",\n\t\t\t\t\tNamespace: \"test-operator-system\",\n\t\t\t\t}\n\t\t\t\tolmclient := Client{KubeClient: fakeClient}\n\t\t\t\terr := olmclient.checkDeploymentErrors(context.TODO(), key, csv)\n\t\t\t\tExpect(err.Error()).To(ContainSubstring(\"Pods not available\"))\n\t\t\t})\n\n\t\t\tIt(\"check error string,when no deployments exist for given CSV\", func() {\n\t\t\t\tfakeClient = fake.NewClientBuilder().Build()\n\t\t\t\tolmclient := Client{KubeClient: fakeClient}\n\t\t\t\tkey := types.NamespacedName{\n\t\t\t\t\tName:      \"test-operator\",\n\t\t\t\t\tNamespace: \"test-operator-system\",\n\t\t\t\t}\n\t\t\t\terr := olmclient.checkDeploymentErrors(context.TODO(), key, csv)\n\t\t\t\tExpect(err.Error()).To(ContainSubstring(\"\\\"test-operator-controller-manager\\\" not found\"))\n\t\t\t\tExpect(err.Error()).To(ContainSubstring(\"\\\"dummy-operator\\\" not found\"))\n\t\t\t})\n\t\t\tIt(\"check error string,when no namespace provided\", func() {\n\t\t\t\tfakeClient = fake.NewClientBuilder().Build()\n\t\t\t\tolmclient := Client{KubeClient: fakeClient}\n\t\t\t\tkey := types.NamespacedName{\n\t\t\t\t\tName: \"test-operator\",\n\t\t\t\t}\n\t\t\t\terr := olmclient.checkDeploymentErrors(context.TODO(), key, csv)\n\t\t\t\tExpect(err.Error()).To(ContainSubstring(\"no namespace provided to get deployment failures\"))\n\t\t\t})\n\t\t})\n\t})\n\n\tDescribe(\"test DoCreate\", func() {\n\t\tvar fakeClient client.Client\n\n\t\tBeforeEach(func() {\n\t\t\tfakeClient = &errClient{cli: fake.NewClientBuilder().Build()}\n\t\t})\n\n\t\tAfterEach(func() {\n\t\t\tfakeClient.(*errClient).reset()\n\t\t})\n\n\t\tIt(\"should create all the resources successfully\", func() {\n\t\t\tcli := Client{KubeClient: fakeClient}\n\n\t\t\tctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)\n\t\t\tdefer cancel()\n\n\t\t\tExpect(cli.DoCreate(ctx,\n\t\t\t\t&corev1.Namespace{\n\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"test-ns\"},\n\t\t\t\t},\n\t\t\t\t&corev1.Pod{\n\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"test-pod\", Namespace: \"test-ns\"},\n\t\t\t\t},\n\t\t\t)).To(Succeed())\n\n\t\t\tns := &corev1.Namespace{}\n\t\t\tExpect(fakeClient.Get(context.Background(), client.ObjectKey{Name: \"test-ns\"}, ns)).To(Succeed())\n\n\t\t\tpod := &corev1.Pod{}\n\t\t\tExpect(fakeClient.Get(context.Background(), client.ObjectKey{Namespace: \"test-ns\", Name: \"test-pod\"}, pod)).To(Succeed())\n\t\t})\n\n\t\tIt(\"should eventually create all the resources successfully\", func() {\n\t\t\tcli := Client{KubeClient: fakeClient}\n\n\t\t\tctx, cancel := context.WithTimeout(context.Background(), 7*time.Second)\n\t\t\tdefer cancel()\n\n\t\t\tExpect(cli.DoCreate(ctx,\n\t\t\t\t&corev1.Namespace{\n\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"test-ns\"},\n\t\t\t\t},\n\t\t\t\t&corev1.Pod{\n\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"eventually-match\", Namespace: \"test-ns\"},\n\t\t\t\t},\n\t\t\t)).To(Succeed())\n\n\t\t\tns := &corev1.Namespace{}\n\t\t\tExpect(fakeClient.Get(context.Background(), client.ObjectKey{Name: \"test-ns\"}, ns)).To(Succeed())\n\n\t\t\tpod := &corev1.Pod{}\n\t\t\tExpect(fakeClient.Get(context.Background(), client.ObjectKey{Namespace: \"test-ns\", Name: \"eventually-match\"}, pod)).To(Succeed())\n\t\t})\n\n\t\tIt(\"should fail with no-match error\", func() {\n\t\t\tcli := Client{KubeClient: fakeClient}\n\n\t\t\tctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)\n\t\t\tdefer cancel()\n\t\t\tExpect(cli.DoCreate(ctx,\n\t\t\t\t&corev1.Namespace{\n\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"test-ns\"},\n\t\t\t\t},\n\t\t\t\t&corev1.Pod{\n\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"no-match\", Namespace: \"test-ns\"},\n\t\t\t\t},\n\t\t\t)).ToNot(Succeed())\n\t\t})\n\n\t\tIt(\"should fail with unknown-error error\", func() {\n\t\t\tcli := Client{KubeClient: fakeClient}\n\n\t\t\tExpect(cli.DoCreate(context.Background(),\n\t\t\t\t&corev1.Namespace{\n\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"test-ns\"},\n\t\t\t\t},\n\t\t\t\t&corev1.Pod{\n\t\t\t\t\tObjectMeta: metav1.ObjectMeta{Name: \"unknown-error\", Namespace: \"test-ns\"},\n\t\t\t\t},\n\t\t\t)).ToNot(Succeed())\n\t\t})\n\t})\n})\n\nvar _ client.Client = &errClient{}\n\ntype errClient struct {\n\tcli            client.Client\n\tnoMatchCounter int\n}\n\nfunc (c *errClient) reset() {\n\tc.noMatchCounter = 0\n}\n\nfunc (c *errClient) Get(ctx context.Context, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error {\n\treturn c.cli.Get(ctx, key, obj, opts...)\n}\n\nfunc (c *errClient) List(ctx context.Context, list client.ObjectList, opts ...client.ListOption) error {\n\treturn c.cli.List(ctx, list, opts...)\n}\nfunc (c *errClient) Create(ctx context.Context, obj client.Object, opts ...client.CreateOption) error {\n\tswitch obj.GetName() {\n\tcase \"no-match\":\n\t\treturn &meta.NoResourceMatchError{}\n\n\tcase \"eventually-match\":\n\t\tif c.noMatchCounter >= 4 {\n\t\t\treturn c.cli.Create(ctx, obj, opts...)\n\t\t}\n\t\tc.noMatchCounter++\n\t\treturn &meta.NoResourceMatchError{}\n\n\tcase \"unknown-error\":\n\t\treturn errors.New(\"fake error\")\n\n\tdefault:\n\t\treturn c.cli.Create(ctx, obj, opts...)\n\t}\n}\n\nfunc (c *errClient) Delete(ctx context.Context, obj client.Object, opts ...client.DeleteOption) error {\n\treturn c.cli.Delete(ctx, obj, opts...)\n}\n\nfunc (c *errClient) Update(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error {\n\treturn c.cli.Update(ctx, obj, opts...)\n}\n\nfunc (c *errClient) Patch(ctx context.Context, obj client.Object, patch client.Patch, opts ...client.PatchOption) error {\n\treturn c.cli.Patch(ctx, obj, patch, opts...)\n}\n\nfunc (c *errClient) DeleteAllOf(ctx context.Context, obj client.Object, opts ...client.DeleteAllOfOption) error {\n\treturn c.cli.DeleteAllOf(ctx, obj, opts...)\n}\n\nfunc (c *errClient) SubResource(subResource string) client.SubResourceClient {\n\treturn c.cli.SubResource(subResource)\n}\n\nfunc (c *errClient) Scheme() *runtime.Scheme {\n\treturn c.cli.Scheme()\n}\n\nfunc (c *errClient) RESTMapper() meta.RESTMapper {\n\treturn c.cli.RESTMapper()\n}\n\nfunc (c *errClient) Status() client.SubResourceWriter {\n\treturn c.cli.Status()\n}\n\nfunc (c *errClient) GroupVersionKindFor(obj runtime.Object) (schema.GroupVersionKind, error) {\n\treturn c.cli.GroupVersionKindFor(obj)\n}\n\nfunc (c *errClient) IsObjectNamespaced(obj runtime.Object) (bool, error) {\n\treturn c.cli.IsObjectNamespaced(obj)\n}\n"
  },
  {
    "path": "internal/olm/client/status.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Package olm provides an API to install, uninstall, and check the\n// status of an Operator Lifecycle Manager installation.\n// TODO: move to OLM repository?\npackage client\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"sort\"\n\t\"text/tabwriter\"\n\n\t\"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions\"\n\tapierrors \"k8s.io/apimachinery/pkg/api/errors\"\n\t\"k8s.io/apimachinery/pkg/api/meta\"\n\t\"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\t\"k8s.io/apimachinery/pkg/runtime/schema\"\n\t\"k8s.io/apimachinery/pkg/types\"\n\tapiutilerrors \"k8s.io/apimachinery/pkg/util/errors\"\n\t\"k8s.io/utils/set\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client\"\n)\n\ntype Status struct {\n\tResources []ResourceStatus\n}\n\ntype ResourceStatus struct {\n\tNamespacedName types.NamespacedName\n\tResource       *unstructured.Unstructured\n\tGVK            schema.GroupVersionKind\n\tError          error\n\n\trequestObject runtime.Object // Needed for context on errors from requests on an object.\n}\n\nfunc (c Client) GetObjectsStatus(ctx context.Context, objs ...client.Object) Status {\n\tvar rss []ResourceStatus\n\tfor _, obj := range objs {\n\t\tgvk := obj.GetObjectKind().GroupVersionKind()\n\t\tnn := types.NamespacedName{\n\t\t\tNamespace: obj.GetNamespace(),\n\t\t\tName:      obj.GetName(),\n\t\t}\n\t\trs := ResourceStatus{\n\t\t\tNamespacedName: nn,\n\t\t\tGVK:            gvk,\n\t\t\trequestObject:  obj,\n\t\t}\n\t\tu := unstructured.Unstructured{}\n\t\tu.SetGroupVersionKind(gvk)\n\t\terr := c.KubeClient.Get(ctx, nn, &u)\n\t\tif err != nil {\n\t\t\trs.Error = fmt.Errorf(\"error getting resource %q with GVK %q: %w\", nn, gvk, err)\n\t\t}\n\t\tif rs.Error == nil {\n\t\t\trs.Resource = &u\n\t\t}\n\t\trss = append(rss, rs)\n\t}\n\n\treturn Status{Resources: rss}\n}\n\n// HasInstalledResources only returns true if at least one resource in s\n// was returned successfully by the API server. A resource error status\n// containing any error except \"not found\", or \"no kind match\" errors\n// for Custom Resources, will result in HasInstalledResources returning\n// false and the error.\nfunc (s Status) HasInstalledResources() (bool, error) {\n\terrs := []error{}\n\tcrdKindSet, err := s.getCRDKindSet()\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"error getting set of CRD kinds in resources: %v\", err)\n\t}\n\t// Sort resources by whether they're installed or not to get consistent\n\t// return values.\n\tsort.Slice(s.Resources, func(i int, _ int) bool {\n\t\treturn s.Resources[i].Resource != nil\n\t})\n\tfor _, r := range s.Resources {\n\t\tif r.Resource != nil {\n\t\t\treturn true, nil\n\t\t} else if r.Error != nil && !apierrors.IsNotFound(r.Error) {\n\t\t\t// We know the error is not a \"resource not found\" error at this point.\n\t\t\t// It still may be the equivalent for a CR, \"no kind match\", if its\n\t\t\t// corresponding CRD has been deleted already. We want to make sure\n\t\t\t// we're only allowing \"no kind match\" errors to be skipped for CR's\n\t\t\t// since we do not know if a kind is a CR kind, hence checking\n\t\t\t// crdKindSet for existence of a resource's kind.\n\t\t\tnkmerr := &meta.NoKindMatchError{}\n\t\t\tif !errors.As(r.Error, &nkmerr) || !crdKindSet.Has(r.GVK.Kind) {\n\t\t\t\terrs = append(errs, r.Error)\n\t\t\t}\n\t\t}\n\t}\n\treturn false, apiutilerrors.NewAggregate(errs)\n}\n\n// getCRDKindSet returns the set of all kinds specified by all CRDs in s.\nfunc (s Status) getCRDKindSet() (set.Set[string], error) {\n\tcrdKindSet := set.New[string]()\n\tfor _, r := range s.Resources {\n\t\tif r.GVK.Kind == \"CustomResourceDefinition\" {\n\t\t\tu := &unstructured.Unstructured{}\n\t\t\tswitch v := r.requestObject.(type) {\n\t\t\tcase *unstructured.Unstructured:\n\t\t\t\tu = v\n\t\t\tdefault:\n\t\t\t\tuObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&v)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\t// Other fields are not important, just the CRD kind.\n\t\t\t\tu.Object = uObj\n\t\t\t}\n\t\t\t// Use unversioned CustomResourceDefinition to avoid implementing cast\n\t\t\t// for all versions.\n\t\t\tcrd := &apiextensions.CustomResourceDefinition{}\n\t\t\terr := runtime.DefaultUnstructuredConverter.FromUnstructured(u.Object, &crd)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tcrdKindSet.Insert(crd.Spec.Names.Kind)\n\t\t}\n\t}\n\treturn crdKindSet, nil\n}\n\nfunc (s Status) String() string {\n\tout := &bytes.Buffer{}\n\ttw := tabwriter.NewWriter(out, 8, 4, 4, ' ', 0)\n\tfmt.Fprintf(tw, \"NAME\\tNAMESPACE\\tKIND\\tSTATUS\\n\")\n\tfor _, r := range s.Resources {\n\t\tnn := r.NamespacedName\n\t\tkind := r.GVK.Kind\n\t\tvar status string\n\t\tif r.Error != nil {\n\t\t\tstatus = r.Error.Error()\n\t\t} else if r.Resource != nil {\n\t\t\tstatus = \"Installed\"\n\t\t} else {\n\t\t\tstatus = \"Unknown\"\n\t\t}\n\t\tfmt.Fprintf(tw, \"%s\\t%s\\t%s\\t%s\\n\", nn.Name, nn.Namespace, kind, status)\n\t}\n\ttw.Flush()\n\n\treturn out.String()\n}\n"
  },
  {
    "path": "internal/olm/fbcutil/util.go",
    "content": "// Copyright 2022 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage fbcutil\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"crypto/sha256\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/operator-framework/operator-registry/alpha/action\"\n\tdeclarativeconfig \"github.com/operator-framework/operator-registry/alpha/declcfg\"\n\t\"github.com/operator-framework/operator-registry/pkg/containertools\"\n\t\"github.com/operator-framework/operator-registry/pkg/image/containerdregistry\"\n\tregistryutil \"github.com/operator-framework/operator-sdk/internal/registry\"\n\tlog \"github.com/sirupsen/logrus\"\n)\n\nconst (\n\tSchemaChannel   = \"olm.channel\"\n\tSchemaPackage   = \"olm.package\"\n\tDefaultChannel  = \"operator-sdk-run-bundle\"\n\tDefaultCacheDir = \"operator-sdk-run-bundle-cache\"\n)\n\nconst (\n\t// defaultIndexImageBase is the base for defaultIndexImage. It is necessary to separate\n\t// them for string comparison when defaulting bundle add mode.\n\tDefaultIndexImageBase = \"quay.io/operator-framework/opm:\"\n\t// DefaultIndexImage is the index base image used if none is specified. It contains no bundles.\n\t// TODO(v2.0.0): pin this image tag to a specific version.\n\tDefaultIndexImage = DefaultIndexImageBase + \"latest\"\n\t// DefaultInitImage is the default image to be used in the registry init container\n\tDefaultInitImage = \"registry.access.redhat.com/ubi9/ubi:9.7\"\n)\n\n// BundleDeclcfg represents a minimal File-Based Catalog.\n// This struct only consists of one Package, Bundle, and Channel blob. It is used to\n// represent the bundle image in the File-Based Catalog format.\ntype BundleDeclcfg struct {\n\tPackage declarativeconfig.Package\n\tChannel declarativeconfig.Channel\n\tBundle  declarativeconfig.Bundle\n}\n\n// FBCContext is a struct that stores all the required information while constructing\n// a new File-Based Catalog on the fly. The fields from this struct are passed as\n// parameters to Operator Registry API calls to generate declarative config objects.\ntype FBCContext struct {\n\tPackage       string\n\tChannelName   string\n\tRefs          []string\n\tChannelEntry  declarativeconfig.ChannelEntry\n\tSkipTLSVerify bool\n\tUseHTTP       bool\n}\n\n// CreateFBC generates an FBC by creating bundle, package and channel blobs.\nfunc (f *FBCContext) CreateFBC(ctx context.Context) (BundleDeclcfg, error) {\n\tvar bundleDC BundleDeclcfg\n\t// Rendering the bundle image into a declarative config format.\n\tdeclcfg, err := RenderRefs(ctx, f.Refs, f.SkipTLSVerify, f.UseHTTP)\n\tif err != nil {\n\t\treturn BundleDeclcfg{}, err\n\t}\n\n\t// Ensuring a valid bundle size.\n\tif len(declcfg.Bundles) != 1 {\n\t\treturn BundleDeclcfg{}, fmt.Errorf(\"bundle image should contain exactly one bundle blob\")\n\t}\n\n\tbundleDC.Bundle = declcfg.Bundles[0]\n\n\t// generate package.\n\tbundleDC.Package = declarativeconfig.Package{\n\t\tSchema:         SchemaPackage,\n\t\tName:           f.Package,\n\t\tDefaultChannel: f.ChannelName,\n\t}\n\n\t// generate channel.\n\tbundleDC.Channel = declarativeconfig.Channel{\n\t\tSchema:  SchemaChannel,\n\t\tName:    f.ChannelName,\n\t\tPackage: f.Package,\n\t\tEntries: []declarativeconfig.ChannelEntry{f.ChannelEntry},\n\t}\n\n\treturn bundleDC, nil\n}\n\n// ValidateAndStringify first converts the generated declarative config to a model and validates it.\n// If the declarative config model is valid, it will convert the declarative config to a YAML string and return it.\nfunc ValidateAndStringify(declcfg *declarativeconfig.DeclarativeConfig) (string, error) {\n\t// validates and converts declarative config to model\n\t_, err := declarativeconfig.ConvertToModel(*declcfg)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"error converting the declarative config to model: %v\", err)\n\t}\n\n\tvar buf bytes.Buffer\n\terr = declarativeconfig.WriteYAML(*declcfg, &buf)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"error writing generated declarative config to JSON encoder: %v\", err)\n\t}\n\n\tif buf.String() == \"\" {\n\t\treturn \"\", errors.New(\"file-based catalog contents cannot be empty\")\n\t}\n\n\treturn buf.String(), nil\n}\n\nfunc NullLogger() *log.Entry {\n\tlogger := log.New()\n\tlogger.SetOutput(io.Discard)\n\treturn log.NewEntry(logger)\n}\n\n// RenderRefs will invoke Operator Registry APIs and return a declarative config object representation\n// of the references that are passed in as a string array.\nfunc RenderRefs(ctx context.Context, refs []string, skipTLSVerify bool, useHTTP bool) (*declarativeconfig.DeclarativeConfig, error) {\n\tcacheDir := dirNameFromRefs(refs)\n\n\tif cacheDir == \"\" {\n\t\tcacheDir = DefaultCacheDir\n\t}\n\treg, err := containerdregistry.NewRegistry(\n\t\tcontainerdregistry.WithLog(NullLogger()),\n\t\tcontainerdregistry.SkipTLSVerify(skipTLSVerify),\n\t\tcontainerdregistry.WithPlainHTTP(useHTTP),\n\t\tcontainerdregistry.WithCacheDir(cacheDir))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error creating new image registry: %v\", err)\n\t}\n\n\tdefer func() {\n\t\terr = reg.Destroy()\n\t\tif err != nil {\n\t\t\tlog.Warn(fmt.Sprintf(\"Unable to cleanup registry. You may have to manually cleanup by removing the %q directory\", cacheDir))\n\t\t}\n\t}()\n\n\trender := action.Render{\n\t\tRefs:     refs,\n\t\tRegistry: reg,\n\t}\n\n\tlog.SetOutput(io.Discard)\n\tdeclcfg, err := render.Run(ctx)\n\tlog.SetOutput(os.Stdout)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error in rendering the bundle and index image: %v\", err)\n\t}\n\n\treturn declcfg, nil\n}\n\nfunc dirNameFromRefs(refs []string) string {\n\tdirNameBytes := []byte(strings.ReplaceAll(strings.Join(refs, \"_\"), \"/\", \"-\"))\n\thash := sha256.New()\n\thash.Write(dirNameBytes)\n\thashBytes := hash.Sum(nil)\n\treturn fmt.Sprintf(\"%x\", hashBytes)\n}\n\n// IsFBC will determine if an index image uses the File-Based Catalog or SQLite index image format.\n// The default index image will adopt the File-Based Catalog format.\nfunc IsFBC(ctx context.Context, indexImage string) (bool, error) {\n\t// adding updates to the IndexImageCatalogCreator if it is an FBC image\n\tcatalogLabels, err := registryutil.GetImageLabels(ctx, nil, indexImage, false)\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"get index image labels: %v\", err)\n\t}\n\t_, hasFBCLabel := catalogLabels[containertools.ConfigsLocationLabel]\n\n\treturn hasFBCLabel || indexImage == DefaultIndexImage, nil\n}\n"
  },
  {
    "path": "internal/olm/fbcutil/util_test.go",
    "content": "// Copyright 2023 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage fbcutil\n\nimport (\n\t\"crypto/sha256\"\n\t\"fmt\"\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nvar _ = Describe(\"test fbutil\", func() {\n\n\temptyListHash := fmt.Sprintf(\"%x\", sha256.New().Sum(nil))\n\n\tContext(\"test dirNameFromRefs\", func() {\n\t\tDescribeTable(\"should name the directory with sha256 of the concatenation of the bundle image names\", func(refs []string, expectedHash string) {\n\t\t\tdirName := dirNameFromRefs(refs)\n\n\t\t\tExpect(dirName).Should(HaveLen(sha256.Size * 2)) // in hex representation, each byte is two hex digits\n\t\t\tExpect(dirName).Should(Equal(expectedHash))\n\t\t},\n\t\t\tEntry(\"long image names\", []string{\n\t\t\t\t\"BtU5KRr8IWafnGTvckShoj3xBb5duLZp/XKHZRpOqdVxhHQkCL0Dy0lSRw0a0M/y158JRQKk1S@6KAauQHujQ30my9sivVYGZahR7R7UUSoUBUmnuFdqGHiUTT0aV5Di2\",\n\t\t\t\t\"lKM63iKupQcUPKd6AAsmRRABbGYNmwFTmQEX6fpswndQdb/niJPLRG8WhzaH84Q3kfZC/7hc3nK7Oeq@L5KxmVqbAz6jXlv1yKna2cH4zbZ3be0pcYNHyCSVUG/ZVqRAo\",\n\t\t\t}, \"cc048355dce06491fd090ce0c3ce5a48db3528250ad13a4fbf4090a3de8c325a\"),\n\t\t\tEntry(\"multiple refs\", []string{\"a/b/c\", \"d/e/f\", \"g/h/i/j\", \"k/l/m/n/o\"}, \"df22ac3ac9e59ed300f70b9c2fdd7128be064652839a813948ee9fd1a2f36581\"),\n\t\t\tEntry(\"single ref\", []string{\"a/b/c\"}, \"cbd2be7b96f770a0326948ebd158cf539fab0627e8adbddc97f7a65c6a8ae59a\"),\n\t\t\tEntry(\"no refs\", []string{}, emptyListHash),\n\t\t\tEntry(\"no refs (nil)\", nil, emptyListHash),\n\t\t)\n\t})\n})\n\nfunc TestRegistry(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"fbutil Suite\")\n}\n"
  },
  {
    "path": "internal/olm/installer/client.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Package olm provides an API to install, uninstall, and check the\n// status of an Operator Lifecycle Manager installation.\n// TODO: move to OLM repository?\npackage installer\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"path/filepath\"\n\t\"time\"\n\n\t\"github.com/blang/semver/v4\"\n\tolmapiv1 \"github.com/operator-framework/api/pkg/operators/v1\"\n\tolmapiv1alpha1 \"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\tolmmanifests \"github.com/operator-framework/operator-sdk/internal/bindata/olm\"\n\tlog \"github.com/sirupsen/logrus\"\n\t\"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured\"\n\t\"k8s.io/apimachinery/pkg/runtime/schema\"\n\t\"k8s.io/apimachinery/pkg/types\"\n\t\"k8s.io/apimachinery/pkg/util/wait\"\n\t\"k8s.io/apimachinery/pkg/util/yaml\"\n\t\"k8s.io/client-go/rest\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client\"\n\n\tolmresourceclient \"github.com/operator-framework/operator-sdk/internal/olm/client\"\n)\n\nconst (\n\tolmOperatorName     = \"olm-operator\"\n\tcatalogOperatorName = \"catalog-operator\"\n\tpackageServerName   = \"packageserver\"\n\tbindataManifestPath = \"olm-manifests\"\n)\n\ntype Client struct {\n\t*olmresourceclient.Client\n\tHTTPClient      http.Client\n\tBaseDownloadURL string\n}\n\nfunc ClientForConfig(cfg *rest.Config) (*Client, error) {\n\thttpClient, err := rest.HTTPClientFor(cfg)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to build an HTTP client for the kubeconfig: %v\", err)\n\t}\n\n\tcl, err := olmresourceclient.NewClientForConfig(cfg, httpClient)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get OLM resource client: %v\", err)\n\t}\n\tc := &Client{\n\t\tClient:          cl,\n\t\tHTTPClient:      *http.DefaultClient,\n\t\tBaseDownloadURL: \"https://github.com/operator-framework/operator-lifecycle-manager/releases\",\n\t}\n\treturn c, nil\n}\n\nfunc (c Client) InstallVersion(ctx context.Context, namespace, version string) (*olmresourceclient.Status, error) {\n\tcrds, resources, err := c.getResources(ctx, version)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get resources: %v\", err)\n\t}\n\n\tlog.Info(\"Checking for existing OLM CRDs\")\n\tcrdObjs := toObjects(crds...)\n\tstatus := c.GetObjectsStatus(ctx, crdObjs...)\n\tcrdsInstalled, err := status.HasInstalledResources()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"detected errored OLM resources: %v\", err)\n\t} else if crdsInstalled {\n\t\treturn nil, errors.New(\n\t\t\t\"detected existing OLM resources: OLM must be completely uninstalled before installation\")\n\t}\n\n\tlog.Info(\"Checking for existing OLM resources\")\n\tnonOlmCrds := filterResources(resources, func(r unstructured.Unstructured) bool {\n\t\treturn r.GroupVersionKind().GroupVersion() != olmapiv1.GroupVersion && r.GroupVersionKind().GroupVersion() != schema.GroupVersion{\n\t\t\tGroup:   olmapiv1alpha1.GroupName,\n\t\t\tVersion: olmapiv1alpha1.GroupVersion,\n\t\t}\n\t})\n\tnonCrdObjs := toObjects(nonOlmCrds...)\n\tstatus = c.GetObjectsStatus(ctx, nonCrdObjs...)\n\tinstalled, err := status.HasInstalledResources()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"detected errored OLM resources: %v\", err)\n\t} else if installed {\n\t\treturn nil, errors.New(\n\t\t\t\"detected existing OLM resources: OLM must be completely uninstalled before installation\")\n\t}\n\n\tlog.Info(\"Installing OLM CRDs...\")\n\tif err := c.DoCreate(ctx, crdObjs...); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create CRDs: %v\", err)\n\t}\n\n\t// Wait for CRDs to be created before creating other resources.\n\terr = wait.PollUntilContextCancel(ctx, time.Second, false, func(ctx context.Context) (bool, error) {\n\t\tstatus := c.GetObjectsStatus(ctx, crdObjs...)\n\t\treturn status.HasInstalledResources()\n\t})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"waiting for CRDs to be installed: %v\", err)\n\t}\n\n\tlog.Print(\"Creating OLM resources...\")\n\tobjs := toObjects(resources...)\n\tif err := c.DoCreate(ctx, objs...); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create CRDs and resources: %v\", err)\n\t}\n\n\tlog.Print(\"Waiting for deployment/olm-operator rollout to complete\")\n\tolmOperatorKey := types.NamespacedName{Namespace: namespace, Name: olmOperatorName}\n\tif err := c.DoRolloutWait(ctx, olmOperatorKey); err != nil {\n\t\treturn nil, fmt.Errorf(\"deployment/%s failed to rollout: %v\", olmOperatorKey.Name, err)\n\t}\n\n\tlog.Print(\"Waiting for deployment/catalog-operator rollout to complete\")\n\tcatalogOperatorKey := types.NamespacedName{Namespace: namespace, Name: catalogOperatorName}\n\tif err := c.DoRolloutWait(ctx, catalogOperatorKey); err != nil {\n\t\treturn nil, fmt.Errorf(\"deployment/%s failed to rollout: %v\", catalogOperatorKey.Name, err)\n\t}\n\n\tsubscriptions := filterResources(resources, func(r unstructured.Unstructured) bool {\n\t\treturn r.GroupVersionKind() == schema.GroupVersionKind{\n\t\t\tGroup:   olmapiv1alpha1.GroupName,\n\t\t\tVersion: olmapiv1alpha1.GroupVersion,\n\t\t\tKind:    olmapiv1alpha1.SubscriptionKind,\n\t\t}\n\t})\n\n\tfor _, sub := range subscriptions {\n\t\tsubscriptionKey := types.NamespacedName{Namespace: sub.GetNamespace(), Name: sub.GetName()}\n\t\tlog.Printf(\"Waiting for subscription/%s to install CSV\", subscriptionKey.Name)\n\t\tcsvKey, err := c.getSubscriptionCSV(ctx, subscriptionKey)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"subscription/%s failed to install CSV: %v\", subscriptionKey.Name, err)\n\t\t}\n\t\tlog.Printf(\"Waiting for clusterserviceversion/%s to reach 'Succeeded' phase\", csvKey.Name)\n\t\tif err := c.DoCSVWait(ctx, csvKey); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"clusterserviceversion/%s failed to reach 'Succeeded' phase\",\n\t\t\t\tcsvKey.Name)\n\t\t}\n\t}\n\n\tpackageServerKey := types.NamespacedName{Namespace: namespace, Name: packageServerName}\n\tlog.Printf(\"Waiting for deployment/%s rollout to complete\", packageServerKey.Name)\n\tif err := c.DoRolloutWait(ctx, packageServerKey); err != nil {\n\t\treturn nil, fmt.Errorf(\"deployment/%s failed to rollout: %v\", packageServerKey.Name, err)\n\t}\n\n\tobjs = toObjects(append(crds, resources...)...)\n\tstatus = c.GetObjectsStatus(ctx, objs...)\n\treturn &status, nil\n}\n\nfunc (c Client) UninstallVersion(ctx context.Context, version string) error {\n\tcrds, resources, err := c.getResources(ctx, version)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to get resources: %v\", err)\n\t}\n\tobjs := toObjects(append(crds, resources...)...)\n\n\tstatus := c.GetObjectsStatus(ctx, objs...)\n\tinstalled, err := status.HasInstalledResources()\n\tif !installed && err == nil {\n\t\treturn olmresourceclient.ErrOLMNotInstalled\n\t}\n\n\tlog.Infof(\"Uninstalling resources for version %q\", version)\n\treturn c.DoDelete(ctx, objs...)\n}\n\nfunc (c Client) GetStatus(ctx context.Context, version string) (*olmresourceclient.Status, error) {\n\tcrds, resources, err := c.getResources(ctx, version)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get resources: %v\", err)\n\t}\n\tobjs := toObjects(append(crds, resources...)...)\n\n\tstatus := c.GetObjectsStatus(ctx, objs...)\n\tinstalled, err := status.HasInstalledResources()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"the OLM installation has resource errors: %v\", err)\n\t} else if !installed {\n\t\treturn nil, olmresourceclient.ErrOLMNotInstalled\n\t}\n\treturn &status, nil\n}\n\nfunc (c Client) getResources(ctx context.Context, version string) ([]unstructured.Unstructured, []unstructured.Unstructured, error) {\n\tlog.Infof(\"Fetching CRDs for version %q\", version)\n\n\tresolvedVersion := formatVersion(version)\n\n\tvar crdResources, olmResources []unstructured.Unstructured\n\tvar err error\n\n\t// If the manifests for the requested version are saved as bindata in SDK, use\n\t// them instead of fetching them from github.\n\tif olmmanifests.HasVersion(version) {\n\t\tlog.Infof(\"Using locally stored resource manifests\")\n\t\tcrdManifestBindataPath := filepath.Join(bindataManifestPath, version+\"-crds.yaml\")\n\t\tcrdResources, err = getPackagedManifests(crdManifestBindataPath)\n\t\tif err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\n\t\tolmManifestBindataPath := filepath.Join(bindataManifestPath, version+\"-olm.yaml\")\n\t\tolmResources, err = getPackagedManifests(olmManifestBindataPath)\n\t\tif err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\t} else {\n\t\tlog.Infof(\"Fetching resources for resolved version %q\", resolvedVersion)\n\t\tcrdResources, err = c.getCRDs(ctx, resolvedVersion)\n\t\tif err != nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"failed to fetch CRDs: %v\", err)\n\t\t}\n\n\t\tolmResources, err = c.getOLM(ctx, resolvedVersion)\n\t\tif err != nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"failed to fetch resources: %v\", err)\n\t\t}\n\t}\n\n\treturn crdResources, olmResources, nil\n}\n\nfunc (c Client) getCRDs(ctx context.Context, version string) ([]unstructured.Unstructured, error) {\n\tresp, err := c.doRequest(ctx, c.crdsURL(version))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"request failed: %v\", err)\n\t}\n\tdefer resp.Body.Close()\n\treturn decodeResources(resp.Body)\n}\n\nfunc (c Client) getOLM(ctx context.Context, version string) ([]unstructured.Unstructured, error) {\n\tresp, err := c.doRequest(ctx, c.olmURL(version))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"request failed: %v\", err)\n\t}\n\tdefer resp.Body.Close()\n\treturn decodeResources(resp.Body)\n}\n\nfunc getPackagedManifests(manifestPath string) ([]unstructured.Unstructured, error) {\n\tdata, err := olmmanifests.Asset(manifestPath)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error retrieving bindata asset: %v\", err)\n\t}\n\n\treader := bytes.NewReader(data)\n\tresources, err := decodeResources(reader)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn resources, nil\n}\n\n// formatVersion returns version if version is not semver, or version prepended with \"v\"\n// if version < 0.17.0 (when OLM changed release tag formats).\nfunc formatVersion(version string) string {\n\tsv, err := semver.ParseTolerant(version)\n\tif err != nil {\n\t\t// Use version as-is, since it might not be semver intentionally.\n\t\treturn version\n\t}\n\tif sv.Major == 0 && sv.Minor < 17 {\n\t\treturn sv.String()\n\t}\n\treturn \"v\" + sv.String()\n}\n\nfunc (c Client) crdsURL(version string) string {\n\treturn fmt.Sprintf(\"%s/crds.yaml\", c.getBaseDownloadURL(version))\n}\n\nfunc (c Client) olmURL(version string) string {\n\treturn fmt.Sprintf(\"%s/olm.yaml\", c.getBaseDownloadURL(version))\n}\n\nfunc (c Client) getBaseDownloadURL(version string) string {\n\tif version == \"latest\" {\n\t\treturn fmt.Sprintf(\"%s/%s/download\", c.BaseDownloadURL, version)\n\t}\n\treturn fmt.Sprintf(\"%s/download/%s\", c.BaseDownloadURL, version)\n}\n\nfunc (c Client) doRequest(ctx context.Context, url string) (*http.Response, error) {\n\treq, err := http.NewRequest(http.MethodGet, url, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"create request: %v\", err)\n\t}\n\treq = req.WithContext(ctx)\n\tresp, err := c.HTTPClient.Do(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed GET '%s': %v\", url, err)\n\t}\n\tif resp.StatusCode != http.StatusOK {\n\t\tdefer resp.Body.Close()\n\t\tbody, err := io.ReadAll(resp.Body)\n\t\tmsg := fmt.Sprintf(\"failed GET '%s': unexpected status code %d, expected %d\", url, resp.StatusCode, http.StatusOK)\n\t\tif resp.StatusCode == 404 {\n\t\t\treturn nil, fmt.Errorf(\"%s; manifests may not exist for this OLM release,\"+\n\t\t\t\t\"please check https://github.com/operator-framework/operator-lifecycle-manager/releases for olm.yaml and crds.yaml\", msg)\n\t\t}\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"%s: %v\", msg, err)\n\t\t}\n\t\treturn nil, fmt.Errorf(\"%s: %s\", msg, string(body))\n\t}\n\treturn resp, nil\n}\n\nfunc toObjects(us ...unstructured.Unstructured) (objs []client.Object) {\n\tfor i := range us {\n\t\tobjs = append(objs, &us[i])\n\t}\n\treturn objs\n}\n\nfunc decodeResources(rds ...io.Reader) (objs []unstructured.Unstructured, err error) {\n\tfor _, r := range rds {\n\t\tdec := yaml.NewYAMLOrJSONDecoder(r, 8)\n\t\tfor {\n\t\t\tvar u unstructured.Unstructured\n\t\t\terr = dec.Decode(&u)\n\t\t\tif err == io.EOF {\n\t\t\t\tbreak\n\t\t\t} else if err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tobjs = append(objs, u)\n\t\t}\n\t}\n\treturn objs, nil\n}\n\nfunc filterResources(resources []unstructured.Unstructured, filter func(unstructured.\n\tUnstructured) bool) (filtered []unstructured.Unstructured) {\n\tfor _, r := range resources {\n\t\tif filter(r) {\n\t\t\tfiltered = append(filtered, r)\n\t\t}\n\t}\n\treturn filtered\n}\n\nfunc (c Client) getSubscriptionCSV(ctx context.Context, subKey types.NamespacedName) (types.NamespacedName, error) {\n\tvar csvKey types.NamespacedName\n\tsubscriptionInstalledCSV := func(pctx context.Context) (bool, error) {\n\t\tsub := olmapiv1alpha1.Subscription{}\n\t\terr := c.KubeClient.Get(pctx, subKey, &sub)\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\t\tinstalledCSV := sub.Status.InstalledCSV\n\t\tif installedCSV == \"\" {\n\t\t\treturn false, nil\n\t\t}\n\t\tcsvKey = types.NamespacedName{\n\t\t\tNamespace: subKey.Namespace,\n\t\t\tName:      installedCSV,\n\t\t}\n\t\tlog.Printf(\"  Found installed CSV %q\", installedCSV)\n\t\treturn true, nil\n\t}\n\treturn csvKey, wait.PollUntilContextCancel(ctx, time.Second, false, subscriptionInstalledCSV)\n}\n"
  },
  {
    "path": "internal/olm/installer/client_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage installer\n\nimport (\n\t\"fmt\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nvar _ = Describe(\"helpers\", func() {\n\tDescribe(\"formatVersion\", func() {\n\t\tconst (\n\t\t\tlatest            = \"latest\"\n\t\t\tzeroSixteen       = \"0.16.0\"\n\t\t\tvZeroSixteen      = \"v\" + zeroSixteen\n\t\t\tzeroSixteenOne    = \"0.16.1\"\n\t\t\tvZeroSixteenOne   = \"v\" + zeroSixteenOne\n\t\t\tzeroSeventeen     = \"0.17.0\"\n\t\t\tvZeroSeventeen    = \"v\" + zeroSeventeen\n\t\t\tzeroSeventeenOne  = \"0.17.1\"\n\t\t\tvZeroSeventeenOne = \"v\" + zeroSeventeenOne\n\t\t\toneTwoThree       = \"1.2.3\"\n\t\t\tvOneTwoThree      = \"v\" + oneTwoThree\n\t\t)\n\n\t\tIt(\"returns a non semantic version as-is\", func() {\n\t\t\tBy(fmt.Sprintf(\"receiving %s\", latest))\n\t\t\tExpect(formatVersion(latest)).To(Equal(latest))\n\t\t})\n\n\t\tIt(\"returns a v-prepended semantic version\", func() {\n\t\t\tBy(fmt.Sprintf(\"receiving %s\", zeroSeventeen))\n\t\t\tExpect(formatVersion(zeroSeventeen)).To(Equal(vZeroSeventeen))\n\n\t\t\tBy(fmt.Sprintf(\"receiving %s\", vZeroSeventeen))\n\t\t\tExpect(formatVersion(vZeroSeventeen)).To(Equal(vZeroSeventeen))\n\n\t\t\tBy(fmt.Sprintf(\"receiving %s\", zeroSeventeenOne))\n\t\t\tExpect(formatVersion(zeroSeventeenOne)).To(Equal(vZeroSeventeenOne))\n\n\t\t\tBy(fmt.Sprintf(\"receiving %s\", vZeroSeventeenOne))\n\t\t\tExpect(formatVersion(vZeroSeventeenOne)).To(Equal(vZeroSeventeenOne))\n\n\t\t\tBy(fmt.Sprintf(\"receiving %s\", oneTwoThree))\n\t\t\tExpect(formatVersion(oneTwoThree)).To(Equal(vOneTwoThree))\n\n\t\t\tBy(fmt.Sprintf(\"receiving %s\", vOneTwoThree))\n\t\t\tExpect(formatVersion(vOneTwoThree)).To(Equal(vOneTwoThree))\n\t\t})\n\n\t\tIt(\"returns a format semantic version\", func() {\n\t\t\tBy(fmt.Sprintf(\"receiving %s\", zeroSixteen))\n\t\t\tExpect(formatVersion(zeroSixteen)).To(Equal(zeroSixteen))\n\n\t\t\tBy(fmt.Sprintf(\"receiving %s\", vZeroSixteen))\n\t\t\tExpect(formatVersion(vZeroSixteen)).To(Equal(zeroSixteen))\n\n\t\t\tBy(fmt.Sprintf(\"receiving %s\", zeroSixteenOne))\n\t\t\tExpect(formatVersion(zeroSixteenOne)).To(Equal(zeroSixteenOne))\n\n\t\t\tBy(fmt.Sprintf(\"receiving %s\", vZeroSixteenOne))\n\t\t\tExpect(formatVersion(vZeroSixteenOne)).To(Equal(zeroSixteenOne))\n\t\t})\n\n\t})\n})\n"
  },
  {
    "path": "internal/olm/installer/installer_suite_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage installer\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nfunc TestRegistry(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"Installer Suite\")\n}\n"
  },
  {
    "path": "internal/olm/installer/manager.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage installer\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"sync\"\n\t\"time\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/pflag\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client/config\"\n)\n\nconst (\n\t// TODO: switch back to latest once olm fixes their releases\n\t// https://github.com/operator-framework/operator-lifecycle-manager/issues/3419\n\tDefaultVersion = \"0.28.0\"\n\tDefaultTimeout = time.Minute * 2\n\t// DefaultOLMNamespace is the namespace where OLM is installed\n\tDefaultOLMNamespace = \"olm\"\n)\n\ntype Manager struct {\n\tClient       *Client\n\tVersion      string\n\tTimeout      time.Duration\n\tOLMNamespace string\n\tonce         sync.Once\n}\n\nfunc (m *Manager) initialize() (err error) {\n\tm.once.Do(func() {\n\t\tif m.Client == nil {\n\t\t\tcfg, cerr := config.GetConfig()\n\t\t\tif cerr != nil {\n\t\t\t\terr = fmt.Errorf(\"failed to get Kubernetes config: %v\", cerr)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tclient, cerr := ClientForConfig(cfg)\n\t\t\tif cerr != nil {\n\t\t\t\terr = fmt.Errorf(\"failed to create manager client: %v\", cerr)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tm.Client = client\n\t\t}\n\t\tif m.Timeout <= 0 {\n\t\t\tm.Timeout = DefaultTimeout\n\t\t}\n\t\tif m.OLMNamespace == \"\" {\n\t\t\tm.OLMNamespace = DefaultOLMNamespace\n\t\t}\n\t})\n\treturn err\n}\n\nfunc (m *Manager) Install() error {\n\tif err := m.initialize(); err != nil {\n\t\treturn err\n\t}\n\n\tctx, cancel := context.WithTimeout(context.Background(), m.Timeout)\n\tdefer cancel()\n\n\tstatus, err := m.Client.InstallVersion(ctx, m.OLMNamespace, m.Version)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tlog.Infof(\"Successfully installed OLM version %q\", m.Version)\n\tfmt.Print(\"\\n\")\n\tfmt.Println(status)\n\treturn nil\n}\n\nfunc (m *Manager) Uninstall() error {\n\tif err := m.initialize(); err != nil {\n\t\treturn err\n\t}\n\n\tctx, cancel := context.WithTimeout(context.Background(), m.Timeout)\n\tdefer cancel()\n\n\tif version, err := m.Client.GetInstalledVersion(ctx, m.OLMNamespace); err != nil {\n\t\tif m.Version == \"\" {\n\t\t\treturn fmt.Errorf(\"error getting installed OLM version (set --version to override the default version): %v\", err)\n\t\t}\n\t} else if m.Version != \"\" {\n\t\tif version != m.Version {\n\t\t\treturn fmt.Errorf(\"mismatched installed version %q vs. supplied version %q\", version, m.Version)\n\t\t}\n\t} else {\n\t\tm.Version = version\n\t}\n\n\tif err := m.Client.UninstallVersion(ctx, m.Version); err != nil {\n\t\treturn err\n\t}\n\n\tlog.Infof(\"Successfully uninstalled OLM version %q\", m.Version)\n\treturn nil\n}\n\nfunc (m *Manager) Status() error {\n\tif err := m.initialize(); err != nil {\n\t\treturn err\n\t}\n\n\tctx, cancel := context.WithTimeout(context.Background(), m.Timeout)\n\tdefer cancel()\n\n\tif version, err := m.Client.GetInstalledVersion(ctx, m.OLMNamespace); err != nil {\n\t\tif m.Version == \"\" {\n\t\t\treturn fmt.Errorf(\"error getting installed OLM version (set --version to override the default version): %v\", err)\n\t\t}\n\t} else if m.Version != \"\" {\n\t\tif version != m.Version {\n\t\t\treturn fmt.Errorf(\"mismatched installed version %q vs. supplied version %q\", version, m.Version)\n\t\t}\n\t} else {\n\t\tm.Version = version\n\t}\n\n\tstatus, err := m.Client.GetStatus(ctx, m.Version)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tlog.Infof(\"Successfully got OLM status for version %q\", m.Version)\n\tfmt.Print(\"\\n\")\n\tfmt.Println(status)\n\treturn nil\n}\n\nfunc (m *Manager) AddToFlagSet(fs *pflag.FlagSet) {\n\tfs.DurationVar(&m.Timeout, \"timeout\", DefaultTimeout, \"time to wait for the command to complete before failing\")\n}\n"
  },
  {
    "path": "internal/olm/operator/bundle/install.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage bundle\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"strings\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/pflag\"\n\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\tdeclarativeconfig \"github.com/operator-framework/operator-registry/alpha/declcfg\"\n\tregistrybundle \"github.com/operator-framework/operator-registry/pkg/lib/bundle\"\n\tfbcutil \"github.com/operator-framework/operator-sdk/internal/olm/fbcutil\"\n\t\"github.com/operator-framework/operator-sdk/internal/olm/operator\"\n\t\"github.com/operator-framework/operator-sdk/internal/olm/operator/registry\"\n)\n\ntype Install struct {\n\tBundleImage string\n\n\t*registry.IndexImageCatalogCreator\n\t*registry.OperatorInstaller\n\n\tcfg *operator.Configuration\n}\n\nfunc NewInstall(cfg *operator.Configuration) Install {\n\ti := Install{\n\t\tOperatorInstaller: registry.NewOperatorInstaller(cfg),\n\t\tcfg:               cfg,\n\t}\n\ti.IndexImageCatalogCreator = registry.NewIndexImageCatalogCreator(cfg)\n\ti.CatalogCreator = i.IndexImageCatalogCreator\n\treturn i\n}\n\nfunc (i *Install) BindFlags(fs *pflag.FlagSet) {\n\tfs.StringVar(&i.IndexImage, \"index-image\", fbcutil.DefaultIndexImage, \"index image in which to inject bundle\")\n\tfs.StringVar(&i.InitImage, \"decompression-image\", fbcutil.DefaultInitImage, \"image used in an init container in \"+\n\t\t\"the registry pod to decompress the compressed catalog contents. cat and gzip binaries are expected to exist \"+\n\t\t\"in the PATH\")\n\tfs.Var(&i.InstallMode, \"install-mode\", \"install mode\")\n\n\t// --mode is hidden so only users who know what they're doing can alter add mode.\n\tfs.StringVar((*string)(&i.BundleAddMode), \"mode\", \"\", \"mode to use for adding bundle to index\")\n\t_ = fs.MarkHidden(\"mode\")\n\n\ti.IndexImageCatalogCreator.BindFlags(fs)\n}\n\nfunc (i Install) Run(ctx context.Context) (*v1alpha1.ClusterServiceVersion, error) {\n\tif err := i.setup(ctx); err != nil {\n\t\treturn nil, err\n\t}\n\treturn i.InstallOperator(ctx)\n}\n\nfunc (i *Install) setup(ctx context.Context) error {\n\t// Validate add mode in case it was set by a user.\n\tif i.BundleAddMode != \"\" {\n\t\tif err := i.BundleAddMode.Validate(); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t//if user sets --skip-tls then set --use-http to true as --skip-tls is deprecated\n\tif i.SkipTLS {\n\t\ti.UseHTTP = true\n\t}\n\n\t// Load bundle labels and set label-dependent values.\n\tlabels, bundle, err := operator.LoadBundle(ctx, i.BundleImage, i.SkipTLSVerify, i.UseHTTP)\n\tif err != nil {\n\t\treturn err\n\t}\n\tcsv := bundle.CSV\n\n\tif err := i.InstallMode.CheckCompatibility(csv, i.cfg.Namespace); err != nil {\n\t\treturn err\n\t}\n\n\t// check if index image adopts File-Based Catalog or SQLite index image format\n\tisFBCImage, err := fbcutil.IsFBC(ctx, i.IndexImage)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error determining whether index %q is FBC or SQLite based: %v\", i.IndexImage, err)\n\t}\n\ti.HasFBCLabel = isFBCImage\n\n\t// set the field to true if FBC label is on the image or for a default index image.\n\tif i.HasFBCLabel {\n\t\tif i.BundleAddMode != \"\" {\n\t\t\treturn fmt.Errorf(\"specifying the bundle add mode is not supported for File-Based Catalog bundles and index images\")\n\t\t}\n\n\t\t// FBC variables\n\t\tf := &fbcutil.FBCContext{\n\t\t\tPackage: labels[registrybundle.PackageLabel],\n\t\t\tRefs:    []string{i.BundleImage},\n\t\t\tChannelEntry: declarativeconfig.ChannelEntry{\n\t\t\t\tName: csv.Name,\n\t\t\t},\n\t\t\tSkipTLSVerify: i.SkipTLSVerify,\n\t\t\tUseHTTP:       i.UseHTTP,\n\t\t}\n\n\t\t// ignore channels for the bundle and instead use the default\n\t\tf.ChannelName = fbcutil.DefaultChannel\n\n\t\t// generate an fbc if an fbc specific label is found on the image or for a default index image.\n\t\tcontent, err := generateFBCContent(ctx, f, i.BundleImage, i.IndexImage)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error generating File-Based Catalog with bundle %q: %v\", i.BundleImage, err)\n\t\t}\n\n\t\ti.FBCContent = content\n\t\ti.Channel = fbcutil.DefaultChannel\n\t} else {\n\t\t// index image is of the SQLite index format.\n\t\tdeprecationMsg := fmt.Sprintf(\"%s is a SQLite index image. SQLite based index images are being deprecated and will be removed in a future release, please migrate your catalogs to the new File-Based Catalog format\", i.IndexImage)\n\t\tlog.Warn(deprecationMsg)\n\n\t\t// set the channel the old way\n\t\ti.Channel = strings.Split(labels[registrybundle.ChannelsLabel], \",\")[0]\n\t}\n\n\ti.OperatorInstaller.PackageName = labels[registrybundle.PackageLabel]\n\ti.CatalogSourceName = operator.CatalogNameForPackage(i.OperatorInstaller.PackageName)\n\ti.StartingCSV = csv.Name\n\ti.SupportedInstallModes = operator.GetSupportedInstallModes(csv.Spec.InstallModes)\n\n\ti.IndexImageCatalogCreator.PackageName = i.OperatorInstaller.PackageName\n\ti.IndexImageCatalogCreator.BundleImage = i.BundleImage\n\n\treturn nil\n}\n\n// generateFBCContent creates a File-Based Catalog using the bundle image and index image from the run bundle command.\nfunc generateFBCContent(ctx context.Context, f *fbcutil.FBCContext, bundleImage, indexImage string) (string, error) {\n\tlog.Infof(\"Creating a File-Based Catalog of the bundle %q\", bundleImage)\n\t// generate a File-Based Catalog representation of the bundle image\n\tbundleDeclcfg, err := f.CreateFBC(ctx)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"error creating a File-Based Catalog with image %q: %v\", bundleImage, err)\n\t}\n\n\tdeclcfg := &declarativeconfig.DeclarativeConfig{\n\t\tBundles:  []declarativeconfig.Bundle{bundleDeclcfg.Bundle},\n\t\tPackages: []declarativeconfig.Package{bundleDeclcfg.Package},\n\t\tChannels: []declarativeconfig.Channel{bundleDeclcfg.Channel},\n\t}\n\n\tif indexImage != fbcutil.DefaultIndexImage { // non-default index image was specified.\n\t\t// since an index image is specified, the bundle image will be added to the index image.\n\t\t// generateExtraFBC will ensure that the bundle is not already present in the index image and error out if it does.\n\t\tdeclcfg, err = generateFBC(ctx, indexImage, bundleDeclcfg, f.SkipTLSVerify, f.UseHTTP)\n\t\tif err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"error adding bundle image %q to index image %q: %v\", bundleImage, indexImage, err)\n\t\t}\n\t}\n\n\t// validate the declarative config and convert it to a string\n\tvar content string\n\tif content, err = fbcutil.ValidateAndStringify(declcfg); err != nil {\n\t\treturn \"\", fmt.Errorf(\"error validating and converting the declarative config object to a string format: %v\", err)\n\t}\n\n\tlog.Infof(\"Generated a valid File-Based Catalog\")\n\n\treturn content, nil\n}\n\n// generateFBC verifies that a bundle is not already present on the index and if not, it renders the bundle contents into a\n// declarative config type.\nfunc generateFBC(ctx context.Context, indexImage string, bundleDeclConfig fbcutil.BundleDeclcfg, skipTLSVerify bool, useHTTP bool) (*declarativeconfig.DeclarativeConfig, error) {\n\tlog.Infof(\"Rendering a File-Based Catalog of the Index Image %q to verify if bundle %q is present\", indexImage, bundleDeclConfig.Bundle.Name)\n\n\timageDeclConfig, err := fbcutil.RenderRefs(ctx, []string{indexImage}, skipTLSVerify, useHTTP)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tfor _, bundle := range imageDeclConfig.Bundles {\n\t\tif bundle.Name == bundleDeclConfig.Bundle.Name && bundle.Package == bundleDeclConfig.Bundle.Package {\n\t\t\treturn nil, fmt.Errorf(\"bundle %q already exists in the index image: %s\", bundleDeclConfig.Bundle.Name, indexImage)\n\t\t}\n\t}\n\n\tfor _, channel := range imageDeclConfig.Channels {\n\t\tif channel.Name == bundleDeclConfig.Channel.Name && channel.Package == bundleDeclConfig.Bundle.Package {\n\t\t\treturn nil, fmt.Errorf(\"channel %q already exists in the index image: %s\", bundleDeclConfig.Channel.Name, indexImage)\n\t\t}\n\t}\n\n\tvar isPackagePresent bool\n\tfor _, pkg := range imageDeclConfig.Packages {\n\t\tif pkg.Name == bundleDeclConfig.Package.Name {\n\t\t\tisPackagePresent = true\n\t\t\tbreak\n\t\t}\n\t}\n\n\textraDeclConfig := &declarativeconfig.DeclarativeConfig{\n\t\tBundles:  append(imageDeclConfig.Bundles, bundleDeclConfig.Bundle),\n\t\tChannels: append(imageDeclConfig.Channels, bundleDeclConfig.Channel),\n\t}\n\n\tif !isPackagePresent {\n\t\textraDeclConfig.Packages = append(imageDeclConfig.Packages, bundleDeclConfig.Package)\n\t}\n\n\tlog.Infof(\"Generated the extra FBC for the bundle image %q\", bundleDeclConfig.Bundle.Name)\n\n\treturn extraDeclConfig, nil\n}\n"
  },
  {
    "path": "internal/olm/operator/bundleupgrade/upgrade.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage bundleupgrade\n\nimport (\n\t\"context\"\n\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\tregistrybundle \"github.com/operator-framework/operator-registry/pkg/lib/bundle\"\n\tfbcutil \"github.com/operator-framework/operator-sdk/internal/olm/fbcutil\"\n\t\"github.com/operator-framework/operator-sdk/internal/olm/operator\"\n\t\"github.com/operator-framework/operator-sdk/internal/olm/operator/registry\"\n\t\"github.com/spf13/pflag\"\n)\n\ntype Upgrade struct {\n\tBundleImage string\n\n\t*registry.IndexImageCatalogCreator\n\t*registry.OperatorInstaller\n\n\tcfg *operator.Configuration\n}\n\nfunc NewUpgrade(cfg *operator.Configuration) Upgrade {\n\tu := Upgrade{\n\t\tOperatorInstaller: registry.NewOperatorInstaller(cfg),\n\t\tcfg:               cfg,\n\t}\n\tu.IndexImageCatalogCreator = registry.NewIndexImageCatalogCreator(cfg)\n\tu.CatalogUpdater = u.IndexImageCatalogCreator\n\treturn u\n}\n\nfunc (u *Upgrade) BindFlags(fs *pflag.FlagSet) {\n\t// --mode is hidden so only users who know what they're doing can alter add mode.\n\tfs.StringVar((*string)(&u.BundleAddMode), \"mode\", \"\", \"mode to use for adding new bundle version to index\")\n\t_ = fs.MarkHidden(\"mode\")\n\n\tu.IndexImageCatalogCreator.BindFlags(fs)\n}\n\nfunc (u Upgrade) Run(ctx context.Context) (*v1alpha1.ClusterServiceVersion, error) {\n\tif err := u.setup(ctx); err != nil {\n\t\treturn nil, err\n\t}\n\treturn u.UpgradeOperator(ctx)\n}\n\nfunc (u *Upgrade) setup(ctx context.Context) error {\n\t// Bundle add mode is defaulted based on in-cluster metadata in u.UpgradeOperator(),\n\t// so validate only if it was set by a user.\n\tif u.BundleAddMode != \"\" {\n\t\tif err := u.BundleAddMode.Validate(); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tlabels, bundle, err := operator.LoadBundle(ctx, u.BundleImage, u.SkipTLSVerify, u.UseHTTP)\n\tif err != nil {\n\t\treturn err\n\t}\n\tcsv := bundle.CSV\n\n\tu.OperatorInstaller.PackageName = labels[registrybundle.PackageLabel]\n\tu.CatalogSourceName = operator.CatalogNameForPackage(u.OperatorInstaller.PackageName)\n\tu.StartingCSV = csv.Name\n\tu.SupportedInstallModes = operator.GetSupportedInstallModes(csv.Spec.InstallModes)\n\n\t// Since an existing CatalogSource will have an annotation containing the existing index image,\n\t// defer defaulting the bundle add mode to after the existing CatalogSource is retrieved.\n\tu.IndexImageCatalogCreator.PackageName = u.OperatorInstaller.PackageName\n\tu.IndexImageCatalogCreator.BundleImage = u.BundleImage\n\tu.IndexImage = fbcutil.DefaultIndexImage\n\n\treturn nil\n}\n"
  },
  {
    "path": "internal/olm/operator/config.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage operator\n\nimport (\n\t\"context\"\n\t\"time\"\n\n\tv1 \"github.com/operator-framework/api/pkg/operators/v1\"\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\t\"github.com/spf13/pflag\"\n\tapiextv1 \"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\t\"k8s.io/client-go/kubernetes/scheme\"\n\t\"k8s.io/client-go/rest\"\n\t\"k8s.io/client-go/tools/clientcmd\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client\"\n)\n\ntype Configuration struct {\n\tNamespace      string\n\tServiceAccount string\n\tKubeconfigPath string\n\tRESTConfig     *rest.Config\n\tClient         client.Client\n\tScheme         *runtime.Scheme\n\tTimeout        time.Duration\n\n\toverrides *clientcmd.ConfigOverrides\n}\n\nfunc (c *Configuration) BindFlags(fs *pflag.FlagSet) {\n\tif c.overrides == nil {\n\t\tc.overrides = &clientcmd.ConfigOverrides{}\n\t}\n\tclientcmd.BindOverrideFlags(c.overrides, fs, clientcmd.ConfigOverrideFlags{\n\t\tContextOverrideFlags: clientcmd.ContextOverrideFlags{\n\t\t\tNamespace: clientcmd.FlagInfo{\n\t\t\t\tLongName:    \"namespace\",\n\t\t\t\tShortName:   \"n\",\n\t\t\t\tDefault:     \"\",\n\t\t\t\tDescription: \"If present, namespace scope for this CLI request\",\n\t\t\t},\n\t\t},\n\t})\n\tfs.StringVar(&c.KubeconfigPath, \"kubeconfig\", \"\",\n\t\t\"Path to the kubeconfig file to use for CLI requests.\")\n\tfs.StringVar(&c.ServiceAccount, \"service-account\", \"\",\n\t\t\"Service account name to bind registry objects to. If unset, the default service account is used. \"+\n\t\t\t\"This value does not override the operator's service account\")\n\tfs.DurationVar(&c.Timeout, \"timeout\", 2*time.Minute,\n\t\t\"Duration to wait for the command to complete before failing\")\n}\n\nfunc (c *Configuration) Load() error {\n\tif c.overrides == nil {\n\t\tc.overrides = &clientcmd.ConfigOverrides{}\n\t}\n\tloadingRules := clientcmd.NewDefaultClientConfigLoadingRules()\n\tloadingRules.ExplicitPath = c.KubeconfigPath\n\tmergedConfig, err := loadingRules.Load()\n\tif err != nil {\n\t\treturn err\n\t}\n\tcfg := clientcmd.NewDefaultClientConfig(*mergedConfig, c.overrides)\n\tcc, err := cfg.ClientConfig()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tns, _, err := cfg.Namespace()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tsch := scheme.Scheme\n\tfor _, f := range []func(*runtime.Scheme) error{\n\t\tv1alpha1.AddToScheme,\n\t\tv1.AddToScheme,\n\t\tapiextv1.AddToScheme,\n\t} {\n\t\tif err := f(sch); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tcl, err := client.New(cc, client.Options{\n\t\tScheme: sch,\n\t})\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tc.Scheme = sch\n\tc.Client = &operatorClient{cl}\n\tif c.Namespace == \"\" {\n\t\tc.Namespace = ns\n\t}\n\tc.RESTConfig = cc\n\n\treturn nil\n}\n\ntype operatorClient struct {\n\tclient.Client\n}\n\nfunc (c *operatorClient) Create(ctx context.Context, obj client.Object, opts ...client.CreateOption) error {\n\topts = append(opts, client.FieldOwner(\"operator-sdk\"))\n\treturn c.Client.Create(ctx, obj, opts...)\n}\n"
  },
  {
    "path": "internal/olm/operator/helpers.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage operator\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\n\tapimanifests \"github.com/operator-framework/api/pkg/manifests\"\n\n\tregistryutil \"github.com/operator-framework/operator-sdk/internal/registry\"\n)\n\nconst (\n\tSDKOperatorGroupName = \"operator-sdk-og\"\n)\n\nfunc CatalogNameForPackage(pkg string) string {\n\treturn fmt.Sprintf(\"%s-catalog\", pkg)\n}\n\n// LoadBundle returns metadata and manifests from within bundleImage.\nfunc LoadBundle(ctx context.Context, bundleImage string, skipTLSVerify bool, useHTTP bool) (registryutil.LabelsMap, *apimanifests.Bundle, error) {\n\tbundlePath, err := registryutil.ExtractBundleImage(ctx, nil, bundleImage, false, skipTLSVerify, useHTTP)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"pull bundle image: %v\", err)\n\t}\n\tdefer func() {\n\t\t_ = os.RemoveAll(bundlePath)\n\t}()\n\n\tlabels, _, err := registryutil.FindBundleMetadata(bundlePath)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"load bundle metadata: %v\", err)\n\t}\n\n\trelManifestsDir, ok := labels.GetManifestsDir()\n\tif !ok {\n\t\treturn nil, nil, fmt.Errorf(\"manifests directory not defined in bundle metadata\")\n\t}\n\tmanifestsDir := filepath.Join(bundlePath, relManifestsDir)\n\tbundle, err := apimanifests.GetBundleFromDir(manifestsDir)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"load bundle: %v\", err)\n\t}\n\n\treturn labels, bundle, nil\n}\n"
  },
  {
    "path": "internal/olm/operator/install_mode.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage operator\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\t\"k8s.io/apimachinery/pkg/util/validation\"\n\t\"k8s.io/utils/set\"\n)\n\ntype InstallMode struct {\n\tInstallModeType  v1alpha1.InstallModeType\n\tTargetNamespaces []string\n}\n\nvar _ flag.Value = &InstallMode{}\n\n// Set is called when the --install-mode flag is passed to the CLI. It will\n// configure the InstallMode based on the values passed in.\nfunc (i *InstallMode) Set(str string) error {\n\tsplit := strings.SplitN(str, \"=\", 2)\n\ti.InstallModeType = v1alpha1.InstallModeType(split[0])\n\tif len(split) == 2 {\n\t\tnamespaces := strings.SplitSeq(split[1], \",\")\n\t\tfor ns := range namespaces {\n\t\t\ti.TargetNamespaces = append(i.TargetNamespaces, strings.TrimSpace(ns))\n\t\t}\n\t\tsort.Strings(i.TargetNamespaces)\n\t} else {\n\t\ti.TargetNamespaces = []string{}\n\t}\n\treturn i.Validate()\n}\n\n// IsEmpty returns true if the InstallModeType is empty.\nfunc (i InstallMode) IsEmpty() bool {\n\treturn i.InstallModeType == \"\"\n}\n\nfunc (i InstallMode) String() string {\n\tswitch i.InstallModeType {\n\tcase v1alpha1.InstallModeTypeSingleNamespace, v1alpha1.InstallModeTypeMultiNamespace:\n\t\treturn fmt.Sprintf(\"%s=%s\", i.InstallModeType, strings.Join(i.TargetNamespaces, \",\"))\n\tdefault:\n\t\treturn string(i.InstallModeType)\n\t}\n}\n\nfunc (InstallMode) Type() string {\n\treturn \"InstallModeValue\"\n}\n\nfunc (i InstallMode) Validate() error {\n\tswitch i.InstallModeType {\n\tcase v1alpha1.InstallModeTypeAllNamespaces, v1alpha1.InstallModeTypeOwnNamespace:\n\t\tif len(i.TargetNamespaces) != 0 {\n\t\t\treturn fmt.Errorf(\"install mode %q must have zero target namespaces\", i.InstallModeType)\n\t\t}\n\tcase v1alpha1.InstallModeTypeSingleNamespace:\n\t\tif len(i.TargetNamespaces) != 1 {\n\t\t\treturn fmt.Errorf(\"install mode %q must have exactly one target namespace\", i.InstallModeType)\n\t\t}\n\tcase v1alpha1.InstallModeTypeMultiNamespace:\n\t\tif len(i.TargetNamespaces) == 0 {\n\t\t\treturn fmt.Errorf(\"install mode %q must have at least one target namespace\", i.InstallModeType)\n\t\t}\n\tcase \"\":\n\t\tif len(i.TargetNamespaces) != 0 {\n\t\t\treturn fmt.Errorf(\"target namespaces defined without type\")\n\t\t}\n\tdefault:\n\t\treturn fmt.Errorf(\"unknown install mode type\")\n\t}\n\tfor _, ns := range i.TargetNamespaces {\n\t\terrs := validation.IsDNS1123Label(ns)\n\t\tif len(errs) > 0 {\n\t\t\treturn fmt.Errorf(\"invalid target namespace %q: %v\", ns, strings.Join(errs, \", \"))\n\t\t}\n\t}\n\treturn nil\n}\n\n// CheckCompatibility checks if an InstallMode is compatible with the operator's namespace and is supported by csv.\nfunc (i InstallMode) CheckCompatibility(csv *v1alpha1.ClusterServiceVersion, operatorNamespace string) error {\n\t// allnamespace was validated in Validate()\n\n\t// own namespace and targetns != opname\n\tif i.InstallModeType == v1alpha1.InstallModeTypeOwnNamespace {\n\t\tif len(i.TargetNamespaces) > 0 && i.TargetNamespaces[0] != operatorNamespace {\n\t\t\treturn fmt.Errorf(\"install mode %s must match operator namespace %q\", i, operatorNamespace)\n\t\t}\n\t}\n\n\t// single namespace and targetns == opname\n\tif i.InstallModeType == v1alpha1.InstallModeTypeSingleNamespace {\n\t\tif len(i.TargetNamespaces) < 1 || i.TargetNamespaces[0] == operatorNamespace {\n\t\t\treturn fmt.Errorf(\"use install mode %q to watch operator's namespace %q\", v1alpha1.InstallModeTypeOwnNamespace, i.TargetNamespaces[0])\n\t\t}\n\t}\n\n\t// ensure the CSV has an installmode\n\tif len(csv.Spec.InstallModes) == 0 {\n\t\treturn fmt.Errorf(\"operator %q is not installable: no supported install modes\", csv.Name)\n\t}\n\n\t// ensure the CSV supports the given installmode\n\tfor _, mode := range csv.Spec.InstallModes {\n\t\tif mode.Type == i.InstallModeType && !mode.Supported {\n\t\t\treturn fmt.Errorf(\"install mode type %q not supported in CSV %q\", i.InstallModeType, csv.GetName())\n\t\t}\n\t}\n\treturn nil\n}\n\n// GetSupportedInstallModes returns the given slice of InstallModes as a\n// String set.\nfunc GetSupportedInstallModes(csvInstallModes []v1alpha1.InstallMode) set.Set[string] {\n\tsupported := set.New[string]()\n\tfor _, im := range csvInstallModes {\n\t\tif im.Supported {\n\t\t\tsupported.Insert(string(im.Type))\n\t\t}\n\t}\n\treturn supported\n}\n"
  },
  {
    "path": "internal/olm/operator/install_mode_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage operator\n\nimport (\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n)\n\nvar _ = Describe(\"InstallMode\", func() {\n\n\tDescribe(\"GetSupportedInstallModes\", func() {\n\t\tIt(\"should return empty set if empty installmodes\", func() {\n\t\t\tsupported := GetSupportedInstallModes([]v1alpha1.InstallMode{})\n\t\t\tExpect(supported.Len()).To(Equal(0))\n\t\t})\n\t\tIt(\"should return empty set if no installmodes are supported\", func() {\n\t\t\tinstallModes := []v1alpha1.InstallMode{\n\t\t\t\t{\n\t\t\t\t\tType:      v1alpha1.InstallModeTypeSingleNamespace,\n\t\t\t\t\tSupported: false,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tType:      v1alpha1.InstallModeTypeOwnNamespace,\n\t\t\t\t\tSupported: false,\n\t\t\t\t},\n\t\t\t}\n\t\t\tsupported := GetSupportedInstallModes(installModes)\n\t\t\tExpect(supported.Len()).To(Equal(0))\n\t\t})\n\t\tIt(\"should return set with supported installmodes\", func() {\n\t\t\tinstallModes := []v1alpha1.InstallMode{\n\t\t\t\t{\n\t\t\t\t\tType:      v1alpha1.InstallModeTypeSingleNamespace,\n\t\t\t\t\tSupported: true,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tType:      v1alpha1.InstallModeTypeOwnNamespace,\n\t\t\t\t\tSupported: true,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tType:      v1alpha1.InstallModeTypeAllNamespaces,\n\t\t\t\t\tSupported: false,\n\t\t\t\t},\n\t\t\t}\n\t\t\tsupported := GetSupportedInstallModes(installModes)\n\t\t\tExpect(supported.Len()).To(Equal(2))\n\t\t\tExpect(supported.Has(string(v1alpha1.InstallModeTypeSingleNamespace))).Should(BeTrue())\n\t\t\tExpect(supported.Has(string(v1alpha1.InstallModeTypeOwnNamespace))).Should(BeTrue())\n\t\t\tExpect(supported.Has(string(v1alpha1.InstallModeTypeAllNamespaces))).Should(BeFalse())\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "internal/olm/operator/operator_suite_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage operator\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nfunc TestOperator(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"Operator Suite\")\n}\n"
  },
  {
    "path": "internal/olm/operator/packagemanifests/install.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage packagemanifests\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\n\tapimanifests \"github.com/operator-framework/api/pkg/manifests\"\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\t\"github.com/spf13/pflag\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/olm/operator\"\n\t\"github.com/operator-framework/operator-sdk/internal/olm/operator/registry\"\n)\n\ntype Install struct {\n\tPackageManifestsDirectory string\n\tVersion                   string\n\n\t*registry.ConfigMapCatalogCreator\n\t*registry.OperatorInstaller\n\n\tcfg *operator.Configuration\n}\n\nfunc NewInstall(cfg *operator.Configuration) Install {\n\ti := Install{\n\t\tConfigMapCatalogCreator: registry.NewConfigMapCatalogCreator(cfg),\n\t\tOperatorInstaller:       registry.NewOperatorInstaller(cfg),\n\t\tcfg:                     cfg,\n\t}\n\ti.CatalogCreator = i.ConfigMapCatalogCreator\n\treturn i\n}\n\nfunc (i *Install) BindFlags(fs *pflag.FlagSet) {\n\tfs.Var(&i.InstallMode, \"install-mode\", \"install mode\")\n\tfs.StringVar(&i.Version, \"version\", \"\", \"Packaged version of the operator to deploy\")\n}\n\nfunc (i Install) Run(ctx context.Context) (*v1alpha1.ClusterServiceVersion, error) {\n\tif err := i.setup(); err != nil {\n\t\treturn nil, err\n\t}\n\treturn i.InstallOperator(ctx)\n}\n\nfunc (i *Install) setup() error {\n\tpkg, bundles, err := loadPackageManifests(i.PackageManifestsDirectory)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"load package manifests: %v\", err)\n\t}\n\tbundle, err := getPackageForVersion(bundles, i.Version)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif err := i.InstallMode.CheckCompatibility(bundle.CSV, i.cfg.Namespace); err != nil {\n\t\treturn err\n\t}\n\n\ti.PackageName = pkg.PackageName\n\ti.CatalogSourceName = operator.CatalogNameForPackage(i.PackageName)\n\ti.StartingCSV = bundle.CSV.GetName()\n\ti.SupportedInstallModes = operator.GetSupportedInstallModes(bundle.CSV.Spec.InstallModes)\n\n\tif i.SupportedInstallModes.Len() == 0 {\n\t\treturn fmt.Errorf(\"operator %q is not installable: no supported install modes\", bundle.CSV.GetName())\n\t}\n\n\ti.Channel, err = getChannelForCSVName(pkg, i.StartingCSV)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\ti.Package = pkg\n\ti.Bundles = bundles\n\n\treturn nil\n}\n\nfunc loadPackageManifests(rootDir string) (*apimanifests.PackageManifest, []*apimanifests.Bundle, error) {\n\t// Operator bundles and metadata.\n\tpkg, bundles, err := apimanifests.GetManifestsDir(rootDir)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tif len(bundles) == 0 {\n\t\treturn nil, nil, errors.New(\"no packages found\")\n\t}\n\tif pkg == nil || pkg.PackageName == \"\" {\n\t\treturn nil, nil, errors.New(\"no package manifest found\")\n\t}\n\treturn pkg, bundles, nil\n}\n\nfunc getPackageForVersion(bundles []*apimanifests.Bundle, version string) (*apimanifests.Bundle, error) {\n\tversions := []string{}\n\tfor _, bundle := range bundles {\n\t\tverStr := bundle.CSV.Spec.Version.String()\n\t\tif verStr == version {\n\t\t\treturn bundle, nil\n\t\t}\n\t\tversions = append(versions, verStr)\n\t}\n\treturn nil, fmt.Errorf(\"no package found for version %s; valid versions: %+q\", version, versions)\n}\n\nfunc getChannelForCSVName(pkg *apimanifests.PackageManifest, csvName string) (string, error) {\n\tfor _, c := range pkg.Channels {\n\t\tif c.CurrentCSVName == csvName {\n\t\t\treturn c.Name, nil\n\t\t}\n\t}\n\treturn \"\", fmt.Errorf(\"no channel in package manifest %s exists for CSV %s\", pkg.PackageName, csvName)\n}\n"
  },
  {
    "path": "internal/olm/operator/registry/catalog.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage registry\n\nimport (\n\t\"context\"\n\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n)\n\ntype CatalogCreator interface {\n\tCreateCatalog(ctx context.Context, name string) (*v1alpha1.CatalogSource, error)\n}\n\ntype CatalogUpdater interface {\n\tUpdateCatalog(ctx context.Context, cs *v1alpha1.CatalogSource, subscription *v1alpha1.Subscription) error\n}\n"
  },
  {
    "path": "internal/olm/operator/registry/configmap/configmap.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage configmap\n\nimport (\n\t\"context\"\n\t\"crypto/sha256\"\n\t\"encoding/base32\"\n\t\"fmt\"\n\t\"strings\"\n\n\tapimanifests \"github.com/operator-framework/api/pkg/manifests\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client\"\n\t\"sigs.k8s.io/yaml\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/util/k8sutil\"\n)\n\n// getRegistryConfigMaps performs a List operation to get all ConfigMaps\n// labelled as belonging to an operator's registry created by operator-sdk.\nfunc (rr *RegistryResources) getRegistryConfigMaps(ctx context.Context, namespace string) ([]corev1.ConfigMap, error) {\n\tlist := corev1.ConfigMapList{}\n\topts := []client.ListOption{\n\t\tclient.MatchingLabels(makeRegistryLabels(rr.Pkg.PackageName)),\n\t\tclient.InNamespace(namespace),\n\t}\n\terr := rr.Client.KubeClient.List(ctx, &list, opts...)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error listing operator %q ConfigMaps: %w\", rr.Pkg.PackageName, err)\n\t}\n\treturn list.Items, nil\n}\n\n// makeConfigMapsForPackageManifests creates a set of ConfigMap binary data\n// for a given PackageManifest and Bundles. Each ConfigMaps's binary data is\n// indexed by the ConfigMap's name.\nfunc makeConfigMapsForPackageManifests(pkg *apimanifests.PackageManifest,\n\tbundles []*apimanifests.Bundle) (map[string]map[string][]byte, error) {\n\n\tvar err error\n\tbinaryDataByConfigMap := make(map[string]map[string][]byte)\n\t// Create a PackageManifest ConfigMap.\n\tcmName := getRegistryConfigMapName(pkg.PackageName) + \"-package\"\n\tbinaryDataByConfigMap[cmName], err = makeObjectBinaryData(pkg)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Create Bundle ConfigMaps.\n\tfor _, bundle := range bundles {\n\t\tversion := bundle.CSV.Spec.Version.String()\n\t\tif version == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"bundle ClusterServiceVersion %s has no version\", bundle.CSV.GetName())\n\t\t}\n\t\t// ConfigMap name containing the bundle's version.\n\t\tcmName := getRegistryConfigMapName(pkg.PackageName) + \"-\" + k8sutil.FormatOperatorNameDNS1123(version)\n\t\tbinaryDataByConfigMap[cmName], err = makeBundleBinaryData(bundle)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\treturn binaryDataByConfigMap, nil\n}\n\n// makeObjectBinaryData creates a ConfigMap's binary data, indexed by a file\n// name key containing names.\nfunc makeObjectBinaryData(obj any, names ...string) (map[string][]byte, error) {\n\tbinaryData := make(map[string][]byte)\n\terr := addObjectToBinaryData(binaryData, obj, names...)\n\treturn binaryData, err\n}\n\n// makeBundleBinaryData creates a ConfigMap's binary data for a Bundle's objects,\n// indexed by a file name key containing each object's name and kind.\nfunc makeBundleBinaryData(bundle *apimanifests.Bundle) (map[string][]byte, error) {\n\tbinaryData := make(map[string][]byte)\n\tfor _, obj := range bundle.Objects {\n\t\terr := addObjectToBinaryData(binaryData, obj, obj.GetName(), obj.GetKind())\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\treturn binaryData, nil\n}\n\n// addObjectToBinaryData adds an object's bytes to binaryData indexed by a\n// file name key containing names.\nfunc addObjectToBinaryData(binaryData map[string][]byte, obj any, names ...string) error {\n\tb, err := yaml.Marshal(obj)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error creating %s binary data: %w\", names, err)\n\t}\n\tbinaryData[makeObjectFileName(b, names...)] = b\n\treturn nil\n}\n\n// makeObjectFileName opaquely creates a unique file name based on data in b\n// and names.\nfunc makeObjectFileName(b []byte, names ...string) string {\n\tfileName := hashContents(b) + \".\"\n\tfor _, name := range names {\n\t\tif name != \"\" {\n\t\t\tfileName += strings.ToLower(name) + \".\"\n\t\t}\n\t}\n\treturn fileName + \"yaml\"\n}\n\n// hashContents creates a sha256 digest of b's bytes.\nfunc hashContents(b []byte) string {\n\th := sha256.New()\n\t_, _ = h.Write(b)\n\tenc := base32.StdEncoding.WithPadding(base32.NoPadding)\n\treturn enc.EncodeToString(h.Sum(nil))\n}\n\nfunc getRegistryConfigMapName(pkgName string) string {\n\tname := k8sutil.FormatOperatorNameDNS1123(pkgName)\n\treturn fmt.Sprintf(\"%s-registry-manifests\", name)\n}\n\n// withBinaryData returns a function that creates entries in the ConfigMap\n// argument's binaryData for each key and []byte value in kvs.\nfunc withBinaryData(kvs map[string][]byte) func(*corev1.ConfigMap) {\n\treturn func(cm *corev1.ConfigMap) {\n\t\tif cm.BinaryData == nil {\n\t\t\tcm.BinaryData = map[string][]byte{}\n\t\t}\n\t\tfor k, v := range kvs {\n\t\t\tcm.BinaryData[k] = v\n\t\t}\n\t}\n}\n\n// newConfigMap creates a new ConfigMap with name in namespace. opts will\n// be applied to the ConfigMap object.\nfunc newConfigMap(name, namespace string, opts ...func(*corev1.ConfigMap)) *corev1.ConfigMap {\n\tcm := &corev1.ConfigMap{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tAPIVersion: corev1.SchemeGroupVersion.String(),\n\t\t\tKind:       \"ConfigMap\",\n\t\t},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      name,\n\t\t\tNamespace: namespace,\n\t\t},\n\t}\n\tfor _, opt := range opts {\n\t\topt(cm)\n\t}\n\treturn cm\n}\n"
  },
  {
    "path": "internal/olm/operator/registry/configmap/configmap_suite_test.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage configmap_test\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nfunc TestConfigmap(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"Configmap Suite\")\n}\n"
  },
  {
    "path": "internal/olm/operator/registry/configmap/configmap_test.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage configmap\n\nimport (\n\t\"context\"\n\t\"crypto/sha256\"\n\t\"encoding/base32\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/blang/semver/v4\"\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\t\"github.com/operator-framework/api/pkg/lib/version\"\n\tapimanifests \"github.com/operator-framework/api/pkg/manifests\"\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\t\"github.com/operator-framework/operator-sdk/internal/olm/client\"\n\t\"github.com/operator-framework/operator-sdk/internal/util/k8sutil\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured\"\n\tclient_cr \"sigs.k8s.io/controller-runtime/pkg/client\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client/fake\"\n\t\"sigs.k8s.io/yaml\"\n)\n\nvar _ = Describe(\"ConfigMap\", func() {\n\n\tDescribe(\"hashContents\", func() {\n\t\tIt(\"should return the hash of the byte array without any error\", func() {\n\t\t\tval := []byte(\"Hello\")\n\t\t\th := sha256.New()\n\t\t\t_, _ = h.Write(val)\n\t\t\tenc := base32.StdEncoding.WithPadding(base32.NoPadding)\n\t\t\tans := enc.EncodeToString(h.Sum(nil))\n\n\t\t\tExpect(hashContents(val)).Should(Equal(ans))\n\t\t})\n\t})\n\n\tDescribe(\"getRegistryConfigMapName\", func() {\n\t\tIt(\"should return the registry configmap name\", func() {\n\t\t\tval := \"Test\"\n\t\t\tname := k8sutil.FormatOperatorNameDNS1123(val)\n\t\t\tans := fmt.Sprintf(\"%s-registry-manifests\", name)\n\n\t\t\tExpect(getRegistryConfigMapName(val)).Should(Equal(ans))\n\t\t})\n\t})\n\n\tDescribe(\"makeObjectFileName\", func() {\n\t\tvar (\n\t\t\tfileName  string\n\t\t\ttestVal   []byte\n\t\t\tuserInput []string\n\t\t)\n\t\tBeforeEach(func() {\n\t\t\ttestVal = []byte(\"test\")\n\t\t\tuserInput = []string{\"userInput\", \"userInput2\"}\n\t\t\tfileName = hashContents(testVal) + \".\"\n\t\t})\n\t\tIt(\"returns the filename with extra user given string\", func() {\n\t\t\tfor _, name := range userInput {\n\t\t\t\tfileName += strings.ToLower(name) + \".\"\n\t\t\t}\n\t\t\tfileName = fileName + \"yaml\"\n\t\t\tExpect(makeObjectFileName(testVal, userInput...)).Should(Equal(fileName))\n\t\t})\n\t\tIt(\"returns the filename without extra user given string\", func() {\n\t\t\tfileName = fileName + \"yaml\"\n\t\t\tExpect(makeObjectFileName(testVal)).Should(Equal(fileName))\n\t\t})\n\t})\n\n\tDescribe(\"addObjectToBinaryData \", func() {\n\t\tIt(\"should add given object to the given binaryData\", func() {\n\t\t\tuserInput := []string{\"userInput\", \"userInput2\"}\n\n\t\t\tb := make(map[string][]byte)\n\t\t\tobj := struct {\n\t\t\t\tval1 string\n\t\t\t\tval2 string\n\t\t\t}{\n\t\t\t\tval1: \"val1\",\n\t\t\t\tval2: \"val2\",\n\t\t\t}\n\n\t\t\tbinaryData := make(map[string][]byte)\n\t\t\texpected, err := yaml.Marshal(obj)\n\t\t\tExpect(err).ShouldNot(HaveOccurred())\n\t\t\tbinaryData[makeObjectFileName(expected, userInput...)] = expected\n\t\t\t// Test and verify function\n\t\t\tExpect(addObjectToBinaryData(b, obj, userInput...)).Should(Succeed())\n\t\t\tExpect(b).Should(Equal(binaryData))\n\t\t})\n\n\t})\n\n\tDescribe(\"makeObjectBinaryData\", func() {\n\t\tIt(\"creates the binary data\", func() {\n\t\t\tbinaryData := make(map[string][]byte)\n\t\t\tobj := struct {\n\t\t\t\tval1 string\n\t\t\t\tval2 string\n\t\t\t}{\n\t\t\t\tval1: \"val1\",\n\t\t\t\tval2: \"val2\",\n\t\t\t}\n\n\t\t\tuserInput := []string{\"userInput\", \"userInput2\"}\n\t\t\tb, e := makeObjectBinaryData(obj, userInput...)\n\t\t\tExpect(e).ShouldNot(HaveOccurred())\n\t\t\t// Test and verify function\n\t\t\tExpect(addObjectToBinaryData(binaryData, obj, userInput...)).Should(Succeed())\n\t\t\tExpect(b).Should(Equal(binaryData))\n\n\t\t})\n\t})\n\n\tDescribe(\"makeBundleBinaryData\", func() {\n\t\tIt(\"should serialize bundle to binary data\", func() {\n\t\t\tb := apimanifests.Bundle{\n\t\t\t\tName: \"testbundle\",\n\t\t\t\tObjects: []*unstructured.Unstructured{\n\t\t\t\t\t{\n\t\t\t\t\t\tObject: map[string]any{\"val1\": \"val1\"},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tObject: map[string]any{\"val2\": \"va2\"},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\n\t\t\tbinaryData, err := makeBundleBinaryData(&b)\n\t\t\tExpect(err).ShouldNot(HaveOccurred())\n\t\t\tval := make(map[string][]byte)\n\t\t\tfor _, obj := range b.Objects {\n\t\t\t\tExpect(addObjectToBinaryData(val, obj, obj.GetName(), obj.GetKind())).Should(Succeed())\n\t\t\t}\n\n\t\t\tExpect(binaryData).Should(Equal(val))\n\t\t})\n\t})\n\n\tDescribe(\"makeConfigMapsForPackageManifests\", func() {\n\t\tvar (\n\t\t\tp apimanifests.PackageManifest\n\t\t\te error\n\t\t\tb []*apimanifests.Bundle\n\t\t)\n\t\tBeforeEach(func() {\n\t\t\tb = []*apimanifests.Bundle{\n\t\t\t\t{\n\t\t\t\t\tName: \"testbundle\",\n\t\t\t\t\tObjects: []*unstructured.Unstructured{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tObject: map[string]any{\"val1\": \"val1\"},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tObject: map[string]any{\"val2\": \"va2\"},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tCSV: &v1alpha1.ClusterServiceVersion{\n\t\t\t\t\t\tSpec: v1alpha1.ClusterServiceVersionSpec{\n\t\t\t\t\t\t\tVersion: version.OperatorVersion{\n\t\t\t\t\t\t\t\tVersion: semver.SpecVersion,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tName: \"testbundle_2\",\n\t\t\t\t\tObjects: []*unstructured.Unstructured{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tObject: map[string]any{\"val1\": \"val1\"},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tObject: map[string]any{\"val2\": \"va2\"},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tCSV: &v1alpha1.ClusterServiceVersion{\n\t\t\t\t\t\tSpec: v1alpha1.ClusterServiceVersionSpec{\n\t\t\t\t\t\t\tVersion: version.OperatorVersion{\n\t\t\t\t\t\t\t\tVersion: semver.SpecVersion,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t\tp = apimanifests.PackageManifest{\n\t\t\t\tPackageName: \"test_package_manifest\",\n\t\t\t\tChannels: []apimanifests.PackageChannel{\n\t\t\t\t\t{Name: \"test_1\",\n\t\t\t\t\t\tCurrentCSVName: \"test_csv_1\",\n\t\t\t\t\t},\n\t\t\t\t\t{Name: \"test_2\",\n\t\t\t\t\t\tCurrentCSVName: \"test_csv_2\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tDefaultChannelName: \"test_channel_name\",\n\t\t\t}\n\t\t})\n\t\tIt(\"should serialize packagemanifest to binary data\", func() {\n\t\t\tbinaryDataByConfigMap, err := makeConfigMapsForPackageManifests(&p, b)\n\t\t\tExpect(err).ShouldNot(HaveOccurred())\n\n\t\t\tval := make(map[string]map[string][]byte)\n\t\t\tcmName := getRegistryConfigMapName(p.PackageName) + \"-package\"\n\t\t\tval[cmName], err = makeObjectBinaryData(p)\n\t\t\tExpect(err).ShouldNot(HaveOccurred())\n\t\t\tfor _, bundle := range b {\n\t\t\t\tversion := bundle.CSV.Spec.Version.String()\n\t\t\t\tcmName := getRegistryConfigMapName(p.PackageName) + \"-\" + k8sutil.FormatOperatorNameDNS1123(version)\n\t\t\t\tval[cmName], e = makeBundleBinaryData(bundle)\n\t\t\t\tExpect(e).ShouldNot(HaveOccurred())\n\t\t\t}\n\n\t\t\tExpect(binaryDataByConfigMap).Should(Equal(val))\n\t\t})\n\n\t})\n\n\tDescribe(\"getRegistryConfigMaps\", func() {\n\t\tvar (\n\t\t\trr   RegistryResources\n\t\t\tlist corev1.ConfigMapList\n\t\t)\n\t\tBeforeEach(func() {\n\t\t\tfakeclient := fake.NewClientBuilder().WithObjects(\n\t\t\t\t&corev1.ConfigMap{\n\t\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\t\tNamespace: \"testns\",\n\t\t\t\t\t\tLabels:    makeRegistryLabels(\"test\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t&corev1.ConfigMap{\n\t\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\t\tNamespace: \"testns2\",\n\t\t\t\t\t\tLabels:    makeRegistryLabels(\"test\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t).Build()\n\t\t\trr = RegistryResources{\n\t\t\t\tClient: &client.Client{\n\t\t\t\t\tKubeClient: fakeclient,\n\t\t\t\t},\n\t\t\t\tPkg: &apimanifests.PackageManifest{\n\t\t\t\t\tPackageName: \"test\",\n\t\t\t\t},\n\t\t\t\tBundles: rr.Bundles,\n\t\t\t}\n\n\t\t\tlist = corev1.ConfigMapList{}\n\t\t})\n\t\tIt(\"performs operations and returns all the configmaps\", func() {\n\t\t\topts := []client_cr.ListOption{\n\t\t\t\tclient_cr.MatchingLabels(makeRegistryLabels(rr.Pkg.PackageName)),\n\t\t\t\tclient_cr.InNamespace(\"testns\"),\n\t\t\t}\n\t\t\tExpect(rr.Client.KubeClient.List(context.TODO(), &list, opts...)).Should(Succeed())\n\t\t\tconfigmaps, err := rr.getRegistryConfigMaps(context.TODO(), \"testns\")\n\t\t\tExpect(err).ShouldNot(HaveOccurred())\n\n\t\t\tExpect(configmaps).Should(Equal(list.Items))\n\t\t})\n\n\t})\n})\n"
  },
  {
    "path": "internal/olm/operator/registry/configmap/deployment.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage configmap\n\nimport (\n\t\"fmt\"\n\n\tappsv1 \"k8s.io/api/apps/v1\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/util/k8sutil\"\n)\n\nconst (\n\t// The image operator-registry's initializer and registry-server binaries are run from.\n\t// This iamge has been pinned to the latest version containing the initializer and registry-server\n\t// binaries, which were deprecated in https://github.com/operator-framework/operator-registry/pull/587.\n\tregistryBaseImage = \"quay.io/operator-framework/upstream-registry-builder:v1.16.0\"\n\t// The port registry-server will listen on within a container.\n\tregistryGRPCPort = 50051\n\t// Path of the bundle database generated by initializer. Use /tmp since it is\n\t// typically world-writable.\n\tregistryDBName = \"/tmp/bundle.db\"\n\t// Path of the log file generated by registry-server. Use /tmp since it is\n\t// typically world-writable.\n\tregistryLogFile = \"/tmp/termination.log\"\n)\n\nfunc getRegistryServerName(pkgName string) string {\n\tname := k8sutil.FormatOperatorNameDNS1123(pkgName)\n\treturn fmt.Sprintf(\"%s-registry-server\", name)\n}\n\n// getRegistryDeploymentLabels creates a set of labels to identify\n// operator-registry Deployment objects.\nfunc getRegistryDeploymentLabels(pkgName string) map[string]string {\n\tlabels := makeRegistryLabels(pkgName)\n\tlabels[\"server-name\"] = getRegistryServerName(pkgName)\n\treturn labels\n}\n\n// applyToDeploymentPodSpec applies f to dep's pod template spec.\nfunc applyToDeploymentPodSpec(dep *appsv1.Deployment, f func(*corev1.PodSpec)) {\n\tf(&dep.Spec.Template.Spec)\n}\n\n// withConfigMapVolume returns a function that appends a volume with name\n// volName containing a reference to a ConfigMap with name cmName to the\n// Deployment argument's pod template spec.\nfunc withConfigMapVolume(volName, cmName string) func(*appsv1.Deployment) {\n\tvolume := corev1.Volume{\n\t\tName: volName,\n\t\tVolumeSource: corev1.VolumeSource{\n\t\t\tConfigMap: &corev1.ConfigMapVolumeSource{\n\t\t\t\tLocalObjectReference: corev1.LocalObjectReference{\n\t\t\t\t\tName: cmName,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\treturn func(dep *appsv1.Deployment) {\n\t\tapplyToDeploymentPodSpec(dep, func(spec *corev1.PodSpec) {\n\t\t\tspec.Volumes = append(spec.Volumes, volume)\n\t\t})\n\t}\n}\n\n// withContainerVolumeMounts returns a function that appends volumeMounts\n// to each container in the Deployment argument's pod template spec. One\n// volumeMount is appended for each path in paths from volume with name\n// volName.\nfunc withContainerVolumeMounts(volName string, paths ...string) func(*appsv1.Deployment) {\n\tvolumeMounts := []corev1.VolumeMount{}\n\tfor _, p := range paths {\n\t\tvolumeMounts = append(volumeMounts, corev1.VolumeMount{\n\t\t\tName:      volName,\n\t\t\tMountPath: p,\n\t\t})\n\t}\n\treturn func(dep *appsv1.Deployment) {\n\t\tapplyToDeploymentPodSpec(dep, func(spec *corev1.PodSpec) {\n\t\t\tfor i := range spec.Containers {\n\t\t\t\tspec.Containers[i].VolumeMounts = append(spec.Containers[i].VolumeMounts, volumeMounts...)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// getDBContainerCmd returns a command string that, when run, does two things:\n//  1. Runs a database initializer on the manifests in the /registry\n//     directory.\n//  2. Runs an operator-registry server serving the bundle database.\nfunc getDBContainerCmd(dbPath, logPath string) string {\n\tinitCmd := fmt.Sprintf(\"/bin/initializer -o %s -m %s\", dbPath, containerManifestsDir)\n\tsrvCmd := fmt.Sprintf(\"/bin/registry-server -d %s -t %s\", dbPath, logPath)\n\treturn fmt.Sprintf(\"%s && exec %s\", initCmd, srvCmd)\n}\n\n// withRegistryGRPCContainer returns a function that appends a container\n// running an operator-registry GRPC server to the Deployment argument's\n// pod template spec.\nfunc withRegistryGRPCContainer(pkgName string) func(*appsv1.Deployment) {\n\tcontainer := corev1.Container{\n\t\tName:       getRegistryServerName(pkgName),\n\t\tImage:      registryBaseImage,\n\t\tWorkingDir: \"/tmp\",\n\t\tCommand:    []string{\"/bin/sh\"},\n\t\tArgs: []string{\n\t\t\t\"-c\",\n\t\t\t// TODO(estroz): grab logs and print if error\n\t\t\tgetDBContainerCmd(registryDBName, registryLogFile),\n\t\t},\n\t\tPorts: []corev1.ContainerPort{\n\t\t\t{Name: \"registry-grpc\", ContainerPort: registryGRPCPort},\n\t\t},\n\t}\n\treturn func(dep *appsv1.Deployment) {\n\t\tapplyToDeploymentPodSpec(dep, func(spec *corev1.PodSpec) {\n\t\t\tspec.Containers = append(spec.Containers, container)\n\t\t})\n\t}\n}\n\n// newRegistryDeployment creates a new Deployment with a name derived from\n// pkgName, the package manifest's packageName, in namespace. The Deployment\n// and replicas are created with labels derived from pkgName. opts will be\n// applied to the Deployment object.\nfunc newRegistryDeployment(pkgName, namespace string, opts ...func(*appsv1.Deployment)) *appsv1.Deployment {\n\tvar replicas int32 = 1\n\tdep := &appsv1.Deployment{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tAPIVersion: appsv1.SchemeGroupVersion.String(),\n\t\t\tKind:       \"Deployment\",\n\t\t},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      getRegistryServerName(pkgName),\n\t\t\tNamespace: namespace,\n\t\t},\n\t\tSpec: appsv1.DeploymentSpec{\n\t\t\tSelector: &metav1.LabelSelector{\n\t\t\t\tMatchLabels: getRegistryDeploymentLabels(pkgName),\n\t\t\t},\n\t\t\tReplicas: &replicas,\n\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\tLabels: getRegistryDeploymentLabels(pkgName),\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\tfor _, opt := range opts {\n\t\topt(dep)\n\t}\n\treturn dep\n}\n"
  },
  {
    "path": "internal/olm/operator/registry/configmap/deployment_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage configmap\n\nimport (\n\t\"fmt\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\tappsv1 \"k8s.io/api/apps/v1\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n)\n\nvar _ = Describe(\"Deployment\", func() {\n\n\tDescribe(\"getRegistryServerName\", func() {\n\t\tIt(\"should return the formatted servername\", func() {\n\t\t\tExpect(getRegistryServerName(\"pkgName\")).Should(Equal(\"pkgname-registry-server\"))\n\t\t\t// This checks if all the special characters are handled correctly\n\t\t\tExpect(getRegistryServerName(\"$abc.foo$@(&#(&!*)@&#\")).Should(Equal(\"abc-foo-registry-server\"))\n\t\t})\n\t})\n\n\tDescribe(\"getRegistryDeploymentLabels\", func() {\n\t\tIt(\"should return the deployment labels for the given package name\", func() {\n\t\t\tlabels := map[string]string{\n\t\t\t\t\"owner\":        \"operator-sdk\",\n\t\t\t\t\"package-name\": \"$abc.foo$@(&#(&!*)@&#\",\n\t\t\t\t\"server-name\":  \"abc-foo-registry-server\",\n\t\t\t}\n\n\t\t\tExpect(getRegistryDeploymentLabels(\"$abc.foo$@(&#(&!*)@&#\")).Should(Equal(labels))\n\t\t})\n\t})\n\n\tDescribe(\"applyToDeploymentPodSpec\", func() {\n\t\tIt(\"should apply f to dep's pod template spec\", func() {\n\t\t\tvar res corev1.PodSpec\n\t\t\tdep := &appsv1.Deployment{\n\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\tReplicas: nil,\n\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\tNodeName: \"testNode\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t\tapplyToDeploymentPodSpec(dep, func(spec *corev1.PodSpec) {\n\t\t\t\tres = *spec\n\t\t\t})\n\n\t\t\tExpect(res.NodeName).Should(Equal(dep.Spec.Template.Spec.NodeName))\n\t\t})\n\t})\n\n\tDescribe(\"withConfigMapVolume\", func() {\n\t\tIt(\"should apply f to dep's pod template spec and apply volumes\", func() {\n\t\t\tdep := &appsv1.Deployment{\n\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\tReplicas: nil,\n\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\tNodeName: \"testNode\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t\texpecteddep := &appsv1.Deployment{\n\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\tReplicas: nil,\n\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\tNodeName: \"testNode2\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t\tvolume := corev1.Volume{\n\t\t\t\tName: \"testVolName\",\n\t\t\t\tVolumeSource: corev1.VolumeSource{\n\t\t\t\t\tConfigMap: &corev1.ConfigMapVolumeSource{\n\t\t\t\t\t\tLocalObjectReference: corev1.LocalObjectReference{\n\t\t\t\t\t\t\tName: \"testCmName\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t\texpecteddep.Spec.Template.Spec.Volumes = append(expecteddep.Spec.Template.Spec.Volumes, volume)\n\t\t\tf := withConfigMapVolume(\"testVolName\", \"testCmName\")\n\t\t\tf(dep)\n\n\t\t\tExpect(dep.Spec.Template.Spec.Volumes).Should(Equal(expecteddep.Spec.Template.Spec.Volumes))\n\t\t})\n\t})\n\n\tDescribe(\"withContainerVolumeMounts\", func() {\n\t\tIt(\"should apply f to dep's pod template spec and apply volumemounts\", func() {\n\t\t\tpaths := []string{\"testPath1\", \"testPath2\"}\n\t\t\tdep := &appsv1.Deployment{\n\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\tReplicas: nil,\n\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\tNodeName: \"testNode\",\n\t\t\t\t\t\t\tContainers: []corev1.Container{\n\t\t\t\t\t\t\t\tcorev1.Container{},\n\t\t\t\t\t\t\t\tcorev1.Container{},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t\texpecteddep := &appsv1.Deployment{\n\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\tReplicas: nil,\n\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\tNodeName: \"testNode2\",\n\t\t\t\t\t\t\tContainers: []corev1.Container{\n\t\t\t\t\t\t\t\tcorev1.Container{},\n\t\t\t\t\t\t\t\tcorev1.Container{},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t\tvolumeMounts := []corev1.VolumeMount{}\n\t\t\tfor _, p := range paths {\n\t\t\t\tvolumeMounts = append(volumeMounts, corev1.VolumeMount{\n\t\t\t\t\tName:      \"testVolName\",\n\t\t\t\t\tMountPath: p,\n\t\t\t\t})\n\t\t\t}\n\t\t\tfor i := range expecteddep.Spec.Template.Spec.Containers {\n\t\t\t\texpecteddep.Spec.Template.Spec.Containers[i].VolumeMounts = append(expecteddep.Spec.Template.Spec.Containers[i].VolumeMounts, volumeMounts...)\n\t\t\t}\n\t\t\tf := withContainerVolumeMounts(\"testVolName\", paths...)\n\t\t\tf(dep)\n\n\t\t\tExpect(dep.Spec.Template.Spec.Containers).Should(Equal(expecteddep.Spec.Template.Spec.Containers))\n\t\t})\n\t})\n\n\tDescribe(\"getDBContainerCmd\", func() {\n\t\tIt(\"should apply f to dep's pod template spec and apply volumes\", func() {\n\t\t\tinitCmd := \"/bin/initializer -o /path/to/database.db -m /registry/manifests\"\n\t\t\tsrvCmd := \"/bin/registry-server -d /path/to/database.db -t /var/log/temp.log\"\n\n\t\t\tExpect(getDBContainerCmd(\"/path/to/database.db\", \"/var/log/temp.log\")).Should(Equal(fmt.Sprintf(\"%s && exec %s\", initCmd, srvCmd)))\n\t\t})\n\t})\n\n\tDescribe(\"withRegistryGRPCContainer\", func() {\n\t\tIt(\"should apply f to dep's pod template spec and append contaiers\", func() {\n\t\t\tcontainer := corev1.Container{\n\t\t\t\tName:       getRegistryServerName(\"testPkg\"),\n\t\t\t\tImage:      registryBaseImage,\n\t\t\t\tWorkingDir: \"/tmp\",\n\t\t\t\tCommand:    []string{\"/bin/sh\"},\n\t\t\t\tArgs: []string{\n\t\t\t\t\t\"-c\",\n\t\t\t\t\tgetDBContainerCmd(registryDBName, registryLogFile),\n\t\t\t\t},\n\t\t\t\tPorts: []corev1.ContainerPort{\n\t\t\t\t\t{Name: \"registry-grpc\", ContainerPort: registryGRPCPort},\n\t\t\t\t},\n\t\t\t}\n\t\t\tdep := &appsv1.Deployment{\n\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\tReplicas: nil,\n\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\tNodeName:   \"testNode\",\n\t\t\t\t\t\t\tContainers: nil,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t\texpecteddep := &appsv1.Deployment{\n\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\tReplicas: nil,\n\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t\t\tNodeName:   \"testNode2\",\n\t\t\t\t\t\t\tContainers: nil,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\n\t\t\texpecteddep.Spec.Template.Spec.Containers = append(expecteddep.Spec.Template.Spec.Containers, container)\n\t\t\tf := withRegistryGRPCContainer(\"testPkg\")\n\t\t\tf(dep)\n\n\t\t\tExpect(dep.Spec.Template.Spec.Containers).Should(Equal(expecteddep.Spec.Template.Spec.Containers))\n\t\t})\n\t})\n\n\tDescribe(\"newRegistryDeployment\", func() {\n\t\tvar (\n\t\t\treplicas int32\n\t\t\tdep      *appsv1.Deployment\n\t\t)\n\t\tBeforeEach(func() {\n\t\t\treplicas = 1\n\t\t\tdep = &appsv1.Deployment{\n\t\t\t\tTypeMeta: metav1.TypeMeta{\n\t\t\t\t\tAPIVersion: appsv1.SchemeGroupVersion.String(),\n\t\t\t\t\tKind:       \"Deployment\",\n\t\t\t\t},\n\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\tName:      getRegistryServerName(\"testPkg\"),\n\t\t\t\t\tNamespace: \"testns\",\n\t\t\t\t},\n\t\t\t\tSpec: appsv1.DeploymentSpec{\n\t\t\t\t\tSelector: &metav1.LabelSelector{\n\t\t\t\t\t\tMatchLabels: getRegistryDeploymentLabels(\"testPkg\"),\n\t\t\t\t\t},\n\t\t\t\t\tReplicas: &replicas,\n\t\t\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\t\t\tLabels: getRegistryDeploymentLabels(\"testPkg\"),\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t})\n\t\tIt(\"should return a dployment\", func() {\n\t\t\tf := withRegistryGRPCContainer(\"testPkg\")\n\t\t\tf(dep)\n\n\t\t\tExpect(dep).Should(Equal(newRegistryDeployment(\"testPkg\", \"testns\", f)))\n\t\t})\n\t\tIt(\"should return a dployment for a custom made function\", func() {\n\t\t\tf := func(d *appsv1.Deployment) {\n\t\t\t\td.Namespace = \"testns2\"\n\t\t\t}\n\t\t\tf(dep)\n\n\t\t\tExpect(dep).Should(Equal(newRegistryDeployment(\"testPkg\", \"testns\", f)))\n\t\t})\n\t\tIt(\"should return a dployment for a multiple functions\", func() {\n\t\t\tf1 := withRegistryGRPCContainer(\"testPkg\")\n\t\t\tf1(dep)\n\n\t\t\tf2 := func(d *appsv1.Deployment) {\n\t\t\t\td.Namespace = \"testns2\"\n\t\t\t}\n\t\t\tf2(dep)\n\n\t\t\tExpect(dep).Should(Equal(newRegistryDeployment(\"testPkg\", \"testns\", f1, f2)))\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "internal/olm/operator/registry/configmap/registry.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage configmap\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"path\"\n\n\tapimanifests \"github.com/operator-framework/api/pkg/manifests\"\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\tlog \"github.com/sirupsen/logrus\"\n\tappsv1 \"k8s.io/api/apps/v1\"\n\tapierrors \"k8s.io/apimachinery/pkg/api/errors\"\n\t\"k8s.io/apimachinery/pkg/types\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client\"\n\t\"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil\"\n\n\tolmclient \"github.com/operator-framework/operator-sdk/internal/olm/client\"\n\t\"github.com/operator-framework/operator-sdk/internal/util/k8sutil\"\n)\n\nconst (\n\t// The root directory containing of a package manifests format for an\n\t// operator, with the package manifest being top-level.\n\tcontainerManifestsDir = \"/registry/manifests\"\n)\n\n// SDKLabels are used to identify certain operator-sdk resources.\nvar SDKLabels = map[string]string{\n\t\"owner\": \"operator-sdk\",\n}\n\n// RegistryResources configures creation/deletion of internal registry-related\n// resources.\ntype RegistryResources struct {\n\tClient  *olmclient.Client\n\tPkg     *apimanifests.PackageManifest\n\tBundles []*apimanifests.Bundle\n}\n\n// IsRegistryExist returns true if a registry Deployment exists in namespace.\nfunc (rr *RegistryResources) IsRegistryExist(ctx context.Context, namespace string) (bool, error) {\n\tdepKey := types.NamespacedName{\n\t\tName:      getRegistryServerName(rr.Pkg.PackageName),\n\t\tNamespace: namespace,\n\t}\n\terr := rr.Client.KubeClient.Get(ctx, depKey, &appsv1.Deployment{})\n\tif err != nil {\n\t\tif apierrors.IsNotFound(err) {\n\t\t\treturn false, nil\n\t\t}\n\t\treturn false, err\n\t}\n\treturn true, nil\n}\n\n// IsRegistryDataStale checks if manifest data stored in the on-cluster\n// registry is stale by comparing it to the currently managed data.\nfunc (rr *RegistryResources) IsRegistryDataStale(ctx context.Context, namespace string) (bool, error) {\n\tconfigMaps, err := rr.getRegistryConfigMaps(ctx, namespace)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\t// Simple length comparison for packages + package manifest ConfigMaps.\n\tif len(configMaps) != len(rr.Bundles)+1 {\n\t\treturn true, nil\n\t}\n\n\tbinaryDataByConfigMap, err := makeConfigMapsForPackageManifests(rr.Pkg, rr.Bundles)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\tfor _, configMap := range configMaps {\n\t\tbinaryData, hasName := binaryDataByConfigMap[configMap.GetName()]\n\t\tif !hasName {\n\t\t\treturn true, nil\n\t\t}\n\t\t// If the number of files to be added to the registry don't match the number\n\t\t// of files currently in the registry, we have added or removed a file.\n\t\tif len(binaryData) != len(configMap.BinaryData) {\n\t\t\treturn true, nil\n\t\t}\n\t\t// Check each binary value's key, which contains a base32-encoded md5 digest\n\t\t// component, against the new set of manifest keys.\n\t\tfor fileKey := range configMap.BinaryData {\n\t\t\tif _, match := binaryData[fileKey]; !match {\n\t\t\t\treturn true, nil\n\t\t\t}\n\t\t\tdelete(binaryData, fileKey)\n\t\t}\n\t\t// Registry is stale if there are new keys not in the existing ConfigMap.\n\t\tif len(binaryData) != 0 {\n\t\t\treturn true, nil\n\t\t}\n\t}\n\treturn false, nil\n}\n\n// CreatePackageManifestsRegistry creates all registry objects required to serve\n// manifests from rr.manifests in namespace.\nfunc (rr *RegistryResources) CreatePackageManifestsRegistry(ctx context.Context, catsrc *v1alpha1.CatalogSource, namespace string) error {\n\tpkgName := rr.Pkg.PackageName\n\tlabels := makeRegistryLabels(pkgName)\n\n\tbinaryDataByConfigMap, err := makeConfigMapsForPackageManifests(rr.Pkg, rr.Bundles)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tcatsrcKey := types.NamespacedName{\n\t\tNamespace: catsrc.Namespace,\n\t\tName:      catsrc.Name,\n\t}\n\tif err := rr.Client.KubeClient.Get(ctx, catsrcKey, catsrc); err != nil {\n\t\treturn fmt.Errorf(\"get catalog source: %v\", err)\n\t}\n\n\t// Objects to create.\n\tobjs := make([]client.Object, 0, len(binaryDataByConfigMap)+2)\n\t// Options for creating a Deployment, since we need to mount all package\n\t// ConfigMaps as volumes into pods.\n\topts := make([]func(*appsv1.Deployment), 0, 2*len(binaryDataByConfigMap)+1)\n\topts = append(opts, withRegistryGRPCContainer(pkgName))\n\t// Build all package ConfigMaps.\n\tfor cmName, binaryData := range binaryDataByConfigMap {\n\t\tcm := newConfigMap(cmName, namespace, withBinaryData(binaryData))\n\t\tcm.SetLabels(labels)\n\t\tif err := controllerutil.SetOwnerReference(catsrc, cm, olmclient.Scheme); err != nil {\n\t\t\treturn fmt.Errorf(\"set configmap %q owner reference: %v\", cm.GetName(), err)\n\t\t}\n\t\tobjs = append(objs, cm)\n\n\t\tvolName := k8sutil.TrimDNS1123Label(cmName + \"-volume\")\n\t\topts = append(opts,\n\t\t\twithConfigMapVolume(volName, cmName),\n\t\t\twithContainerVolumeMounts(volName, path.Join(containerManifestsDir, cmName)),\n\t\t)\n\t}\n\n\t// Add registry Deployment and Service to objects.\n\tdep := newRegistryDeployment(pkgName, namespace, opts...)\n\tdep.SetLabels(labels)\n\tif err := controllerutil.SetOwnerReference(catsrc, dep, olmclient.Scheme); err != nil {\n\t\treturn fmt.Errorf(\"set deployment %q owner reference: %v\", dep.GetName(), err)\n\t}\n\tservice := newRegistryService(pkgName, namespace, withTCPPort(\"grpc\", registryGRPCPort))\n\tservice.SetLabels(labels)\n\tif err := controllerutil.SetOwnerReference(catsrc, service, olmclient.Scheme); err != nil {\n\t\treturn fmt.Errorf(\"set service %q owner reference: %v\", service.GetName(), err)\n\t}\n\tobjs = append(objs, dep, service)\n\n\tif err := rr.Client.DoCreate(ctx, objs...); err != nil {\n\t\treturn fmt.Errorf(\"error creating operator %q registry-server objects: %w\", pkgName, err)\n\t}\n\n\t// Wait for registry Deployment rollout.\n\tdepKey := types.NamespacedName{\n\t\tName:      dep.GetName(),\n\t\tNamespace: namespace,\n\t}\n\tlog.Infof(\"Waiting for Deployment %q rollout to complete\", depKey)\n\tif err := rr.Client.DoRolloutWait(ctx, depKey); err != nil {\n\t\treturn fmt.Errorf(\"error waiting for Deployment %q to roll out: %w\", depKey, err)\n\t}\n\n\treturn nil\n}\n\n// DeletePackageManifestsRegistry deletes all registry objects serving manifests\n// for an operator in namespace.\n// TODO: delete by owner reference.\nfunc (rr *RegistryResources) DeletePackageManifestsRegistry(ctx context.Context, namespace string) error {\n\n\t// List all registry ConfigMaps by label.\n\tconfigMaps, err := rr.getRegistryConfigMaps(ctx, namespace)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Delete registry Deployment, Service, and ConfigMaps by type.\n\tobjs := make([]client.Object, len(configMaps)+2)\n\tfor i := range configMaps {\n\t\tobjs[i] = &configMaps[i]\n\t}\n\tpkgName := rr.Pkg.PackageName\n\tobjs[len(objs)-2] = newRegistryDeployment(pkgName, namespace)\n\tobjs[len(objs)-1] = newRegistryService(pkgName, namespace)\n\terr = rr.Client.DoDelete(ctx, objs...)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error deleting operator %q registry-server objects: %w\", pkgName, err)\n\t}\n\n\treturn nil\n}\n\n// GetRegistryServiceAddr returns a Service's DNS name + port for a given\n// pkgName and namespace.\nfunc GetRegistryServiceAddr(pkgName, namespace string) string {\n\tname := getRegistryServerName(pkgName)\n\treturn fmt.Sprintf(\"%s.%s.svc.cluster.local:%d\", name, namespace, registryGRPCPort)\n}\n\n// makeRegistryLabels creates a set of labels to identify operator-registry objects.\nfunc makeRegistryLabels(pkgName string) map[string]string {\n\tlabels := map[string]string{\n\t\t\"package-name\": k8sutil.TrimDNS1123Label(pkgName),\n\t}\n\tfor k, v := range SDKLabels {\n\t\tlabels[k] = v\n\t}\n\treturn labels\n}\n"
  },
  {
    "path": "internal/olm/operator/registry/configmap/registry_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage configmap\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/blang/semver/v4\"\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\t\"github.com/operator-framework/api/pkg/lib/version\"\n\tapimanifests \"github.com/operator-framework/api/pkg/manifests\"\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\t\"github.com/operator-framework/operator-sdk/internal/olm/client\"\n\t\"github.com/operator-framework/operator-sdk/internal/util/k8sutil\"\n\tappsv1 \"k8s.io/api/apps/v1\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\tapierrors \"k8s.io/apimachinery/pkg/api/errors\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured\"\n\t\"k8s.io/apimachinery/pkg/types\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client/fake\"\n)\n\nvar _ = Describe(\"Registry\", func() {\n\n\tDescribe(\"makeRegistryLabels\", func() {\n\t\tIt(\"should return the registry label\", func() {\n\t\t\tlabels := map[string]string{\n\t\t\t\t\"package-name\": k8sutil.TrimDNS1123Label(\"pkgName\"),\n\t\t\t}\n\t\t\tfor k, v := range SDKLabels {\n\t\t\t\tlabels[k] = v\n\t\t\t}\n\n\t\t\tExpect(makeRegistryLabels(\"pkgName\")).Should(Equal(labels))\n\t\t})\n\t})\n\n\tDescribe(\"GetRegistryServiceAddr\", func() {\n\t\tIt(\"should return a Service's DNS name + port for a given pkgName and namespace\", func() {\n\t\t\tname := fmt.Sprintf(\"%s.%s.svc.cluster.local:%d\", getRegistryServerName(\"pkgName\"), \"testns\", registryGRPCPort)\n\n\t\t\tExpect(GetRegistryServiceAddr(\"pkgName\", \"testns\")).Should(Equal(name))\n\t\t})\n\t})\n\n\tDescribe(\"DeletePackageManifestsRegistry\", func() {\n\t\tIt(\"should delete the package manifest registry\", func() {\n\t\t\tfakeclient := fake.NewClientBuilder().WithObjects(\n\t\t\t\t&corev1.ConfigMap{\n\t\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\t\tNamespace: \"testns\",\n\t\t\t\t\t\tLabels:    makeRegistryLabels(\"test\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tnewRegistryDeployment(\"pkgName\", \"testns\"),\n\t\t\t\tnewRegistryService(\"pkgName\", \"testns\"),\n\t\t\t).Build()\n\t\t\trr := RegistryResources{\n\t\t\t\tPkg: &apimanifests.PackageManifest{\n\t\t\t\t\tPackageName: \"pkgName\",\n\t\t\t\t\tChannels: []apimanifests.PackageChannel{\n\t\t\t\t\t\tapimanifests.PackageChannel{\n\t\t\t\t\t\t\tName: \"pkgChannelTest\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tBundles: []*apimanifests.Bundle{\n\t\t\t\t\t{\n\t\t\t\t\t\tName: \"testbundle\",\n\t\t\t\t\t\tObjects: []*unstructured.Unstructured{\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tObject: map[string]any{\"val1\": \"val1\"},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tObject: map[string]any{\"val2\": \"va2\"},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tCSV: &v1alpha1.ClusterServiceVersion{\n\t\t\t\t\t\t\tSpec: v1alpha1.ClusterServiceVersionSpec{\n\t\t\t\t\t\t\t\tVersion: version.OperatorVersion{\n\t\t\t\t\t\t\t\t\tVersion: semver.SpecVersion,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tClient: &client.Client{\n\t\t\t\t\tKubeClient: fakeclient,\n\t\t\t\t},\n\t\t\t}\n\t\t\tdep := appsv1.Deployment{}\n\t\t\tExpect(\n\t\t\t\trr.Client.KubeClient.Get(context.TODO(), types.NamespacedName{Name: getRegistryServerName(\"pkgName\"), Namespace: \"testns\"}, &dep),\n\t\t\t).Should(Succeed())\n\t\t\tExpect(rr.DeletePackageManifestsRegistry(context.TODO(), \"testns\")).Should(Succeed())\n\n\t\t\terr := rr.Client.KubeClient.Get(context.TODO(), types.NamespacedName{Name: \"pkgName-registry-server\", Namespace: \"testns\"}, &dep)\n\t\t\tExpect(apierrors.IsNotFound(err)).Should(BeTrue())\n\t\t})\n\t})\n\n\tDescribe(\"IsRegistryExist\", func() {\n\t\tvar (\n\t\t\ttestns string\n\t\t\trr     RegistryResources\n\t\t)\n\t\tBeforeEach(func() {\n\t\t\ttestns = \"testns\"\n\t\t\tfakeclient := fake.NewClientBuilder().WithObjects(\n\t\t\t\t&corev1.ConfigMap{\n\t\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\t\tNamespace: testns,\n\t\t\t\t\t\tLabels:    makeRegistryLabels(\"test\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tnewRegistryDeployment(\"pkgName\", testns),\n\t\t\t\tnewRegistryService(\"pkgName\", testns),\n\t\t\t).Build()\n\t\t\trr = RegistryResources{\n\t\t\t\tPkg: &apimanifests.PackageManifest{\n\t\t\t\t\tPackageName: \"pkgName\",\n\t\t\t\t\tChannels: []apimanifests.PackageChannel{\n\t\t\t\t\t\tapimanifests.PackageChannel{\n\t\t\t\t\t\t\tName: \"pkgChannelTest\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tBundles: []*apimanifests.Bundle{\n\t\t\t\t\t{\n\t\t\t\t\t\tName: \"testbundle\",\n\t\t\t\t\t\tObjects: []*unstructured.Unstructured{\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tObject: map[string]any{\"val1\": \"val1\"},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tObject: map[string]any{\"val2\": \"va2\"},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tCSV: &v1alpha1.ClusterServiceVersion{\n\t\t\t\t\t\t\tSpec: v1alpha1.ClusterServiceVersionSpec{\n\t\t\t\t\t\t\t\tVersion: version.OperatorVersion{\n\t\t\t\t\t\t\t\t\tVersion: semver.SpecVersion,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tClient: &client.Client{\n\t\t\t\t\tKubeClient: fakeclient,\n\t\t\t\t},\n\t\t\t}\n\t\t})\n\n\t\tIt(\"should return true if a deployment exitsts in the registry\", func() {\n\t\t\ttemp, err := rr.IsRegistryExist(context.TODO(), testns)\n\t\t\tExpect(err).ShouldNot(HaveOccurred())\n\t\t\tExpect(temp).Should(BeTrue())\n\t\t})\n\n\t\tIt(\"should return false if a deployment does not exitst in the registry\", func() {\n\t\t\tvar (\n\t\t\t\terr  error\n\t\t\t\ttemp bool\n\t\t\t)\n\n\t\t\tExpect(rr.DeletePackageManifestsRegistry(context.TODO(), testns)).Should(Succeed())\n\n\t\t\ttemp, err = rr.IsRegistryExist(context.TODO(), testns)\n\t\t\tExpect(err).ShouldNot(HaveOccurred())\n\t\t\tExpect(temp).Should(BeFalse())\n\t\t})\n\t})\n\n\tDescribe(\"IsRegistryDataStale\", func() {\n\t\tvar (\n\t\t\ttestns string\n\t\t\trr     RegistryResources\n\t\t)\n\t\tBeforeEach(func() {\n\t\t\ttestns = \"testns\"\n\t\t\tfakeclient := fake.NewClientBuilder().WithObjects(\n\t\t\t\t&corev1.ConfigMap{\n\t\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\t\tName:      \"config1\",\n\t\t\t\t\t\tNamespace: testns,\n\t\t\t\t\t\tLabels:    makeRegistryLabels(\"pkgName\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t&corev1.ConfigMap{\n\t\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\t\tName:      \"config2\",\n\t\t\t\t\t\tNamespace: testns,\n\t\t\t\t\t\tLabels:    makeRegistryLabels(\"pkgName\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tnewRegistryDeployment(\"pkgName\", testns),\n\t\t\t\tnewRegistryService(\"pkgName\", testns),\n\t\t\t).Build()\n\t\t\trr = RegistryResources{\n\t\t\t\tPkg: &apimanifests.PackageManifest{\n\t\t\t\t\tPackageName: \"pkgName\",\n\t\t\t\t\tChannels: []apimanifests.PackageChannel{\n\t\t\t\t\t\tapimanifests.PackageChannel{\n\t\t\t\t\t\t\tName: \"pkgChannelTest\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tBundles: []*apimanifests.Bundle{\n\t\t\t\t\t{\n\t\t\t\t\t\tPackage: \"pkgName\",\n\t\t\t\t\t\tName:    \"testbundle\",\n\t\t\t\t\t\tObjects: []*unstructured.Unstructured{\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tObject: map[string]any{\"val1\": \"val1\"},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tObject: map[string]any{\"val2\": \"va2\"},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tCSV: &v1alpha1.ClusterServiceVersion{\n\t\t\t\t\t\t\tSpec: v1alpha1.ClusterServiceVersionSpec{\n\t\t\t\t\t\t\t\tVersion: version.OperatorVersion{\n\t\t\t\t\t\t\t\t\tVersion: semver.SpecVersion,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tClient: &client.Client{\n\t\t\t\t\tKubeClient: fakeclient,\n\t\t\t\t},\n\t\t\t}\n\t\t})\n\n\t\tIt(\"should return true if there are no registry configmaps\", func() {\n\t\t\trr.Client.KubeClient = fake.NewClientBuilder().Build()\n\t\t\ttemp, err := rr.IsRegistryDataStale(context.TODO(), testns)\n\n\t\t\tExpect(err).ShouldNot(HaveOccurred())\n\t\t\tExpect(temp).Should(BeTrue())\n\t\t})\n\n\t\tIt(\"should return true if the configmap does not exist\", func() {\n\t\t\ttemp, err := rr.IsRegistryDataStale(context.TODO(), testns)\n\n\t\t\tExpect(err).ShouldNot(HaveOccurred())\n\t\t\tExpect(temp).Should(BeTrue())\n\t\t})\n\n\t\tIt(\"should return true if the number of files to be added to the registry don't match the numberof files currently in the registry\", func() {\n\t\t\trr.Client.KubeClient = fake.NewClientBuilder().WithObjects(\n\t\t\t\t&corev1.ConfigMap{\n\t\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\t\tName:      getRegistryConfigMapName(\"pkgName\") + \"-package\",\n\t\t\t\t\t\tNamespace: testns,\n\t\t\t\t\t\tLabels:    makeRegistryLabels(\"pkgName\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t&corev1.ConfigMap{\n\t\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\t\tName:      \"config2\",\n\t\t\t\t\t\tNamespace: testns,\n\t\t\t\t\t\tLabels:    makeRegistryLabels(\"pkgName\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tnewRegistryDeployment(\"pkgName\", testns),\n\t\t\t\tnewRegistryService(\"pkgName\", testns),\n\t\t\t).Build()\n\t\t\ttemp, err := rr.IsRegistryDataStale(context.TODO(), testns)\n\n\t\t\tExpect(err).ShouldNot(HaveOccurred())\n\t\t\tExpect(temp).Should(BeTrue())\n\t\t})\n\n\t\tIt(\"should return true if the binary data does not have a filekey\", func() {\n\t\t\tbinarydata, _ := makeObjectBinaryData(struct {\n\t\t\t\tval1 string\n\t\t\t\tval2 string\n\t\t\t}{\n\t\t\t\tval1: \"val1\",\n\t\t\t\tval2: \"val2\",\n\t\t\t}, \"userInput\")\n\t\t\trr.Client.KubeClient = fake.NewClientBuilder().WithObjects(\n\t\t\t\t&corev1.ConfigMap{\n\t\t\t\t\tBinaryData: binarydata,\n\t\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\t\tName:      getRegistryConfigMapName(\"pkgName\") + \"-package\",\n\t\t\t\t\t\tNamespace: testns,\n\t\t\t\t\t\tLabels:    makeRegistryLabels(\"pkgName\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t&corev1.ConfigMap{\n\t\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\t\tName:      \"config2\",\n\t\t\t\t\t\tNamespace: testns,\n\t\t\t\t\t\tLabels:    makeRegistryLabels(\"pkgName\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tnewRegistryDeployment(\"pkgName\", testns),\n\t\t\t\tnewRegistryService(\"pkgName\", testns),\n\t\t\t).Build()\n\t\t\ttemp, err := rr.IsRegistryDataStale(context.TODO(), testns)\n\n\t\t\tExpect(err).ShouldNot(HaveOccurred())\n\t\t\tExpect(temp).Should(BeTrue())\n\t\t})\n\n\t\tIt(\"should return true if it fails in the next iteration\", func() {\n\t\t\tbinarydata, _ := makeObjectBinaryData(&apimanifests.PackageManifest{\n\t\t\t\tPackageName: \"pkgName\",\n\t\t\t\tChannels: []apimanifests.PackageChannel{\n\t\t\t\t\tapimanifests.PackageChannel{\n\t\t\t\t\t\tName: \"pkgChannelTest\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t})\n\t\t\trr.Client.KubeClient = fake.NewClientBuilder().WithObjects(\n\t\t\t\t&corev1.ConfigMap{\n\t\t\t\t\tBinaryData: binarydata,\n\t\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\t\tName:      getRegistryConfigMapName(\"pkgName\") + \"-package\",\n\t\t\t\t\t\tNamespace: testns,\n\t\t\t\t\t\tLabels:    makeRegistryLabels(\"pkgName\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t&corev1.ConfigMap{\n\t\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\t\tName:      getRegistryConfigMapName(\"pkgName2\") + \"-package\",\n\t\t\t\t\t\tNamespace: testns,\n\t\t\t\t\t\tLabels:    makeRegistryLabels(\"pkgName\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tnewRegistryDeployment(\"pkgName\", testns),\n\t\t\t\tnewRegistryService(\"pkgName\", testns),\n\t\t\t).Build()\n\t\t\ttemp, err := rr.IsRegistryDataStale(context.TODO(), testns)\n\n\t\t\tExpect(err).ShouldNot(HaveOccurred())\n\t\t\tExpect(temp).Should(BeTrue())\n\t\t})\n\t})\n\n\t// TODO: Test CreatePackageManifestsRegistry and Test to make IsRegistryDataStale to return false\n\n})\n"
  },
  {
    "path": "internal/olm/operator/registry/configmap/service.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage configmap\n\nimport (\n\tcorev1 \"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/util/intstr\"\n)\n\n// withTCPPort returns a function that appends a service port to a Service's\n// port list with name and TCP port portNum.\nfunc withTCPPort(name string, portNum int32) func(*corev1.Service) {\n\treturn func(service *corev1.Service) {\n\t\tservice.Spec.Ports = append(service.Spec.Ports, corev1.ServicePort{\n\t\t\tName:       name,\n\t\t\tProtocol:   corev1.ProtocolTCP,\n\t\t\tPort:       portNum,\n\t\t\tTargetPort: intstr.FromInt(int(portNum)),\n\t\t})\n\t}\n}\n\n// newRegistryService creates a new Service with a name derived from pkgName\n// the package manifest's packageName, in namespace. The Service is created\n// with labels derived from pkgName. opts will be applied to the Service object.\nfunc newRegistryService(pkgName, namespace string, opts ...func(*corev1.Service)) *corev1.Service {\n\tservice := &corev1.Service{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tAPIVersion: corev1.SchemeGroupVersion.String(),\n\t\t\tKind:       \"Service\",\n\t\t},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      getRegistryServerName(pkgName),\n\t\t\tNamespace: namespace,\n\t\t},\n\t\tSpec: corev1.ServiceSpec{\n\t\t\tSelector: getRegistryDeploymentLabels(pkgName),\n\t\t},\n\t}\n\tfor _, opt := range opts {\n\t\topt(service)\n\t}\n\treturn service\n}\n"
  },
  {
    "path": "internal/olm/operator/registry/configmap/service_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage configmap\n\nimport (\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n)\n\nvar _ = Describe(\"Service\", func() {\n\tDescribe(\"withTCPPort\", func() {\n\t\tIt(\"should append the portnumber in the service\", func() {\n\t\t\tser := &corev1.Service{\n\t\t\t\tSpec: corev1.ServiceSpec{\n\t\t\t\t\tPorts: []corev1.ServicePort{\n\t\t\t\t\t\tcorev1.ServicePort{\n\t\t\t\t\t\t\tName: \"testport\",\n\t\t\t\t\t\t\tPort: 8000,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\n\t\t\tx := withTCPPort(\"testport\", 8080)\n\t\t\tx(ser)\n\t\t\tExpect(ser.Spec.Ports[1].Port).To(Equal(int32(8080)))\n\t\t\tExpect(ser.Spec.Ports[0].Port).To(Equal(int32(8000)))\n\t\t})\n\t})\n\n\tDescribe(\"newRegistryService\", func() {\n\t\tvar (\n\t\t\tres     *corev1.Service\n\t\t\tservice *corev1.Service\n\t\t)\n\t\tBeforeEach(func() {\n\t\t\tservice = &corev1.Service{\n\t\t\t\tTypeMeta: metav1.TypeMeta{\n\t\t\t\t\tAPIVersion: corev1.SchemeGroupVersion.String(),\n\t\t\t\t\tKind:       \"Service\",\n\t\t\t\t},\n\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\tName:      getRegistryServerName(\"pkgName\"),\n\t\t\t\t\tNamespace: \"testns\",\n\t\t\t\t},\n\t\t\t\tSpec: corev1.ServiceSpec{\n\t\t\t\t\tSelector: getRegistryDeploymentLabels(\"pkgName\"),\n\t\t\t\t},\n\t\t\t}\n\t\t})\n\t\tIt(\"should return a service with the specified pkgName\", func() {\n\t\t\tres = newRegistryService(\"pkgName\", \"testns\", withTCPPort(\"testport\", 8080))\n\t\t\tx := withTCPPort(\"testport\", 8080)\n\t\t\tx(service)\n\n\t\t\tExpect(res).Should(Equal(service))\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "internal/olm/operator/registry/configmap.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage registry\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\tapimanifests \"github.com/operator-framework/api/pkg/manifests\"\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\tlog \"github.com/sirupsen/logrus\"\n\tapierrors \"k8s.io/apimachinery/pkg/api/errors\"\n\t\"k8s.io/apimachinery/pkg/types\"\n\t\"k8s.io/client-go/util/retry\"\n\n\tolmclient \"github.com/operator-framework/operator-sdk/internal/olm/client\"\n\t\"github.com/operator-framework/operator-sdk/internal/olm/operator\"\n\t\"github.com/operator-framework/operator-sdk/internal/olm/operator/registry/configmap\"\n)\n\ntype ConfigMapCatalogCreator struct {\n\tPackage *apimanifests.PackageManifest\n\tBundles []*apimanifests.Bundle\n\n\tcfg *operator.Configuration\n}\n\nfunc NewConfigMapCatalogCreator(cfg *operator.Configuration) *ConfigMapCatalogCreator {\n\treturn &ConfigMapCatalogCreator{\n\t\tcfg: cfg,\n\t}\n}\n\nfunc (c ConfigMapCatalogCreator) CreateCatalog(ctx context.Context, name string) (*v1alpha1.CatalogSource, error) {\n\tcs := newCatalogSource(name, c.cfg.Namespace,\n\t\twithSDKPublisher(c.Package.PackageName))\n\tif err := c.cfg.Client.Create(ctx, cs); err != nil {\n\t\treturn nil, fmt.Errorf(\"error creating catalog source: %w\", err)\n\t}\n\n\tif err := c.registryUp(ctx, cs); err != nil {\n\t\treturn nil, fmt.Errorf(\"error creating registry resources: %w\", err)\n\t}\n\n\tif err := c.updateCatalogSource(ctx, cs); err != nil {\n\t\treturn nil, fmt.Errorf(\"error updating catalog source: %w\", err)\n\t}\n\n\treturn cs, nil\n}\n\nfunc (c ConfigMapCatalogCreator) registryUp(ctx context.Context, cs *v1alpha1.CatalogSource) (err error) {\n\trr := configmap.RegistryResources{\n\t\tPkg:     c.Package,\n\t\tBundles: c.Bundles,\n\t\tClient: &olmclient.Client{\n\t\t\tKubeClient: c.cfg.Client,\n\t\t},\n\t}\n\n\tif exists, err := rr.IsRegistryExist(ctx, c.cfg.Namespace); err != nil {\n\t\treturn fmt.Errorf(\"error checking registry existence: %v\", err)\n\t} else if exists {\n\t\tif isRegistryStale, err := rr.IsRegistryDataStale(ctx, c.cfg.Namespace); err == nil {\n\t\t\tif !isRegistryStale {\n\t\t\t\tlog.Infof(\"%s registry data is current\", c.Package.PackageName)\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tlog.Infof(\"A stale %s registry exists, deleting\", c.Package.PackageName)\n\t\t\tif err = rr.DeletePackageManifestsRegistry(ctx, c.cfg.Namespace); err != nil {\n\t\t\t\treturn fmt.Errorf(\"error deleting registered package: %w\", err)\n\t\t\t}\n\t\t} else if !apierrors.IsNotFound(err) {\n\t\t\treturn fmt.Errorf(\"error checking registry data: %w\", err)\n\t\t}\n\t}\n\tlog.Infof(\"Creating %s registry\", c.Package.PackageName)\n\tif err := rr.CreatePackageManifestsRegistry(ctx, cs, c.cfg.Namespace); err != nil {\n\t\treturn fmt.Errorf(\"error registering package: %w\", err)\n\t}\n\n\treturn nil\n}\n\n// updateCatalogSource gets the registry address of the newly created\n// ephemeral packagemanifest index pod and updates the catalog source\n// with the necessary address and source type fields to enable the\n// catalog source to connect to the registry.\nfunc (c *ConfigMapCatalogCreator) updateCatalogSource(ctx context.Context, cs *v1alpha1.CatalogSource) error {\n\tregistryGRPCAddr := configmap.GetRegistryServiceAddr(c.Package.PackageName, c.cfg.Namespace)\n\tcatsrcKey := types.NamespacedName{\n\t\tNamespace: c.cfg.Namespace,\n\t\tName:      cs.GetName(),\n\t}\n\tif err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {\n\t\tif err := c.cfg.Client.Get(ctx, catsrcKey, cs); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tcs.Spec.Address = registryGRPCAddr\n\t\tcs.Spec.SourceType = v1alpha1.SourceTypeGrpc\n\n\t\treturn c.cfg.Client.Update(ctx, cs)\n\t}); err != nil {\n\t\treturn fmt.Errorf(\"error setting grpc address on catalog source: %v\", err)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "internal/olm/operator/registry/configmap_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//\thttp://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\npackage registry\n\nimport (\n\t\"context\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client/fake\"\n\n\tapimanifests \"github.com/operator-framework/api/pkg/manifests\"\n\t\"github.com/operator-framework/operator-sdk/internal/olm/operator\"\n)\n\nvar _ = Describe(\"Configmap\", func() {\n\n\tDescribe(\"NewConfigMapCatalogCreator\", func() {\n\t\tIt(\"should return a configmapcreator instance\", func() {\n\t\t\tcfg := operator.Configuration{\n\t\t\t\tNamespace: \"testns\",\n\t\t\t}\n\n\t\t\tctlog := NewConfigMapCatalogCreator(&cfg)\n\t\t\tExpect(ctlog.cfg.Namespace).Should(Equal(cfg.Namespace))\n\t\t})\n\t})\n\n\tDescribe(\"CreateCatalog\", func() {\n\t\tIt(\"should return an error if creation fails\", func() {\n\t\t\tctlog := &ConfigMapCatalogCreator{\n\t\t\t\tcfg: &operator.Configuration{\n\t\t\t\t\tNamespace: \"testns\",\n\t\t\t\t\tClient: fake.NewClientBuilder().WithObjects(\n\t\t\t\t\t\tnewCatalogSource(\"pkgName\", \"testns\", withSDKPublisher(\"pkgName\")),\n\t\t\t\t\t).Build(),\n\t\t\t\t},\n\t\t\t\tPackage: &apimanifests.PackageManifest{\n\t\t\t\t\tPackageName: \"pkgName\",\n\t\t\t\t},\n\t\t\t}\n\n\t\t\tx, err := ctlog.CreateCatalog(context.TODO(), \"pkgName\")\n\t\t\tExpect(err.Error()).Should(ContainSubstring(\"error creating catalog source\"))\n\t\t\tExpect(x).Should(BeNil())\n\t\t})\n\t})\n\n\tDescribe(\"updateCatalogSource\", func() {\n\t\tIt(\"should update the catalog source\", func() {\n\t\t\tcs := newCatalogSource(\"pkgName\", \"testns\", withSDKPublisher(\"pkgName\"))\n\t\t\tctlog := &ConfigMapCatalogCreator{\n\t\t\t\tcfg: &operator.Configuration{\n\t\t\t\t\tNamespace: \"testns\",\n\t\t\t\t\tClient:    fake.NewClientBuilder().WithObjects(cs).Build(),\n\t\t\t\t},\n\t\t\t\tPackage: &apimanifests.PackageManifest{\n\t\t\t\t\tPackageName: \"pkgName\",\n\t\t\t\t},\n\t\t\t}\n\t\t\texpected := cs.DeepCopy()\n\t\t\tExpect(ctlog.updateCatalogSource(context.TODO(), cs)).Should(Succeed())\n\t\t\tExpect(expected.Spec.Address).ShouldNot(Equal(cs.Spec.Address))\n\t\t\tExpect(expected.Spec.SourceType).ShouldNot(Equal(cs.Spec.SourceType))\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "internal/olm/operator/registry/fbcindex/configMapWriter.go",
    "content": "// Copyright 2023 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage fbcindex\n\nimport (\n\t\"bytes\"\n\t\"compress/gzip\"\n\t\"fmt\"\n\n\tcorev1 \"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n)\n\nconst (\n\tyamlSeparator    = \"\\n---\\n\"\n\tgzipSuffixLength = 13\n\tmaxGZIPLength    = maxConfigMapSize - gzipSuffixLength\n\n\tConfigMapEncodingAnnotationKey  = \"olm.contentEncoding\"\n\tConfigMapEncodingAnnotationGzip = \"gzip+base64\"\n)\n\n/*\nThis file implements the actual building of the CM list. It uses the template method design pattern to implement both\nregular string VM, and compressed binary CM.\n\nThe method itself is FBCRegistryPod.getConfigMaps. This file contains the actual implementation of the writing actions,\nused by the method.\n*/\n\ntype configMapWriter interface {\n\treset()\n\tnewConfigMap(string) *corev1.ConfigMap\n\tgetFilePath() string\n\tisEmpty() bool\n\texceedMaxLength(cmSize int, data string) (bool, error)\n\tcloseCM(cm *corev1.ConfigMap) error\n\taddData(data string) error\n\tcontinueAddData(data string) error\n\twriteLastFragment(cm *corev1.ConfigMap) error\n}\n\ntype gzipCMWriter struct {\n\tactualBuff   *bytes.Buffer\n\thelperBuff   *bytes.Buffer\n\tactualWriter *gzip.Writer\n\thelperWriter *gzip.Writer\n\tcmName       string\n\tnamespace    string\n}\n\nfunc newGZIPWriter(name, namespace string) *gzipCMWriter {\n\tactualBuff := &bytes.Buffer{}\n\thelperBuff := &bytes.Buffer{}\n\n\treturn &gzipCMWriter{\n\t\tactualBuff:   actualBuff,\n\t\thelperBuff:   helperBuff,\n\t\tactualWriter: gzip.NewWriter(actualBuff),\n\t\thelperWriter: gzip.NewWriter(helperBuff),\n\t\tcmName:       name,\n\t\tnamespace:    namespace,\n\t}\n}\n\nfunc (cmw *gzipCMWriter) reset() {\n\tcmw.actualBuff.Reset()\n\tcmw.actualWriter.Reset(cmw.actualBuff)\n\tcmw.helperBuff.Reset()\n\tcmw.helperWriter.Reset(cmw.helperBuff)\n}\n\nfunc (cmw *gzipCMWriter) newConfigMap(name string) *corev1.ConfigMap {\n\treturn &corev1.ConfigMap{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tAPIVersion: corev1.SchemeGroupVersion.String(),\n\t\t\tKind:       \"ConfigMap\",\n\t\t},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tNamespace: cmw.namespace,\n\t\t\tName:      name,\n\t\t\tAnnotations: map[string]string{\n\t\t\t\tConfigMapEncodingAnnotationKey: ConfigMapEncodingAnnotationGzip,\n\t\t\t},\n\t\t},\n\t\tBinaryData: map[string][]byte{},\n\t}\n}\n\nfunc (cmw *gzipCMWriter) getFilePath() string {\n\treturn fmt.Sprintf(\"%s.yaml.gz\", defaultConfigMapKey)\n}\n\nfunc (cmw *gzipCMWriter) isEmpty() bool {\n\treturn cmw.actualBuff.Len() > 0\n}\n\nfunc (cmw *gzipCMWriter) exceedMaxLength(cmSize int, data string) (bool, error) {\n\t_, err := cmw.helperWriter.Write([]byte(data))\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\terr = cmw.helperWriter.Flush()\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\treturn cmSize+cmw.helperBuff.Len() > maxGZIPLength, nil\n}\n\nfunc (cmw *gzipCMWriter) closeCM(cm *corev1.ConfigMap) error {\n\terr := cmw.actualWriter.Close()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\terr = cmw.actualWriter.Flush()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tcm.BinaryData[defaultConfigMapKey] = make([]byte, cmw.actualBuff.Len())\n\tcopy(cm.BinaryData[defaultConfigMapKey], cmw.actualBuff.Bytes())\n\n\tcmw.reset()\n\n\treturn nil\n}\n\nfunc (cmw *gzipCMWriter) addData(data string) error {\n\tdataBytes := []byte(data)\n\t_, err := cmw.helperWriter.Write(dataBytes)\n\tif err != nil {\n\t\treturn err\n\t}\n\t_, err = cmw.actualWriter.Write(dataBytes)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// continueAddData completes adding the data after starting adding it in exceedMaxLength\nfunc (cmw *gzipCMWriter) continueAddData(data string) error {\n\t_, err := cmw.actualWriter.Write([]byte(data))\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\nfunc (cmw *gzipCMWriter) writeLastFragment(cm *corev1.ConfigMap) error {\n\terr := cmw.actualWriter.Close()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tcm.BinaryData[defaultConfigMapKey] = cmw.actualBuff.Bytes()\n\treturn nil\n}\n"
  },
  {
    "path": "internal/olm/operator/registry/fbcindex/fbc_registry_pod.go",
    "content": "// Copyright 2022 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage fbcindex\n\nimport (\n\t\"bufio\"\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"path\"\n\t\"strings\"\n\t\"time\"\n\n\t\"k8s.io/apimachinery/pkg/util/yaml\"\n\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\tlog \"github.com/sirupsen/logrus\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\tapierrors \"k8s.io/apimachinery/pkg/api/errors\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/types\"\n\t\"k8s.io/apimachinery/pkg/util/wait\"\n\t\"k8s.io/client-go/util/retry\"\n\tpointer \"k8s.io/utils/ptr\"\n\t\"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/olm/operator\"\n\t\"github.com/operator-framework/operator-sdk/internal/olm/operator/registry/index\"\n\t\"github.com/operator-framework/operator-sdk/internal/util/k8sutil\"\n)\n\nconst (\n\t// defaultGRPCPort is the default grpc container port that the registry pod exposes\n\tdefaultGRPCPort = 50051\n\n\tdefaultContainerName     = \"registry-grpc\"\n\tdefaultInitContainerName = \"registry-grpc-init\"\n\tdefaultContainerPortName = \"grpc\"\n\n\tdefaultConfigMapKey = \"extraFBC\"\n\n\tmaxConfigMapSize = 1 * 1024 * 1024\n)\n\n// FBCRegistryPod holds resources necessary for creation of a registry pod in FBC scenarios.\ntype FBCRegistryPod struct { //nolint:maligned\n\t// BundleItems contains all bundles to be added to a registry pod.\n\tBundleItems []index.BundleItem\n\n\t// ImagePullPolicy is the image pull policy for the registry pod, default is PullAlways\n\tImagePullPolicy corev1.PullPolicy\n\n\t// Index image contains a database of pointers to operator manifest content that is queriable via an API.\n\t// new version of an operator bundle when published can be added to an index image\n\tIndexImage string\n\n\t// InitImage is the image to be used in the registry init container\n\tInitImage string\n\n\t// GRPCPort is the container grpc port\n\tGRPCPort int32\n\n\t// pod represents a kubernetes *corev1.pod that will be created on a cluster using an index image\n\tpod *corev1.Pod\n\n\t// FBCContent represents the contents of the FBC file (string YAML).\n\tFBCContent string\n\n\t// FBCIndexRootDir is the FBC directory that exists under root of an FBC container image.\n\t// This directory has the File-Based Catalog representation of a catalog index.\n\tFBCIndexRootDir string\n\n\t// SecurityContext defines the security context which will enable the\n\t// SecurityContext on the Pod\n\tSecurityContext string\n\n\tconfigMapName string\n\n\tcmWriter configMapWriter\n\n\tcfg *operator.Configuration\n}\n\n// init initializes the FBCRegistryPod struct.\nfunc (f *FBCRegistryPod) init(cfg *operator.Configuration, cs *v1alpha1.CatalogSource) error {\n\tif f.GRPCPort == 0 {\n\t\tf.GRPCPort = defaultGRPCPort\n\t}\n\n\tif f.FBCIndexRootDir == \"\" {\n\t\tf.FBCIndexRootDir = fmt.Sprintf(\"/%s-configs\", cs.Name)\n\t}\n\n\tif f.configMapName == \"\" {\n\t\tf.configMapName = fmt.Sprintf(\"%s-configmap\", cs.Name)\n\t}\n\n\tf.cfg = cfg\n\n\tf.cmWriter = newGZIPWriter(f.configMapName, cfg.Namespace)\n\n\t// validate the FBCRegistryPod struct and ensure required fields are set\n\tif err := f.validate(); err != nil {\n\t\treturn fmt.Errorf(\"invalid FBC registry pod: %v\", err)\n\t}\n\n\t// podForBundleRegistry() to make the pod definition\n\tpod, err := f.podForBundleRegistry(cs)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error building registry pod definition: %v\", err)\n\t}\n\tf.pod = pod\n\n\treturn nil\n}\n\n// Create creates a bundle registry pod built from an fbc index image,\n// sets the catalog source as the owner for the pod and verifies that\n// the pod is running\nfunc (f *FBCRegistryPod) Create(ctx context.Context, cfg *operator.Configuration, cs *v1alpha1.CatalogSource) (*corev1.Pod, error) {\n\tif err := f.init(cfg, cs); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// make catalog source the owner of registry pod object\n\tif err := controllerutil.SetOwnerReference(cs, f.pod, f.cfg.Scheme); err != nil {\n\t\treturn nil, fmt.Errorf(\"error setting owner reference: %w\", err)\n\t}\n\n\t// Add security context if the user passed in the --security-context-config flag\n\tif f.SecurityContext == \"restricted\" {\n\t\tf.pod.Spec.SecurityContext = &corev1.PodSecurityContext{\n\t\t\tSeccompProfile: &corev1.SeccompProfile{\n\t\t\t\tType: corev1.SeccompProfileTypeRuntimeDefault,\n\t\t\t},\n\t\t}\n\n\t\t// Update the Registry Pod container security context to be restrictive\n\t\tf.pod.Spec.Containers[0].SecurityContext = &corev1.SecurityContext{\n\t\t\tPrivileged:               pointer.To(false),\n\t\t\tReadOnlyRootFilesystem:   pointer.To(false),\n\t\t\tAllowPrivilegeEscalation: pointer.To(false),\n\t\t\tCapabilities: &corev1.Capabilities{\n\t\t\t\tDrop: []corev1.Capability{\"ALL\"},\n\t\t\t},\n\t\t}\n\t}\n\n\tif f.ImagePullPolicy == \"\" {\n\t\tf.ImagePullPolicy = corev1.PullAlways\n\t}\n\tf.pod.Spec.Containers[0].ImagePullPolicy = f.ImagePullPolicy\n\n\tif err := f.cfg.Client.Create(ctx, f.pod); err != nil {\n\t\treturn nil, fmt.Errorf(\"error creating pod: %w\", err)\n\t}\n\n\t// get registry pod key\n\tpodKey := types.NamespacedName{\n\t\tNamespace: f.cfg.Namespace,\n\t\tName:      f.pod.GetName(),\n\t}\n\n\t// poll and verify that pod is running\n\tpodCheck := wait.ConditionWithContextFunc(func(pctx context.Context) (done bool, err error) {\n\t\terr = f.cfg.Client.Get(pctx, podKey, f.pod)\n\t\tif err != nil {\n\t\t\treturn false, fmt.Errorf(\"error getting pod %s: %w\", f.pod.Name, err)\n\t\t}\n\t\treturn f.pod.Status.Phase == corev1.PodRunning, nil\n\t})\n\n\t// check pod status to be `Running`\n\tif err := f.checkPodStatus(ctx, podCheck); err != nil {\n\t\treturn nil, fmt.Errorf(\"registry pod did not become ready: %w\", err)\n\t}\n\tlog.Infof(\"Created registry pod: %s\", f.pod.Name)\n\treturn f.pod, nil\n}\n\n// checkPodStatus polls and verifies that the pod status is running\nfunc (f *FBCRegistryPod) checkPodStatus(ctx context.Context, podCheck wait.ConditionWithContextFunc) error {\n\t// poll every 200 ms until podCheck is true or context is done\n\terr := wait.PollUntilContextCancel(ctx, 200*time.Millisecond, false, podCheck)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error waiting for registry pod %s to run: %v\", f.pod.Name, err)\n\t}\n\n\treturn err\n}\n\n// validate will ensure that RegistryPod required fields are set\n// and throws error if not set\nfunc (f *FBCRegistryPod) validate() error {\n\tif len(f.BundleItems) == 0 {\n\t\treturn errors.New(\"bundle image set cannot be empty\")\n\t}\n\tfor _, item := range f.BundleItems {\n\t\tif item.ImageTag == \"\" {\n\t\t\treturn errors.New(\"bundle image cannot be empty\")\n\t\t}\n\t}\n\n\tif f.IndexImage == \"\" {\n\t\treturn errors.New(\"index image cannot be empty\")\n\t}\n\n\treturn nil\n}\n\nfunc GetRegistryPodHost(ipStr string) string {\n\treturn fmt.Sprintf(\"%s:%d\", ipStr, defaultGRPCPort)\n}\n\n// getPodName will return a string constructed from the bundle Image name\nfunc getPodName(bundleImage string) string {\n\t// todo(rashmigottipati): need to come up with human-readable references\n\t// to be able to handle SHA references in the bundle images\n\treturn k8sutil.TrimDNS1123Label(k8sutil.FormatOperatorNameDNS1123(bundleImage))\n}\n\n// podForBundleRegistry constructs and returns the registry pod definition\n// and throws error when unable to build the pod definition successfully\nfunc (f *FBCRegistryPod) podForBundleRegistry(cs *v1alpha1.CatalogSource) (*corev1.Pod, error) {\n\t// rp was already validated so len(f.BundleItems) must be greater than 0.\n\tbundleImage := f.BundleItems[len(f.BundleItems)-1].ImageTag\n\n\t// construct the container command for pod spec\n\tcontainerCmd := fmt.Sprintf(`opm serve %s -p %d`, f.FBCIndexRootDir, f.GRPCPort) //f.getContainerCmd()\n\n\t// create ConfigMap if it does not exist,\n\t// if it exists, then update it with new content.\n\tcms, err := f.createConfigMaps(cs)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"configMap error: %w\", err)\n\t}\n\n\tvar (\n\t\tvolumes            []corev1.Volume\n\t\tsharedVolumeMounts []corev1.VolumeMount\n\t\tgzipVolumeMount    []corev1.VolumeMount\n\t)\n\n\tfor _, cm := range cms {\n\t\tvolumes = append(volumes, corev1.Volume{\n\t\t\tName: k8sutil.TrimDNS1123Label(cm.Name + \"-volume\"),\n\t\t\tVolumeSource: corev1.VolumeSource{\n\t\t\t\tConfigMap: &corev1.ConfigMapVolumeSource{\n\t\t\t\t\tItems: []corev1.KeyToPath{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tKey:  defaultConfigMapKey,\n\t\t\t\t\t\t\tPath: path.Join(cm.Name, f.cmWriter.getFilePath()),\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tLocalObjectReference: corev1.LocalObjectReference{\n\t\t\t\t\t\tName: cm.Name,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t})\n\n\t\tvolumes = append(volumes, corev1.Volume{\n\t\t\tName: k8sutil.TrimDNS1123Label(cm.Name + \"-unzip\"),\n\t\t\tVolumeSource: corev1.VolumeSource{\n\t\t\t\tEmptyDir: &corev1.EmptyDirVolumeSource{},\n\t\t\t},\n\t\t})\n\n\t\tvm := corev1.VolumeMount{\n\t\t\tName:      k8sutil.TrimDNS1123Label(cm.Name + \"-unzip\"),\n\t\t\tMountPath: path.Join(f.FBCIndexRootDir, cm.Name),\n\t\t\tSubPath:   cm.Name,\n\t\t}\n\n\t\tsharedVolumeMounts = append(sharedVolumeMounts, vm)\n\n\t\tgzipVolumeMount = append(gzipVolumeMount, corev1.VolumeMount{\n\t\t\tName:      k8sutil.TrimDNS1123Label(cm.Name + \"-volume\"),\n\t\t\tMountPath: path.Join(\"/compressed\", f.FBCIndexRootDir, cm.Name),\n\t\t\tSubPath:   cm.Name,\n\t\t})\n\t}\n\n\t// make the pod definition\n\tf.pod = &corev1.Pod{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      getPodName(bundleImage),\n\t\t\tNamespace: f.cfg.Namespace,\n\t\t},\n\t\tSpec: corev1.PodSpec{\n\t\t\t// DO NOT set RunAsUser and RunAsNonRoot, we must leave this empty to allow\n\t\t\t// those that want to use this command against Openshift vendor do not face issues.\n\t\t\t//\n\t\t\t// Why not set RunAsUser?\n\t\t\t// RunAsUser cannot be set because in OpenShift each namespace has a valid range like\n\t\t\t// [1000680000, 1000689999]. Therefore, values like 1001 will not work. Also, in OCP each namespace\n\t\t\t// has a valid range allocate. Therefore, by leaving it empty the OCP will adopt RunAsUser strategy\n\t\t\t// of MustRunAsRange. The PSA will look for the openshift.io/sa.scc.uid-range annotation\n\t\t\t// in the namespace to populate RunAsUser fields when the pod be admitted. Note that\n\t\t\t// is NOT possible to know a valid value that could be accepeted beforehand.\n\t\t\t//\n\t\t\t// Why not set RunAsNonRoot?\n\t\t\t// If we set RunAsNonRoot = true and the image informed does not define the UserID\n\t\t\t// (i.e. in the Dockerfile we have not `USER 11211:11211 `) then, the Pod will fail to run with the\n\t\t\t// error `\"container has runAsNonRoot and image will run as root …` in ANY Kubernetes cluster.\n\t\t\t// (vanilla or OCP). Therefore, by leaving it empty this field will be set by OCP if/when the Pod be\n\t\t\t// qualified for restricted-v2 SCC policy.\n\n\t\t\t// TODO: remove when OpenShift 4.10 and Kubernetes 1.19 be no longer supported\n\t\t\t// Why not set SeccompProfile?\n\t\t\t// This option can only work in OCP versions >= 4.11 and Kubernetes versions >= 19.\n\t\t\t//\n\t\t\t// 2022-09-27 (jesusr): We added a --security-context-config flag to run bundle\n\t\t\t// that will add the following stanza to the pod. This will allow\n\t\t\t// users to selectively enable this stanza. Once this context\n\t\t\t// becomes the default, we should uncomment this code and remove the\n\t\t\t// --security-context-config flag.\n\t\t\t// ---- end of update comment\n\t\t\t//\n\t\t\t// SecurityContext: &corev1.PodSecurityContext{\n\t\t\t//     SeccompProfile: &corev1.SeccompProfile{\n\t\t\t//         Type: corev1.SeccompProfileTypeRuntimeDefault,\n\t\t\t//     },\n\t\t\t// },\n\t\t\tVolumes: volumes,\n\t\t\tContainers: []corev1.Container{\n\t\t\t\t{\n\t\t\t\t\tName:  defaultContainerName,\n\t\t\t\t\tImage: f.IndexImage,\n\t\t\t\t\tCommand: []string{\n\t\t\t\t\t\t\"sh\",\n\t\t\t\t\t\t\"-c\",\n\t\t\t\t\t\tcontainerCmd,\n\t\t\t\t\t},\n\t\t\t\t\tPorts: []corev1.ContainerPort{\n\t\t\t\t\t\t{Name: defaultContainerPortName, ContainerPort: f.GRPCPort},\n\t\t\t\t\t},\n\t\t\t\t\tVolumeMounts: sharedVolumeMounts,\n\t\t\t\t},\n\t\t\t},\n\t\t\tServiceAccountName: f.cfg.ServiceAccount,\n\t\t},\n\t}\n\n\tf.addGZIPInitContainer(sharedVolumeMounts, gzipVolumeMount)\n\n\treturn f.pod, nil\n}\n\nfunc (f *FBCRegistryPod) addGZIPInitContainer(containerVolumeMount []corev1.VolumeMount, gzipVolumeMount []corev1.VolumeMount) {\n\tinitContainerVolumeMount := append(containerVolumeMount, gzipVolumeMount...)\n\tf.pod.Spec.InitContainers = append(f.pod.Spec.InitContainers, corev1.Container{\n\t\tName:  defaultInitContainerName,\n\t\tImage: f.InitImage,\n\t\tCommand: []string{\n\t\t\t\"sh\",\n\t\t\t\"-c\",\n\t\t\tfmt.Sprintf(`for dir in /compressed%s/*configmap-partition*; do `, f.FBCIndexRootDir) +\n\t\t\t\t`for f in ${dir}/*; do ` +\n\t\t\t\t`file=\"${f%.*}\";` +\n\t\t\t\t`file=\"${file#/compressed}\";` +\n\t\t\t\t`cat ${f} | gzip -d -c > \"${file}\";` +\n\t\t\t\t\"done;\" +\n\t\t\t\t\"done;\",\n\t\t},\n\t\tVolumeMounts: initContainerVolumeMount,\n\t})\n}\n\n// createConfigMap creates a ConfigMap if it does not exist and if it does, then update it with new content.\n// Also, sets the owner reference by making CatalogSource the owner of ConfigMap object for cleanup purposes.\nfunc (f *FBCRegistryPod) createConfigMaps(cs *v1alpha1.CatalogSource) ([]*corev1.ConfigMap, error) {\n\t// By default just use the partitioning logic.\n\t// If the entire FBC contents can fit in one ConfigMap it will.\n\tcms, err := f.partitionedConfigMaps()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Loop through all the ConfigMaps and set the OwnerReference and try to create them\n\tfor _, cm := range cms {\n\t\t// set owner reference by making catalog source the owner of ConfigMap object\n\t\tif err := controllerutil.SetOwnerReference(cs, cm, f.cfg.Scheme); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"set configmap %q owner reference: %v\", cm.GetName(), err)\n\t\t}\n\n\t\terr := f.createOrUpdateConfigMap(cm)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\treturn cms, nil\n}\n\n// partitionedConfigMaps will create and return a list of *corev1.ConfigMap\n// that represents all the ConfigMaps that will need to be created to\n// properly have all the FBC contents rendered in the registry pod.\nfunc (f *FBCRegistryPod) partitionedConfigMaps() ([]*corev1.ConfigMap, error) {\n\tvar err error\n\n\tvar yamlDefs []string\n\tyamlReader := yaml.NewYAMLReader(bufio.NewReader(strings.NewReader(f.FBCContent)))\n\tfor {\n\t\tdoc, err := yamlReader.Read()\n\t\tif errors.Is(err, io.EOF) {\n\t\t\tbreak\n\t\t}\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif len(doc) == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tyamlDefs = append(yamlDefs, string(doc))\n\t}\n\n\tconfigMaps, err := f.getConfigMaps(yamlDefs)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn configMaps, nil\n}\n\n// getConfigMaps builds a list of configMaps, to contain the bundle.\nfunc (f *FBCRegistryPod) getConfigMaps(yamlDefs []string) ([]*corev1.ConfigMap, error) {\n\tdefer f.cmWriter.reset()\n\n\tcm := f.cmWriter.newConfigMap(fmt.Sprintf(\"%s-partition-1\", f.configMapName))\n\tconfigMaps := []*corev1.ConfigMap{cm}\n\tcmSize := cm.Size()\n\n\tpartitionCount := 1\n\n\t// for each chunk of yaml see if it can be added to the ConfigMap partition\n\tfor _, yamlDef := range yamlDefs {\n\t\tyamlDef = strings.TrimSpace(yamlDef)\n\t\tif len(yamlDef) == 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\tif f.cmWriter.isEmpty() {\n\t\t\tdata := yamlSeparator + yamlDef\n\t\t\texceeded, err := f.cmWriter.exceedMaxLength(cmSize, data)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tif exceeded {\n\t\t\t\terr = f.cmWriter.closeCM(cm)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\n\t\t\t\tpartitionCount++\n\n\t\t\t\tcm = f.cmWriter.newConfigMap(fmt.Sprintf(\"%s-partition-%d\", f.configMapName, partitionCount))\n\t\t\t\tconfigMaps = append(configMaps, cm)\n\t\t\t\tcmSize = cm.Size()\n\n\t\t\t\terr = f.cmWriter.addData(yamlDef)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\terr = f.cmWriter.continueAddData(data)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\terr := f.cmWriter.addData(yamlDef)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\t}\n\n\t// write the data of the last cm\n\terr := f.cmWriter.writeLastFragment(cm)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn configMaps, nil\n}\n\n// createOrUpdateConfigMap will create a ConfigMap if it doesn't exist or\n// update it if it already exists.\nfunc (f *FBCRegistryPod) createOrUpdateConfigMap(cm *corev1.ConfigMap) error {\n\tcmKey := types.NamespacedName{\n\t\tNamespace: cm.GetNamespace(),\n\t\tName:      cm.GetName(),\n\t}\n\n\t// create a ConfigMap if it does not exist;\n\t// update it with new data if it already exists.\n\tif err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {\n\t\ttempCm := &corev1.ConfigMap{}\n\t\terr := f.cfg.Client.Get(context.TODO(), cmKey, tempCm)\n\t\tif apierrors.IsNotFound(err) {\n\t\t\tif err := f.cfg.Client.Create(context.TODO(), cm); err != nil {\n\t\t\t\treturn fmt.Errorf(\"error creating ConfigMap: %w\", err)\n\t\t\t}\n\t\t\treturn nil\n\t\t}\n\t\t// update ConfigMap with new FBCContent\n\t\ttempCm.Data = cm.Data\n\t\ttempCm.BinaryData = cm.BinaryData\n\t\treturn f.cfg.Client.Update(context.TODO(), tempCm)\n\t}); err != nil {\n\t\treturn fmt.Errorf(\"error updating ConfigMap: %w\", err)\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "internal/olm/operator/registry/fbcindex/fbc_registry_pod_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage fbcindex\n\nimport (\n\t\"bytes\"\n\t\"compress/gzip\"\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"math/rand\"\n\t\"regexp\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\t\"github.com/operator-framework/operator-sdk/internal/olm/operator\"\n\t\"github.com/operator-framework/operator-sdk/internal/olm/operator/registry/index\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\t\"k8s.io/apimachinery/pkg/types\"\n\t\"k8s.io/apimachinery/pkg/util/wait\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client\"\n\tfakeclient \"sigs.k8s.io/controller-runtime/pkg/client/fake\"\n)\n\nconst testIndexImageTag = \"some-image:v1.2.3\"\n\nfunc TestCreateRegistryPod(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"Test Registry Pod Suite\")\n}\n\n// newFakeClient() returns a fake controller runtime client\nfunc newFakeClient() client.Client {\n\treturn fakeclient.NewClientBuilder().Build()\n}\n\nvar _ = Describe(\"FBCRegistryPod\", func() {\n\n\tvar defaultBundleItems = []index.BundleItem{{\n\t\tImageTag: \"quay.io/example/example-operator-bundle:0.2.0\",\n\t\tAddMode:  index.SemverBundleAddMode,\n\t}}\n\n\tDescribe(\"creating registry pod\", func() {\n\t\tvar (\n\t\t\trp  *FBCRegistryPod\n\t\t\tcfg *operator.Configuration\n\t\t\tcs  *v1alpha1.CatalogSource\n\t\t)\n\n\t\tJustBeforeEach(func() {\n\t\t\tcs = &v1alpha1.CatalogSource{\n\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\tName: \"test-catalogsource\",\n\t\t\t\t},\n\t\t\t}\n\n\t\t\tschm := runtime.NewScheme()\n\t\t\tExpect(v1alpha1.AddToScheme(schm)).ShouldNot(HaveOccurred())\n\n\t\t\tcfg = &operator.Configuration{\n\t\t\t\tClient:    newFakeClient(),\n\t\t\t\tNamespace: \"test-default\",\n\t\t\t\tScheme:    schm,\n\t\t\t}\n\t\t\trp = &FBCRegistryPod{\n\t\t\t\tBundleItems: defaultBundleItems,\n\t\t\t\tIndexImage:  testIndexImageTag,\n\t\t\t}\n\t\t\tBy(\"initializing the FBCRegistryPod\")\n\t\t\tExpect(rp.init(cfg, cs)).To(Succeed())\n\t\t})\n\n\t\tContext(\"with valid registry pod values\", func() {\n\n\t\t\tIt(\"should create the FBCRegistryPod successfully\", func() {\n\t\t\t\texpectedPodName := \"quay-io-example-example-operator-bundle-0-2-0\"\n\t\t\t\tExpect(rp).NotTo(BeNil())\n\t\t\t\tExpect(rp.pod.Name).To(Equal(expectedPodName))\n\t\t\t\tExpect(rp.pod.Namespace).To(Equal(rp.cfg.Namespace))\n\t\t\t\tExpect(rp.pod.Spec.Containers[0].Name).To(Equal(defaultContainerName))\n\t\t\t\tExpect(rp.pod.Spec.Containers).Should(HaveLen(1))\n\t\t\t\tExpect(rp.pod.Spec.Containers[0].Ports).Should(HaveLen(1))\n\t\t\t\tExpect(rp.pod.Spec.Containers[0].Ports[0].ContainerPort).To(Equal(rp.GRPCPort))\n\t\t\t\tExpect(rp.pod.Spec.Containers[0].Command).Should(HaveLen(3))\n\t\t\t\tExpect(rp.pod.Spec.Containers[0].Command).Should(ContainElements(\"sh\", \"-c\", containerCommandFor(rp.FBCIndexRootDir, rp.GRPCPort)))\n\t\t\t\tExpect(rp.pod.Spec.InitContainers).Should(HaveLen(1))\n\t\t\t})\n\n\t\t\tIt(\"should create a registry pod when database path is not provided\", func() {\n\t\t\t\tExpect(rp.FBCIndexRootDir).To(Equal(fmt.Sprintf(\"/%s-configs\", cs.Name)))\n\t\t\t})\n\t\t})\n\n\t\tContext(\"with invalid registry pod values\", func() {\n\n\t\t\tIt(\"should error when bundle image is not provided\", func() {\n\t\t\t\texpectedErr := \"bundle image set cannot be empty\"\n\t\t\t\trp := &FBCRegistryPod{}\n\t\t\t\terr := rp.init(cfg, cs)\n\t\t\t\tExpect(err).To(HaveOccurred())\n\t\t\t\tExpect(err.Error()).Should(ContainSubstring(expectedErr))\n\t\t\t})\n\n\t\t\tIt(\"checkPodStatus should return error when pod check is false and context is done\", func() {\n\t\t\t\trp := &FBCRegistryPod{\n\t\t\t\t\tBundleItems: defaultBundleItems,\n\t\t\t\t\tIndexImage:  testIndexImageTag,\n\t\t\t\t}\n\t\t\t\tExpect(rp.init(cfg, cs)).To(Succeed())\n\n\t\t\t\tmockBadPodCheck := wait.ConditionWithContextFunc(func(_ context.Context) (done bool, err error) {\n\t\t\t\t\treturn false, fmt.Errorf(\"error waiting for registry pod\")\n\t\t\t\t})\n\n\t\t\t\texpectedErr := \"error waiting for registry pod\"\n\t\t\t\t// create a new context with a deadline of 1 millisecond\n\t\t\t\tctx, cancel := context.WithTimeout(context.Background(), 1*time.Millisecond)\n\t\t\t\tcancel()\n\n\t\t\t\terr := rp.checkPodStatus(ctx, mockBadPodCheck)\n\t\t\t\tExpect(err).To(HaveOccurred())\n\t\t\t\tExpect(err.Error()).Should(ContainSubstring(expectedErr))\n\t\t\t})\n\t\t})\n\n\t\tContext(\"creating a compressed ConfigMap\", func() {\n\t\t\tIt(\"cmWriter.makeBaseConfigMap() should return a basic ConfigMap manifest\", func() {\n\t\t\t\tcm := rp.cmWriter.newConfigMap(\"test-cm\")\n\t\t\t\tExpect(cm.Name).Should(Equal(\"test-cm\"))\n\t\t\t\tExpect(cm.GetObjectKind().GroupVersionKind()).Should(Equal(corev1.SchemeGroupVersion.WithKind(\"ConfigMap\")))\n\t\t\t\tExpect(cm.GetNamespace()).Should(Equal(cfg.Namespace))\n\t\t\t\tExpect(cm.Data).Should(BeNil())\n\t\t\t\tExpect(cm.BinaryData).ShouldNot(BeNil())\n\t\t\t\tExpect(cm.BinaryData).Should(BeEmpty())\n\t\t\t})\n\n\t\t\tIt(\"partitionedConfigMaps() should return a single compressed ConfigMap\", func() {\n\t\t\t\trp.FBCContent = testYaml\n\t\t\t\texpectedYaml := strings.TrimPrefix(strings.TrimSpace(testYaml), \"---\\n\")\n\n\t\t\t\tcms, err := rp.partitionedConfigMaps()\n\t\t\t\tExpect(err).ShouldNot(HaveOccurred())\n\t\t\t\tExpect(cms).Should(HaveLen(1))\n\t\t\t\tExpect(cms[0].BinaryData).Should(HaveKey(\"extraFBC\"))\n\n\t\t\t\tBy(\"uncompressed the BinaryData\")\n\t\t\t\tuncompressed := decompressCM(cms[0])\n\t\t\t\tExpect(uncompressed).Should(Equal(expectedYaml))\n\t\t\t})\n\n\t\t\tIt(\"partitionedConfigMaps() should return a single compressed ConfigMap for large yaml\", func() {\n\t\t\t\tlargeYaml := strings.Builder{}\n\t\t\t\tfor largeYaml.Len() < maxConfigMapSize {\n\t\t\t\t\tlargeYaml.WriteString(testYaml)\n\t\t\t\t}\n\t\t\t\trp.FBCContent = largeYaml.String()\n\n\t\t\t\texpectedYaml := strings.TrimPrefix(strings.TrimSpace(largeYaml.String()), \"---\\n\")\n\t\t\t\texpectedYaml = regexp.MustCompile(`\\n\\n+`).ReplaceAllString(expectedYaml, \"\\n\")\n\n\t\t\t\tcms, err := rp.partitionedConfigMaps()\n\t\t\t\tExpect(err).ShouldNot(HaveOccurred())\n\t\t\t\tExpect(cms).Should(HaveLen(1))\n\t\t\t\tExpect(cms[0].BinaryData).Should(HaveKey(\"extraFBC\"))\n\n\t\t\t\tactualBinaryData := cms[0].BinaryData[\"extraFBC\"]\n\t\t\t\tExpect(len(actualBinaryData)).Should(BeNumerically(\"<\", maxConfigMapSize))\n\t\t\t\tBy(\"uncompress the BinaryData\")\n\t\t\t\tuncompressed := decompressCM(cms[0])\n\t\t\t\tExpect(uncompressed).Should(Equal(expectedYaml))\n\t\t\t})\n\n\t\t\tIt(\"partitionedConfigMaps() should return a multiple compressed ConfigMaps for a huge yaml\", func() {\n\t\t\t\t// build completely random yamls. This is because gzip relies on duplications, and so repeated text is\n\t\t\t\t// compressed very well, so we'll need a really huge input to create more than one CM. When using random\n\t\t\t\t// input, gzip will create larger output, and we can get to multiple CM with much smaller input.\n\t\t\t\tlargeYamlBuilder := strings.Builder{}\n\t\t\t\tfor largeYamlBuilder.Len() < maxConfigMapSize*2 {\n\t\t\t\t\tlargeYamlBuilder.WriteString(generateRandYaml())\n\t\t\t\t}\n\t\t\t\tlargeYaml := largeYamlBuilder.String()\n\t\t\t\trp.FBCContent = largeYaml\n\n\t\t\t\texpectedYaml := strings.TrimSpace(largeYaml)\n\t\t\t\texpectedYaml = regexp.MustCompile(`\\n\\n+`).ReplaceAllString(expectedYaml, \"\\n\")\n\n\t\t\t\tcms, err := rp.partitionedConfigMaps()\n\t\t\t\tExpect(err).ShouldNot(HaveOccurred())\n\n\t\t\t\tExpect(cms).Should(HaveLen(2))\n\t\t\t\tExpect(cms[0].BinaryData).Should(HaveKey(\"extraFBC\"))\n\t\t\t\tExpect(cms[1].BinaryData).Should(HaveKey(\"extraFBC\"))\n\t\t\t\tdecompressed1 := decompressCM(cms[1])\n\t\t\t\tdecompressed0 := decompressCM(cms[0])\n\t\t\t\tExpect(decompressed0 + \"\\n---\\n\" + decompressed1).Should(Equal(expectedYaml))\n\t\t\t})\n\n\t\t\tIt(\"createOrUpdateConfigMap() should create the compressed ConfigMap if it does not exist\", func() {\n\t\t\t\tcm := rp.cmWriter.newConfigMap(\"test-cm\")\n\t\t\t\tcm.BinaryData[\"test\"] = compress(\"hello test world!\")\n\n\t\t\t\tExpect(rp.createOrUpdateConfigMap(cm)).Should(Succeed())\n\n\t\t\t\ttestCm := &corev1.ConfigMap{}\n\t\t\t\tExpect(rp.cfg.Client.Get(context.TODO(), types.NamespacedName{Namespace: rp.cfg.Namespace, Name: cm.GetName()}, testCm)).Should(Succeed())\n\t\t\t\tExpect(testCm).Should(BeEquivalentTo(cm))\n\t\t\t})\n\n\t\t\tIt(\"createOrUpdateConfigMap() should update the compressed ConfigMap if it already exists\", func() {\n\t\t\t\tcm := rp.cmWriter.newConfigMap(\"test-cm\")\n\t\t\t\tcm.BinaryData[\"test\"] = compress(\"hello test world!\")\n\t\t\t\tExpect(rp.cfg.Client.Create(context.TODO(), cm)).Should(Succeed())\n\t\t\t\tcm.BinaryData[\"test\"] = compress(\"hello changed world!\")\n\t\t\t\tcm.SetResourceVersion(\"2\")\n\n\t\t\t\tExpect(rp.createOrUpdateConfigMap(cm)).Should(Succeed())\n\n\t\t\t\ttestCm := &corev1.ConfigMap{}\n\t\t\t\tExpect(rp.cfg.Client.Get(context.TODO(), types.NamespacedName{Namespace: rp.cfg.Namespace, Name: cm.GetName()}, testCm)).Should(Succeed())\n\t\t\t\tExpect(testCm).Should(BeEquivalentTo(cm))\n\t\t\t})\n\n\t\t\tIt(\"createOrUpdateConfigMap() should update the uncompressed-old ConfigMap if it already exists\", func() {\n\t\t\t\torigCM := &corev1.ConfigMap{\n\t\t\t\t\tTypeMeta: metav1.TypeMeta{\n\t\t\t\t\t\tAPIVersion: corev1.SchemeGroupVersion.String(),\n\t\t\t\t\t\tKind:       \"ConfigMap\",\n\t\t\t\t\t},\n\t\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\t\tNamespace: rp.cfg.Namespace,\n\t\t\t\t\t\tName:      \"test-cm\",\n\t\t\t\t\t},\n\t\t\t\t\tData: map[string]string{\"test\": \"hello test world!\"},\n\t\t\t\t}\n\n\t\t\t\tExpect(rp.cfg.Client.Create(context.TODO(), origCM)).Should(Succeed())\n\t\t\t\tcm := rp.cmWriter.newConfigMap(\"test-cm\")\n\t\t\t\tcm.BinaryData[\"test\"] = compress(\"hello changed world!\")\n\t\t\t\tcm.SetResourceVersion(\"2\")\n\n\t\t\t\tExpect(rp.createOrUpdateConfigMap(cm)).Should(Succeed())\n\n\t\t\t\ttestCm := &corev1.ConfigMap{}\n\t\t\t\tExpect(rp.cfg.Client.Get(context.TODO(), types.NamespacedName{Namespace: rp.cfg.Namespace, Name: cm.GetName()}, testCm)).Should(Succeed())\n\t\t\t\tExpect(cm.Data).Should(BeNil())\n\t\t\t\tExpect(testCm.BinaryData).Should(BeEquivalentTo(cm.BinaryData))\n\t\t\t})\n\n\t\t\tIt(\"createConfigMaps() should create a single compressed ConfigMap\", func() {\n\t\t\t\trp.FBCContent = testYaml\n\n\t\t\t\texpectedYaml := strings.TrimPrefix(strings.TrimSpace(testYaml), \"---\\n\")\n\t\t\t\texpectedName := fmt.Sprintf(\"%s-configmap-partition-1\", cs.GetName())\n\n\t\t\t\tcms, err := rp.createConfigMaps(cs)\n\t\t\t\tExpect(err).ShouldNot(HaveOccurred())\n\t\t\t\tExpect(cms).Should(HaveLen(1))\n\t\t\t\tExpect(cms[0].GetNamespace()).Should(Equal(rp.cfg.Namespace))\n\t\t\t\tExpect(cms[0].GetName()).Should(Equal(expectedName))\n\t\t\t\tExpect(cms[0].Data).Should(BeNil())\n\t\t\t\tExpect(cms[0].BinaryData).Should(HaveKey(\"extraFBC\"))\n\t\t\t\tuncompressed := decompressCM(cms[0])\n\t\t\t\tExpect(uncompressed).Should(Equal(expectedYaml))\n\n\t\t\t\ttestCm := &corev1.ConfigMap{}\n\t\t\t\tExpect(rp.cfg.Client.Get(context.TODO(), types.NamespacedName{Namespace: rp.cfg.Namespace, Name: expectedName}, testCm)).Should(Succeed())\n\t\t\t\tExpect(testCm.BinaryData).Should(HaveKey(\"extraFBC\"))\n\t\t\t\tExpect(testCm.Data).Should(BeNil())\n\t\t\t\tuncompressed = decompressCM(testCm)\n\t\t\t\tExpect(uncompressed).Should(Equal(expectedYaml))\n\t\t\t\tExpect(testCm.OwnerReferences).Should(HaveLen(1))\n\t\t\t})\n\n\t\t\tIt(\"should create the compressed FBCRegistryPod successfully\", func() {\n\t\t\t\texpectedPodName := \"quay-io-example-example-operator-bundle-0-2-0\"\n\t\t\t\tExpect(rp).NotTo(BeNil())\n\t\t\t\tExpect(rp.pod.Name).To(Equal(expectedPodName))\n\t\t\t\tExpect(rp.pod.Namespace).To(Equal(rp.cfg.Namespace))\n\t\t\t\tExpect(rp.pod.Spec.Containers[0].Name).To(Equal(defaultContainerName))\n\t\t\t\tExpect(rp.pod.Spec.Containers).Should(HaveLen(1))\n\t\t\t\tExpect(rp.pod.Spec.Containers[0].Ports).Should(HaveLen(1))\n\t\t\t\tExpect(rp.pod.Spec.Containers[0].Ports[0].ContainerPort).To(Equal(rp.GRPCPort))\n\t\t\t\tExpect(rp.pod.Spec.Containers[0].Command).Should(HaveLen(3))\n\t\t\t\tExpect(rp.pod.Spec.Containers[0].Command).Should(ContainElements(\"sh\", \"-c\", containerCommandFor(rp.FBCIndexRootDir, rp.GRPCPort)))\n\t\t\t\tExpect(rp.pod.Spec.InitContainers).Should(HaveLen(1))\n\t\t\t\tExpect(rp.pod.Spec.InitContainers[0].VolumeMounts).Should(HaveLen(2))\n\t\t\t})\n\t\t})\n\t})\n})\n\nfunc decompressCM(cm *corev1.ConfigMap) string {\n\tactualBinaryData := cm.BinaryData[\"extraFBC\"]\n\tExpectWithOffset(1, len(actualBinaryData)).Should(BeNumerically(\"<\", maxConfigMapSize))\n\tBy(\"uncompress the BinaryData\")\n\tcompressed := bytes.NewBuffer(actualBinaryData)\n\treader, err := gzip.NewReader(compressed)\n\tExpectWithOffset(1, err).ShouldNot(HaveOccurred())\n\tvar uncompressed bytes.Buffer\n\tExpectWithOffset(1, reader.Close()).Should(Succeed())\n\t_, err = io.Copy(&uncompressed, reader)\n\tExpectWithOffset(1, err).ShouldNot(HaveOccurred())\n\n\treturn uncompressed.String()\n}\n\n// containerCommandFor returns the expected container command for a db path and set of bundle items.\nfunc containerCommandFor(indexRootDir string, grpcPort int32) string { //nolint:unparam\n\treturn fmt.Sprintf(\"opm serve %s -p %d\", indexRootDir, grpcPort)\n}\n\nconst testYaml = `\n---\nname: 'Vada O''Connell'\nemail: braun.leta@hirthe.biz\nphone: 815.290.6848\ndescription: 'Sit velit accusantium repellat itaque quisquam dolorem. Necessitatibus et provident explicabo. Animi officia enim omnis unde odio odio. Inventore autem repellendus ducimus et et et iure.'\naddress:\n    streetName: 'Terence Garden'\n    streetAddress: '644 Ward Ranch'\n    city: 'North Newtonhaven'\n    postcode: 37068-6948\n    country: 'Saudi Arabia'\n---\nname: 'Miss Rita Gulgowski'\nemail: oran02@gmail.com\nphone: '+13346133601'\ndescription: 'Inventore recusandae ducimus nemo consequatur. Dolorum vel voluptas sint tempore iste maiores. Voluptatem nisi incidunt sit. Vel et officiis eum enim dolores dolor.'\naddress:\n    streetName: 'Skylar Gateway'\n    streetAddress: '8717 Karley Creek Suite 375'\n    city: Kuhlmanshire\n    postcode: '59539'\n    country: Bolivia\n---\nname: 'Prof. Laverna Stanton'\nemail: nicklaus.turner@gmail.com\nphone: 928.205.3796\ndescription: 'Fugiat quos aspernatur iste fugit provident fugit aut. Optio rem exercitationem quas esse et nesciunt velit excepturi. Doloremque aliquid iure aut quaerat id repellat.'\naddress:\n    streetName: 'Kamron Roads'\n    streetAddress: '956 Lemke Camp'\n    city: Malikatown\n    postcode: '89393'\n    country: 'French Southern Territories'\n`\nconst charTbl = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_+=*&^%$#@!,.;~/\\\\|\"\n\nvar rnd = rand.New(rand.NewSource(time.Now().UnixMilli()))\n\nfunc randField() string {\n\n\tfieldNameLength := rnd.Intn(15) + 5\n\tfieldName := make([]byte, fieldNameLength)\n\tfor i := 0; i < fieldNameLength; i++ {\n\t\tfieldName[i] = charTbl[rnd.Intn('z'-'a'+1)]\n\t}\n\n\t// random field name between 5 and 45\n\tsize := rnd.Intn(40) + 5\n\n\tvalue := make([]byte, size)\n\tfor i := 0; i < size; i++ {\n\t\tvalue[i] = charTbl[rnd.Intn(len(charTbl))]\n\t}\n\treturn fmt.Sprintf(\"%s: %q\\n\", fieldName, value)\n}\n\nfunc generateRandYaml() string {\n\tnumLines := rnd.Intn(45) + 5\n\n\tb := strings.Builder{}\n\tb.WriteString(\"---\\n\")\n\tfor i := 0; i < numLines; i++ {\n\t\tb.WriteString(randField())\n\t}\n\treturn b.String()\n}\n\nvar (\n\tcompressBuff = &bytes.Buffer{}\n\tcompressor   = gzip.NewWriter(compressBuff)\n)\n\nfunc compress(s string) []byte {\n\tcompressBuff.Reset()\n\tcompressor.Reset(compressBuff)\n\n\tinput := bytes.NewBufferString(s)\n\t_, err := io.Copy(compressor, input)\n\tExpectWithOffset(1, err).ShouldNot(HaveOccurred())\n\n\tExpect(compressor.Flush()).Should(Succeed())\n\tExpect(compressor.Close()).Should(Succeed())\n\n\treturn compressBuff.Bytes()\n}\n"
  },
  {
    "path": "internal/olm/operator/registry/index/bundle_add_mode.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage index\n\nimport \"fmt\"\n\n// BundleAddMode is the mode to add a bundle to an index.\ntype BundleAddMode string\n\nconst (\n\t// SemverBundleAddMode - bundle add mode for semver\n\tSemverBundleAddMode BundleAddMode = \"semver\"\n\t// ReplacesBundleAddMode - bundle add mode for replaces\n\tReplacesBundleAddMode BundleAddMode = \"replaces\"\n)\n\nvar modes = []BundleAddMode{SemverBundleAddMode, ReplacesBundleAddMode}\n\nfunc (m BundleAddMode) Validate() error {\n\tswitch m {\n\tcase SemverBundleAddMode, ReplacesBundleAddMode:\n\tcase \"\":\n\t\treturn fmt.Errorf(\"bundle add mode cannot be empty, must be one of: %+q\", modes)\n\tdefault:\n\t\treturn fmt.Errorf(\"bundle add mode %q does not exist, must be one of: %+q\", m, modes)\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "internal/olm/operator/registry/index/registry_pod.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage index\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"path\"\n\t\"text/template\"\n\t\"time\"\n\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\tlog \"github.com/sirupsen/logrus\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/types\"\n\t\"k8s.io/apimachinery/pkg/util/wait\"\n\tpointer \"k8s.io/utils/ptr\"\n\t\"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/olm/operator\"\n\t\"github.com/operator-framework/operator-sdk/internal/util/k8sutil\"\n)\n\nconst (\n\t// defaultGRPCPort is the default grpc container port that the registry pod exposes\n\tdefaultGRPCPort = 50051\n\tdefaultDBPath   = \"/database/index.db\"\n\n\tdefaultContainerName     = \"registry-grpc\"\n\tdefaultContainerPortName = \"grpc\"\n)\n\n// BundleItem contains the metadata of a bundle image relevant to the registry pod.\ntype BundleItem struct {\n\t// ImageTag is the bundle image's tag.\n\tImageTag string `json:\"imageTag\"`\n\t// AddMode describes how the bundle should be added to an index image.\n\tAddMode BundleAddMode `json:\"mode\"`\n}\n\n// SQLiteRegistryPod holds resources necessary for creation of a registry server\ntype SQLiteRegistryPod struct { //nolint:maligned\n\t// BundleItems contains all bundles to be added to a registry pod.\n\tBundleItems []BundleItem\n\n\t// ImagePullPolicy is the image pull policy for the registry pod, default is PullAlways\n\tImagePullPolicy corev1.PullPolicy\n\n\t// Index image contains a database of pointers to operator manifest content that is queriable via an API.\n\t// new version of an operator bundle when published can be added to an index image\n\tIndexImage string\n\n\t// DBPath refers to the registry DB;\n\t// if an index image is provided, the existing registry DB is located at /database/index.db\n\tDBPath string\n\n\t// GRPCPort is the container grpc port\n\tGRPCPort int32\n\n\t// SecretName holds the name of an image pull secret to mount into the Pod so `opm registry add`\n\t// can pull bundle images from a private registry.\n\tSecretName string\n\n\t// SecretName holds the name of a secret for a CA cert file containing root certificates.\n\t// This file is transiently added to the registry Pod's cert pool via `opm registry add --ca-file`.\n\t// The secret's key for this file must be \"cert.pem\".\n\tCASecretName string\n\n\t// SkipTLSVerify represents skip TLS certificate verification for container image registries while pulling bundles.\n\tSkipTLSVerify bool `json:\"SkipTLSVerify\"`\n\n\t// UseHTTP uses plain HTTP for container image registries while pulling bundles.\n\tUseHTTP bool `json:\"UseHTTP\"`\n\n\t// SecurityContext defines the security context which will enable the\n\t// SecurityContext on the Pod\n\tSecurityContext string\n\n\t// pod represents a kubernetes *corev1.pod that will be created on a cluster using an index image\n\tpod *corev1.Pod\n\n\tcfg *operator.Configuration\n}\n\n// init initializes the SQLiteRegistryPod struct and sets defaults for empty fields\nfunc (rp *SQLiteRegistryPod) init(cfg *operator.Configuration) error {\n\tif rp.GRPCPort == 0 {\n\t\trp.GRPCPort = defaultGRPCPort\n\t}\n\tif rp.DBPath == \"\" {\n\t\trp.DBPath = defaultDBPath\n\t}\n\trp.cfg = cfg\n\n\t// validate the SQLiteRegistryPod struct and ensure required fields are set\n\tif err := rp.validate(); err != nil {\n\t\treturn fmt.Errorf(\"invalid registry pod: %v\", err)\n\t}\n\n\t// podForBundleRegistry() to make the pod definition\n\tpod, err := rp.podForBundleRegistry()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error building registry pod definition: %v\", err)\n\t}\n\trp.pod = pod\n\n\treturn nil\n}\n\n// Create creates a bundle registry pod built from an index image,\n// sets the catalog source as the owner for the pod and verifies that\n// the pod is running\nfunc (rp *SQLiteRegistryPod) Create(ctx context.Context, cfg *operator.Configuration, cs *v1alpha1.CatalogSource) (*corev1.Pod, error) {\n\tif err := rp.init(cfg); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// make catalog source the owner of registry pod object\n\tif err := controllerutil.SetOwnerReference(cs, rp.pod, rp.cfg.Scheme); err != nil {\n\t\treturn nil, fmt.Errorf(\"error setting owner reference: %w\", err)\n\t}\n\n\t// Add security context if the user passed in the --security-context-config flag\n\tif rp.SecurityContext == \"restricted\" {\n\t\trp.pod.Spec.SecurityContext = &corev1.PodSecurityContext{\n\t\t\tSeccompProfile: &corev1.SeccompProfile{\n\t\t\t\tType: corev1.SeccompProfileTypeRuntimeDefault,\n\t\t\t},\n\t\t}\n\n\t\t// Update the Registry Pod container security context to be restrictive\n\t\trp.pod.Spec.Containers[0].SecurityContext = &corev1.SecurityContext{\n\t\t\tPrivileged:               pointer.To(false),\n\t\t\tReadOnlyRootFilesystem:   pointer.To(false),\n\t\t\tAllowPrivilegeEscalation: pointer.To(false),\n\t\t\tCapabilities: &corev1.Capabilities{\n\t\t\t\tDrop: []corev1.Capability{\"ALL\"},\n\t\t\t},\n\t\t}\n\t}\n\n\tif rp.ImagePullPolicy == \"\" {\n\t\trp.ImagePullPolicy = corev1.PullAlways\n\t}\n\trp.pod.Spec.Containers[0].ImagePullPolicy = rp.ImagePullPolicy\n\n\tif err := rp.cfg.Client.Create(ctx, rp.pod); err != nil {\n\t\treturn nil, fmt.Errorf(\"error creating pod: %w\", err)\n\t}\n\n\t// get registry pod key\n\tpodKey := types.NamespacedName{\n\t\tNamespace: rp.cfg.Namespace,\n\t\tName:      rp.pod.GetName(),\n\t}\n\n\t// poll and verify that pod is running\n\tpodCheck := wait.ConditionWithContextFunc(func(pctx context.Context) (done bool, err error) {\n\t\terr = rp.cfg.Client.Get(pctx, podKey, rp.pod)\n\t\tif err != nil {\n\t\t\treturn false, fmt.Errorf(\"error getting pod %s: %w\", rp.pod.Name, err)\n\t\t}\n\t\treturn rp.pod.Status.Phase == corev1.PodRunning, nil\n\t})\n\n\t// check pod status to be `Running`\n\tif err := rp.checkPodStatus(ctx, podCheck); err != nil {\n\t\treturn nil, fmt.Errorf(\"registry pod did not become ready: %w\", err)\n\t}\n\tlog.Infof(\"Created registry pod: %s\", rp.pod.Name)\n\treturn rp.pod, nil\n}\n\n// checkPodStatus polls and verifies that the pod status is running\nfunc (rp *SQLiteRegistryPod) checkPodStatus(ctx context.Context, podCheck wait.ConditionWithContextFunc) error {\n\t// poll every 200 ms until podCheck is true or context is done\n\terr := wait.PollUntilContextCancel(ctx, 200*time.Millisecond, false, podCheck)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error waiting for registry pod %s to run: %v\", rp.pod.Name, err)\n\t}\n\n\treturn err\n}\n\n// validate will ensure that SQLiteRegistryPod required fields are set\n// and throws error if not set\nfunc (rp *SQLiteRegistryPod) validate() error {\n\tif len(rp.BundleItems) == 0 {\n\t\treturn errors.New(\"bundle image set cannot be empty\")\n\t}\n\tfor _, item := range rp.BundleItems {\n\t\tif item.ImageTag == \"\" {\n\t\t\treturn errors.New(\"bundle image cannot be empty\")\n\t\t}\n\t\tif err := item.AddMode.Validate(); err != nil {\n\t\t\treturn fmt.Errorf(\"invalid bundle add mode: %v\", err)\n\t\t}\n\t}\n\n\tif rp.IndexImage == \"\" {\n\t\treturn errors.New(\"index image cannot be empty\")\n\t}\n\n\treturn nil\n}\n\nfunc GetRegistryPodHost(ipStr string) string {\n\treturn fmt.Sprintf(\"%s:%d\", ipStr, defaultGRPCPort)\n}\n\n// getPodName will return a string constructed from the bundle Image name\nfunc getPodName(bundleImage string) string {\n\t// todo(rashmigottipati): need to come up with human-readable references\n\t// to be able to handle SHA references in the bundle images\n\treturn k8sutil.TrimDNS1123Label(k8sutil.FormatOperatorNameDNS1123(bundleImage))\n}\n\n// podForBundleRegistry constructs and returns the registry pod definition\n// and throws error when unable to build the pod definition successfully\nfunc (rp *SQLiteRegistryPod) podForBundleRegistry() (*corev1.Pod, error) {\n\t// rp was already validated so len(rp.BundleItems) must be greater than 0.\n\tbundleImage := rp.BundleItems[len(rp.BundleItems)-1].ImageTag\n\n\t// construct the container command for pod spec\n\tcontainerCmd, err := rp.getContainerCmd()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// make the pod definition\n\trp.pod = &corev1.Pod{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      getPodName(bundleImage),\n\t\t\tNamespace: rp.cfg.Namespace,\n\t\t},\n\t\tSpec: corev1.PodSpec{\n\t\t\t// DO NOT set RunAsUser and RunAsNonRoot, we must leave this empty to allow\n\t\t\t// those that want to use this command against Openshift vendor do not face issues.\n\t\t\t//\n\t\t\t// Why not set RunAsUser?\n\t\t\t// RunAsUser cannot be set because in OpenShift each namespace has a valid range like\n\t\t\t// [1000680000, 1000689999]. Therefore, values like 1001 will not work. Also, in OCP each namespace\n\t\t\t// has a valid range allocate. Therefore, by leaving it empty the OCP will adopt RunAsUser strategy\n\t\t\t// of MustRunAsRange. The PSA will look for the openshift.io/sa.scc.uid-range annotation\n\t\t\t// in the namespace to populate RunAsUser fields when the pod be admitted. Note that\n\t\t\t// is NOT possible to know a valid value that could be accepeted beforehand.\n\t\t\t//\n\t\t\t// Why not set RunAsNonRoot?\n\t\t\t// If we set RunAsNonRoot = true and the image informed does not define the UserID\n\t\t\t// (i.e. in the Dockerfile we have not `USER 11211:11211 `) then, the Pod will fail to run with the\n\t\t\t// error `\"container has runAsNonRoot and image will run as root …` in ANY Kubernetes cluster.\n\t\t\t// (vanilla or OCP). Therefore, by leaving it empty this field will be set by OCP if/when the Pod be\n\t\t\t// qualified for restricted-v2 SCC policy.\n\t\t\t//\n\t\t\t// TODO: remove when OpenShift 4.10 and Kubernetes 1.19 be no longer supported\n\t\t\t// Why not set SeccompProfile?\n\t\t\t// This option can only work in OCP versions >= 4.11 and Kubernetes versions >= 19.\n\t\t\t//\n\t\t\t// 2022-09-27 (jesusr): We added a --security-context-config flag to run bundle\n\t\t\t// that will add the following stanza to the pod. This will allow\n\t\t\t// users to selectively enable this stanza. Once this context\n\t\t\t// becomes the default, we should uncomment this code and remove the\n\t\t\t// --security-context-config flag.\n\t\t\t// ---- end of update comment\n\t\t\t//\n\t\t\t// SecurityContext: &corev1.PodSecurityContext{\n\t\t\t//     SeccompProfile: &corev1.SeccompProfile{\n\t\t\t//         Type: corev1.SeccompProfileTypeRuntimeDefault,\n\t\t\t//     },\n\t\t\t// },\n\t\t\tContainers: []corev1.Container{\n\t\t\t\t{\n\t\t\t\t\tName:  defaultContainerName,\n\t\t\t\t\tImage: rp.IndexImage,\n\t\t\t\t\tCommand: []string{\n\t\t\t\t\t\t\"sh\",\n\t\t\t\t\t\t\"-c\",\n\t\t\t\t\t\tcontainerCmd,\n\t\t\t\t\t},\n\t\t\t\t\tPorts: []corev1.ContainerPort{\n\t\t\t\t\t\t{Name: defaultContainerPortName, ContainerPort: rp.GRPCPort},\n\t\t\t\t\t},\n\t\t\t\t\tWorkingDir: \"/tmp\",\n\t\t\t\t},\n\t\t\t},\n\t\t\tServiceAccountName: rp.cfg.ServiceAccount,\n\t\t},\n\t}\n\n\taddImagePullSecret(rp.pod, rp.SecretName)\n\taddCertSecret(rp.pod, rp.CASecretName)\n\n\treturn rp.pod, nil\n}\n\n// addImagePullSecret creates a docker config volume for secretName\n// and a volumeMount for that secret in each container in pod.\nfunc addImagePullSecret(pod *corev1.Pod, secretName string) {\n\tif secretName == \"\" {\n\t\treturn\n\t}\n\n\t// Require a non-legacy docker config secret.\n\tvolume := makeSecretVolume(secretName, corev1.KeyToPath{Key: \".dockerconfigjson\", Path: \".docker/config.json\"})\n\tpod.Spec.Volumes = append(pod.Spec.Volumes, volume)\n\n\taddVolumeMountForSecret(pod, volume.Name, \"/root\")\n}\n\n// addCertSecret creates and mounts a volume containing a CA root certificate\n// to pass to `opm registry add`.\nfunc addCertSecret(pod *corev1.Pod, secretName string) {\n\tif secretName == \"\" {\n\t\treturn\n\t}\n\n\t// Ensure the secret contains a key \"cert.pem\".\n\tvolume := makeSecretVolume(secretName, corev1.KeyToPath{Key: \"cert.pem\", Path: \"cert.pem\"})\n\tpod.Spec.Volumes = append(pod.Spec.Volumes, volume)\n\n\taddVolumeMountForSecret(pod, volume.Name, \"/certs\")\n}\n\nfunc makeSecretVolume(secretName string, items ...corev1.KeyToPath) corev1.Volume {\n\treturn corev1.Volume{\n\t\tName: secretName,\n\t\tVolumeSource: corev1.VolumeSource{\n\t\t\tSecret: &corev1.SecretVolumeSource{\n\t\t\t\tSecretName:  secretName,\n\t\t\t\tDefaultMode: newInt32(0400),\n\t\t\t\tOptional:    newBool(false),\n\t\t\t\tItems:       items,\n\t\t\t},\n\t\t},\n\t}\n}\n\nfunc addVolumeMountForSecret(pod *corev1.Pod, secretName, mountPath string) {\n\tvolumeMount := corev1.VolumeMount{\n\t\tName:      secretName,\n\t\tReadOnly:  true,\n\t\tMountPath: mountPath,\n\t}\n\tfor i := range pod.Spec.Containers {\n\t\tpod.Spec.Containers[i].VolumeMounts = append(pod.Spec.Containers[i].VolumeMounts, volumeMount)\n\t}\n}\n\nfunc newInt32(i int32) *int32 {\n\tip := new(int32)\n\t*ip = i\n\treturn ip\n}\n\nfunc newBool(b bool) *bool {\n\tbp := new(bool)\n\t*bp = b\n\treturn bp\n}\n\nconst cmdTemplate = `[[ -f {{ .DBPath }} ]] && cp {{ .DBPath }} /tmp/tmp.db; \\\n{{- range $i, $item := .BundleItems }}\nopm registry add -d /tmp/tmp.db -b {{ $item.ImageTag }} --mode={{ $item.AddMode }}{{ if $.CASecretName }} --ca-file=/certs/cert.pem{{ end }} --skip-tls-verify={{ $.SkipTLSVerify }} --use-http={{ $.UseHTTP }} && \\\n{{- end }}\nexec opm registry serve -d /tmp/tmp.db -p {{ .GRPCPort }}\n`\n\n// getContainerCmd uses templating to construct the container command\n// and throws error if unable to parse and execute the container command\nfunc (rp *SQLiteRegistryPod) getContainerCmd() (string, error) {\n\t// create a custom dirname template function\n\tfuncMap := template.FuncMap{\n\t\t\"dirname\": path.Dir,\n\t}\n\n\t// add the custom dirname template function to the\n\t// template's FuncMap and parse the cmdTemplate\n\tt := template.Must(template.New(\"cmd\").Funcs(funcMap).Parse(cmdTemplate))\n\n\t// execute the command by applying the parsed template to command\n\t// and write command output to out\n\tout := &bytes.Buffer{}\n\tif err := t.Execute(out, rp); err != nil {\n\t\treturn \"\", fmt.Errorf(\"parse container command: %w\", err)\n\t}\n\n\treturn out.String(), nil\n}\n"
  },
  {
    "path": "internal/olm/operator/registry/index/registry_pod_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage index\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\t\"github.com/operator-framework/operator-sdk/internal/olm/operator\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\t\"k8s.io/apimachinery/pkg/util/wait\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client\"\n\tfakeclient \"sigs.k8s.io/controller-runtime/pkg/client/fake\"\n)\n\nconst testIndexImageTag = \"some-image:v1.2.3\"\nconst caSecretName = \"foo-secret\"\n\n// newFakeClient() returns a fake controller runtime client\nfunc newFakeClient() client.Client {\n\treturn fakeclient.NewClientBuilder().Build()\n}\n\nfunc TestCreateRegistryPod(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"Test Registry Pod Suite\")\n}\n\nvar _ = Describe(\"SQLiteRegistryPod\", func() {\n\n\tvar defaultBundleItems = []BundleItem{{\n\t\tImageTag: \"quay.io/example/example-operator-bundle:0.2.0\",\n\t\tAddMode:  SemverBundleAddMode,\n\t}}\n\n\tDescribe(\"creating registry pod\", func() {\n\n\t\tContext(\"with valid registry pod values\", func() {\n\n\t\t\tvar (\n\t\t\t\trp  *SQLiteRegistryPod\n\t\t\t\tcfg *operator.Configuration\n\t\t\t\tpod *corev1.Pod\n\t\t\t\terr error\n\t\t\t)\n\n\t\t\tBeforeEach(func() {\n\t\t\t\tcfg = &operator.Configuration{\n\t\t\t\t\tClient:    newFakeClient(),\n\t\t\t\t\tNamespace: \"test-default\",\n\t\t\t\t}\n\t\t\t\trp = &SQLiteRegistryPod{\n\t\t\t\t\tBundleItems: defaultBundleItems,\n\t\t\t\t\tIndexImage:  testIndexImageTag,\n\t\t\t\t}\n\t\t\t\tBy(\"initializing the SQLiteRegistryPod\")\n\t\t\t\tExpect(rp.init(cfg)).To(Succeed())\n\t\t\t})\n\n\t\t\tIt(\"should create the SQLiteRegistryPod successfully\", func() {\n\t\t\t\texpectedPodName := \"quay-io-example-example-operator-bundle-0-2-0\"\n\t\t\t\tExpect(rp).NotTo(BeNil())\n\t\t\t\tExpect(rp.pod.Name).To(Equal(expectedPodName))\n\t\t\t\tExpect(rp.pod.Namespace).To(Equal(rp.cfg.Namespace))\n\t\t\t\tExpect(rp.pod.Spec.Containers[0].Name).To(Equal(defaultContainerName))\n\t\t\t\tif len(rp.pod.Spec.Containers) > 0 {\n\t\t\t\t\tif len(rp.pod.Spec.Containers[0].Ports) > 0 {\n\t\t\t\t\t\tExpect(rp.pod.Spec.Containers[0].Ports[0].ContainerPort).To(Equal(rp.GRPCPort))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tIt(\"should create a registry pod when database path is not provided\", func() {\n\t\t\t\tExpect(rp.DBPath).To(Equal(\"/database/index.db\"))\n\t\t\t})\n\n\t\t\tIt(\"should return a valid container command for one image\", func() {\n\t\t\t\toutput, err := rp.getContainerCmd()\n\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\tExpect(output).Should(Equal(containerCommandFor(defaultDBPath, defaultBundleItems, false, rp.SkipTLSVerify, false)))\n\t\t\t})\n\n\t\t\tIt(\"should return a container command with --ca-file\", func() {\n\t\t\t\trp.CASecretName = caSecretName\n\t\t\t\toutput, err := rp.getContainerCmd()\n\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\tExpect(output).Should(Equal(containerCommandFor(defaultDBPath, defaultBundleItems, true, rp.SkipTLSVerify, false)))\n\t\t\t})\n\n\t\t\tIt(\"should return a container command for image with --skip-tls-verify\", func() {\n\t\t\t\tif len(defaultBundleItems) > 0 {\n\t\t\t\t\tbundles := []BundleItem{defaultBundleItems[0]}\n\t\t\t\t\trp.BundleItems = bundles\n\t\t\t\t\trp.SkipTLSVerify = true\n\t\t\t\t\toutput, err := rp.getContainerCmd()\n\t\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\t\tExpect(output).Should(Equal(containerCommandFor(defaultDBPath, bundles, false, rp.SkipTLSVerify, false)))\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tIt(\"should return a valid container command for three images\", func() {\n\t\t\t\tbundleItems := append(defaultBundleItems,\n\t\t\t\t\tBundleItem{\n\t\t\t\t\t\tImageTag: \"quay.io/example/example-operator-bundle:0.3.0\",\n\t\t\t\t\t\tAddMode:  ReplacesBundleAddMode,\n\t\t\t\t\t},\n\t\t\t\t\tBundleItem{\n\t\t\t\t\t\tImageTag: \"quay.io/example/example-operator-bundle:1.0.1\",\n\t\t\t\t\t\tAddMode:  SemverBundleAddMode,\n\t\t\t\t\t},\n\t\t\t\t\tBundleItem{\n\t\t\t\t\t\tImageTag: \"localhost/example-operator-bundle:1.0.1\",\n\t\t\t\t\t\tAddMode:  SemverBundleAddMode,\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t\trp2 := SQLiteRegistryPod{\n\t\t\t\t\tDBPath:        defaultDBPath,\n\t\t\t\t\tGRPCPort:      defaultGRPCPort,\n\t\t\t\t\tBundleItems:   bundleItems,\n\t\t\t\t\tSkipTLSVerify: true,\n\t\t\t\t}\n\t\t\t\toutput, err := rp2.getContainerCmd()\n\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\tExpect(output).Should(Equal(containerCommandFor(defaultDBPath, bundleItems, false, rp2.SkipTLSVerify, false)))\n\t\t\t})\n\n\t\t\tIt(\"should return a valid container command for one image\", func() {\n\t\t\t\toutput, err := rp.getContainerCmd()\n\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\tExpect(output).Should(Equal(containerCommandFor(defaultDBPath, defaultBundleItems, false, false, rp.UseHTTP)))\n\t\t\t})\n\n\t\t\tIt(\"should return a container command with --ca-file\", func() {\n\t\t\t\trp.CASecretName = caSecretName\n\t\t\t\toutput, err := rp.getContainerCmd()\n\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\tExpect(output).Should(Equal(containerCommandFor(defaultDBPath, defaultBundleItems, true, false, rp.UseHTTP)))\n\t\t\t})\n\n\t\t\tIt(\"should return a container command for image with --use-http\", func() {\n\t\t\t\tif len(defaultBundleItems) > 0 {\n\t\t\t\t\tbundles := []BundleItem{defaultBundleItems[0]}\n\t\t\t\t\trp.BundleItems = bundles\n\t\t\t\t\trp.UseHTTP = true\n\t\t\t\t\toutput, err := rp.getContainerCmd()\n\t\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\t\tExpect(output).Should(Equal(containerCommandFor(defaultDBPath, bundles, false, false, rp.UseHTTP)))\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tIt(\"should return a valid container command for three images\", func() {\n\t\t\t\tbundleItems := append(defaultBundleItems,\n\t\t\t\t\tBundleItem{\n\t\t\t\t\t\tImageTag: \"quay.io/example/example-operator-bundle:0.3.0\",\n\t\t\t\t\t\tAddMode:  ReplacesBundleAddMode,\n\t\t\t\t\t},\n\t\t\t\t\tBundleItem{\n\t\t\t\t\t\tImageTag: \"quay.io/example/example-operator-bundle:1.0.1\",\n\t\t\t\t\t\tAddMode:  SemverBundleAddMode,\n\t\t\t\t\t},\n\t\t\t\t\tBundleItem{\n\t\t\t\t\t\tImageTag: \"localhost/example-operator-bundle:1.0.1\",\n\t\t\t\t\t\tAddMode:  SemverBundleAddMode,\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t\trp2 := SQLiteRegistryPod{\n\t\t\t\t\tDBPath:      defaultDBPath,\n\t\t\t\t\tGRPCPort:    defaultGRPCPort,\n\t\t\t\t\tBundleItems: bundleItems,\n\t\t\t\t\tUseHTTP:     true,\n\t\t\t\t}\n\t\t\t\toutput, err := rp2.getContainerCmd()\n\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\tExpect(output).Should(Equal(containerCommandFor(defaultDBPath, bundleItems, false, false, rp2.UseHTTP)))\n\t\t\t})\n\n\t\t\tIt(\"check pod status should return successfully when pod check is true\", func() {\n\t\t\t\tmockGoodPodCheck := wait.ConditionWithContextFunc(func(_ context.Context) (done bool, err error) {\n\t\t\t\t\treturn true, nil\n\t\t\t\t})\n\n\t\t\t\tExpect(rp.checkPodStatus(context.Background(), mockGoodPodCheck)).To(Succeed())\n\t\t\t})\n\n\t\t\tIt(\"adds secrets and a service account to the pod\", func() {\n\t\t\t\tcfg.ServiceAccount = \"foo\"\n\t\t\t\trp.SecretName = caSecretName\n\n\t\t\t\tpod, err = rp.podForBundleRegistry()\n\t\t\t\tExpect(err).NotTo((HaveOccurred()))\n\t\t\t\tExpect(pod.Spec.ServiceAccountName).To(Equal(cfg.ServiceAccount))\n\t\t\t\tExpect(pod.Spec.Volumes).To(Equal([]corev1.Volume{\n\t\t\t\t\t{\n\t\t\t\t\t\tName: \"foo-secret\",\n\t\t\t\t\t\tVolumeSource: corev1.VolumeSource{\n\t\t\t\t\t\t\tSecret: &corev1.SecretVolumeSource{\n\t\t\t\t\t\t\t\tSecretName:  \"foo-secret\",\n\t\t\t\t\t\t\t\tDefaultMode: newInt32(0400),\n\t\t\t\t\t\t\t\tOptional:    newBool(false),\n\t\t\t\t\t\t\t\tItems: []corev1.KeyToPath{\n\t\t\t\t\t\t\t\t\t{Key: \".dockerconfigjson\", Path: \".docker/config.json\"},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t}))\n\t\t\t\tfor _, container := range pod.Spec.Containers {\n\t\t\t\t\tExpect(container.VolumeMounts).To(Equal([]corev1.VolumeMount{\n\t\t\t\t\t\t{Name: \"foo-secret\", ReadOnly: true, MountPath: \"/root\"},\n\t\t\t\t\t}))\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\n\t\tContext(\"with invalid registry pod values\", func() {\n\t\t\tvar cfg *operator.Configuration\n\t\t\tBeforeEach(func() {\n\t\t\t\tcfg = &operator.Configuration{\n\t\t\t\t\tClient:    newFakeClient(),\n\t\t\t\t\tNamespace: \"test-default\",\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tIt(\"should error when bundle image is not provided\", func() {\n\t\t\t\texpectedErr := \"bundle image set cannot be empty\"\n\t\t\t\trp := &SQLiteRegistryPod{}\n\t\t\t\terr := rp.init(cfg)\n\t\t\t\tExpect(err).To(HaveOccurred())\n\t\t\t\tExpect(err.Error()).Should(ContainSubstring(expectedErr))\n\t\t\t})\n\n\t\t\tIt(\"should not accept any other bundle add mode other than semver or replaces\", func() {\n\t\t\t\texpectedErr := `bundle add mode \"invalid\" does not exist`\n\t\t\t\trp := &SQLiteRegistryPod{\n\t\t\t\t\tBundleItems: []BundleItem{{ImageTag: \"quay.io/example/example-operator-bundle:0.2.0\", AddMode: \"invalid\"}},\n\t\t\t\t}\n\t\t\t\terr := rp.init(cfg)\n\t\t\t\tExpect(err).To(HaveOccurred())\n\t\t\t\tExpect(err.Error()).Should(ContainSubstring(expectedErr))\n\t\t\t})\n\n\t\t\tIt(\"checkPodStatus should return error when pod check is false and context is done\", func() {\n\t\t\t\trp := &SQLiteRegistryPod{\n\t\t\t\t\tBundleItems: defaultBundleItems,\n\t\t\t\t\tIndexImage:  testIndexImageTag,\n\t\t\t\t}\n\t\t\t\tExpect(rp.init(cfg)).To(Succeed())\n\n\t\t\t\tmockBadPodCheck := wait.ConditionWithContextFunc(func(_ context.Context) (done bool, err error) {\n\t\t\t\t\treturn false, fmt.Errorf(\"error waiting for registry pod\")\n\t\t\t\t})\n\n\t\t\t\texpectedErr := \"error waiting for registry pod\"\n\t\t\t\t// create a new context with a deadline of 1 millisecond\n\t\t\t\tctx, cancel := context.WithTimeout(context.Background(), 1*time.Millisecond)\n\t\t\t\tcancel()\n\n\t\t\t\terr := rp.checkPodStatus(ctx, mockBadPodCheck)\n\t\t\t\tExpect(err).To(HaveOccurred())\n\t\t\t\tExpect(err.Error()).Should(ContainSubstring(expectedErr))\n\t\t\t})\n\t\t})\n\t})\n})\n\n// containerCommandFor returns the expected container command for a db path and set of bundle items.\nfunc containerCommandFor(dbPath string, items []BundleItem, hasCA, skipTLSVerify bool, useHTTP bool) string { //nolint:unparam\n\tvar caFlag string\n\tif hasCA {\n\t\tcaFlag = \" --ca-file=/certs/cert.pem\"\n\t}\n\tadditions := &strings.Builder{}\n\tfor _, item := range items {\n\t\tfmt.Fprintf(additions, \"opm registry add -d /tmp/tmp.db -b %s --mode=%s%s --skip-tls-verify=%v --use-http=%v && \\\\\\n\", item.ImageTag, item.AddMode, caFlag, skipTLSVerify, useHTTP)\n\t}\n\n\treturn fmt.Sprintf(\"[[ -f %s ]] && cp %s /tmp/tmp.db; \\\\\\n%sexec opm registry serve -d /tmp/tmp.db -p 50051\\n\", dbPath, dbPath, additions.String())\n}\n"
  },
  {
    "path": "internal/olm/operator/registry/index_image.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage registry\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/pflag\"\n\tgofunk \"github.com/thoas/go-funk\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\tapierrors \"k8s.io/apimachinery/pkg/api/errors\"\n\t\"k8s.io/apimachinery/pkg/types\"\n\t\"k8s.io/apimachinery/pkg/util/wait\"\n\t\"k8s.io/client-go/util/retry\"\n\n\tdeclarativeconfig \"github.com/operator-framework/operator-registry/alpha/declcfg\"\n\tfbcutil \"github.com/operator-framework/operator-sdk/internal/olm/fbcutil\"\n\t\"github.com/operator-framework/operator-sdk/internal/olm/operator\"\n\t\"github.com/operator-framework/operator-sdk/internal/olm/operator/registry/fbcindex\"\n\t\"github.com/operator-framework/operator-sdk/internal/olm/operator/registry/index\"\n\tregistryutil \"github.com/operator-framework/operator-sdk/internal/registry\"\n)\n\n// Internal CatalogSource annotations.\nconst (\n\toperatorFrameworkGroup = \"operators.operatorframework.io\"\n\n\t// Holds the base index image tag used to create a catalog.\n\tindexImageAnnotation = operatorFrameworkGroup + \"/index-image\"\n\t// Holds all bundle image and add mode pairs in the current catalog.\n\tinjectedBundlesAnnotation = operatorFrameworkGroup + \"/injected-bundles\"\n\t// Holds the name of the existing registry pod associated with a catalog.\n\tregistryPodNameAnnotation = operatorFrameworkGroup + \"/registry-pod-name\"\n)\n\n// TODO: Change this to use the values in operator-framework/api\n// once the release containing the enums is pulled into SDK\ntype SecurityContextType string\n\nconst (\n\tLegacy     SecurityContextType = \"legacy\"\n\tRestricted SecurityContextType = \"restricted\"\n)\n\n// SecurityContext represents the enum from the CatalogSource API\n// It is also being used by the binding flags to allow validation of the enum\n// values\ntype SecurityContext struct {\n\tContextType SecurityContextType\n}\n\nfunc (sc *SecurityContext) String() string {\n\treturn string(sc.ContextType)\n}\n\nfunc (sc *SecurityContext) Set(value string) error {\n\tswitch value {\n\tcase \"legacy\", \"restricted\":\n\t\tsc.ContextType = SecurityContextType(value)\n\t\treturn nil\n\tdefault:\n\t\treturn fmt.Errorf(\"must be one of \\\"legacy\\\", or \\\"restricted\\\"\")\n\t}\n}\n\nfunc (sc *SecurityContext) IsEmpty() bool {\n\treturn sc.ContextType == \"\"\n}\n\nfunc (sc *SecurityContext) Type() string {\n\treturn \"SecurityContext\"\n}\n\ntype IndexImageCatalogCreator struct {\n\tSkipTLS         bool\n\tSkipTLSVerify   bool\n\tUseHTTP         bool\n\tHasFBCLabel     bool\n\tFBCContent      string\n\tPackageName     string\n\tImagePullPolicy string\n\tIndexImage      string\n\tInitImage       string\n\tBundleImage     string\n\tSecretName      string\n\tCASecretName    string\n\tBundleAddMode   index.BundleAddMode\n\tPreviousBundles []string\n\tcfg             *operator.Configuration\n\tChannelName     string\n\tSecurityContext SecurityContext\n}\n\nvar _ CatalogCreator = &IndexImageCatalogCreator{}\nvar _ CatalogUpdater = &IndexImageCatalogCreator{}\n\nfunc NewIndexImageCatalogCreator(cfg *operator.Configuration) *IndexImageCatalogCreator {\n\treturn &IndexImageCatalogCreator{\n\t\tcfg: cfg,\n\t}\n}\n\nfunc (c *IndexImageCatalogCreator) BindFlags(fs *pflag.FlagSet) {\n\tfs.StringVar(&c.SecretName, \"pull-secret-name\", \"\",\n\t\t\"Name of image pull secret (\\\"type: kubernetes.io/dockerconfigjson\\\") required \"+\n\t\t\t\"to pull bundle images. This secret *must* be both in the namespace and an \"+\n\t\t\t\"imagePullSecret of the service account that this command is configured to run in\")\n\tfs.StringVar(&c.CASecretName, \"ca-secret-name\", \"\",\n\t\t\"Name of a generic secret containing a PEM root certificate file required to pull bundle images. \"+\n\t\t\t\"This secret *must* be in the namespace that this command is configured to run in, \"+\n\t\t\t\"and the file *must* be encoded under the key \\\"cert.pem\\\"\")\n\n\t_ = fs.MarkDeprecated(\"skip-tls\", \"use --skip-tls-verify or --use-http instead\")\n\t_ = fs.MarkHidden(\"skip-tls\")\n\n\tfs.BoolVar(&c.SkipTLS, \"skip-tls\", false, \"skip authentication of image registry TLS \"+\n\t\t\"certificate when pulling a bundle image in-cluster\")\n\n\tfs.BoolVar(&c.SkipTLSVerify, \"skip-tls-verify\", false, \"skip TLS certificate verification for container image registries \"+\n\t\t\"while pulling bundles\")\n\tfs.BoolVar(&c.UseHTTP, \"use-http\", false, \"use plain HTTP for container image registries \"+\n\t\t\"while pulling bundles\")\n\tfs.StringVar(&c.ImagePullPolicy, \"image-pull-policy\", string(corev1.PullAlways), \"image pull policy for the registry pod\")\n\n\t// default to Legacy\n\tc.SecurityContext = SecurityContext{ContextType: Legacy}\n\tfs.Var(&c.SecurityContext, \"security-context-config\", \"specifies the security context to use for the catalog pod. allowed: 'restricted', 'legacy'.\")\n}\n\nfunc (c IndexImageCatalogCreator) CreateCatalog(ctx context.Context, name string) (*v1alpha1.CatalogSource, error) {\n\t// Create a CatalogSource with displaName, publisher, and any secrets.\n\tcs := newCatalogSource(name, c.cfg.Namespace,\n\t\twithSDKPublisher(c.PackageName),\n\t\twithSecrets(c.SecretName),\n\t\twithGrpcPodSecurityContextConfig(c.SecurityContext.String()),\n\t)\n\tif err := c.cfg.Client.Create(ctx, cs); err != nil {\n\t\treturn nil, fmt.Errorf(\"error creating catalog source: %v\", err)\n\t}\n\n\tc.setAddMode()\n\n\tnewItems := []index.BundleItem{{ImageTag: c.BundleImage, AddMode: c.BundleAddMode}}\n\tif err := c.createAnnotatedRegistry(ctx, cs, newItems); err != nil {\n\t\treturn nil, fmt.Errorf(\"error creating registry pod: %v\", err)\n\t}\n\n\treturn cs, nil\n}\n\n// getChannelHead retrieves the channel head from an array of entries\nfunc getChannelHead(entries []declarativeconfig.ChannelEntry) (string, error) {\n\tnameMap := make(map[string]bool)\n\treplacesMap := make(map[string]bool)\n\n\tfor i := range entries {\n\t\tnameMap[entries[i].Name] = true\n\t\tif entries[i].Replaces != \"\" {\n\t\t\treplacesMap[entries[i].Replaces] = true\n\t\t}\n\t}\n\n\t// gets the CSV name that does not appear in any replaces field in the entries array\n\tfor key := range nameMap {\n\t\tif _, present := replacesMap[key]; !present {\n\t\t\treturn key, nil\n\t\t}\n\t}\n\n\t// this should not be reached since there must be an edge to upgrade from\n\treturn \"\", errors.New(\"no channel head found\")\n}\n\n// handleTraditionalUpgrade upgrades an operator that was installed using OLM. Subsequent upgrades will go through the runFBCUpgrade function\nfunc handleTraditionalUpgrade(ctx context.Context, indexImage string, bundleImage string, channelName string, skipTLSVerify bool, useHTTP bool) (string, error) {\n\t// render the index image\n\toriginalDeclCfg, err := fbcutil.RenderRefs(ctx, []string{indexImage}, skipTLSVerify, useHTTP)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"error rendering index %q\", indexImage)\n\t}\n\n\t// render the bundle image\n\tbundleDeclConfig, err := fbcutil.RenderRefs(ctx, []string{bundleImage}, skipTLSVerify, useHTTP)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"error rendering bundle image %q\", bundleImage)\n\t}\n\n\tif len(bundleDeclConfig.Bundles) != 1 {\n\t\treturn \"\", errors.New(\"rendered bundle must have exactly one bundle\")\n\t}\n\n\t// search for the specific channel in which the upgrade needs to take place, and upgrade from the channel head\n\tfor i := range originalDeclCfg.Channels {\n\t\tif originalDeclCfg.Channels[i].Name == channelName && originalDeclCfg.Channels[i].Package == bundleDeclConfig.Bundles[0].Package {\n\t\t\t// found specific channel\n\t\t\tchannelHead, err := getChannelHead(originalDeclCfg.Channels[i].Entries)\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", err\n\t\t\t}\n\t\t\tentry := declarativeconfig.ChannelEntry{\n\t\t\t\tName:     bundleDeclConfig.Bundles[0].Name,\n\t\t\t\tReplaces: channelHead,\n\t\t\t}\n\t\t\toriginalDeclCfg.Channels[i].Entries = append(originalDeclCfg.Channels[i].Entries, entry)\n\t\t\tbreak\n\t\t}\n\t}\n\n\t// add the upgraded bundle to resulting declarative config\n\toriginalDeclCfg.Bundles = append(originalDeclCfg.Bundles, bundleDeclConfig.Bundles[0])\n\n\t// validate the declarative config and convert it to a string\n\tvar content string\n\tif content, err = fbcutil.ValidateAndStringify(originalDeclCfg); err != nil {\n\t\treturn \"\", fmt.Errorf(\"error validating and converting the declarative config object to a string format: %v\", err)\n\t}\n\n\tlog.Infof(\"Generated a valid Upgraded File-Based Catalog\")\n\n\treturn content, nil\n}\n\n// runFBCUpgrade starts the process of upgrading a bundle in an FBC. This function will recreate the FBC that was generated\n// during run bundle and upgrade a specific bundle in the specified channel.\nfunc (c *IndexImageCatalogCreator) runFBCUpgrade(ctx context.Context) error {\n\t// render the index image if it is not the default index image\n\tvar refs []string\n\tif c.IndexImage != fbcutil.DefaultIndexImage {\n\t\trefs = append(refs, c.IndexImage)\n\t}\n\n\toriginalDeclcfg, err := fbcutil.RenderRefs(ctx, refs, c.SkipTLSVerify, c.UseHTTP)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// add the upgraded bundle to the list of previous bundles so that they can be rendered with a single API call\n\tc.PreviousBundles = append(c.PreviousBundles, c.BundleImage)\n\tf := &fbcutil.FBCContext{\n\t\tPackage:     c.PackageName,\n\t\tRefs:        c.PreviousBundles,\n\t\tChannelName: c.ChannelName,\n\t}\n\n\t// Adding the FBC \"f\" to the originalDeclcfg to generate a new FBC\n\tdeclcfg, err := upgradeFBC(ctx, f, originalDeclcfg, c.SkipTLSVerify, c.UseHTTP)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error creating the upgraded FBC: %v\", err)\n\t}\n\n\t// validate the declarative config and convert it to a string\n\tvar content string\n\tif content, err = fbcutil.ValidateAndStringify(declcfg); err != nil {\n\t\treturn fmt.Errorf(\"error validating/stringifying the declarative config object: %v\", err)\n\t}\n\n\tlog.Infof(\"Generated a valid Upgraded File-Based Catalog\")\n\n\tc.FBCContent = content\n\n\treturn nil\n}\n\n// upgradeFBC constructs a new File-Based Catalog from both the FBCContext object and the declarative config object. This function will check to see\n// if the FBCContext object \"f\" is already present in the original declarative config.\nfunc upgradeFBC(ctx context.Context, f *fbcutil.FBCContext, originalDeclCfg *declarativeconfig.DeclarativeConfig, skipTLSVerify bool, useHTTP bool) (*declarativeconfig.DeclarativeConfig, error) {\n\tdeclcfg, err := fbcutil.RenderRefs(ctx, f.Refs, skipTLSVerify, useHTTP)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Ensuring a valid bundle size\n\tif len(declcfg.Bundles) < 1 {\n\t\treturn nil, fmt.Errorf(\"bundle image should contain at least one bundle blob\")\n\t}\n\n\textraDeclConfig := &declarativeconfig.DeclarativeConfig{}\n\t// declcfg contains all the bundles we need to insert to form the new FBC\n\tentries := []declarativeconfig.ChannelEntry{} // Used when generating a new channel\n\n\t// Checking if the existing file-based catalog (before upgrade) contains the bundle and channel that we intend to insert.\n\t// If the bundle already exists, we error out. If the channel already exists, we store the index of the channel. This\n\t// index will be used to access the channel from the declarative config object\n\tchannelExists := false\n\tchannelIndex := -1\n\tchannelHead := \"\"\n\tfor i, channel := range originalDeclCfg.Channels {\n\t\t// Find the specific channel that the bundle needs to be inserted into\n\t\tif channel.Name == f.ChannelName && channel.Package == f.Package {\n\t\t\tchannelExists = true\n\t\t\tchannelIndex = i\n\t\t\t// Check if the CSV name is already present in the channel's entries\n\t\t\tfor _, entry := range channel.Entries {\n\t\t\t\t// Our upgraded bundle image is the last element of the refs we passed in\n\t\t\t\tif entry.Name == declcfg.Bundles[len(declcfg.Bundles)-1].Name {\n\t\t\t\t\treturn nil, fmt.Errorf(\"bundle %q already exists in the Index Image %q\", declcfg.Bundles[len(declcfg.Bundles)-1].Name, entry.Name)\n\t\t\t\t}\n\t\t\t}\n\t\t\tchannelHead, err = getChannelHead(channel.Entries)\n\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\textraDeclConfig.Channels = append(extraDeclConfig.Channels, channel)\n\n\t\t\tbreak // We only want to search through the specific channel\n\t\t}\n\t}\n\n\t// Storing a list of the existing bundles and their packages for easier querying via maps\n\texistingBundles := make(map[string]string)\n\tfor _, bundle := range originalDeclCfg.Bundles {\n\t\texistingBundles[bundle.Name] = bundle.Package\n\t}\n\n\tfor i, bundle := range declcfg.Bundles {\n\t\t// if it is not present in the bundles array or belongs to a different package, we can add it\n\t\tif _, present := existingBundles[bundle.Name]; !present || existingBundles[bundle.Name] != bundle.Package {\n\t\t\textraDeclConfig.Bundles = append(extraDeclConfig.Bundles, bundle)\n\t\t}\n\n\t\t// constructing a new entry to add\n\t\tentry := declarativeconfig.ChannelEntry{\n\t\t\tName: declcfg.Bundles[i].Name,\n\t\t}\n\t\tif i > 0 {\n\t\t\tentry.Replaces = declcfg.Bundles[i-1].Name\n\t\t} else if channelExists {\n\t\t\tentry.Replaces = channelHead\n\t\t}\n\n\t\t// either add it to a new channel or an existing channel\n\t\tif channelExists {\n\t\t\textraDeclConfig.Channels[channelIndex].Entries = []declarativeconfig.ChannelEntry{entry}\n\t\t} else {\n\t\t\tentries = append(entries, entry)\n\t\t}\n\t}\n\n\t// create a new channel if it does not exist\n\tif !channelExists {\n\t\tchannel := declarativeconfig.Channel{\n\t\t\tSchema:  fbcutil.SchemaChannel,\n\t\t\tName:    f.ChannelName,\n\t\t\tPackage: f.Package,\n\t\t\tEntries: entries,\n\t\t}\n\t\textraDeclConfig.Channels = []declarativeconfig.Channel{channel}\n\t}\n\n\t// always add the package as we are starting with a new empty DeclarativeConfig\n\tpackageBlob := declarativeconfig.Package{\n\t\tSchema:         fbcutil.SchemaPackage,\n\t\tName:           f.Package,\n\t\tDefaultChannel: f.ChannelName,\n\t}\n\textraDeclConfig.Packages = []declarativeconfig.Package{packageBlob}\n\n\t// copy over any other FBC metadata\n\textraDeclConfig.Others = originalDeclCfg.Others\n\n\treturn extraDeclConfig, nil\n}\n\n// UpdateCatalog links a new registry pod in catalog source by updating the address and annotations,\n// then deletes existing registry pod based on annotation name found in catalog source object\nfunc (c IndexImageCatalogCreator) UpdateCatalog(ctx context.Context, cs *v1alpha1.CatalogSource, subscription *v1alpha1.Subscription) error {\n\tvar prevRegistryPodName string\n\n\tif subscription != nil && c.ChannelName == \"\" {\n\t\tc.ChannelName = subscription.Spec.Channel\n\t}\n\n\tif c.ChannelName == \"\" {\n\t\tc.ChannelName = fbcutil.DefaultChannel\n\t}\n\n\tif annotations := cs.GetAnnotations(); len(annotations) != 0 {\n\t\tif value, hasAnnotation := annotations[indexImageAnnotation]; hasAnnotation && value != \"\" {\n\t\t\tc.IndexImage = value\n\t\t}\n\n\t\t// search for the list of the previous injected bundles using the catalog source's annotations\n\t\tif value, hasAnnotation := annotations[injectedBundlesAnnotation]; hasAnnotation && value != \"\" {\n\t\t\tvar injectedBundles []map[string]any\n\t\t\tif err := json.Unmarshal([]byte(annotations[injectedBundlesAnnotation]), &injectedBundles); err != nil {\n\t\t\t\treturn fmt.Errorf(\"unable to unmarshal injected bundles json: %v\", err)\n\t\t\t}\n\t\t\tfor i := range injectedBundles {\n\t\t\t\tc.PreviousBundles = append(c.PreviousBundles, injectedBundles[i][\"imageTag\"].(string))\n\t\t\t}\n\t\t}\n\t\tprevRegistryPodName = annotations[registryPodNameAnnotation]\n\t}\n\n\texistingItems, err := getExistingBundleItems(cs.GetAnnotations())\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error getting existing bundles from CatalogSource %s annotations: %v\", cs.GetName(), err)\n\t}\n\tannotationsNotFound := len(existingItems) == 0\n\n\tif annotationsNotFound {\n\t\tif cs.Spec.Image == \"\" {\n\t\t\t// if no annotations exist and image reference is empty, error out\n\t\t\treturn errors.New(\"cannot upgrade: no catalog image reference exists in catalog source spec or annotations\")\n\t\t}\n\n\t\t// if no annotations exist and image reference exists, set it to index image\n\t\tc.IndexImage = cs.Spec.Image\n\n\t\t// check if index image adopts File-Based Catalog or SQLite index image format\n\t\tisFBCImage, err := fbcutil.IsFBC(ctx, c.IndexImage)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"unable to determine if index image adopts File-Based Catalog or SQLite format: %v\", err)\n\t\t}\n\t\tc.HasFBCLabel = isFBCImage\n\n\t\t// Upgrade a bundle that was installed using OLM\n\t\tif c.HasFBCLabel {\n\t\t\t// bundle add modes are not supported for FBC\n\t\t\tif c.BundleAddMode != \"\" {\n\t\t\t\treturn fmt.Errorf(\"specifying the bundle add mode is not supported for File-Based Catalog bundles and index images\")\n\t\t\t}\n\n\t\t\t// Upgrading when installed traditionally by OLM\n\t\t\tupgradedFBC, err := handleTraditionalUpgrade(ctx, c.IndexImage, c.BundleImage, subscription.Spec.Channel, c.SkipTLSVerify, c.UseHTTP)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"unable to upgrade bundle: %v\", err)\n\t\t\t}\n\t\t\tc.FBCContent = upgradedFBC\n\t\t}\n\t} else {\n\t\t// check if index image adopts File-Based Catalog or SQLite index image format\n\t\tisFBCImage, err := fbcutil.IsFBC(ctx, c.IndexImage)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error in upgrading the bundle %q that was installed traditionally\", c.BundleImage)\n\t\t}\n\t\tc.HasFBCLabel = isFBCImage\n\n\t\t// Upgrade an installed bundle from catalog source annotations\n\t\tif c.HasFBCLabel {\n\t\t\t// bundle add modes are not supported for FBC\n\t\t\tif c.BundleAddMode != \"\" {\n\t\t\t\treturn fmt.Errorf(\"specifying the bundle add mode is not supported for File-Based Catalog bundles and index images\")\n\t\t\t}\n\n\t\t\terr = c.runFBCUpgrade(ctx)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"error in upgrading FBC: %v\", err)\n\t\t\t}\n\t\t}\n\t}\n\n\tc.setAddMode()\n\n\tnewItem := index.BundleItem{ImageTag: c.BundleImage, AddMode: c.BundleAddMode}\n\texistingItems = append(existingItems, newItem)\n\n\topts := []func(*v1alpha1.CatalogSource){\n\t\t// set `spec.Image` field to empty as we set the address in CatalogSource to registry pod IP\n\t\tfunc(cs *v1alpha1.CatalogSource) { cs.Spec.Image = \"\" },\n\t}\n\n\t// Add non-present secrets to the CatalogSource so private bundle images can be pulled.\n\tif !gofunk.ContainsString(cs.Spec.Secrets, c.SecretName) {\n\t\topts = append(opts, withSecrets(c.SecretName))\n\t}\n\n\tif err := c.createAnnotatedRegistry(ctx, cs, existingItems, opts...); err != nil {\n\t\treturn fmt.Errorf(\"error creating registry: %v\", err)\n\t}\n\n\tlog.Infof(\"Updated catalog source %s with address and annotations\", cs.GetName())\n\n\tif prevRegistryPodName != \"\" {\n\t\tif err = c.deleteRegistryPod(ctx, prevRegistryPodName); err != nil {\n\t\t\treturn fmt.Errorf(\"error cleaning up previous registry: %v\", err)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// Default add mode here since it depends on an existing annotation.\n// TODO(v2.0.0): this should default to semver mode.\nfunc (c *IndexImageCatalogCreator) setAddMode() {\n\tif c.BundleAddMode == \"\" {\n\t\tif strings.HasPrefix(c.IndexImage, fbcutil.DefaultIndexImageBase) {\n\t\t\tc.BundleAddMode = index.SemverBundleAddMode\n\t\t} else {\n\t\t\tc.BundleAddMode = index.ReplacesBundleAddMode\n\t\t}\n\t}\n}\n\n// createAnnotatedRegistry creates a registry pod and updates cs with annotations constructed\n// from items and that pod, then applies updateFields.\nfunc (c IndexImageCatalogCreator) createAnnotatedRegistry(ctx context.Context, cs *v1alpha1.CatalogSource,\n\titems []index.BundleItem, updates ...func(*v1alpha1.CatalogSource)) (err error) {\n\tvar pod *corev1.Pod\n\tif c.IndexImage == \"\" {\n\t\tc.IndexImage = fbcutil.DefaultIndexImage\n\t}\n\tif c.InitImage == \"\" {\n\t\tc.InitImage = fbcutil.DefaultInitImage\n\t}\n\n\tif c.HasFBCLabel {\n\t\t// Initialize and create the FBC registry pod.\n\t\tfbcRegistryPod := fbcindex.FBCRegistryPod{\n\t\t\tBundleItems:     items,\n\t\t\tIndexImage:      c.IndexImage,\n\t\t\tInitImage:       c.InitImage,\n\t\t\tFBCContent:      c.FBCContent,\n\t\t\tSecurityContext: c.SecurityContext.String(),\n\t\t\tImagePullPolicy: corev1.PullPolicy(c.ImagePullPolicy),\n\t\t}\n\n\t\tpod, err = fbcRegistryPod.Create(ctx, c.cfg, cs)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t} else {\n\t\t// Initialize and create registry pod\n\t\tregistryPod := index.SQLiteRegistryPod{\n\t\t\tBundleItems:     items,\n\t\t\tIndexImage:      c.IndexImage,\n\t\t\tSecretName:      c.SecretName,\n\t\t\tCASecretName:    c.CASecretName,\n\t\t\tSkipTLSVerify:   c.SkipTLSVerify,\n\t\t\tUseHTTP:         c.UseHTTP,\n\t\t\tSecurityContext: c.SecurityContext.String(),\n\t\t\tImagePullPolicy: corev1.PullPolicy(c.ImagePullPolicy),\n\t\t}\n\n\t\tif registryPod.DBPath, err = c.getDBPath(ctx); err != nil {\n\t\t\treturn fmt.Errorf(\"get database path: %v\", err)\n\t\t}\n\n\t\tpod, err = registryPod.Create(ctx, c.cfg, cs)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// JSON marshal injected bundles\n\tinjectedBundlesJSON, err := json.Marshal(items)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error marshaling added bundles: %v\", err)\n\t}\n\t// Annotations for catalog source\n\tupdatedAnnotations := map[string]string{\n\t\tindexImageAnnotation:      c.IndexImage,\n\t\tinjectedBundlesAnnotation: string(injectedBundlesJSON),\n\t\tregistryPodNameAnnotation: pod.GetName(),\n\t}\n\n\t// Update catalog source with source type as grpc, new registry pod address as the pod IP,\n\t// and annotations from items and the pod.\n\tkey := types.NamespacedName{Namespace: cs.GetNamespace(), Name: cs.GetName()}\n\tif err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {\n\t\tif err := c.cfg.Client.Get(ctx, key, cs); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tupdateCatalogSourceFields(cs, pod, updatedAnnotations)\n\t\tfor _, update := range updates {\n\t\t\tupdate(cs)\n\t\t}\n\t\treturn c.cfg.Client.Update(ctx, cs)\n\t}); err != nil {\n\t\treturn fmt.Errorf(\"error updating catalog source: %w\", err)\n\t}\n\n\treturn nil\n}\n\n// getDBPath returns the database path from the index image's labels.\nfunc (c IndexImageCatalogCreator) getDBPath(ctx context.Context) (string, error) {\n\tlabels, err := registryutil.GetImageLabels(ctx, nil, c.IndexImage, false)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"get index image labels: %v\", err)\n\t}\n\treturn labels[\"operators.operatorframework.io.index.database.v1\"], nil\n}\n\n// updateCatalogSourceFields updates cs's spec to reference targetPod's IP address for a gRPC connection\n// and overwrites all annotations with keys matching those in newAnnotations.\nfunc updateCatalogSourceFields(cs *v1alpha1.CatalogSource, targetPod *corev1.Pod, newAnnotations map[string]string) {\n\t// set `spec.Address` and `spec.SourceType` as grpc\n\tcs.Spec.Address = index.GetRegistryPodHost(targetPod.Status.PodIP)\n\tcs.Spec.SourceType = v1alpha1.SourceTypeGrpc\n\n\t// set annotations\n\tannotations := cs.GetAnnotations()\n\tif annotations == nil {\n\t\tannotations = make(map[string]string, len(newAnnotations))\n\t}\n\tfor k, v := range newAnnotations {\n\t\tannotations[k] = v\n\t}\n\tcs.SetAnnotations(annotations)\n}\n\n// getExistingBundleItems reads and decodes the value of injectedBundlesAnnotation\n// if it exists. len(items) == 0 if no annotation is found or is empty.\nfunc getExistingBundleItems(annotations map[string]string) (items []index.BundleItem, err error) {\n\tif len(annotations) == 0 {\n\t\treturn items, nil\n\t}\n\texistingBundleItems, hasItems := annotations[injectedBundlesAnnotation]\n\tif !hasItems || existingBundleItems == \"\" {\n\t\treturn items, nil\n\t}\n\tif err = json.Unmarshal([]byte(existingBundleItems), &items); err != nil {\n\t\treturn items, fmt.Errorf(\"error unmarshaling existing bundles: %v\", err)\n\t}\n\treturn items, nil\n}\n\nfunc (c IndexImageCatalogCreator) deleteRegistryPod(ctx context.Context, podName string) error {\n\t// get registry pod key\n\tpodKey := types.NamespacedName{\n\t\tNamespace: c.cfg.Namespace,\n\t\tName:      podName,\n\t}\n\n\tpod := corev1.Pod{}\n\tpodCheck := wait.ConditionWithContextFunc(func(pctx context.Context) (done bool, err error) {\n\t\tif err := c.cfg.Client.Get(pctx, podKey, &pod); err != nil {\n\t\t\treturn false, fmt.Errorf(\"error getting previous registry pod %s: %w\", podName, err)\n\t\t}\n\t\treturn true, nil\n\t})\n\n\tif err := wait.PollUntilContextCancel(ctx, 200*time.Millisecond, false, podCheck); err != nil {\n\t\treturn fmt.Errorf(\"error getting previous registry pod: %v\", err)\n\t}\n\n\tif err := c.cfg.Client.Delete(ctx, &pod); err != nil && !apierrors.IsNotFound(err) {\n\t\treturn fmt.Errorf(\"delete %q: %v\", pod.GetName(), err)\n\t} else if err == nil {\n\t\tlog.Infof(\"Deleted previous registry pod with name %q\", pod.GetName())\n\t}\n\n\t// Failure of the old pod to clean up should block and cause the caller to error out if it fails,\n\t// since the old pod may still be connected to OLM.\n\tif err := wait.PollUntilContextCancel(ctx, 200*time.Millisecond, false, func(pctx context.Context) (bool, error) {\n\t\tif err := c.cfg.Client.Get(pctx, podKey, &pod); apierrors.IsNotFound(err) {\n\t\t\treturn true, nil\n\t\t} else if err != nil {\n\t\t\treturn false, err\n\t\t}\n\t\treturn false, nil\n\t}); err != nil {\n\t\treturn fmt.Errorf(\"old registry pod %q failed to delete (%v), requires manual cleanup\", pod.GetName(), err)\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "internal/olm/operator/registry/index_image_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage registry\n\nimport (\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nvar _ = Describe(\"IndexImage\", func() {\n\tContext(\"SecurityContext\", func() {\n\t\tDescribe(\"String\", func() {\n\t\t\tIt(\"should return a string value of the enum\", func() {\n\t\t\t\tsc := SecurityContext{}\n\t\t\t\tExpect(sc.String()).To(Equal(\"\"))\n\t\t\t\tsc = SecurityContext{ContextType: Legacy}\n\t\t\t\tExpect(sc.String()).To(Equal(\"legacy\"))\n\t\t\t})\n\t\t})\n\t\tDescribe(\"Set\", func() {\n\t\t\tvar sc SecurityContext\n\t\t\tBeforeEach(func() {\n\t\t\t\tsc = SecurityContext{}\n\t\t\t\tExpect(sc.String()).To(Equal(\"\"))\n\t\t\t})\n\t\t\tIt(\"should not error with valid values\", func() {\n\t\t\t\terr := sc.Set(\"legacy\")\n\t\t\t\tExpect(sc.String()).To(Equal(\"legacy\"))\n\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\terr = sc.Set(\"restricted\")\n\t\t\t\tExpect(sc.String()).To(Equal(\"restricted\"))\n\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t})\n\t\t\tIt(\"should return an error with unsupported values\", func() {\n\t\t\t\terr := sc.Set(\"fake\")\n\t\t\t\tExpect(err).To(HaveOccurred())\n\t\t\t\tExpect(err.Error()).To(Equal(\"must be one of \\\"legacy\\\", or \\\"restricted\\\"\"))\n\n\t\t\t\terr = sc.Set(\"\")\n\t\t\t\tExpect(err).To(HaveOccurred())\n\t\t\t\tExpect(err.Error()).To(Equal(\"must be one of \\\"legacy\\\", or \\\"restricted\\\"\"))\n\t\t\t})\n\t\t})\n\t\tDescribe(\"IsEmpty\", func() {\n\t\t\tvar sc SecurityContext\n\t\t\tBeforeEach(func() {\n\t\t\t\tsc = SecurityContext{}\n\t\t\t\tExpect(sc.String()).To(Equal(\"\"))\n\t\t\t})\n\t\t\tIt(\"should return true default instantiation\", func() {\n\t\t\t\tExpect(sc.IsEmpty()).To(BeTrue())\n\t\t\t})\n\t\t\tIt(\"should return false if set a value\", func() {\n\t\t\t\t_ = sc.Set(\"legacy\")\n\t\t\t\tExpect(sc.IsEmpty()).To(BeFalse())\n\n\t\t\t\t_ = sc.Set(\"restricted\")\n\t\t\t\tExpect(sc.IsEmpty()).To(BeFalse())\n\t\t\t})\n\t\t})\n\t\tDescribe(\"Type\", func() {\n\t\t\tIt(\"should return SecurityContext\", func() {\n\t\t\t\tsc := SecurityContext{}\n\t\t\t\tExpect(sc.Type()).To(Equal(\"SecurityContext\"))\n\t\t\t})\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "internal/olm/operator/registry/olm_resources.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage registry\n\nimport (\n\t\"fmt\"\n\n\tv1 \"github.com/operator-framework/api/pkg/operators/v1\"\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/olm/operator\"\n\t\"github.com/operator-framework/operator-sdk/internal/util/k8sutil\"\n)\n\nfunc getSubscriptionName(csvName string) string {\n\tname := k8sutil.FormatOperatorNameDNS1123(csvName)\n\treturn fmt.Sprintf(\"%s-sub\", name)\n}\n\n// withCatalogSource returns a function that sets the Subscription argument's\n// target CatalogSource's name and namespace.\nfunc withCatalogSource(csName, csNamespace string) func(*v1alpha1.Subscription) {\n\treturn func(sub *v1alpha1.Subscription) {\n\t\tsub.Spec.CatalogSource = csName\n\t\tsub.Spec.CatalogSourceNamespace = csNamespace\n\t}\n}\n\n// withPackageChannel returns a function that sets the Subscription argument's\n// target package, channel, and starting CSV to those in channel.\nfunc withPackageChannel(pkgName, channelName, startingCSV string) func(*v1alpha1.Subscription) {\n\treturn func(sub *v1alpha1.Subscription) {\n\t\tsub.Spec.Package = pkgName\n\t\tsub.Spec.Channel = channelName\n\t\tsub.Spec.StartingCSV = startingCSV\n\t}\n}\n\n// withInstallPlanApproval sets the Subscription's install plan approval field\n// to manual\nfunc withInstallPlanApproval(approval v1alpha1.Approval) func(*v1alpha1.Subscription) {\n\treturn func(sub *v1alpha1.Subscription) {\n\t\tif sub.Spec == nil {\n\t\t\tsub.Spec = &v1alpha1.SubscriptionSpec{}\n\t\t}\n\t\tsub.Spec.InstallPlanApproval = approval\n\t}\n}\n\n// newSubscription creates a new Subscription for a CSV with a name derived\n// from csvName, the CSV's objectmeta.name, in namespace. opts will be applied\n// to the Subscription object.\nfunc newSubscription(csvName, namespace string, opts ...func(*v1alpha1.Subscription)) *v1alpha1.Subscription {\n\tsub := &v1alpha1.Subscription{}\n\tsub.SetGroupVersionKind(v1alpha1.SchemeGroupVersion.WithKind(v1alpha1.SubscriptionKind))\n\tsub.SetName(getSubscriptionName(csvName))\n\tsub.SetNamespace(namespace)\n\tsub.Spec = &v1alpha1.SubscriptionSpec{}\n\tfor _, opt := range opts {\n\t\topt(sub)\n\t}\n\treturn sub\n}\n\nfunc withSDKPublisher(pkgName string) func(*v1alpha1.CatalogSource) {\n\treturn func(cs *v1alpha1.CatalogSource) {\n\t\tcs.Spec.DisplayName = pkgName\n\t\tcs.Spec.Publisher = \"operator-sdk\"\n\t}\n}\n\n// withSecrets adds secretNames to a CatalogSource's secrets. Secrets are\n// assumed to be image pull secrets (\"type: kubernetes.io/dockerconfigjson\").\nfunc withSecrets(secretNames ...string) func(*v1alpha1.CatalogSource) {\n\treturn func(cs *v1alpha1.CatalogSource) {\n\t\tcs.Spec.Secrets = append(cs.Spec.Secrets, secretNames...)\n\t}\n}\n\nfunc withGrpcPodSecurityContextConfig(securityContextConfig string) func(*v1alpha1.CatalogSource) {\n\treturn func(cs *v1alpha1.CatalogSource) {\n\t\tif cs.Spec.GrpcPodConfig == nil {\n\t\t\tcs.Spec.GrpcPodConfig = &v1alpha1.GrpcPodConfig{}\n\t\t}\n\t\tcs.Spec.GrpcPodConfig.SecurityContextConfig = v1alpha1.SecurityConfig(securityContextConfig)\n\t}\n}\n\n// newCatalogSource creates a new CatalogSource with a name derived from\n// pkgName, the package manifest's packageName, in namespace. opts will\n// be applied to the CatalogSource object.\nfunc newCatalogSource(name, namespace string, opts ...func(*v1alpha1.CatalogSource)) *v1alpha1.CatalogSource {\n\tcs := &v1alpha1.CatalogSource{}\n\tcs.SetGroupVersionKind(v1alpha1.SchemeGroupVersion.WithKind(v1alpha1.CatalogSourceKind))\n\tcs.SetName(name)\n\tcs.SetNamespace(namespace)\n\tfor _, opt := range opts {\n\t\topt(cs)\n\t}\n\treturn cs\n}\n\n// withTargetNamespaces returns a function that sets the OperatorGroup argument's targetNamespaces to namespaces.\n// namespaces can be length 0..N; if namespaces length is 0, targetNamespaces is unset, indicating a global scope.\nfunc withTargetNamespaces(namespaces ...string) func(*v1.OperatorGroup) {\n\treturn func(og *v1.OperatorGroup) {\n\t\tif len(namespaces) != 0 && namespaces[0] != \"\" {\n\t\t\tog.Spec.TargetNamespaces = namespaces\n\t\t}\n\t}\n}\n\n// newSDKOperatorGroup creates a new OperatorGroup with name\n// sdkOperatorGroupName in namespace. opts will be applied to the\n// OperatorGroup object. Note that the default OperatorGroup has a global\n// scope.\nfunc newSDKOperatorGroup(namespace string, opts ...func(*v1.OperatorGroup)) *v1.OperatorGroup {\n\tog := &v1.OperatorGroup{}\n\tog.SetGroupVersionKind(v1.SchemeGroupVersion.WithKind(v1.OperatorGroupKind))\n\tog.SetName(operator.SDKOperatorGroupName)\n\tog.SetNamespace(namespace)\n\tfor _, opt := range opts {\n\t\topt(og)\n\t}\n\treturn og\n}\n"
  },
  {
    "path": "internal/olm/operator/registry/olm_resources_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage registry\n\nimport (\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nvar _ = Describe(\"newCatalogSource\", func() {\n\tDescribe(\"newCatalogSource\", func() {\n\t\tIt(\"should create a CatalogSource with name and namespace set\", func() {\n\t\t\tcs := newCatalogSource(\"fakeName\", \"fakeNS\")\n\t\t\tExpect(cs.ObjectMeta.Name).To(Equal(\"fakeName\"))\n\t\t\tExpect(cs.ObjectMeta.Namespace).To(Equal(\"fakeNS\"))\n\t\t})\n\t})\n\tDescribe(\"withSDKPublisher\", func() {\n\t\tIt(\"should set the display name and publisher of a CatalogSource\", func() {\n\t\t\tcs := newCatalogSource(\"fakeName\", \"fakeNS\", withSDKPublisher(\"fakeDisplay\"))\n\t\t\tExpect(cs.Spec.DisplayName).To(Equal(\"fakeDisplay\"))\n\t\t\tExpect(cs.Spec.Publisher).To(Equal(\"operator-sdk\"))\n\t\t})\n\t})\n\tDescribe(\"withInstallPlanApproval\", func() {\n\t\tIt(\"should set the display name and publisher of a CatalogSource\", func() {\n\t\t\tcs := newCatalogSource(\"fakeName\", \"fakeNS\", withSDKPublisher(\"fakeDisplay\"))\n\t\t\tExpect(cs.Spec.DisplayName).To(Equal(\"fakeDisplay\"))\n\t\t\tExpect(cs.Spec.Publisher).To(Equal(\"operator-sdk\"))\n\t\t})\n\t})\n\n})\n"
  },
  {
    "path": "internal/olm/operator/registry/operator_installer.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage registry\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"time\"\n\n\tv1 \"github.com/operator-framework/api/pkg/operators/v1\"\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\tlog \"github.com/sirupsen/logrus\"\n\t\"k8s.io/apimachinery/pkg/types\"\n\t\"k8s.io/apimachinery/pkg/util/wait\"\n\t\"k8s.io/client-go/util/retry\"\n\t\"k8s.io/utils/set\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client\"\n\n\tolmclient \"github.com/operator-framework/operator-sdk/internal/olm/client\"\n\t\"github.com/operator-framework/operator-sdk/internal/olm/operator\"\n\n\tcorev1 \"k8s.io/api/core/v1\"\n)\n\ntype OperatorInstaller struct {\n\tCatalogSourceName     string\n\tPackageName           string\n\tStartingCSV           string\n\tChannel               string\n\tInstallMode           operator.InstallMode\n\tCatalogCreator        CatalogCreator\n\tCatalogUpdater        CatalogUpdater\n\tSupportedInstallModes set.Set[string]\n\n\tcfg *operator.Configuration\n}\n\nfunc NewOperatorInstaller(cfg *operator.Configuration) *OperatorInstaller {\n\treturn &OperatorInstaller{cfg: cfg}\n}\n\nfunc (o OperatorInstaller) InstallOperator(ctx context.Context) (*v1alpha1.ClusterServiceVersion, error) {\n\tcs, err := o.CatalogCreator.CreateCatalog(ctx, o.CatalogSourceName)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"create catalog: %v\", err)\n\t}\n\tlog.Infof(\"Created CatalogSource: %s\", cs.GetName())\n\n\t// TODO: OLM doesn't appear to propagate the \"READY\" connection status to the\n\t// catalogsource in a timely manner even though its catalog-operator reports\n\t// a connection almost immediately. This condition either needs to be\n\t// propagated more quickly by OLM or we need to find a different resource to\n\t// probe for readiness.\n\t//\n\t// if err := o.waitForCatalogSource(ctx, cs); err != nil {\n\t// \treturn nil, err\n\t// }\n\n\t// Ensure Operator Group\n\tif err = o.ensureOperatorGroup(ctx); err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar subscription *v1alpha1.Subscription\n\t// Create Subscription\n\tif subscription, err = o.createSubscription(ctx, cs.GetName()); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Wait for the Install Plan to be generated\n\tif err = o.waitForInstallPlan(ctx, subscription); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Approve Install Plan for the subscription\n\tif err = o.approveInstallPlan(ctx, subscription); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Wait for successfully installed CSV\n\tcsv, err := o.getInstalledCSV(ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tlog.Infof(\"OLM has successfully installed %q\", o.StartingCSV)\n\n\treturn csv, nil\n}\n\nfunc (o OperatorInstaller) UpgradeOperator(ctx context.Context) (*v1alpha1.ClusterServiceVersion, error) {\n\tsubList := &v1alpha1.SubscriptionList{}\n\n\toptions := client.ListOptions{\n\t\tNamespace: o.cfg.Namespace,\n\t}\n\tif err := o.cfg.Client.List(ctx, subList, &options); err != nil {\n\t\treturn nil, fmt.Errorf(\"error getting list of subscriptions: %v\", err)\n\t}\n\n\t// If there are no subscriptions found, then the previous operator version doesn't exist, so return error\n\tif len(subList.Items) == 0 {\n\t\treturn nil, errors.New(\"no existing operator found in the cluster to upgrade\")\n\t}\n\n\tvar subscription *v1alpha1.Subscription\n\tfor i := range subList.Items {\n\t\ts := subList.Items[i]\n\t\tif o.PackageName == s.Spec.Package {\n\t\t\tsubscription = &s\n\t\t\tbreak\n\t\t}\n\t}\n\n\tif subscription == nil {\n\t\treturn nil, fmt.Errorf(\"subscription for package %q not found\", o.PackageName)\n\t}\n\n\tlog.Infof(\"Found existing subscription with name %s and namespace %s\", subscription.Name, subscription.Namespace)\n\n\t// Get existing catalog source from the subsription\n\tcatsrcKey := types.NamespacedName{\n\t\tNamespace: subscription.Spec.CatalogSourceNamespace,\n\t\tName:      subscription.Spec.CatalogSource,\n\t}\n\n\tcs := &v1alpha1.CatalogSource{}\n\tif err := o.cfg.Client.Get(ctx, catsrcKey, cs); err != nil {\n\t\treturn nil, fmt.Errorf(\"error getting catalog source matching the existing subscription: %w\", err)\n\t}\n\tlog.Infof(\"Found existing catalog source with name %s and namespace %s\", cs.Name, cs.Namespace)\n\n\t// Update catalog source\n\terr := o.CatalogUpdater.UpdateCatalog(ctx, cs, subscription)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"update catalog error: %v\", err)\n\t}\n\n\t// Wait for the Install Plan to be generated\n\tif err = o.waitForInstallPlan(ctx, subscription); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Approve Install Plan for the subscription\n\tif err = o.approveInstallPlan(ctx, subscription); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Wait for successfully installed CSV\n\tcsv, err := o.getInstalledCSV(ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tlog.Infof(\"Successfully upgraded to %q\", o.StartingCSV)\n\n\treturn csv, nil\n}\n\n//nolint:unused\nfunc (o OperatorInstaller) waitForCatalogSource(ctx context.Context, cs *v1alpha1.CatalogSource) error {\n\tcatSrcKey := client.ObjectKeyFromObject(cs)\n\n\t// verify that catalog source connection status is READY\n\tcatSrcCheck := wait.ConditionWithContextFunc(func(pctx context.Context) (done bool, err error) {\n\t\tif err := o.cfg.Client.Get(pctx, catSrcKey, cs); err != nil {\n\t\t\treturn false, err\n\t\t}\n\t\tif cs.Status.GRPCConnectionState != nil {\n\t\t\tif cs.Status.GRPCConnectionState.LastObservedState == \"READY\" {\n\t\t\t\treturn true, nil\n\t\t\t}\n\t\t}\n\t\treturn false, nil\n\t})\n\n\tif err := wait.PollUntilContextCancel(ctx, 200*time.Millisecond, false, catSrcCheck); err != nil {\n\t\treturn fmt.Errorf(\"catalog source connection is not ready: %v\", err)\n\t}\n\n\treturn nil\n}\n\nfunc (o OperatorInstaller) ensureOperatorGroup(ctx context.Context) error {\n\t// Check OperatorGroup existence, since we cannot create a second OperatorGroup in namespace.\n\tog, ogFound, err := o.getOperatorGroup(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tsupported := o.SupportedInstallModes\n\n\t// --install-mode was given\n\tif !o.InstallMode.IsEmpty() {\n\t\tif o.InstallMode.InstallModeType == v1alpha1.InstallModeTypeSingleNamespace &&\n\t\t\to.InstallMode.TargetNamespaces[0] == o.cfg.Namespace {\n\t\t\treturn fmt.Errorf(\"use install mode %q to watch operator's namespace %q\", v1alpha1.InstallModeTypeOwnNamespace, o.cfg.Namespace)\n\t\t}\n\n\t\tsupported = supported.Intersection(set.New(string(o.InstallMode.InstallModeType)))\n\t\tif supported.Len() == 0 {\n\t\t\treturn fmt.Errorf(\"operator %q does not support install mode %q\", o.StartingCSV, o.InstallMode.InstallModeType)\n\t\t}\n\t}\n\n\ttargetNamespaces, err := o.getTargetNamespaces(supported)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif !ogFound {\n\t\tif og, err = o.createOperatorGroup(ctx, targetNamespaces); err != nil {\n\t\t\treturn fmt.Errorf(\"create operator group: %v\", err)\n\t\t}\n\t\tlog.Infof(\"OperatorGroup %q created\", og.Name)\n\t} else if err := o.isOperatorGroupCompatible(*og, targetNamespaces); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc (o *OperatorInstaller) createOperatorGroup(ctx context.Context, targetNamespaces []string) (*v1.OperatorGroup, error) {\n\tog := newSDKOperatorGroup(o.cfg.Namespace, withTargetNamespaces(targetNamespaces...))\n\tif err := o.cfg.Client.Create(ctx, og); err != nil {\n\t\treturn nil, err\n\t}\n\treturn og, nil\n}\n\nfunc (o *OperatorInstaller) isOperatorGroupCompatible(og v1.OperatorGroup, targetNamespaces []string) error {\n\t// no install mode use the existing operator group\n\tif o.InstallMode.IsEmpty() {\n\t\treturn nil\n\t}\n\n\t// otherwise, check that the target namespaces match\n\ttargets := set.New(targetNamespaces...)\n\togtargets := set.New(og.Spec.TargetNamespaces...)\n\tif !ogtargets.Equal(targets) {\n\t\treturn fmt.Errorf(\"existing operatorgroup %q is not compatible with install mode %q\", og.Name, o.InstallMode)\n\t}\n\n\treturn nil\n}\n\n// getOperatorGroup returns true if an OperatorGroup in the desired namespace was found.\n// If more than one operator group exists in namespace, this function will return an error\n// since CSVs in namespace will have an error status in that case.\nfunc (o OperatorInstaller) getOperatorGroup(ctx context.Context) (*v1.OperatorGroup, bool, error) {\n\togList := &v1.OperatorGroupList{}\n\tif err := o.cfg.Client.List(ctx, ogList, client.InNamespace(o.cfg.Namespace)); err != nil {\n\t\treturn nil, false, err\n\t}\n\tif len(ogList.Items) == 0 {\n\t\treturn nil, false, nil\n\t}\n\tif len(ogList.Items) != 1 {\n\t\tvar names []string\n\t\tfor _, og := range ogList.Items {\n\t\t\tnames = append(names, og.GetName())\n\t\t}\n\t\treturn nil, true, fmt.Errorf(\"more than one operator group in namespace %s: %+q\", o.cfg.Namespace, names)\n\t}\n\treturn &ogList.Items[0], true, nil\n}\n\nfunc (o OperatorInstaller) createSubscription(ctx context.Context, csName string) (*v1alpha1.Subscription, error) {\n\tsub := newSubscription(o.StartingCSV, o.cfg.Namespace,\n\t\twithPackageChannel(o.PackageName, o.Channel, o.StartingCSV),\n\t\twithCatalogSource(csName, o.cfg.Namespace),\n\t\twithInstallPlanApproval(v1alpha1.ApprovalManual))\n\n\tif err := o.cfg.Client.Create(ctx, sub); err != nil {\n\t\treturn nil, fmt.Errorf(\"error creating subscription: %w\", err)\n\t}\n\tlog.Infof(\"Created Subscription: %s\", sub.Name)\n\n\treturn sub, nil\n}\n\nfunc (o OperatorInstaller) getInstalledCSV(ctx context.Context) (*v1alpha1.ClusterServiceVersion, error) {\n\tc := olmclient.Client{KubeClient: o.cfg.Client}\n\n\t// BUG(estroz): if namespace is not contained in targetNamespaces,\n\t// DoCSVWait will fail because the CSV is not deployed in namespace.\n\tnn := types.NamespacedName{\n\t\tName:      o.StartingCSV,\n\t\tNamespace: o.cfg.Namespace,\n\t}\n\tlog.Infof(\"Waiting for ClusterServiceVersion %q to reach 'Succeeded' phase\", nn)\n\tif err := c.DoCSVWait(ctx, nn); err != nil {\n\t\treturn nil, fmt.Errorf(\"error waiting for CSV to install: %w\", err)\n\t}\n\n\t// TODO: check status of all resources in the desired bundle/package.\n\tcsv := &v1alpha1.ClusterServiceVersion{}\n\tif err := o.cfg.Client.Get(ctx, nn, csv); err != nil {\n\t\treturn nil, fmt.Errorf(\"error getting installed CSV: %w\", err)\n\t}\n\treturn csv, nil\n}\n\n// approveInstallPlan approves the install plan for a subscription, which will\n// generate a CSV\nfunc (o OperatorInstaller) approveInstallPlan(ctx context.Context, sub *v1alpha1.Subscription) error {\n\tip := v1alpha1.InstallPlan{}\n\n\tipKey := types.NamespacedName{\n\t\tName:      sub.Status.InstallPlanRef.Name,\n\t\tNamespace: sub.Status.InstallPlanRef.Namespace,\n\t}\n\n\tif err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {\n\t\tif err := o.cfg.Client.Get(ctx, ipKey, &ip); err != nil {\n\t\t\treturn fmt.Errorf(\"error getting install plan: %v\", err)\n\t\t}\n\t\t// approve the install plan by setting Approved to true\n\t\tip.Spec.Approved = true\n\t\treturn o.cfg.Client.Update(ctx, &ip)\n\t}); err != nil {\n\t\treturn err\n\t}\n\n\tlog.Infof(\"Approved InstallPlan %s for the Subscription: %s\", ipKey.Name, sub.Name)\n\n\treturn nil\n}\n\n// waitForInstallPlan verifies if an Install Plan exists through subscription status\nfunc (o OperatorInstaller) waitForInstallPlan(ctx context.Context, sub *v1alpha1.Subscription) error {\n\tsubKey := types.NamespacedName{\n\t\tNamespace: sub.GetNamespace(),\n\t\tName:      sub.GetName(),\n\t}\n\n\t// Get the previous InstallPlanRef\n\tprevIPRef := corev1.ObjectReference{}\n\tif sub.Status.InstallPlanRef != nil {\n\t\tprevIPRef = *sub.Status.InstallPlanRef\n\t}\n\n\tipCheck := wait.ConditionWithContextFunc(func(pctx context.Context) (done bool, err error) {\n\t\tif err := o.cfg.Client.Get(pctx, subKey, sub); err != nil {\n\t\t\treturn false, err\n\t\t}\n\t\tif sub.Status.InstallPlanRef != nil && sub.Status.InstallPlanRef.Name != prevIPRef.Name {\n\t\t\treturn true, nil\n\t\t}\n\t\treturn false, nil\n\t})\n\n\tif err := wait.PollUntilContextCancel(ctx, 200*time.Millisecond, false, ipCheck); err != nil {\n\t\treturn fmt.Errorf(\"install plan is not available for the subscription %s: %v\", sub.Name, err)\n\t}\n\treturn nil\n}\n\nfunc (o *OperatorInstaller) getTargetNamespaces(supported set.Set[string]) ([]string, error) {\n\tswitch {\n\tcase supported.Has(string(v1alpha1.InstallModeTypeAllNamespaces)):\n\t\treturn nil, nil\n\tcase supported.Has(string(v1alpha1.InstallModeTypeOwnNamespace)):\n\t\treturn []string{o.cfg.Namespace}, nil\n\tcase supported.Has(string(v1alpha1.InstallModeTypeSingleNamespace)):\n\t\treturn o.InstallMode.TargetNamespaces, nil\n\tcase supported.Has(string(v1alpha1.InstallModeTypeMultiNamespace)):\n\t\tlog.Warn(\"The selected install mode MultiNamespace may cause tenancy issues and is not recommended\")\n\t\treturn o.InstallMode.TargetNamespaces, nil\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"no supported install modes\")\n\t}\n}\n"
  },
  {
    "path": "internal/olm/operator/registry/operator_installer_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage registry\n\nimport (\n\t\"context\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\tv1 \"github.com/operator-framework/api/pkg/operators/v1\"\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\t\"k8s.io/apimachinery/pkg/types\"\n\t\"k8s.io/utils/set\"\n\tcrclient \"sigs.k8s.io/controller-runtime/pkg/client\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client/fake\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/olm/operator\"\n)\n\nconst name = \"fakeName\"\nconst namespace = \"fakeNS\"\n\nvar _ = Describe(\"OperatorInstaller\", func() {\n\tDescribe(\"NewOperatorInstaller\", func() {\n\t\tIt(\"should create an OperatorInstaller\", func() {\n\t\t\tcfg := &operator.Configuration{}\n\t\t\toi := NewOperatorInstaller(cfg)\n\t\t\tExpect(oi).ToNot(BeNil())\n\t\t})\n\t})\n\n\tDescribe(\"createSubscription\", func() {\n\t\tvar (\n\t\t\toi  *OperatorInstaller\n\t\t\tsch *runtime.Scheme\n\t\t)\n\t\tBeforeEach(func() {\n\t\t\t// Setup and fake client\n\t\t\tcfg := &operator.Configuration{}\n\t\t\tsch = runtime.NewScheme()\n\t\t\tExpect(v1.AddToScheme(sch)).To(Succeed())\n\t\t\tExpect(v1alpha1.AddToScheme(sch)).To(Succeed())\n\t\t\tcfg.Client = fake.NewClientBuilder().WithScheme(sch).Build()\n\n\t\t\toi = NewOperatorInstaller(cfg)\n\t\t\toi.StartingCSV = \"testname\"\n\t\t\toi.cfg.Namespace = \"testns\"\n\t\t})\n\n\t\tIt(\"should create the subscription with the fake client\", func() {\n\t\t\tsub, err := oi.createSubscription(context.TODO(), \"huzzah\")\n\t\t\tExpect(err).ToNot(HaveOccurred())\n\n\t\t\tretSub := &v1alpha1.Subscription{}\n\t\t\tsubKey := types.NamespacedName{\n\t\t\t\tNamespace: sub.GetNamespace(),\n\t\t\t\tName:      sub.GetName(),\n\t\t\t}\n\t\t\terr = oi.cfg.Client.Get(context.TODO(), subKey, retSub)\n\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\tExpect(retSub.GetName()).To(Equal(sub.GetName()))\n\t\t\tExpect(retSub.GetNamespace()).To(Equal(sub.GetNamespace()))\n\t\t})\n\n\t\tIt(\"should pass through any client errors (duplicate)\", func() {\n\n\t\t\tsub := newSubscription(oi.StartingCSV, oi.cfg.Namespace, withCatalogSource(\"duplicate\", oi.cfg.Namespace))\n\t\t\toi.cfg.Client = fake.NewClientBuilder().WithScheme(sch).WithObjects(sub).Build()\n\n\t\t\t_, err := oi.createSubscription(context.TODO(), \"duplicate\")\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t\tExpect(err.Error()).Should(ContainSubstring(\"error creating subscription\"))\n\t\t})\n\t})\n\n\tDescribe(\"getInstalledCSV\", func() {\n\t\tvar (\n\t\t\tcfg *operator.Configuration\n\t\t\toi  *OperatorInstaller\n\t\t\tsch *runtime.Scheme\n\t\t)\n\t\tBeforeEach(func() {\n\t\t\t// Setup and fake client\n\t\t\tcfg = &operator.Configuration{}\n\t\t\tsch = runtime.NewScheme()\n\t\t\tExpect(v1.AddToScheme(sch)).To(Succeed())\n\t\t\tExpect(v1alpha1.AddToScheme(sch)).To(Succeed())\n\n\t\t\toi = NewOperatorInstaller(cfg)\n\t\t\toi.StartingCSV = \"somename\"\n\t\t\toi.cfg.Namespace = \"somenamespace\"\n\t\t})\n\t\tIt(\"should return installed CSV with no error\", func() {\n\t\t\tcfg.Client = fake.NewClientBuilder().WithScheme(sch).WithObjects(\n\t\t\t\t&v1alpha1.ClusterServiceVersion{\n\t\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\t\tName:      \"somename\",\n\t\t\t\t\t\tNamespace: \"somenamespace\",\n\t\t\t\t\t},\n\t\t\t\t\tStatus: v1alpha1.ClusterServiceVersionStatus{\n\t\t\t\t\t\tPhase: v1alpha1.CSVPhaseSucceeded,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t).Build()\n\n\t\t\tcsv, err := oi.getInstalledCSV(context.TODO())\n\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\tExpect(csv).ToNot(BeNil())\n\t\t\tExpect(csv.Name).To(Equal(\"somename\"))\n\t\t\tExpect(csv.Namespace).To(Equal(\"somenamespace\"))\n\t\t\tExpect(csv.Status.Phase).To(Equal(v1alpha1.CSVPhaseSucceeded))\n\t\t})\n\t\tIt(\"should return an error when CSV fails\", func() {\n\t\t\tcfg.Client = fake.NewClientBuilder().WithScheme(sch).WithObjects(\n\t\t\t\t&v1alpha1.ClusterServiceVersion{\n\t\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\t\tName:      \"somename\",\n\t\t\t\t\t\tNamespace: \"somenamespace\",\n\t\t\t\t\t},\n\t\t\t\t\tStatus: v1alpha1.ClusterServiceVersionStatus{\n\t\t\t\t\t\tPhase:   v1alpha1.CSVPhaseFailed,\n\t\t\t\t\t\tReason:  v1alpha1.CSVReasonInstallCheckFailed,\n\t\t\t\t\t\tMessage: \"test message\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t).Build()\n\n\t\t\tcsv, err := oi.getInstalledCSV(context.TODO())\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t\tExpect(err.Error()).Should(ContainSubstring(\"error waiting for CSV to install\"))\n\t\t\tExpect(err.Error()).Should(ContainSubstring(\"test message\"))\n\t\t\tExpect(csv).To(BeNil())\n\t\t})\n\t})\n\n\tDescribe(\"approveInstallPlan\", func() {\n\t\tvar (\n\t\t\toi  *OperatorInstaller\n\t\t\tsch *runtime.Scheme\n\t\t)\n\t\tBeforeEach(func() {\n\t\t\tcfg := &operator.Configuration{}\n\t\t\tsch = runtime.NewScheme()\n\t\t\tExpect(v1alpha1.AddToScheme(sch)).To(Succeed())\n\t\t\toi = NewOperatorInstaller(cfg)\n\t\t})\n\n\t\tIt(\"should update the install plan\", func() {\n\t\t\toi.cfg.Client = fake.NewClientBuilder().WithScheme(sch).WithObjects(\n\t\t\t\t&v1alpha1.InstallPlan{\n\t\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\t\tName:      name,\n\t\t\t\t\t\tNamespace: namespace,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t).Build()\n\n\t\t\tip := &v1alpha1.InstallPlan{}\n\t\t\tipKey := types.NamespacedName{\n\t\t\t\tNamespace: namespace,\n\t\t\t\tName:      name,\n\t\t\t}\n\n\t\t\terr := oi.cfg.Client.Get(context.TODO(), ipKey, ip)\n\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\tExpect(ip.Name).To(Equal(name))\n\t\t\tExpect(ip.Namespace).To(Equal(namespace))\n\n\t\t\t// Test\n\t\t\tsub := &v1alpha1.Subscription{\n\t\t\t\tStatus: v1alpha1.SubscriptionStatus{\n\t\t\t\t\tInstallPlanRef: &corev1.ObjectReference{\n\t\t\t\t\t\tName:      name,\n\t\t\t\t\t\tNamespace: namespace,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t\terr = oi.approveInstallPlan(context.TODO(), sub)\n\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\terr = oi.cfg.Client.Get(context.TODO(), ipKey, ip)\n\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\tExpect(ip.Name).To(Equal(name))\n\t\t\tExpect(ip.Namespace).To(Equal(namespace))\n\t\t\tExpect(ip.Spec.Approved).To(BeTrue())\n\t\t})\n\t\tIt(\"should return an error if the install plan does not exist.\", func() {\n\t\t\toi.cfg.Client = fake.NewClientBuilder().WithScheme(sch).Build()\n\t\t\tsub := &v1alpha1.Subscription{\n\t\t\t\tStatus: v1alpha1.SubscriptionStatus{\n\t\t\t\t\tInstallPlanRef: &corev1.ObjectReference{\n\t\t\t\t\t\tName:      name,\n\t\t\t\t\t\tNamespace: namespace,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t\terr := oi.approveInstallPlan(context.TODO(), sub)\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t\tExpect(err.Error()).Should(ContainSubstring(\"error getting install plan\"))\n\t\t})\n\t})\n\n\tDescribe(\"waitForInstallPlan\", func() {\n\t\tvar (\n\t\t\toi  *OperatorInstaller\n\t\t\tsch *runtime.Scheme\n\t\t)\n\t\tBeforeEach(func() {\n\t\t\t// Setup and fake client\n\t\t\tcfg := &operator.Configuration{}\n\t\t\tsch = runtime.NewScheme()\n\t\t\tExpect(v1alpha1.AddToScheme(sch)).To(Succeed())\n\t\t\tcfg.Client = fake.NewClientBuilder().WithScheme(sch).Build()\n\n\t\t\toi = NewOperatorInstaller(cfg)\n\t\t\toi.StartingCSV = name\n\t\t\toi.cfg.Namespace = namespace\n\t\t})\n\t\tIt(\"should return an error if the subscription does not exist.\", func() {\n\t\t\tsub := newSubscription(oi.StartingCSV, oi.cfg.Namespace, withCatalogSource(\"duplicate\", oi.cfg.Namespace))\n\n\t\t\terr := oi.waitForInstallPlan(context.TODO(), sub)\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t\tExpect(err.Error()).Should(ContainSubstring(\"install plan is not available for the subscription\"))\n\n\t\t})\n\t\tIt(\"should return if subscription has an install plan and previous install plan is nil\", func() {\n\t\t\tname := name\n\t\t\tnamespace := namespace\n\t\t\tprevSub := &v1alpha1.Subscription{\n\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\tName:      name,\n\t\t\t\t\tNamespace: namespace,\n\t\t\t\t},\n\t\t\t}\n\n\t\t\tsub := &v1alpha1.Subscription{\n\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\tName:      name,\n\t\t\t\t\tNamespace: namespace,\n\t\t\t\t},\n\t\t\t\tStatus: v1alpha1.SubscriptionStatus{\n\t\t\t\t\tInstallPlanRef: &corev1.ObjectReference{\n\t\t\t\t\t\tName:      name,\n\t\t\t\t\t\tNamespace: namespace,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t\terr := oi.cfg.Client.Create(context.TODO(), sub)\n\t\t\tExpect(err).ToNot(HaveOccurred())\n\n\t\t\terr = oi.waitForInstallPlan(context.TODO(), prevSub)\n\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t})\n\t\tIt(\"should return if subscription has an install plan and is different than previous install plan\", func() {\n\t\t\tname := name\n\t\t\tnamespace := namespace\n\t\t\tprevSub := &v1alpha1.Subscription{\n\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\tName:      name,\n\t\t\t\t\tNamespace: namespace,\n\t\t\t\t},\n\t\t\t\tStatus: v1alpha1.SubscriptionStatus{\n\t\t\t\t\tInstallPlanRef: &corev1.ObjectReference{\n\t\t\t\t\t\tName:      name + \"diff\",\n\t\t\t\t\t\tNamespace: namespace + \"diff\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\n\t\t\tsub := &v1alpha1.Subscription{\n\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\tName:      name,\n\t\t\t\t\tNamespace: namespace,\n\t\t\t\t},\n\t\t\t\tStatus: v1alpha1.SubscriptionStatus{\n\t\t\t\t\tInstallPlanRef: &corev1.ObjectReference{\n\t\t\t\t\t\tName:      name,\n\t\t\t\t\t\tNamespace: namespace,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t\terr := oi.cfg.Client.Create(context.TODO(), sub)\n\t\t\tExpect(err).ToNot(HaveOccurred())\n\n\t\t\terr = oi.waitForInstallPlan(context.TODO(), prevSub)\n\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t})\n\t})\n\n\tDescribe(\"ensureOperatorGroup\", func() {\n\t\tvar (\n\t\t\toi     OperatorInstaller\n\t\t\tclient crclient.Client\n\t\t)\n\t\tBeforeEach(func() {\n\t\t\tsch := runtime.NewScheme()\n\t\t\tExpect(v1.AddToScheme(sch)).To(Succeed())\n\t\t\tclient = fake.NewClientBuilder().WithScheme(sch).Build()\n\t\t\toi = OperatorInstaller{\n\t\t\t\tcfg: &operator.Configuration{\n\t\t\t\t\tScheme:    sch,\n\t\t\t\t\tClient:    client,\n\t\t\t\t\tNamespace: \"testns\",\n\t\t\t\t},\n\t\t\t}\n\n\t\t\t// setup supported install modes\n\t\t\tmodes := []v1alpha1.InstallMode{\n\t\t\t\t{\n\t\t\t\t\tType:      v1alpha1.InstallModeTypeSingleNamespace,\n\t\t\t\t\tSupported: true,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tType:      v1alpha1.InstallModeTypeOwnNamespace,\n\t\t\t\t\tSupported: true,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tType:      v1alpha1.InstallModeTypeMultiNamespace,\n\t\t\t\t\tSupported: true,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tType:      v1alpha1.InstallModeTypeAllNamespaces,\n\t\t\t\t\tSupported: true,\n\t\t\t\t},\n\t\t\t}\n\t\t\toi.SupportedInstallModes = operator.GetSupportedInstallModes(modes)\n\t\t})\n\t\tIt(\"should return an error when problems finding OperatorGroup\", func() {\n\t\t\toi.cfg.Client = fake.NewClientBuilder().Build()\n\t\t\terr := oi.ensureOperatorGroup(context.TODO())\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t})\n\t\tIt(\"should return an error if there are no supported modes\", func() {\n\t\t\toi.SupportedInstallModes = operator.GetSupportedInstallModes([]v1alpha1.InstallMode{})\n\t\t\terr := oi.ensureOperatorGroup(context.TODO())\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t\tExpect(err.Error()).Should(ContainSubstring(\"no supported install modes\"))\n\t\t})\n\t\tContext(\"with no existing OperatorGroup\", func() {\n\t\t\tContext(\"given SingleNamespace\", func() {\n\t\t\t\tIt(\"should create one with the given target namespaces\", func() {\n\t\t\t\t\t_ = oi.InstallMode.Set(string(v1alpha1.InstallModeTypeSingleNamespace))\n\t\t\t\t\toi.InstallMode.TargetNamespaces = []string{\"anotherns\"}\n\t\t\t\t\tExpect(oi.ensureOperatorGroup(context.TODO())).To(Succeed())\n\n\t\t\t\t\tog, found, err := oi.getOperatorGroup(context.TODO())\n\t\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\t\tExpect(found).To(BeTrue())\n\t\t\t\t\tExpect(og).ToNot(BeNil())\n\t\t\t\t\tExpect(og.Name).To(Equal(\"operator-sdk-og\"))\n\t\t\t\t\tExpect(og.Namespace).To(Equal(\"testns\"))\n\t\t\t\t\tExpect(og.Spec.TargetNamespaces).To(Equal([]string{\"anotherns\"}))\n\t\t\t\t})\n\t\t\t\tIt(\"should return an error if target matches operator ns\", func() {\n\t\t\t\t\t_ = oi.InstallMode.Set(string(v1alpha1.InstallModeTypeSingleNamespace))\n\t\t\t\t\toi.InstallMode.TargetNamespaces = []string{\"testns\"}\n\t\t\t\t\terr := oi.ensureOperatorGroup(context.TODO())\n\t\t\t\t\tExpect(err).To(HaveOccurred())\n\t\t\t\t\tExpect(err.Error()).Should(ContainSubstring(\"use install mode \\\"OwnNamespace\\\"\"))\n\t\t\t\t})\n\t\t\t})\n\t\t\tContext(\"given OwnNamespace\", func() {\n\t\t\t\tIt(\"should create one with the given target namespaces\", func() {\n\t\t\t\t\t_ = oi.InstallMode.Set(string(v1alpha1.InstallModeTypeOwnNamespace))\n\t\t\t\t\tExpect(oi.ensureOperatorGroup(context.TODO())).To(Succeed())\n\n\t\t\t\t\tog, found, err := oi.getOperatorGroup(context.TODO())\n\t\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\t\tExpect(found).To(BeTrue())\n\t\t\t\t\tExpect(og).ToNot(BeNil())\n\t\t\t\t\tExpect(og.Name).To(Equal(\"operator-sdk-og\"))\n\t\t\t\t\tExpect(og.Namespace).To(Equal(\"testns\"))\n\t\t\t\t\tExpect(og.Spec.TargetNamespaces).To(HaveLen(1))\n\t\t\t\t})\n\t\t\t})\n\t\t\tContext(\"given MultiNamespaces\", func() {\n\t\t\t\tIt(\"should create one with the given target namespaces\", func() {\n\t\t\t\t\t_ = oi.InstallMode.Set(string(v1alpha1.InstallModeTypeMultiNamespace))\n\t\t\t\t\toi.InstallMode.TargetNamespaces = []string{\"anotherns1\", \"anotherns2\"}\n\t\t\t\t\tExpect(oi.ensureOperatorGroup(context.TODO())).To(Succeed())\n\n\t\t\t\t\tog, found, err := oi.getOperatorGroup(context.TODO())\n\t\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\t\tExpect(found).To(BeTrue())\n\t\t\t\t\tExpect(og).ToNot(BeNil())\n\t\t\t\t\tExpect(og.Name).To(Equal(\"operator-sdk-og\"))\n\t\t\t\t\tExpect(og.Namespace).To(Equal(\"testns\"))\n\t\t\t\t\tExpect(og.Spec.TargetNamespaces).To(Equal([]string{\"anotherns1\", \"anotherns2\"}))\n\t\t\t\t})\n\t\t\t})\n\t\t\tContext(\"given AllNamespaces\", func() {\n\t\t\t\tIt(\"should create one with the given target namespaces\", func() {\n\t\t\t\t\t_ = oi.InstallMode.Set(string(v1alpha1.InstallModeTypeAllNamespaces))\n\t\t\t\t\tExpect(oi.ensureOperatorGroup(context.TODO())).To(Succeed())\n\n\t\t\t\t\tog, found, err := oi.getOperatorGroup(context.TODO())\n\t\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\t\tExpect(found).To(BeTrue())\n\t\t\t\t\tExpect(og).ToNot(BeNil())\n\t\t\t\t\tExpect(og.Name).To(Equal(\"operator-sdk-og\"))\n\t\t\t\t\tExpect(og.Namespace).To(Equal(\"testns\"))\n\t\t\t\t\tExpect(og.Spec.TargetNamespaces).To(BeEmpty())\n\t\t\t\t})\n\t\t\t})\n\t\t})\n\t\tContext(\"with an existing OperatorGroup\", func() {\n\t\t\tContext(\"given AllNamespaces\", func() {\n\t\t\t\tBeforeEach(func() {\n\t\t\t\t\t_ = oi.InstallMode.Set(string(v1alpha1.InstallModeTypeAllNamespaces))\n\t\t\t\t})\n\t\t\t\tIt(\"should return nil for AllNamespaces with empty targets\", func() {\n\t\t\t\t\t// context, client, name, ns, targets\n\t\t\t\t\toog := createOperatorGroupHelper(context.TODO(), client, \"existing-og\", \"testns\")\n\t\t\t\t\tExpect(oi.ensureOperatorGroup(context.TODO())).To(Succeed())\n\n\t\t\t\t\tog, found, err := oi.getOperatorGroup(context.TODO())\n\t\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\t\tExpect(found).To(BeTrue())\n\t\t\t\t\tExpect(og.Name).To(Equal(oog.Name))\n\t\t\t\t\tExpect(og.Namespace).To(Equal(oog.Namespace))\n\t\t\t\t})\n\t\t\t\tIt(\"should return an error for AllNamespaces when target is not empty\", func() {\n\t\t\t\t\t// context, client, name, ns, targets\n\t\t\t\t\t_ = createOperatorGroupHelper(context.TODO(), client, \"existing-og\",\n\t\t\t\t\t\t\"testns\", \"incompatiblens\")\n\t\t\t\t\terr := oi.ensureOperatorGroup(context.TODO())\n\t\t\t\t\tExpect(err).Should(HaveOccurred())\n\t\t\t\t\tExpect(err.Error()).To(ContainSubstring(\"is not compatible\"))\n\t\t\t\t})\n\t\t\t})\n\t\t\tContext(\"given OwnNamespace\", func() {\n\t\t\t\tBeforeEach(func() {\n\t\t\t\t\t_ = oi.InstallMode.Set(string(v1alpha1.InstallModeTypeOwnNamespace))\n\t\t\t\t})\n\t\t\t\tIt(\"should return nil for OwnNamespace when target matches operator\", func() {\n\t\t\t\t\toog := createOperatorGroupHelper(context.TODO(), client, \"existing-og\",\n\t\t\t\t\t\t\"testns\", \"testns\")\n\t\t\t\t\terr := oi.ensureOperatorGroup(context.TODO())\n\t\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\n\t\t\t\t\tog, found, err := oi.getOperatorGroup(context.TODO())\n\t\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\t\tExpect(found).To(BeTrue())\n\t\t\t\t\tExpect(og.Name).To(Equal(oog.Name))\n\t\t\t\t\tExpect(og.Namespace).To(Equal(oog.Namespace))\n\t\t\t\t})\n\t\t\t\tIt(\"should return an error for OwnNamespace when target does not match operator\", func() {\n\t\t\t\t\t_ = createOperatorGroupHelper(context.TODO(), client, \"existing-og\",\n\t\t\t\t\t\t\"testns\", \"incompatiblens\")\n\t\t\t\t\terr := oi.ensureOperatorGroup(context.TODO())\n\t\t\t\t\tExpect(err).Should(HaveOccurred())\n\t\t\t\t\tExpect(err.Error()).To(ContainSubstring(\"is not compatible\"))\n\t\t\t\t})\n\t\t\t})\n\t\t\tContext(\"given SingleNamespace\", func() {\n\t\t\t\tBeforeEach(func() {\n\t\t\t\t\t_ = oi.InstallMode.Set(string(v1alpha1.InstallModeTypeSingleNamespace))\n\t\t\t\t})\n\t\t\t\tIt(\"should return nil for SingleNamespace when target differs from operator\", func() {\n\t\t\t\t\toi.InstallMode.TargetNamespaces = []string{\"anotherns\"}\n\t\t\t\t\toog := createOperatorGroupHelper(context.TODO(), client, \"existing-og\",\n\t\t\t\t\t\t\"testns\", \"anotherns\")\n\t\t\t\t\tExpect(oi.ensureOperatorGroup(context.TODO())).To(Succeed())\n\n\t\t\t\t\tog, found, err := oi.getOperatorGroup(context.TODO())\n\t\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\t\tExpect(found).To(BeTrue())\n\t\t\t\t\tExpect(og.Name).To(Equal(oog.Name))\n\t\t\t\t\tExpect(og.Namespace).To(Equal(oog.Namespace))\n\t\t\t\t})\n\t\t\t\tIt(\"should return an error for SingleNamespace when target matches operator\", func() {\n\t\t\t\t\toi.InstallMode.TargetNamespaces = []string{\"testns\"}\n\t\t\t\t\t_ = createOperatorGroupHelper(context.TODO(), client, \"existing-og\",\n\t\t\t\t\t\t\"testns\", \"testns\")\n\t\t\t\t\terr := oi.ensureOperatorGroup(context.TODO())\n\t\t\t\t\tExpect(err).Should(HaveOccurred())\n\t\t\t\t\tExpect(err.Error()).To(ContainSubstring(\"use install mode \\\"OwnNamespace\\\"\"))\n\t\t\t\t})\n\t\t\t})\n\t\t})\n\t})\n\tDescribe(\"createOperatorGroup\", func() {\n\t\tvar (\n\t\t\toi     OperatorInstaller\n\t\t\tclient crclient.Client\n\t\t)\n\t\tBeforeEach(func() {\n\t\t\tsch := runtime.NewScheme()\n\t\t\tExpect(v1.AddToScheme(sch)).To(Succeed())\n\t\t\tclient = fake.NewClientBuilder().WithScheme(sch).Build()\n\t\t\toi = OperatorInstaller{\n\t\t\t\tcfg: &operator.Configuration{\n\t\t\t\t\tScheme:    sch,\n\t\t\t\t\tClient:    client,\n\t\t\t\t\tNamespace: \"testnamespace\",\n\t\t\t\t},\n\t\t\t}\n\t\t})\n\t\tIt(\"should return an error if OperatorGroup already exists\", func() {\n\t\t\t_ = createOperatorGroupHelper(context.TODO(), client,\n\t\t\t\toperator.SDKOperatorGroupName, \"testnamespace\")\n\n\t\t\tog, err := oi.createOperatorGroup(context.TODO(), nil)\n\t\t\tExpect(og).Should(BeNil())\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t})\n\t\tIt(\"should create the OperatorGroup\", func() {\n\t\t\tog, err := oi.createOperatorGroup(context.TODO(), nil)\n\t\t\tExpect(og).ShouldNot(BeNil())\n\t\t\tExpect(og.Name).To(Equal(operator.SDKOperatorGroupName))\n\t\t\tExpect(og.Namespace).To(Equal(\"testnamespace\"))\n\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t})\n\t})\n\n\tDescribe(\"isOperatorGroupCompatible\", func() {\n\t\tvar (\n\t\t\toi OperatorInstaller\n\t\t\tog v1.OperatorGroup\n\t\t)\n\t\tBeforeEach(func() {\n\t\t\toi = OperatorInstaller{}\n\t\t\tog = createOperatorGroupHelper(context.TODO(), nil, \"existing-og\", \"default\", \"default\")\n\t\t})\n\t\tIt(\"should return an error if namespaces do not match\", func() {\n\t\t\toi.InstallMode = operator.InstallMode{\n\t\t\t\tInstallModeType:  v1alpha1.InstallModeTypeOwnNamespace,\n\t\t\t\tTargetNamespaces: []string{\"wontmatchns\"},\n\t\t\t}\n\n\t\t\terr := oi.isOperatorGroupCompatible(og, oi.InstallMode.TargetNamespaces)\n\t\t\tExpect(err).Should(HaveOccurred())\n\t\t\tExpect(err.Error()).Should(ContainSubstring(\"is not compatible\"))\n\t\t})\n\t\tIt(\"should return nil if no installmode is empty\", func() {\n\t\t\t// empty install mode\n\t\t\toi.InstallMode = operator.InstallMode{}\n\t\t\tExpect(oi.InstallMode.IsEmpty()).To(BeTrue())\n\t\t\tExpect(oi.isOperatorGroupCompatible(og, oi.InstallMode.TargetNamespaces)).Should(Succeed())\n\t\t})\n\t\tIt(\"should return nil if namespaces match\", func() {\n\t\t\toi.InstallMode = operator.InstallMode{\n\t\t\t\tInstallModeType:  v1alpha1.InstallModeTypeOwnNamespace,\n\t\t\t\tTargetNamespaces: []string{\"matchingns\"},\n\t\t\t}\n\t\t\taog := createOperatorGroupHelper(context.TODO(), nil, \"existing-og\", \"testns\", \"matchingns\")\n\t\t\tExpect(oi.isOperatorGroupCompatible(aog, oi.InstallMode.TargetNamespaces)).Should(Succeed())\n\t\t})\n\t})\n\n\tDescribe(\"getOperatorGroup\", func() {\n\t\tvar (\n\t\t\toi     OperatorInstaller\n\t\t\tclient crclient.Client\n\t\t)\n\t\tBeforeEach(func() {\n\t\t\tsch := runtime.NewScheme()\n\t\t\tExpect(v1.AddToScheme(sch)).To(Succeed())\n\t\t\tclient = fake.NewClientBuilder().WithScheme(sch).Build()\n\t\t\toi = OperatorInstaller{\n\t\t\t\tcfg: &operator.Configuration{\n\t\t\t\t\tScheme:    sch,\n\t\t\t\t\tClient:    client,\n\t\t\t\t\tNamespace: \"atestns\",\n\t\t\t\t},\n\t\t\t}\n\t\t})\n\t\tIt(\"should return an error if no OperatorGroups exist\", func() {\n\t\t\toi.cfg.Client = fake.NewClientBuilder().Build()\n\t\t\tgrp, found, err := oi.getOperatorGroup(context.TODO())\n\t\t\tExpect(grp).To(BeNil())\n\t\t\tExpect(found).To(BeFalse())\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t})\n\t\tIt(\"should return nothing if namespace does not match\", func() {\n\t\t\toi.cfg.Namespace = namespace\n\t\t\t_ = createOperatorGroupHelper(context.TODO(), client, \"og1\", \"atestns\")\n\t\t\tgrp, found, err := oi.getOperatorGroup(context.TODO())\n\t\t\tExpect(grp).To(BeNil())\n\t\t\tExpect(found).To(BeFalse())\n\t\t\tExpect(err).ShouldNot(HaveOccurred())\n\t\t})\n\t\tIt(\"should return an error when more than OperatorGroup found\", func() {\n\t\t\t_ = createOperatorGroupHelper(context.TODO(), client, \"og1\", \"atestns\")\n\t\t\t_ = createOperatorGroupHelper(context.TODO(), client, \"og2\", \"atestns\")\n\t\t\tgrp, found, err := oi.getOperatorGroup(context.TODO())\n\t\t\tExpect(grp).To(BeNil())\n\t\t\tExpect(found).To(BeTrue())\n\t\t\tExpect(err).Should(HaveOccurred())\n\t\t})\n\t\tIt(\"should return list of OperatorGroups\", func() {\n\t\t\tog := createOperatorGroupHelper(context.TODO(), client, \"og1\", \"atestns\")\n\t\t\tgrp, found, err := oi.getOperatorGroup(context.TODO())\n\t\t\tExpect(grp).ShouldNot(BeNil())\n\t\t\tExpect(grp.Name).To(Equal(og.Name))\n\t\t\tExpect(grp.Namespace).To(Equal(og.Namespace))\n\t\t\tExpect(found).To(BeTrue())\n\t\t\tExpect(err).ShouldNot(HaveOccurred())\n\t\t})\n\t})\n\n\tDescribe(\"getTargetNamespaces\", func() {\n\t\tvar (\n\t\t\toi        OperatorInstaller\n\t\t\tsupported set.Set[string]\n\t\t)\n\t\tBeforeEach(func() {\n\t\t\toi = OperatorInstaller{\n\t\t\t\tcfg: &operator.Configuration{},\n\t\t\t}\n\t\t\tsupported = set.New[string]()\n\t\t})\n\t\tIt(\"should return an error when nothing is supported\", func() {\n\t\t\ttarget, err := oi.getTargetNamespaces(supported)\n\t\t\tExpect(target).To(BeNil())\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t\tExpect(err.Error()).To(Equal(\"no supported install modes\"))\n\t\t})\n\t\tIt(\"should return nothing when AllNamespaces is supported\", func() {\n\t\t\tsupported.Insert(string(v1alpha1.InstallModeTypeAllNamespaces))\n\t\t\ttarget, err := oi.getTargetNamespaces(supported)\n\t\t\tExpect(target).To(BeNil())\n\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t})\n\t\tIt(\"should return operator's namespace when OwnNamespace is supported\", func() {\n\t\t\toi.cfg.Namespace = \"test-ns\"\n\t\t\tsupported.Insert(string(v1alpha1.InstallModeTypeOwnNamespace))\n\t\t\ttarget, err := oi.getTargetNamespaces(supported)\n\t\t\tExpect(target).To(HaveLen(1))\n\t\t\tExpect(target[0]).To(Equal(\"test-ns\"))\n\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t})\n\t\tIt(\"should return configured namespace when SingleNamespace is passed in\", func() {\n\n\t\t\toi.InstallMode = operator.InstallMode{\n\t\t\t\tInstallModeType:  v1alpha1.InstallModeTypeSingleNamespace,\n\t\t\t\tTargetNamespaces: []string{\"test-ns\"},\n\t\t\t}\n\n\t\t\tsupported.Insert(string(v1alpha1.InstallModeTypeSingleNamespace))\n\t\t\ttarget, err := oi.getTargetNamespaces(supported)\n\t\t\tExpect(target).To(HaveLen(1))\n\t\t\tExpect(target[0]).To(Equal(\"test-ns\"))\n\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t})\n\t\tIt(\"should return configured namespace when MultiNamespace is passed in\", func() {\n\n\t\t\toi.InstallMode = operator.InstallMode{\n\t\t\t\tInstallModeType:  v1alpha1.InstallModeTypeMultiNamespace,\n\t\t\t\tTargetNamespaces: []string{\"test-ns1\", \"test-ns2\"},\n\t\t\t}\n\n\t\t\tsupported.Insert(string(v1alpha1.InstallModeTypeMultiNamespace))\n\t\t\ttarget, err := oi.getTargetNamespaces(supported)\n\t\t\tExpect(target).To(HaveLen(2))\n\t\t\tExpect(target).To(Equal([]string{\"test-ns1\", \"test-ns2\"}))\n\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t})\n\t})\n})\n\nfunc createOperatorGroupHelper(ctx context.Context, c crclient.Client, name, namespace string, targetNamespaces ...string) v1.OperatorGroup {\n\tog := v1.OperatorGroup{}\n\tog.SetGroupVersionKind(v1.SchemeGroupVersion.WithKind(\"OperatorGroup\"))\n\tog.SetName(name)\n\tog.SetNamespace(namespace)\n\tog.Spec.TargetNamespaces = targetNamespaces\n\tog.Status.Namespaces = targetNamespaces\n\tif c != nil {\n\t\tExpectWithOffset(1, c.Create(ctx, &og)).Should(Succeed())\n\t}\n\treturn og\n}\n"
  },
  {
    "path": "internal/olm/operator/registry/registry_suite_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage registry\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nfunc TestRegistry(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"Registry Suite\")\n}\n"
  },
  {
    "path": "internal/olm/operator/uninstall.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage operator\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"strings\"\n\t\"time\"\n\n\tv1 \"github.com/operator-framework/api/pkg/operators/v1\"\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/pflag\"\n\tapierrors \"k8s.io/apimachinery/pkg/api/errors\"\n\t\"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured\"\n\t\"k8s.io/apimachinery/pkg/runtime/schema\"\n\t\"k8s.io/apimachinery/pkg/types\"\n\t\"k8s.io/apimachinery/pkg/util/wait\"\n\t\"k8s.io/kubectl/pkg/util/slice\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client\"\n)\n\nconst (\n\tcrdKind = \"CustomResourceDefinition\"\n)\n\ntype Uninstall struct {\n\tconfig *Configuration\n\n\tPackage                  string\n\tDeleteAll                bool\n\tDeleteCRDs               bool\n\tDeleteOperatorGroups     bool\n\tDeleteOperatorGroupNames []string\n\n\tLogf func(string, ...any)\n}\n\nfunc NewUninstall(cfg *Configuration) *Uninstall {\n\treturn &Uninstall{\n\t\tconfig: cfg,\n\t}\n}\n\nfunc (u *Uninstall) BindFlags(fs *pflag.FlagSet) {\n\tfs.BoolVar(&u.DeleteCRDs, \"delete-crds\", false, \"If set to true, owned CRDs and CRs will be deleted\")\n\tfs.BoolVar(&u.DeleteAll, \"delete-all\", true, \"If set to true, all other delete options will be enabled\")\n\tfs.BoolVar(&u.DeleteOperatorGroups, \"delete-operator-groups\", false, \"If set to true, operator groups will be deleted\")\n}\n\ntype ErrPackageNotFound struct {\n\tPackageName string\n}\n\nfunc (e ErrPackageNotFound) Error() string {\n\treturn fmt.Sprintf(\"package %q not found\", e.PackageName)\n}\n\nfunc (u *Uninstall) Run(ctx context.Context) error {\n\tif u.DeleteAll {\n\t\tu.DeleteCRDs = true\n\t\tu.DeleteOperatorGroups = true\n\t}\n\n\tsubs := v1alpha1.SubscriptionList{}\n\tif err := u.config.Client.List(ctx, &subs, client.InNamespace(u.config.Namespace)); err != nil {\n\t\treturn fmt.Errorf(\"list subscriptions: %v\", err)\n\t}\n\n\t// Use nil objects to determine if the underlying was found.\n\t// If it was, the object will != nil.\n\tvar subObj, csvObj, csObj client.Object\n\tvar sub *v1alpha1.Subscription\n\tvar crds []client.Object\n\tcatsrc := &v1alpha1.CatalogSource{}\n\tcatsrc.SetNamespace(u.config.Namespace)\n\tcatsrc.SetName(CatalogNameForPackage(u.Package))\n\n\tfor i := range subs.Items {\n\t\ts := subs.Items[i]\n\t\tif u.Package == s.Spec.Package {\n\t\t\tsub = &s\n\t\t\tbreak\n\t\t}\n\t}\n\n\tcatsrcKey := client.ObjectKeyFromObject(catsrc)\n\tif sub != nil {\n\t\tsubObj = sub\n\t\t// Use the subscription's catalog source data only if available.\n\t\tkeyFromSpec := types.NamespacedName{\n\t\t\tNamespace: sub.Spec.CatalogSourceNamespace,\n\t\t\tName:      sub.Spec.CatalogSource,\n\t\t}\n\t\tif catsrcKey.Name != \"\" && catsrcKey.Namespace != \"\" {\n\t\t\tcatsrcKey = keyFromSpec\n\t\t}\n\n\t\t// CSV name may either be the installed or current name in a subscription's status,\n\t\t// depending on installation state.\n\t\tcsvKey := types.NamespacedName{\n\t\t\tName:      sub.Status.InstalledCSV,\n\t\t\tNamespace: u.config.Namespace,\n\t\t}\n\t\tif csvKey.Name == \"\" {\n\t\t\tcsvKey.Name = sub.Status.CurrentCSV\n\t\t}\n\t\t// This value can be empty which will cause errors.\n\t\tif csvKey.Name != \"\" {\n\t\t\tcsv := &v1alpha1.ClusterServiceVersion{}\n\t\t\tif err := u.config.Client.Get(ctx, csvKey, csv); err != nil && !apierrors.IsNotFound(err) {\n\t\t\t\treturn fmt.Errorf(\"error getting installed CSV %q: %v\", csvKey.Name, err)\n\t\t\t} else if err == nil {\n\t\t\t\tcrds = getCRDs(csv)\n\t\t\t}\n\t\t\tcsvObj = csv\n\t\t}\n\t}\n\n\t// Get the catalog source to make sure the correct error is returned.\n\tif err := u.config.Client.Get(ctx, catsrcKey, catsrc); err == nil {\n\t\tcsObj = catsrc\n\t} else if !apierrors.IsNotFound(err) {\n\t\treturn fmt.Errorf(\"error get catalog source: %v\", err)\n\t}\n\n\t// Deletion order:\n\t//\n\t// 1. Subscription to prevent further installs or upgrades of the operator while cleaning up.\n\t// 2. CustomResourceDefinitions so the operator has a chance to handle CRs that have finalizers.\n\t// 3. ClusterServiceVersion. OLM puts an ownerref on every namespaced resource to the CSV,\n\t//    and an owner label on every cluster scoped resource so they get gc'd on deletion.\n\t// 4. CatalogSource. All other resources installed by OLM or operator-sdk related to this\n\t//    package will be gc'd.\n\n\t// Subscriptions can be deleted asynchronously.\n\tif err := u.deleteObjects(ctx, false, subObj); err != nil {\n\t\treturn err\n\t}\n\tvar objs []client.Object\n\n\tif u.DeleteCRDs {\n\t\tobjs = append(objs, crds...)\n\t} else {\n\t\tlog.Info(\"Skipping CRD deletion\")\n\n\t}\n\n\tobjs = append(objs, csvObj, csObj)\n\t// These objects may have owned resources/finalizers, so block on deletion.\n\tif err := u.deleteObjects(ctx, true, objs...); err != nil {\n\t\treturn err\n\t}\n\n\t// If the last subscription in the namespace was deleted and the operator group is\n\t// the one operator-sdk created, delete it.\n\tif u.DeleteOperatorGroups {\n\t\tif err := u.deleteOperatorGroup(ctx); err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\tlog.Info(\"Skipping Operator Groups deletion\")\n\t}\n\n\t// If no objects were cleaned up, the package was not found.\n\tif subObj == nil && csObj == nil && csvObj == nil && len(crds) == 0 {\n\t\treturn &ErrPackageNotFound{u.Package}\n\t}\n\treturn nil\n}\n\nfunc (u *Uninstall) deleteOperatorGroup(ctx context.Context) error {\n\tsubs := v1alpha1.SubscriptionList{}\n\tif err := u.config.Client.List(ctx, &subs, client.InNamespace(u.config.Namespace)); err != nil {\n\t\treturn fmt.Errorf(\"list subscriptions: %v\", err)\n\t}\n\tif len(subs.Items) != 0 {\n\t\treturn nil\n\t}\n\togs := v1.OperatorGroupList{}\n\tif err := u.config.Client.List(ctx, &ogs, client.InNamespace(u.config.Namespace)); err != nil {\n\t\treturn fmt.Errorf(\"list operatorgroups: %v\", err)\n\t}\n\tfor _, og := range ogs.Items {\n\t\tif len(u.DeleteOperatorGroupNames) == 0 || slice.ContainsString(u.DeleteOperatorGroupNames, og.GetName(), nil) {\n\t\t\tif err := u.deleteObjects(ctx, false, &og); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (u *Uninstall) deleteObjects(ctx context.Context, waitForDelete bool, objs ...client.Object) error {\n\tfor _, obj := range objs {\n\t\tif obj == nil {\n\t\t\tcontinue\n\t\t}\n\t\tgvks, _, err := u.config.Scheme.ObjectKinds(obj)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tlowerKind := strings.ToLower(gvks[0].Kind)\n\t\tif err := u.config.Client.Delete(ctx, obj); err != nil && !apierrors.IsNotFound(err) {\n\t\t\treturn fmt.Errorf(\"delete %s %q: %v\", lowerKind, obj.GetName(), err)\n\t\t} else if err == nil {\n\t\t\tu.Logf(\"%s %q deleted\", lowerKind, obj.GetName())\n\t\t}\n\t\tif waitForDelete {\n\t\t\tkey := client.ObjectKeyFromObject(obj)\n\t\t\tif err := wait.PollUntilContextCancel(ctx, 250*time.Millisecond, false, func(pctx context.Context) (bool, error) {\n\t\t\t\tif err := u.config.Client.Get(pctx, key, obj); apierrors.IsNotFound(err) {\n\t\t\t\t\treturn true, nil\n\t\t\t\t} else if err != nil {\n\t\t\t\t\treturn false, err\n\t\t\t\t}\n\t\t\t\treturn false, nil\n\t\t\t}); err != nil {\n\t\t\t\treturn fmt.Errorf(\"wait for %s deleted: %v\", lowerKind, err)\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// getCRDs returns the list of CRDs required by a CSV.\nfunc getCRDs(csv *v1alpha1.ClusterServiceVersion) (crds []client.Object) {\n\tfor _, resource := range csv.Status.RequirementStatus {\n\t\tif resource.Kind == crdKind {\n\t\t\tobj := &unstructured.Unstructured{}\n\t\t\tobj.SetGroupVersionKind(schema.GroupVersionKind{\n\t\t\t\tGroup:   resource.Group,\n\t\t\t\tVersion: resource.Version,\n\t\t\t\tKind:    resource.Kind,\n\t\t\t})\n\t\t\tobj.SetName(resource.Name)\n\t\t\tcrds = append(crds, obj)\n\t\t}\n\t}\n\treturn\n}\n"
  },
  {
    "path": "internal/plugins/helm/v1/api.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage v1\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/iancoleman/strcase\"\n\t\"github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/chartutil\"\n\t\"github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/scaffolds\"\n\t\"github.com/operator-framework/operator-sdk/internal/plugins/util\"\n\t\"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/pflag\"\n\t\"helm.sh/helm/v3/pkg/chart\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/config\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/machinery\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/model/resource\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/plugin\"\n)\n\nconst (\n\tcrdVersionFlag       = \"crd-version\"\n\thelmChartFlag        = \"helm-chart\"\n\thelmChartRepoFlag    = \"helm-chart-repo\"\n\thelmChartVersionFlag = \"helm-chart-version\"\n\n\tdefaultCrdVersion = \"v1\"\n\tlegacyCrdVersion  = \"v1beta1\"\n\n\t// defaultGroup is the Kubernetes CRD API Group used for fetched charts when the --group flag is not specified\n\tdefaultGroup = \"charts\"\n\t// defaultVersion is the Kubernetes CRD API Version used for fetched charts when the --version flag is not specified\n\tdefaultVersion = \"v1alpha1\"\n)\n\ntype createAPIOptions struct {\n\t// CRDVersion is the version of the `apiextensions.k8s.io` API which will be used to generate the CRD.\n\tCRDVersion string\n\n\tchartOptions chartutil.Options\n}\n\n// UpdateResource updates the base resource with the information obtained from the flags\nfunc (opts createAPIOptions) UpdateResource(res *resource.Resource) {\n\tres.API = &resource.API{\n\t\tCRDVersion: opts.CRDVersion,\n\t\tNamespaced: true,\n\t}\n\n\t// Ensure that Path is empty and Controller false\n\tres.Path = \"\"\n\tres.Controller = false\n}\n\nvar _ plugin.CreateAPISubcommand = &createAPISubcommand{}\n\ntype createAPISubcommand struct {\n\tconfig   config.Config\n\tresource *resource.Resource\n\tchart    *chart.Chart\n\toptions  createAPIOptions\n}\n\nfunc (p *createAPISubcommand) UpdateMetadata(cliMeta plugin.CLIMetadata, subcmdMeta *plugin.SubcommandMetadata) {\n\tsubcmdMeta.Description = `Scaffold a Kubernetes API that is backed by a Helm chart.\n`\n\tsubcmdMeta.Examples = fmt.Sprintf(`  $ %s create api \\\n      --group=apps --version=v1alpha1 \\\n      --kind=AppService\n\n  $ %[1]s create api \\\n      --group=apps --version=v1alpha1 \\\n      --kind=AppService \\\n      --helm-chart=myrepo/app\n\n  $ %[1]s create api \\\n      --helm-chart=myrepo/app\n\n  $ %[1]s create api \\\n      --helm-chart=myrepo/app \\\n      --helm-chart-version=1.2.3\n\n  $ %[1]s create api \\\n      --helm-chart=app \\\n      --helm-chart-repo=https://charts.mycompany.com/\n\n  $ %[1]s create api \\\n      --helm-chart=app \\\n      --helm-chart-repo=https://charts.mycompany.com/ \\\n      --helm-chart-version=1.2.3\n\n  $ %[1]s create api \\\n      --helm-chart=/path/to/local/chart-directories/app/\n\n  $ %[1]s create api \\\n      --helm-chart=/path/to/local/chart-archives/app-1.2.3.tgz\n\n  $ %[1]s create api \\\n      --helm-chart=oci://charts.mycompany.com/example-namespace/app:1.2.3\n`, cliMeta.CommandName)\n}\n\n// BindFlags will set the flags for the plugin\nfunc (p *createAPISubcommand) BindFlags(fs *pflag.FlagSet) {\n\tfs.SortFlags = false\n\n\tfs.StringVar(&p.options.chartOptions.Chart, helmChartFlag, \"\", \"helm chart\")\n\tfs.StringVar(&p.options.chartOptions.Repo, helmChartRepoFlag, \"\", \"helm chart repository\")\n\tfs.StringVar(&p.options.chartOptions.Version, helmChartVersionFlag, \"\", \"helm chart version (default: latest)\")\n\n\tfs.StringVar(&p.options.CRDVersion, crdVersionFlag, defaultCrdVersion, \"crd version to generate\")\n\t// (not required raise an error in this case)\n\t// nolint:errcheck,gosec\n\tfs.MarkDeprecated(crdVersionFlag, util.WarnMessageRemovalV1beta1)\n}\n\nfunc (p *createAPISubcommand) InjectConfig(c config.Config) error {\n\tp.config = c\n\n\treturn nil\n}\n\nfunc (p *createAPISubcommand) PreScaffold(machinery.Filesystem) error {\n\tif p.options.CRDVersion == legacyCrdVersion {\n\t\tlogrus.Warn(util.WarnMessageRemovalV1beta1)\n\t}\n\treturn nil\n}\n\nfunc (p *createAPISubcommand) InjectResource(res *resource.Resource) error {\n\tp.resource = res\n\n\t// The following checks and the chart creation would be a better fit for PreScaffold method\n\t// but, as having a chart sets some default values for the resource's GVK, we need to do it here.\n\tvar err error\n\tif len(strings.TrimSpace(p.options.chartOptions.Chart)) == 0 {\n\t\t// Chart repo and version can only be provided if chart was provided.\n\t\tif len(strings.TrimSpace(p.options.chartOptions.Repo)) != 0 {\n\t\t\treturn fmt.Errorf(\"value of --%s can only be used with --%s\", helmChartRepoFlag, helmChartFlag)\n\t\t}\n\t\tif len(p.options.chartOptions.Version) != 0 {\n\t\t\treturn fmt.Errorf(\"value of --%s can only be used with --%s\", helmChartVersionFlag, helmChartFlag)\n\t\t}\n\n\t\t// Kind is required if no chart was provided as it is used for the chart name.\n\t\t// While the resource validation will detect this, the error yielded would not\n\t\t// mention the option of providing the chart flag. Additionally, by checking it\n\t\t// here we can create the new chart before resource validation.\n\t\tif len(p.resource.Kind) == 0 {\n\t\t\treturn fmt.Errorf(\"either --%s or --%s need to be provided\", kindFlag, helmChartFlag)\n\t\t}\n\n\t\tp.chart, err = chartutil.NewChart(strings.ToLower(p.resource.Kind))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\tp.chart, err = chartutil.LoadChart(p.options.chartOptions)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// In case we loaded a chart and some resource flags were not set we will set defaults.\n\t\tif p.resource.Group == \"\" {\n\t\t\tp.resource.Group = defaultGroup\n\t\t}\n\t\tif p.resource.Version == \"\" {\n\t\t\tp.resource.Version = defaultVersion\n\t\t}\n\t\tif p.resource.Kind == \"\" {\n\t\t\tp.resource.Kind = strcase.ToCamel(p.chart.Name())\n\t\t\tif p.resource.Plural == \"\" {\n\t\t\t\tp.resource.Plural = resource.RegularPlural(p.resource.Kind)\n\t\t\t}\n\t\t}\n\t}\n\n\tp.options.UpdateResource(p.resource)\n\n\tif err := p.resource.Validate(); err != nil {\n\t\treturn err\n\t}\n\n\t// Check that resource doesn't have the API scaffolded\n\tif res, err := p.config.GetResource(p.resource.GVK); err == nil && res.HasAPI() {\n\t\treturn errors.New(\"the API resource already exists\")\n\t}\n\n\t// Check that the provided group can be added to the project\n\t// nolint:staticcheck\n\tif !p.config.IsMultiGroup() && p.config.ResourcesLength() != 0 && !p.config.HasGroup(p.resource.Group) {\n\t\treturn fmt.Errorf(\"multiple groups are not allowed by default, to enable multi-group set 'multigroup: true' in your PROJECT file\")\n\t}\n\n\t// Selected CRD version must match existing CRD versions.\n\t// nolint:staticcheck\n\tif hasDifferentAPIVersion(p.config.ListCRDVersions(), p.resource.API.CRDVersion) {\n\t\treturn fmt.Errorf(\"only one CRD version can be used for all resources, cannot add %q\", p.resource.API.CRDVersion)\n\t}\n\n\treturn nil\n}\n\nfunc (p *createAPISubcommand) Scaffold(fs machinery.Filesystem) error {\n\tif err := util.RemoveKustomizeCRDManifests(); err != nil {\n\t\treturn fmt.Errorf(\"error removing kustomization CRD manifests: %v\", err)\n\t}\n\tif err := util.UpdateKustomizationsCreateAPI(); err != nil {\n\t\treturn fmt.Errorf(\"error updating kustomization.yaml files: %v\", err)\n\t}\n\n\tscaffolder := scaffolds.NewAPIScaffolder(p.config, *p.resource, p.chart)\n\tscaffolder.InjectFS(fs)\n\tif err := scaffolder.Scaffold(); err != nil {\n\t\treturn err\n\t}\n\t// NOTE: previous step fetches the dependencies of the chart.Chart, so reloading may be needed if used afterwards\n\n\treturn nil\n}\n\n// hasDifferentCRDVersion returns true if any other CRD version is tracked in the project configuration.\nfunc hasDifferentAPIVersion(versions []string, version string) bool {\n\tif len(versions) == 0 {\n\t\treturn false\n\t}\n\treturn len(versions) > 1 || versions[0] != version\n}\n"
  },
  {
    "path": "internal/plugins/helm/v1/chartutil/chart.go",
    "content": "// Copyright 2018 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage chartutil\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\t\"helm.sh/helm/v3/pkg/chart\"\n\t\"helm.sh/helm/v3/pkg/chart/loader\"\n\t\"helm.sh/helm/v3/pkg/chartutil\"\n\t\"helm.sh/helm/v3/pkg/cli\"\n\t\"helm.sh/helm/v3/pkg/downloader\"\n\t\"helm.sh/helm/v3/pkg/getter\"\n\t\"helm.sh/helm/v3/pkg/registry\"\n\t\"helm.sh/helm/v3/pkg/repo\"\n)\n\nconst (\n\t// HelmChartsDir is the relative directory within a SDK project where Helm charts are stored.\n\tHelmChartsDir = \"helm-charts\"\n)\n\n// Options is used to configure how a Helm chart is scaffolded\n// for a new Helm operator project.\ntype Options struct {\n\t// Chart is a chart reference for a local or remote chart.\n\tChart string\n\n\t// Repo is a URL to a custom chart repository.\n\tRepo string\n\n\t// Version is the version of the chart to fetch.\n\tVersion string\n}\n\n// NewChart creates a new helm chart for the project from helm's default template.\n// It returns a chart.Chart that references the newly created chart or an error.\nfunc NewChart(name string) (*chart.Chart, error) {\n\ttmpDir, err := os.MkdirTemp(\"\", \"osdk-helm-chart\")\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer func() {\n\t\tif err := os.RemoveAll(tmpDir); err != nil {\n\t\t\tlog.Errorf(\"Failed to remove temporary directory %s: %v\", tmpDir, err)\n\t\t}\n\t}()\n\n\t// Create a new chart\n\tchartPath, err := chartutil.Create(name, tmpDir)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn loader.Load(chartPath)\n}\n\n// LoadChart creates a new helm chart for the project based on the passed opts.\n// It returns a chart.Chart that references the newly created chart or an error.\n//\n// If opts.Chart is a local file, it verifies that it is a valid helm chart\n// archive and returns its chart.Chart representation.\n//\n// If opts.Chart is a local directory, it verifies that it is a valid helm chart\n// directory and returns its chart.Chart representation.\n//\n// For any other value of opts.Chart, it attempts to fetch the helm chart from a\n// remote repository.\n//\n// If opts.Repo is not specified, the following chart reference formats are supported:\n//\n//   - <repoName>/<chartName>: Fetch the helm chart named chartName from the helm\n//     chart repository named repoName, as specified in the\n//     $HELM_HOME/repositories/repositories.yaml file.\n//\n//   - <url>: Fetch the helm chart archive at the specified URL.\n//\n// If opts.Repo is specified, only one chart reference format is supported:\n//\n//   - <chartName>: Fetch the helm chart named chartName in the helm chart repository\n//     specified by opts.Repo\n//\n// If opts.Version is not set, it will fetch the latest available version of the helm\n// chart. Otherwise, it will fetch the specified version.\n// opts.Version is not used when opts.Chart itself refers to a specific version, for\n// example when it is a local path or a URL.\nfunc LoadChart(opts Options) (*chart.Chart, error) {\n\ttmpDir, err := os.MkdirTemp(\"\", \"osdk-helm-chart\")\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer func() {\n\t\tif err := os.RemoveAll(tmpDir); err != nil {\n\t\t\tlog.Errorf(\"Failed to remove temporary directory %s: %v\", tmpDir, err)\n\t\t}\n\t}()\n\n\tchartPath := opts.Chart\n\n\t// If it is a remote chart, download it to a temp dir first\n\tif _, err := os.Stat(opts.Chart); err != nil {\n\t\tchartPath, err = downloadChart(tmpDir, opts)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\treturn loader.Load(chartPath)\n}\n\nfunc downloadChart(destDir string, opts Options) (string, error) {\n\tsettings := cli.New()\n\tgetters := getter.All(settings)\n\n\t// Create registry client for OCI registry support\n\tregistryClient, err := registry.NewClient()\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to create registry client: %w\", err)\n\t}\n\n\tc := downloader.ChartDownloader{\n\t\tOut:              os.Stderr,\n\t\tGetters:          getters,\n\t\tRepositoryConfig: settings.RepositoryConfig,\n\t\tRepositoryCache:  settings.RepositoryCache,\n\t\tRegistryClient:   registryClient,\n\t}\n\n\tif opts.Repo != \"\" {\n\t\tchartURL, err := repo.FindChartInRepoURL(opts.Repo, opts.Chart, opts.Version, \"\", \"\", \"\", getters)\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t\topts.Chart = chartURL\n\t}\n\n\tchartArchive, _, err := c.DownloadTo(opts.Chart, opts.Version, destDir)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\treturn chartArchive, nil\n}\n\n// ScaffoldChart scaffolds the provided chart.Chart to a known directory relative to projectDir\n//\n// # It also fetches the dependencies and reloads the chart.Chart\n//\n// It returns the reloaded chart, the relative path, or an error.\nfunc ScaffoldChart(chrt *chart.Chart, projectDir string) (*chart.Chart, string, error) {\n\tchartsPath := filepath.Join(projectDir, HelmChartsDir)\n\n\t// Save it into our project's helm-charts directory.\n\tif err := chartutil.SaveDir(chrt, chartsPath); err != nil {\n\t\treturn chrt, \"\", err\n\t}\n\n\tchartPath := filepath.Join(chartsPath, chrt.Name())\n\n\t// Fetch dependencies\n\tif err := fetchChartDependencies(chartPath); err != nil {\n\t\treturn chrt, \"\", fmt.Errorf(\"failed to fetch chart dependencies: %w\", err)\n\t}\n\n\t// Reload chart in case dependencies changed\n\tchrt, err := loader.Load(chartPath)\n\tif err != nil {\n\t\treturn chrt, \"\", fmt.Errorf(\"failed to reload chart: %w\", err)\n\t}\n\n\treturn chrt, filepath.Join(HelmChartsDir, chrt.Name()), nil\n}\n\nfunc fetchChartDependencies(chartPath string) error {\n\tsettings := cli.New()\n\tgetters := getter.All(settings)\n\n\t// Create registry client for OCI registry support\n\tregistryClient, err := registry.NewClient()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to create registry client: %w\", err)\n\t}\n\n\tout := &bytes.Buffer{}\n\tman := &downloader.Manager{\n\t\tOut:              out,\n\t\tChartPath:        chartPath,\n\t\tGetters:          getters,\n\t\tRepositoryConfig: settings.RepositoryConfig,\n\t\tRepositoryCache:  settings.RepositoryCache,\n\t\tRegistryClient:   registryClient,\n\t}\n\tif err := man.Build(); err != nil {\n\t\tfmt.Println(out.String())\n\t\treturn err\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "internal/plugins/helm/v1/chartutil/chart_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage chartutil_test\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"helm.sh/helm/v3/pkg/chart\"\n\t\"helm.sh/helm/v3/pkg/repo/repotest\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/chartutil\"\n)\n\nfunc TestChart(t *testing.T) {\n\tsrv, err := repotest.NewTempServerWithCleanup(t, \"testdata/*.tgz\")\n\tif err != nil {\n\t\tt.Fatalf(\"Failed to create new temp server: %s\", err)\n\t}\n\tdefer srv.Stop()\n\n\tif err := srv.LinkIndices(); err != nil {\n\t\tt.Fatalf(\"Failed to link server indices: %s\", err)\n\t}\n\n\tconst (\n\t\tchartName          = \"test-chart\"\n\t\tlatestVersion      = \"1.2.3\"\n\t\tpreviousVersion    = \"1.2.0\"\n\t\tnonExistentVersion = \"0.0.1\"\n\t\tcustomKind         = \"MyApp\"\n\t\tcustomExpectName   = \"myapp\"\n\t)\n\n\ttestCases := []createChartTestCase{\n\t\t{\n\t\t\tname:      \"from scaffold no apiVersion\",\n\t\t\texpectErr: true,\n\t\t},\n\t\t{\n\t\t\tname:             \"version without helm chart\",\n\t\t\thelmChartVersion: latestVersion,\n\t\t\texpectErr:        true,\n\t\t},\n\t\t{\n\t\t\tname:          \"repo without helm chart\",\n\t\t\thelmChartRepo: srv.URL(),\n\t\t\texpectErr:     true,\n\t\t},\n\t\t{\n\t\t\tname:             \"non-existent version\",\n\t\t\thelmChart:        \"test/\" + chartName,\n\t\t\thelmChartVersion: nonExistentVersion,\n\t\t\texpectErr:        true,\n\t\t},\n\t\t{\n\t\t\tname:               \"from scaffold with kind\",\n\t\t\tkind:               customKind,\n\t\t\texpectChartName:    customExpectName,\n\t\t\texpectChartVersion: \"0.1.0\",\n\t\t},\n\t\t{\n\t\t\tname:               \"from directory\",\n\t\t\thelmChart:          filepath.Join(\".\", \"testdata\", chartName),\n\t\t\texpectChartName:    chartName,\n\t\t\texpectChartVersion: latestVersion,\n\t\t},\n\t\t{\n\t\t\tname:               \"from archive\",\n\t\t\thelmChart:          filepath.Join(\".\", \"testdata\", fmt.Sprintf(\"%s-%s.tgz\", chartName, latestVersion)),\n\t\t\texpectChartName:    chartName,\n\t\t\texpectChartVersion: latestVersion,\n\t\t},\n\t\t{\n\t\t\tname:               \"from url\",\n\t\t\thelmChart:          fmt.Sprintf(\"%s/%s-%s.tgz\", srv.URL(), chartName, latestVersion),\n\t\t\texpectChartName:    chartName,\n\t\t\texpectChartVersion: latestVersion,\n\t\t},\n\t\t{\n\t\t\tname:               \"from repo and name implicit latest\",\n\t\t\thelmChart:          \"test/\" + chartName,\n\t\t\texpectChartName:    chartName,\n\t\t\texpectChartVersion: latestVersion,\n\t\t},\n\t\t{\n\t\t\tname:               \"from repo and name implicit latest with kind\",\n\t\t\thelmChart:          \"test/\" + chartName,\n\t\t\tkind:               customKind,\n\t\t\texpectChartName:    chartName,\n\t\t\texpectChartVersion: latestVersion,\n\t\t},\n\t\t{\n\t\t\tname:               \"from repo and name explicit latest\",\n\t\t\thelmChart:          \"test/\" + chartName,\n\t\t\thelmChartVersion:   latestVersion,\n\t\t\texpectChartName:    chartName,\n\t\t\texpectChartVersion: latestVersion,\n\t\t},\n\t\t{\n\t\t\tname:               \"from repo and name explicit previous\",\n\t\t\thelmChart:          \"test/\" + chartName,\n\t\t\thelmChartVersion:   previousVersion,\n\t\t\texpectChartName:    chartName,\n\t\t\texpectChartVersion: previousVersion,\n\t\t},\n\t\t{\n\t\t\tname:               \"from name and repo url implicit latest\",\n\t\t\thelmChart:          chartName,\n\t\t\thelmChartRepo:      srv.URL(),\n\t\t\texpectChartName:    chartName,\n\t\t\texpectChartVersion: latestVersion,\n\t\t},\n\t\t{\n\t\t\tname:               \"from name and repo url explicit latest\",\n\t\t\thelmChart:          chartName,\n\t\t\thelmChartRepo:      srv.URL(),\n\t\t\thelmChartVersion:   latestVersion,\n\t\t\texpectChartName:    chartName,\n\t\t\texpectChartVersion: latestVersion,\n\t\t},\n\t\t{\n\t\t\tname:               \"from name and repo url explicit previous\",\n\t\t\thelmChart:          chartName,\n\t\t\thelmChartRepo:      srv.URL(),\n\t\t\thelmChartVersion:   previousVersion,\n\t\t\texpectChartName:    chartName,\n\t\t\texpectChartVersion: previousVersion,\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\trunTestCase(t, srv.Root(), tc)\n\t\t})\n\t}\n}\n\ntype createChartTestCase struct {\n\tname string\n\n\tkind             string\n\thelmChart        string\n\thelmChartVersion string\n\thelmChartRepo    string\n\n\texpectChartName    string\n\texpectChartVersion string\n\texpectErr          bool\n}\n\nfunc runTestCase(t *testing.T, testDir string, tc createChartTestCase) {\n\toutputDir := filepath.Join(testDir, \"output\")\n\tassert.NoError(t, os.Mkdir(outputDir, 0755))\n\tdefer os.RemoveAll(outputDir)\n\n\tos.Setenv(\"XDG_CONFIG_HOME\", filepath.Join(testDir, \".config\"))\n\tos.Setenv(\"XDG_CACHE_HOME\", filepath.Join(testDir, \".cache\"))\n\tos.Setenv(\"HELM_REPOSITORY_CONFIG\", filepath.Join(testDir, \"repositories.yaml\"))\n\tos.Setenv(\"HELM_REPOSITORY_CACHE\", filepath.Join(testDir))\n\tdefer os.Unsetenv(\"XDG_CONFIG_HOME\")\n\tdefer os.Unsetenv(\"XDG_CACHE_HOME\")\n\tdefer os.Unsetenv(\"HELM_REPOSITORY_CONFIG\")\n\tdefer os.Unsetenv(\"HELM_REPOSITORY_CACHE\")\n\n\tvar (\n\t\tchrt *chart.Chart\n\t\terr  error\n\t)\n\tif tc.helmChart != \"\" {\n\t\topts := chartutil.Options{\n\t\t\tChart:   tc.helmChart,\n\t\t\tVersion: tc.helmChartVersion,\n\t\t\tRepo:    tc.helmChartRepo,\n\t\t}\n\t\tchrt, err = chartutil.LoadChart(opts)\n\t} else {\n\t\tchrt, err = chartutil.NewChart(strings.ToLower(tc.kind))\n\t}\n\n\tif tc.expectErr {\n\t\tassert.Error(t, err)\n\t\treturn\n\t}\n\n\tif !assert.NoError(t, err) {\n\t\treturn\n\t}\n\tassert.Equal(t, tc.expectChartName, chrt.Name())\n\tassert.Equal(t, tc.expectChartVersion, chrt.Metadata.Version)\n\n\t_, chartPath, err := chartutil.ScaffoldChart(chrt, outputDir)\n\tassert.NoError(t, err)\n\tassert.Equal(t, filepath.Join(chartutil.HelmChartsDir, tc.expectChartName), chartPath)\n}\n"
  },
  {
    "path": "internal/plugins/helm/v1/chartutil/testdata/test-chart/.helmignore",
    "content": "# Patterns to ignore when building packages.\n# This supports shell glob matching, relative path matching, and\n# negation (prefixed with !). Only one pattern per line.\n.DS_Store\n# Common VCS dirs\n.git/\n.gitignore\n.bzr/\n.bzrignore\n.hg/\n.hgignore\n.svn/\n# Common backup files\n*.swp\n*.bak\n*.tmp\n*~\n# Various IDEs\n.project\n.idea/\n*.tmproj\n.vscode/\n"
  },
  {
    "path": "internal/plugins/helm/v1/chartutil/testdata/test-chart/Chart.yaml",
    "content": "apiVersion: v2\nname: test-chart\ndescription: A Helm chart for Kubernetes\n\n# A chart can be either an 'application' or a 'library' chart.\n#\n# Application charts are a collection of templates that can be packaged into versioned archives\n# to be deployed.\n#\n# Library charts provide useful utilities or functions for the chart developer. They're included as\n# a dependency of application charts to inject those utilities and functions into the rendering\n# pipeline. Library charts do not define any templates and therefore cannot be deployed.\ntype: application\n\n# This is the chart version. This version number should be incremented each time you make changes\n# to the chart and its templates, including the app version.\nversion: 1.2.3\n\n# This is the version number of the application being deployed. This version number should be\n# incremented each time you make changes to the application.\nappVersion: 1.16.0\n"
  },
  {
    "path": "internal/plugins/helm/v1/chartutil/testdata/test-chart/templates/NOTES.txt",
    "content": "1. Get the application URL by running these commands:\n{{- if .Values.ingress.enabled }}\n{{- range $host := .Values.ingress.hosts }}\n  {{- range .paths }}\n  http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ . }}\n  {{- end }}\n{{- end }}\n{{- else if contains \"NodePort\" .Values.service.type }}\n  export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath=\"{.spec.ports[0].nodePort}\" services {{ include \"test-chart.fullname\" . }})\n  export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath=\"{.items[0].status.addresses[0].address}\")\n  echo http://$NODE_IP:$NODE_PORT\n{{- else if contains \"LoadBalancer\" .Values.service.type }}\n     NOTE: It may take a few minutes for the LoadBalancer IP to be available.\n           You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include \"test-chart.fullname\" . }}'\n  export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include \"test-chart.fullname\" . }} --template \"{{\"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}\"}}\")\n  echo http://$SERVICE_IP:{{ .Values.service.port }}\n{{- else if contains \"ClusterIP\" .Values.service.type }}\n  export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l \"app.kubernetes.io/name={{ include \"test-chart.name\" . }},app.kubernetes.io/instance={{ .Release.Name }}\" -o jsonpath=\"{.items[0].metadata.name}\")\n  echo \"Visit http://127.0.0.1:8080 to use your application\"\n  kubectl port-forward $POD_NAME 8080:80\n{{- end }}\n"
  },
  {
    "path": "internal/plugins/helm/v1/chartutil/testdata/test-chart/templates/_helpers.tpl",
    "content": "{{/* vim: set filetype=mustache: */}}\n{{/*\nExpand the name of the chart.\n*/}}\n{{- define \"test-chart.name\" -}}\n{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix \"-\" -}}\n{{- end -}}\n\n{{/*\nCreate a default fully qualified app name.\nWe truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).\nIf release name contains chart name it will be used as a full name.\n*/}}\n{{- define \"test-chart.fullname\" -}}\n{{- if .Values.fullnameOverride -}}\n{{- .Values.fullnameOverride | trunc 63 | trimSuffix \"-\" -}}\n{{- else -}}\n{{- $name := default .Chart.Name .Values.nameOverride -}}\n{{- if contains $name .Release.Name -}}\n{{- .Release.Name | trunc 63 | trimSuffix \"-\" -}}\n{{- else -}}\n{{- printf \"%s-%s\" .Release.Name $name | trunc 63 | trimSuffix \"-\" -}}\n{{- end -}}\n{{- end -}}\n{{- end -}}\n\n{{/*\nCreate chart name and version as used by the chart label.\n*/}}\n{{- define \"test-chart.chart\" -}}\n{{- printf \"%s-%s\" .Chart.Name .Chart.Version | replace \"+\" \"_\" | trunc 63 | trimSuffix \"-\" -}}\n{{- end -}}\n\n{{/*\nCommon labels\n*/}}\n{{- define \"test-chart.labels\" -}}\nhelm.sh/chart: {{ include \"test-chart.chart\" . }}\n{{ include \"test-chart.selectorLabels\" . }}\n{{- if .Chart.AppVersion }}\napp.kubernetes.io/version: {{ .Chart.AppVersion | quote }}\n{{- end }}\napp.kubernetes.io/managed-by: {{ .Release.Service }}\n{{- end -}}\n\n{{/*\nSelector labels\n*/}}\n{{- define \"test-chart.selectorLabels\" -}}\napp.kubernetes.io/name: {{ include \"test-chart.name\" . }}\napp.kubernetes.io/instance: {{ .Release.Name }}\n{{- end -}}\n\n{{/*\nCreate the name of the service account to use\n*/}}\n{{- define \"test-chart.serviceAccountName\" -}}\n{{ default \"controller-manager\" .Values.serviceAccount.name }}\n{{- end -}}"
  },
  {
    "path": "internal/plugins/helm/v1/chartutil/testdata/test-chart/templates/deployment.yaml",
    "content": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: {{ include \"test-chart.fullname\" . }}\n  labels:\n    {{- include \"test-chart.labels\" . | nindent 4 }}\nspec:\n  replicas: {{ .Values.replicaCount }}\n  selector:\n    matchLabels:\n      {{- include \"test-chart.selectorLabels\" . | nindent 6 }}\n  template:\n    metadata:\n      labels:\n        {{- include \"test-chart.selectorLabels\" . | nindent 8 }}\n    spec:\n    {{- with .Values.imagePullSecrets }}\n      imagePullSecrets:\n        {{- toYaml . | nindent 8 }}\n    {{- end }}\n      serviceAccountName: {{ include \"test-chart.serviceAccountName\" . }}\n      securityContext:\n        {{- toYaml .Values.podSecurityContext | nindent 8 }}\n      containers:\n        - name: {{ .Chart.Name }}\n          securityContext:\n            {{- toYaml .Values.securityContext | nindent 12 }}\n          image: \"{{ .Values.image.repository }}:{{ .Chart.AppVersion }}\"\n          imagePullPolicy: {{ .Values.image.pullPolicy }}\n          ports:\n            - name: http\n              containerPort: 80\n              protocol: TCP\n          livenessProbe:\n            httpGet:\n              path: /\n              port: http\n          readinessProbe:\n            httpGet:\n              path: /\n              port: http\n          resources:\n            {{- toYaml .Values.resources | nindent 12 }}\n      {{- with .Values.nodeSelector }}\n      nodeSelector:\n        {{- toYaml . | nindent 8 }}\n      {{- end }}\n    {{- with .Values.affinity }}\n      affinity:\n        {{- toYaml . | nindent 8 }}\n    {{- end }}\n    {{- with .Values.tolerations }}\n      tolerations:\n        {{- toYaml . | nindent 8 }}\n    {{- end }}\n"
  },
  {
    "path": "internal/plugins/helm/v1/chartutil/testdata/test-chart/templates/ingress.yaml",
    "content": "{{- if .Values.ingress.enabled -}}\n{{- $fullName := include \"test-chart.fullname\" . -}}\n{{- $svcPort := .Values.service.port -}}\napiVersion: networking.k8s.io/v1beta1\nkind: Ingress\nmetadata:\n  name: {{ $fullName }}\n  labels:\n    {{- include \"test-chart.labels\" . | nindent 4 }}\n  {{- with .Values.ingress.annotations }}\n  annotations:\n    {{- toYaml . | nindent 4 }}\n  {{- end }}\nspec:\n{{- if .Values.ingress.tls }}\n  tls:\n  {{- range .Values.ingress.tls }}\n    - hosts:\n      {{- range .hosts }}\n        - {{ . | quote }}\n      {{- end }}\n      secretName: {{ .secretName }}\n  {{- end }}\n{{- end }}\n  rules:\n  {{- range .Values.ingress.hosts }}\n    - host: {{ .host | quote }}\n      http:\n        paths:\n        {{- range .paths }}\n          - path: {{ . }}\n            backend:\n              serviceName: {{ $fullName }}\n              servicePort: {{ $svcPort }}\n        {{- end }}\n  {{- end }}\n{{- end }}\n"
  },
  {
    "path": "internal/plugins/helm/v1/chartutil/testdata/test-chart/templates/service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  name: {{ include \"test-chart.fullname\" . }}\n  labels:\n    {{- include \"test-chart.labels\" . | nindent 4 }}\nspec:\n  type: {{ .Values.service.type }}\n  ports:\n    - port: {{ .Values.service.port }}\n      targetPort: http\n      protocol: TCP\n      name: http\n  selector:\n    {{- include \"test-chart.selectorLabels\" . | nindent 4 }}\n"
  },
  {
    "path": "internal/plugins/helm/v1/chartutil/testdata/test-chart/templates/serviceaccount.yaml",
    "content": "{{- if .Values.serviceAccount.create -}}\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: {{ include \"test-chart.serviceAccountName\" . }}\n  labels:\n{{ include \"test-chart.labels\" . | nindent 4 }}\n{{- end -}}\n"
  },
  {
    "path": "internal/plugins/helm/v1/chartutil/testdata/test-chart/templates/tests/test-connection.yaml",
    "content": "apiVersion: v1\nkind: Pod\nmetadata:\n  name: \"{{ include \"test-chart.fullname\" . }}-test-connection\"\n  labels:\n{{ include \"test-chart.labels\" . | nindent 4 }}\n  annotations:\n    \"helm.sh/hook\": test-success\nspec:\n  containers:\n    - name: wget\n      image: busybox\n      command: ['wget']\n      args:  ['{{ include \"test-chart.fullname\" . }}:{{ .Values.service.port }}']\n  restartPolicy: Never\n"
  },
  {
    "path": "internal/plugins/helm/v1/chartutil/testdata/test-chart/values.yaml",
    "content": "# Default values for test-chart.\n# This is a YAML-formatted file.\n# Declare variables to be passed into your templates.\n\nreplicaCount: 1\n\nimage:\n  repository: nginx\n  pullPolicy: IfNotPresent\n\nimagePullSecrets: []\nnameOverride: \"\"\nfullnameOverride: \"\"\n\nserviceAccount:\n  # Specifies whether a service account should be created\n  create: true\n  # The name of the service account to use.\n  # If not set and create is true, a name is generated using the fullname template\n  name:\n\npodSecurityContext: {}\n  # fsGroup: 2000\n\nsecurityContext: {}\n  # capabilities:\n  #   drop:\n  #   - ALL\n  # readOnlyRootFilesystem: true\n  # runAsNonRoot: true\n  # runAsUser: 1000\n\nservice:\n  type: ClusterIP\n  port: 80\n\ningress:\n  enabled: false\n  annotations: {}\n    # kubernetes.io/ingress.class: nginx\n    # kubernetes.io/tls-acme: \"true\"\n  hosts:\n    - host: chart-example.local\n      paths: []\n  tls: []\n  #  - secretName: chart-example-tls\n  #    hosts:\n  #      - chart-example.local\n\nresources: {}\n  # We usually recommend not to specify default resources and to leave this as a conscious\n  # choice for the user. This also increases chances charts run on environments with little\n  # resources, such as Minikube. If you do want to specify resources, uncomment the following\n  # lines, adjust them as necessary, and remove the curly braces after 'resources:'.\n  # limits:\n  #   cpu: 100m\n  #   memory: 128Mi\n  # requests:\n  #   cpu: 100m\n  #   memory: 128Mi\n\nnodeSelector: {}\n\ntolerations: []\n\naffinity: {}\n"
  },
  {
    "path": "internal/plugins/helm/v1/init.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage v1\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\n\t\"github.com/spf13/pflag\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/config\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/machinery\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/plugin\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/plugin/util\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/scaffolds\"\n\tsdkpluginutil \"github.com/operator-framework/operator-sdk/internal/plugins/util\"\n)\n\nconst (\n\tgroupFlag   = \"group\"\n\tversionFlag = \"version\"\n\tkindFlag    = \"kind\"\n)\n\ntype initSubcommand struct {\n\tapiSubcommand createAPISubcommand\n\n\tconfig config.Config\n\n\t// For help text.\n\tcommandName string\n\n\t// Flags\n\tgroup   string\n\tversion string\n\tkind    string\n}\n\nvar _ plugin.InitSubcommand = &initSubcommand{}\n\n// UpdateContext define plugin context\nfunc (p *initSubcommand) UpdateMetadata(cliMeta plugin.CLIMetadata, subcmdMeta *plugin.SubcommandMetadata) {\n\tsubcmdMeta.Description = `Initialize a new Helm-based operator project.\n\nWrites the following files:\n- a helm-charts directory with the chart(s) to build releases from\n- a watches.yaml file that defines the mapping between your API and a Helm chart\n- a PROJECT file with the domain and project layout configuration\n- a Makefile to build the project\n- a Kustomization.yaml for customizating manifests\n- a Patch file for customizing image for manager manifests\n- a Patch file for enabling prometheus metrics\n`\n\tsubcmdMeta.Examples = fmt.Sprintf(`  $ %[1]s init --plugins=%[2]s \\\n      --domain=example.com \\\n      --group=apps \\\n      --version=v1alpha1 \\\n      --kind=AppService\n\n  $ %[1]s init --plugins=%[2]s \\\n      --project-name=myapp\n      --domain=example.com \\\n      --group=apps \\\n      --version=v1alpha1 \\\n      --kind=AppService\n\n  $ %[1]s init --plugins=%[2]s \\\n      --domain=example.com \\\n      --group=apps \\\n      --version=v1alpha1 \\\n      --kind=AppService \\\n      --helm-chart=myrepo/app\n\n  $ %[1]s init --plugins=%[2]s \\\n      --domain=example.com \\\n      --helm-chart=myrepo/app\n\n  $ %[1]s init --plugins=%[2]s \\\n      --domain=example.com \\\n      --helm-chart=myrepo/app \\\n      --helm-chart-version=1.2.3\n\n  $ %[1]s init --plugins=%[2]s \\\n      --domain=example.com \\\n      --helm-chart=app \\\n      --helm-chart-repo=https://charts.mycompany.com/\n\n  $ %[1]s init --plugins=%[2]s \\\n      --domain=example.com \\\n      --helm-chart=app \\\n      --helm-chart-repo=https://charts.mycompany.com/ \\\n      --helm-chart-version=1.2.3\n\n  $ %[1]s init --plugins=%[2]s \\\n      --domain=example.com \\\n      --helm-chart=/path/to/local/chart-directories/app/\n\n  $ %[1]s init --plugins=%[2]s \\\n      --domain=example.com \\\n      --helm-chart=/path/to/local/chart-archives/app-1.2.3.tgz\n`, cliMeta.CommandName, pluginKey)\n\n\tp.commandName = cliMeta.CommandName\n}\n\nfunc (p *initSubcommand) BindFlags(fs *pflag.FlagSet) {\n\tfs.SortFlags = false\n\tfs.StringVar(&p.group, groupFlag, \"\", \"resource Group\")\n\tfs.StringVar(&p.version, versionFlag, \"\", \"resource Version\")\n\tfs.StringVar(&p.kind, kindFlag, \"\", \"resource Kind\")\n\tp.apiSubcommand.BindFlags(fs)\n}\n\nfunc (p *initSubcommand) InjectConfig(c config.Config) error {\n\tp.config = c\n\treturn nil\n}\n\nfunc (p *initSubcommand) Scaffold(fs machinery.Filesystem) error {\n\tif err := addInitCustomizations(p.config.GetProjectName()); err != nil {\n\t\treturn fmt.Errorf(\"error updating init manifests: %s\", err)\n\t}\n\n\tscaffolder := scaffolds.NewInitScaffolder(p.config)\n\tscaffolder.InjectFS(fs)\n\treturn scaffolder.Scaffold()\n}\n\n// PostScaffold will run the required actions after the default plugin scaffold\nfunc (p *initSubcommand) PostScaffold() error {\n\tdoAPI := p.group != \"\" || p.version != \"\" || p.kind != \"\" || p.apiSubcommand.options.chartOptions.Chart != \"\"\n\tif !doAPI {\n\t\tfmt.Printf(\"Next: define a resource with:\\n$ %s create api\\n\", p.commandName)\n\t} else {\n\t\targs := []string{\"create\", \"api\"}\n\t\t// The following three checks should match the default values in sig.k8s.io/kubebuilder/v4/pkg/cli/resource.go\n\t\tif p.group != \"\" {\n\t\t\targs = append(args, fmt.Sprintf(\"--%s\", groupFlag), p.group)\n\t\t}\n\t\tif p.version != \"\" {\n\t\t\targs = append(args, fmt.Sprintf(\"--%s\", versionFlag), p.version)\n\t\t}\n\t\tif p.kind != \"\" {\n\t\t\targs = append(args, fmt.Sprintf(\"--%s\", kindFlag), p.kind)\n\t\t}\n\t\tif p.apiSubcommand.options.CRDVersion != defaultCrdVersion {\n\t\t\targs = append(args, fmt.Sprintf(\"--%s\", crdVersionFlag), p.apiSubcommand.options.CRDVersion)\n\t\t}\n\t\tif p.apiSubcommand.options.chartOptions.Chart != \"\" {\n\t\t\targs = append(args, fmt.Sprintf(\"--%s\", helmChartFlag), p.apiSubcommand.options.chartOptions.Chart)\n\t\t}\n\t\tif p.apiSubcommand.options.chartOptions.Repo != \"\" {\n\t\t\targs = append(args, fmt.Sprintf(\"--%s\", helmChartRepoFlag), p.apiSubcommand.options.chartOptions.Repo)\n\t\t}\n\t\tif p.apiSubcommand.options.chartOptions.Version != \"\" {\n\t\t\targs = append(args, fmt.Sprintf(\"--%s\", helmChartVersionFlag), p.apiSubcommand.options.chartOptions.Version)\n\t\t}\n\t\tif err := util.RunCmd(\"Creating the API\", os.Args[0], args...); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// addInitCustomizations will perform the required customizations for this plugin on the common base\nfunc addInitCustomizations(projectName string) error {\n\tmanagerFile := filepath.Join(\"config\", \"manager\", \"manager.yaml\")\n\tmanagerMetricsPatch := filepath.Join(\"config\", \"default\", \"manager_metrics_patch.yaml\")\n\n\t// todo: we ought to use afero instead. Replace this methods to insert/update\n\t// by https://github.com/kubernetes-sigs/kubebuilder/pull/2119\n\n\terr := util.InsertCode(managerFile,\n\t\t\"--leader-elect\",\n\t\tfmt.Sprintf(\"\\n          - --leader-election-id=%s\", projectName))\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Remove the call to the command as manager. Helm has not been exposing this entrypoint\n\t// todo: provide the manager entrypoint for helm and then remove it\n\tconst command = `command:\n        - /manager\n        `\n\terr = util.ReplaceInFile(managerFile, command, \"\")\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Enable the proper auth/metrics flags for helm\n\terr = util.ReplaceInFile(managerMetricsPatch,\n\t\t`# This patch adds the args to allow exposing the metrics endpoint using HTTPS\n- op: add\n  path: /spec/template/spec/containers/0/args/0\n  value: --metrics-bind-address=:8443`, `# This patch adds the args to allow exposing the metrics endpoint using HTTPS\n- op: add\n  path: /spec/template/spec/containers/0/args/0\n  value: --metrics-bind-address=:8443\n# This patch adds the args to allow securing the metrics endpoint\n- op: add\n  path: /spec/template/spec/containers/0/args/0\n  value: --metrics-secure\n# This patch adds the args to allow RBAC-based authn/authz the metrics endpoint\n- op: add\n  path: /spec/template/spec/containers/0/args/0\n  value: --metrics-require-rbac`)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif err := sdkpluginutil.UpdateKustomizationsInit(); err != nil {\n\t\treturn fmt.Errorf(\"error updating kustomization.yaml files: %v\", err)\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "internal/plugins/helm/v1/plugin.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage v1\n\nimport (\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/config\"\n\tcfgv3 \"sigs.k8s.io/kubebuilder/v4/pkg/config/v3\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/plugin\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/plugins\"\n)\n\nconst pluginName = \"base.helm\" + plugins.DefaultNameQualifier\n\nvar (\n\tpluginVersion            = plugin.Version{Number: 1}\n\tsupportedProjectVersions = []config.Version{cfgv3.Version}\n\tpluginKey                = plugin.KeyFor(Plugin{})\n)\n\nvar (\n\t_ plugin.Plugin    = Plugin{}\n\t_ plugin.Init      = Plugin{}\n\t_ plugin.CreateAPI = Plugin{}\n)\n\ntype Plugin struct {\n\tinitSubcommand\n\tcreateAPISubcommand\n}\n\nfunc (Plugin) Name() string                                         { return pluginName }\nfunc (Plugin) Version() plugin.Version                              { return pluginVersion }\nfunc (Plugin) SupportedProjectVersions() []config.Version           { return supportedProjectVersions }\nfunc (p Plugin) GetInitSubcommand() plugin.InitSubcommand           { return &p.initSubcommand }\nfunc (p Plugin) GetCreateAPISubcommand() plugin.CreateAPISubcommand { return &p.createAPISubcommand }\n"
  },
  {
    "path": "internal/plugins/helm/v1/scaffolds/api.go",
    "content": "/*\nCopyright 2019 The Kubernetes Authors.\nModifications copyright 2020 The Operator-SDK Authors\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage scaffolds\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\n\t\"helm.sh/helm/v3/pkg/chart\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/config\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/machinery\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/model/resource\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/plugins\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/chartutil\"\n\t\"github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/scaffolds/internal/templates\"\n\t\"github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/scaffolds/internal/templates/config/crd\"\n\t\"github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac\"\n\t\"github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/scaffolds/internal/templates/config/samples\"\n)\n\nvar _ plugins.Scaffolder = &apiScaffolder{}\n\n// apiScaffolder contains configuration for generating scaffolding for Go type\n// representing the API and controller that implements the behavior for the API.\ntype apiScaffolder struct {\n\tfs machinery.Filesystem\n\n\tconfig   config.Config\n\tresource resource.Resource\n\tchrt     *chart.Chart\n}\n\n// NewAPIScaffolder returns a new plugins.Scaffolder for API/controller creation operations\nfunc NewAPIScaffolder(cfg config.Config, res resource.Resource, chrt *chart.Chart) plugins.Scaffolder {\n\treturn &apiScaffolder{\n\t\tconfig:   cfg,\n\t\tresource: res,\n\t\tchrt:     chrt,\n\t}\n}\n\n// InjectFS implements plugins.Scaffolder\nfunc (s *apiScaffolder) InjectFS(fs machinery.Filesystem) {\n\ts.fs = fs\n}\n\n// Scaffold implements plugins.Scaffolder\nfunc (s *apiScaffolder) Scaffold() error {\n\tif err := s.config.UpdateResource(s.resource); err != nil {\n\t\treturn err\n\t}\n\n\t// Get current directory\n\tprojectDir, err := os.Getwd()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Save the loaded chart.Chart\n\tvar chartPath string\n\ts.chrt, chartPath, err = chartutil.ScaffoldChart(s.chrt, projectDir)\n\tif err != nil {\n\t\treturn err\n\t}\n\tfmt.Printf(\"Created %s\\n\", chartPath)\n\n\t// Initialize the machinery.Scaffold that will write the files to disk\n\tscaffold := machinery.NewScaffold(s.fs,\n\t\t// NOTE: kubebuilder's default permissions are only for root users\n\t\tmachinery.WithDirectoryPermissions(0755),\n\t\tmachinery.WithFilePermissions(0644),\n\t\tmachinery.WithConfig(s.config),\n\t\tmachinery.WithResource(&s.resource),\n\t)\n\n\tif err := scaffold.Execute(\n\t\t&templates.WatchesUpdater{ChartPath: chartPath},\n\t\t&crd.CRD{},\n\t\t&crd.Kustomization{},\n\t\t&rbac.ManagerRoleUpdater{Chart: s.chrt},\n\t\t&samples.CustomResource{ChartPath: chartPath, Chart: s.chrt},\n\t); err != nil {\n\t\treturn fmt.Errorf(\"error scaffolding APIs: %w\", err)\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "internal/plugins/helm/v1/scaffolds/doc.go",
    "content": "/*\nCopyright 2018 The Kubernetes Authors.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\n// Package scaffolds contains libraries for scaffolding code to use with helm-operator\npackage scaffolds\n"
  },
  {
    "path": "internal/plugins/helm/v1/scaffolds/init.go",
    "content": "/*\nCopyright 2019 The Kubernetes Authors.\nModifications copyright 2020 The Operator-SDK Authors\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage scaffolds\n\nimport (\n\tkustomizev2 \"sigs.k8s.io/kubebuilder/v4/pkg/plugins/common/kustomize/v2\"\n\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/config\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/machinery\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/plugins\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/chartutil\"\n\t\"github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/scaffolds/internal/templates\"\n\t\"github.com/operator-framework/operator-sdk/internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac\"\n\t\"github.com/operator-framework/operator-sdk/internal/version\"\n)\n\nconst imageName = \"controller:latest\"\n\n// helmOperatorVersion is set to the version of helm-operator at compile-time.\nvar helmOperatorVersion = version.ImageVersion\n\nvar _ plugins.Scaffolder = &initScaffolder{}\n\ntype initScaffolder struct {\n\tfs machinery.Filesystem\n\n\tconfig config.Config\n}\n\n// NewInitScaffolder returns a new plugins.Scaffolder for project initialization operations\nfunc NewInitScaffolder(config config.Config) plugins.Scaffolder {\n\treturn &initScaffolder{\n\t\tconfig: config,\n\t}\n}\n\n// InjectFS implements plugins.Scaffolder\nfunc (s *initScaffolder) InjectFS(fs machinery.Filesystem) {\n\ts.fs = fs\n}\n\n// Scaffold implements Scaffolder\nfunc (s *initScaffolder) Scaffold() error {\n\t// Initialize the machinery.Scaffold that will write the files to disk\n\tscaffold := machinery.NewScaffold(s.fs,\n\t\t// NOTE: kubebuilder's default permissions are only for root users\n\t\tmachinery.WithDirectoryPermissions(0755),\n\t\tmachinery.WithFilePermissions(0644),\n\t\tmachinery.WithConfig(s.config),\n\t)\n\n\tif err := s.fs.FS.MkdirAll(chartutil.HelmChartsDir, 0755); err != nil {\n\t\treturn err\n\t}\n\n\treturn scaffold.Execute(\n\t\t&templates.Dockerfile{\n\t\t\tHelmOperatorVersion: helmOperatorVersion,\n\t\t},\n\t\t&templates.GitIgnore{},\n\t\t&templates.Makefile{\n\t\t\tImage:               imageName,\n\t\t\tKustomizeVersion:    kustomizev2.KustomizeVersion,\n\t\t\tHelmOperatorVersion: helmOperatorVersion,\n\t\t},\n\t\t&templates.Watches{},\n\t\t&rbac.ManagerRole{},\n\t)\n}\n"
  },
  {
    "path": "internal/plugins/helm/v1/scaffolds/internal/templates/config/crd/crd.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage crd\n\nimport (\n\t\"fmt\"\n\t\"path/filepath\"\n\n\t\"github.com/kr/text\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/machinery\"\n)\n\nvar _ machinery.Template = &CRD{}\n\n// CRD scaffolds a manifest for CRD sample.\ntype CRD struct {\n\tmachinery.TemplateMixin\n\tmachinery.ResourceMixin\n}\n\n// SetTemplateDefaults implements machinery.Template\nfunc (f *CRD) SetTemplateDefaults() error {\n\tif f.Path == \"\" {\n\t\tf.Path = filepath.Join(\"config\", \"crd\", \"bases\", fmt.Sprintf(\"%s_%%[plural].yaml\", f.Resource.QualifiedGroup()))\n\t}\n\tf.Path = f.Resource.Replacer().Replace(f.Path)\n\n\tf.IfExistsAction = machinery.Error\n\n\tf.TemplateBody = fmt.Sprintf(crdTemplate,\n\t\ttext.Indent(openAPIV3SchemaTemplate, \"    \"),\n\t\ttext.Indent(openAPIV3SchemaTemplate, \"      \"),\n\t)\n\n\treturn nil\n}\n\nconst crdTemplate = `---\napiVersion: apiextensions.k8s.io/{{ .Resource.API.CRDVersion }}\nkind: CustomResourceDefinition\nmetadata:\n  name: {{ .Resource.Plural }}.{{ .Resource.QualifiedGroup }}\nspec:\n  group: {{ .Resource.QualifiedGroup }}\n  names:\n    kind: {{ .Resource.Kind }}\n    listKind: {{ .Resource.Kind }}List\n    plural: {{ .Resource.Plural }}\n    singular: {{ .Resource.Kind | lower }}\n  scope: Namespaced\n{{- if eq .Resource.API.CRDVersion \"v1beta1\" }}\n  subresources:\n    status: {}\n  validation:\n%s\n{{- end }}\n  versions:\n  - name: {{ .Resource.Version }}\n{{- if eq .Resource.API.CRDVersion \"v1\" }}\n    schema:\n%s\n{{- end }}\n    served: true\n    storage: true\n{{- if eq .Resource.API.CRDVersion \"v1\" }}\n    subresources:\n      status: {}\n{{- end }}\n`\n\nconst openAPIV3SchemaTemplate = `openAPIV3Schema:\n  description: {{ .Resource.Kind }} is the Schema for the {{ .Resource.Plural }} API\n  properties:\n    apiVersion:\n      description: 'APIVersion defines the versioned schema of this representation\n        of an object. Servers should convert recognized schemas to the latest\n        internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'\n      type: string\n    kind:\n      description: 'Kind is a string value representing the REST resource this\n        object represents. Servers may infer this from the endpoint the client\n        submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'\n      type: string\n    metadata:\n      type: object\n    spec:\n      description: Spec defines the desired state of {{ .Resource.Kind }}\n      type: object\n      x-kubernetes-preserve-unknown-fields: true\n    status:\n      description: Status defines the observed state of {{ .Resource.Kind }}\n      type: object\n      x-kubernetes-preserve-unknown-fields: true\n  type: object\n`\n"
  },
  {
    "path": "internal/plugins/helm/v1/scaffolds/internal/templates/config/crd/kustomization.go",
    "content": "/*\nCopyright 2019 The Kubernetes Authors.\nModifications copyright 2020 The Operator-SDK Authors\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage crd\n\nimport (\n\t\"fmt\"\n\t\"path/filepath\"\n\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/machinery\"\n)\n\nvar (\n\t_ machinery.Template = &Kustomization{}\n\t_ machinery.Inserter = &Kustomization{}\n)\n\n// Kustomization scaffolds the kustomization file in manager folder.\ntype Kustomization struct {\n\tmachinery.TemplateMixin\n\tmachinery.ResourceMixin\n}\n\n// SetTemplateDefaults implements machinery.Template\nfunc (f *Kustomization) SetTemplateDefaults() error {\n\tif f.Path == \"\" {\n\t\tf.Path = filepath.Join(\"config\", \"crd\", \"kustomization.yaml\")\n\t}\n\n\tf.TemplateBody = fmt.Sprintf(kustomizationTemplate, machinery.NewMarkerFor(f.Path, resourceMarker))\n\n\treturn nil\n}\n\nconst (\n\tresourceMarker = \"crdkustomizeresource\"\n)\n\n// GetMarkers implements machinery.Inserter\nfunc (f *Kustomization) GetMarkers() []machinery.Marker {\n\treturn []machinery.Marker{\n\t\tmachinery.NewMarkerFor(f.Path, resourceMarker),\n\t}\n}\n\nconst (\n\tresourceCodeFragment = `- bases/%s_%s.yaml\n`\n)\n\n// GetCodeFragments implements machinery.Inserter\nfunc (f *Kustomization) GetCodeFragments() machinery.CodeFragmentsMap {\n\treturn machinery.CodeFragmentsMap{\n\t\t// Generate resource code fragments\n\t\tmachinery.NewMarkerFor(f.Path, resourceMarker): []string{\n\t\t\tfmt.Sprintf(resourceCodeFragment, f.Resource.QualifiedGroup(), f.Resource.Plural),\n\t\t},\n\t}\n}\n\nvar kustomizationTemplate = `# This kustomization.yaml is not intended to be run by itself,\n# since it depends on service name and namespace that are out of this kustomize package.\n# It should be run by config/default\nresources:\n%s\n`\n"
  },
  {
    "path": "internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/manager_role.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage rbac\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strings\"\n\t\"text/template\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\t\"helm.sh/helm/v3/pkg/action\"\n\t\"helm.sh/helm/v3/pkg/chart\"\n\t\"helm.sh/helm/v3/pkg/chartutil\"\n\t\"helm.sh/helm/v3/pkg/releaseutil\"\n\trbacv1 \"k8s.io/api/rbac/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured\"\n\t\"k8s.io/client-go/discovery\"\n\tcrconfig \"sigs.k8s.io/controller-runtime/pkg/client/config\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/machinery\"\n\t\"sigs.k8s.io/yaml\"\n)\n\nvar _ machinery.Template = &ManagerRole{}\n\nvar defaultRoleFile = filepath.Join(\"config\", \"rbac\", \"role.yaml\")\n\n// ManagerRole scaffolds the role.yaml file\ntype ManagerRole struct {\n\tmachinery.TemplateMixin\n}\n\n// SetTemplateDefaults implements machinery.Template\nfunc (f *ManagerRole) SetTemplateDefaults() error {\n\tif f.Path == \"\" {\n\t\tf.Path = defaultRoleFile\n\t}\n\n\tf.TemplateBody = fmt.Sprintf(roleTemplate, machinery.NewMarkerFor(f.Path, rulesMarker))\n\tf.IfExistsAction = machinery.OverwriteFile\n\n\treturn nil\n}\n\nvar _ machinery.Inserter = &ManagerRoleUpdater{}\n\ntype ManagerRoleUpdater struct {\n\tmachinery.ResourceMixin\n\n\tChart            *chart.Chart\n\tSkipDefaultRules bool\n\tCustomRules      []rbacv1.PolicyRule\n}\n\nfunc (*ManagerRoleUpdater) GetPath() string {\n\treturn defaultRoleFile\n}\n\nfunc (*ManagerRoleUpdater) GetIfExistsAction() machinery.IfExistsAction {\n\treturn machinery.OverwriteFile\n}\n\nconst (\n\trulesMarker = \"rules\"\n)\n\nfunc (f *ManagerRoleUpdater) GetMarkers() []machinery.Marker {\n\treturn []machinery.Marker{\n\t\tmachinery.NewMarkerFor(defaultRoleFile, rulesMarker),\n\t}\n}\n\nfunc (f *ManagerRoleUpdater) GetCodeFragments() machinery.CodeFragmentsMap {\n\tfragments := make(machinery.CodeFragmentsMap, 1)\n\n\t// If resource is not being provided we are creating the file, not updating it\n\tif f.Resource == nil {\n\t\treturn fragments\n\t}\n\n\tif k8sCfg, err := crconfig.GetConfig(); err != nil {\n\t\tlog.Warnf(\"Using default RBAC rules: failed to get Kubernetes config: %s\", err)\n\t} else if dc, err := discovery.NewDiscoveryClientForConfig(k8sCfg); err != nil {\n\t\tlog.Warnf(\"Using default RBAC rules: failed to create Kubernetes discovery client: %s\", err)\n\t} else {\n\t\tf.updateForChart(dc)\n\t}\n\n\tbuf := &bytes.Buffer{}\n\ttmpl := template.Must(template.New(\"rules\").Parse(rulesFragment))\n\terr := tmpl.Execute(buf, f)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// Generate rule fragment\n\trules := []string{buf.String()}\n\n\tif len(rules) != 0 {\n\t\tfragments[machinery.NewMarkerFor(defaultRoleFile, rulesMarker)] = rules\n\t}\n\treturn fragments\n}\n\nconst roleTemplate = `apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  name: manager-role\nrules:\n##\n## Base operator rules\n##\n# We need to get namespaces so the operator can read namespaces to ensure they exist\n- apiGroups:\n  - \"\"\n  resources:\n  - namespaces\n  verbs:\n  - get\n# We need to manage Helm release secrets\n- apiGroups:\n  - \"\"\n  resources:\n  - secrets\n  verbs:\n  - \"*\"\n# We need to create events on CRs about things happening during reconciliation\n- apiGroups:\n  - \"\"\n  resources:\n  - events\n  verbs:\n  - create\n\n%s\n`\n\nconst rulesFragment = `##\n## Rules for {{.Resource.QualifiedGroup}}/{{.Resource.Version}}, Kind: {{.Resource.Kind}}\n##\n- apiGroups:\n  - {{.Resource.QualifiedGroup}}\n  resources:\n  - {{.Resource.Plural}}\n  - {{.Resource.Plural}}/status\n  - {{.Resource.Plural}}/finalizers\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n{{- if not .SkipDefaultRules }}\n- apiGroups:\n  - \"\"\n  resources:\n  - pods\n  - services\n  - services/finalizers\n  - endpoints\n  - persistentvolumeclaims\n  - events\n  - configmaps\n  - secrets\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n- apiGroups:\n  - apps\n  resources:\n  - deployments\n  - daemonsets\n  - replicasets\n  - statefulsets\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n{{- end }}\n{{- range .CustomRules }}\n- verbs:\n  {{- range .Verbs }}\n  - \"{{ . }}\"\n  {{- end }}\n  {{- with .APIGroups }}\n  apiGroups:\n  {{- range . }}\n  - \"{{ . }}\"\n  {{- end }}\n  {{- end }}\n  {{- with .Resources }}\n  resources:\n  {{- range . }}\n  - \"{{ . }}\"\n  {{- end }}\n  {{- end }}\n  {{- with .ResourceNames }}\n  resourceNames:\n  {{- range . }}\n  - \"{{ . }}\"\n  {{- end }}\n  {{- end }}\n  {{- with .NonResourceURLs }}\n  nonResourceURLs:\n  {{- range . }}\n  - \"{{ . }}\"\n  {{- end }}\n  {{- end }}\n{{- end }}\n\n`\n\n// roleDiscoveryInterface is an interface that contains just the discovery\n// methods needed by the Helm role scaffold generator. Requiring just this\n// interface simplifies testing.\ntype roleDiscoveryInterface interface {\n\tServerGroupsAndResources() ([]*metav1.APIGroup, []*metav1.APIResourceList, error)\n}\n\n// updateForChart updates the role scaffold from the provided helm chart. It\n// renders a release manifest using the chart's default values and uses the Kubernetes\n// discovery API to lookup each resource in the resulting manifest.\n// The role scaffold will have IsClusterScoped=true if the chart lists cluster scoped resources\nfunc (f *ManagerRoleUpdater) updateForChart(dc roleDiscoveryInterface) {\n\tfmt.Println(\"Generating RBAC rules\")\n\n\tclusterResourceRules, namespacedResourceRules, err := generateRoleRules(dc, f.Chart)\n\tif err != nil {\n\t\tlog.Warnf(\"Using default RBAC rules: failed to generate RBAC rules: %s\", err)\n\t\treturn\n\t}\n\n\tf.SkipDefaultRules = true\n\tf.CustomRules = append(f.CustomRules, append(clusterResourceRules,\n\t\tnamespacedResourceRules...)...)\n\n\tlog.Warn(\"The RBAC rules generated in config/rbac/role.yaml are based on the chart's default manifest.\" +\n\t\t\" Some rules may be missing for resources that are only enabled with custom values, and\" +\n\t\t\" some existing rules may be overly broad. Double check the rules generated in config/rbac/role.yaml\" +\n\t\t\" to ensure they meet the operator's permission requirements.\")\n}\n\nfunc generateRoleRules(dc roleDiscoveryInterface, chart *chart.Chart) ([]rbacv1.PolicyRule,\n\t[]rbacv1.PolicyRule, error) {\n\t_, serverResources, err := dc.ServerGroupsAndResources()\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"failed to get server resources: %v\", err)\n\t}\n\n\tmanifests, err := getDefaultManifests(chart)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"failed to get default manifest: %v\", err)\n\t}\n\n\t// Use maps of sets of resources, keyed by their group. This helps us\n\t// de-duplicate resources within a group as we traverse the manifests.\n\tclusterGroups := map[string]map[string]struct{}{}\n\tnamespacedGroups := map[string]map[string]struct{}{}\n\n\tfor _, m := range manifests {\n\t\tname := m.Name\n\t\tcontent := strings.TrimSpace(m.Content)\n\n\t\t// Ignore NOTES.txt, helper manifests, and empty manifests.\n\t\tb := filepath.Base(name)\n\t\tif b == \"NOTES.txt\" {\n\t\t\tcontinue\n\t\t}\n\t\tif strings.HasPrefix(b, \"_\") {\n\t\t\tcontinue\n\t\t}\n\t\tif content == \"\" || content == \"---\" {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Extract the gvk from the template\n\t\tresource := unstructured.Unstructured{}\n\t\terr := yaml.Unmarshal([]byte(content), &resource)\n\t\tif err != nil {\n\t\t\tlog.Warnf(\"Skipping rule generation for %s. Failed to parse manifest: %s\", name, err)\n\t\t\tcontinue\n\t\t}\n\t\tgroupVersion := resource.GetAPIVersion()\n\t\tgroup := resource.GroupVersionKind().Group\n\t\tkind := resource.GroupVersionKind().Kind\n\n\t\t// If we don't have the group or the kind, we won't be able to\n\t\t// create a valid role rule, log a warning and continue.\n\t\tif groupVersion == \"\" {\n\t\t\tlog.Warnf(\"Skipping rule generation for %s. Failed to determine resource apiVersion.\", name)\n\t\t\tcontinue\n\t\t}\n\t\tif kind == \"\" {\n\t\t\tlog.Warnf(\"Skipping rule generation for %s. Failed to determine resource kind.\", name)\n\t\t\tcontinue\n\t\t}\n\n\t\tif resourceName, namespaced, ok := getResource(serverResources, groupVersion, kind); ok {\n\t\t\tif !namespaced {\n\t\t\t\tif clusterGroups[group] == nil {\n\t\t\t\t\tclusterGroups[group] = map[string]struct{}{}\n\t\t\t\t}\n\t\t\t\tclusterGroups[group][resourceName] = struct{}{}\n\t\t\t} else {\n\t\t\t\tif namespacedGroups[group] == nil {\n\t\t\t\t\tnamespacedGroups[group] = map[string]struct{}{}\n\t\t\t\t}\n\t\t\t\tnamespacedGroups[group][resourceName] = struct{}{}\n\t\t\t}\n\t\t} else {\n\t\t\tlog.Warnf(\"Skipping rule generation for %s. Failed to determine resource scope for %s.\",\n\t\t\t\tname, resource.GroupVersionKind())\n\t\t\tcontinue\n\t\t}\n\t}\n\n\t// convert map[string]map[string]struct{} to []rbacv1.PolicyRule\n\tclusterRules := buildRulesFromGroups(clusterGroups)\n\tnamespacedRules := buildRulesFromGroups(namespacedGroups)\n\n\treturn clusterRules, namespacedRules, nil\n}\n\nfunc getDefaultManifests(c *chart.Chart) ([]releaseutil.Manifest, error) {\n\tinstall := action.NewInstall(&action.Configuration{})\n\tinstall.DryRun = true\n\tinstall.ReleaseName = \"release-name\"\n\tinstall.Replace = true\n\tinstall.ClientOnly = true\n\trel, err := install.Run(c, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to render chart templates: %v\", err)\n\t}\n\t_, manifests, err := releaseutil.SortManifests(releaseutil.SplitManifests(rel.Manifest),\n\t\tchartutil.DefaultVersionSet, releaseutil.InstallOrder)\n\treturn manifests, err\n}\n\nfunc getResource(namespacedResourceList []*metav1.APIResourceList, groupVersion, kind string) (string, bool, bool) {\n\tfor _, apiResourceList := range namespacedResourceList {\n\t\tif apiResourceList.GroupVersion == groupVersion {\n\t\t\tfor _, apiResource := range apiResourceList.APIResources {\n\t\t\t\tif apiResource.Kind == kind {\n\t\t\t\t\treturn apiResource.Name, apiResource.Namespaced, true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn \"\", false, false\n}\n\nfunc buildRulesFromGroups(groups map[string]map[string]struct{}) []rbacv1.PolicyRule {\n\trules := []rbacv1.PolicyRule{}\n\tfor group, resourceNames := range groups {\n\t\tresources := []string{}\n\t\tfor resource := range resourceNames {\n\t\t\tresources = append(resources, resource)\n\t\t}\n\t\tsort.Strings(resources)\n\t\trules = append(rules, rbacv1.PolicyRule{\n\t\t\tAPIGroups: []string{group},\n\t\t\tResources: resources,\n\t\t\tVerbs:     []string{rbacv1.VerbAll},\n\t\t})\n\t}\n\treturn rules\n}\n"
  },
  {
    "path": "internal/plugins/helm/v1/scaffolds/internal/templates/config/rbac/manager_role_test.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage rbac\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"helm.sh/helm/v3/pkg/chart\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n)\n\nfunc TestGenerateRoleScaffold(t *testing.T) {\n\tvalidDiscoveryClient := &mockRoleDiscoveryClient{\n\t\tserverGroupsAndResources: func() ([]*metav1.APIGroup, []*metav1.APIResourceList, error) {\n\t\t\treturn simpleGroupList(), simpleResourcesList(), nil\n\t\t},\n\t}\n\n\tbrokenDiscoveryClient := &mockRoleDiscoveryClient{\n\t\tserverGroupsAndResources: func() ([]*metav1.APIGroup, []*metav1.APIResourceList, error) {\n\t\t\treturn nil, nil, errors.New(\"no server resources\")\n\t\t},\n\t}\n\n\ttestCases := []roleScaffoldTestCase{\n\t\t{\n\t\t\tname:                   \"fallback to default with unparsable template\",\n\t\t\tchart:                  failChart(),\n\t\t\texpectSkipDefaultRules: false,\n\t\t\texpectLenCustomRules:   0,\n\t\t},\n\t\t{\n\t\t\tname:                   \"skip rule for unknown API\",\n\t\t\tchart:                  unknownAPIChart(),\n\t\t\texpectSkipDefaultRules: true,\n\t\t\texpectLenCustomRules:   1,\n\t\t},\n\t\t{\n\t\t\tname:                   \"namespaced manifest\",\n\t\t\tchart:                  namespacedChart(),\n\t\t\texpectSkipDefaultRules: true,\n\t\t\texpectLenCustomRules:   1,\n\t\t},\n\t\t{\n\t\t\tname:                   \"cluster scoped manifest\",\n\t\t\tchart:                  clusterScopedChart(),\n\t\t\texpectSkipDefaultRules: true,\n\t\t\texpectLenCustomRules:   2,\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(fmt.Sprintf(\"%s with valid discovery client\", tc.name), func(t *testing.T) {\n\t\t\tf := ManagerRoleUpdater{Chart: tc.chart}\n\t\t\tf.updateForChart(validDiscoveryClient)\n\t\t\tassert.Equal(t, tc.expectSkipDefaultRules, f.SkipDefaultRules)\n\t\t\tassert.Equal(t, tc.expectLenCustomRules, len(f.CustomRules))\n\t\t})\n\n\t\tt.Run(fmt.Sprintf(\"%s with broken discovery client\", tc.name), func(t *testing.T) {\n\t\t\tf := ManagerRoleUpdater{Chart: tc.chart}\n\t\t\tf.updateForChart(brokenDiscoveryClient)\n\t\t\tassert.Equal(t, false, f.SkipDefaultRules)\n\t\t\tassert.Equal(t, 0, len(f.CustomRules))\n\t\t})\n\t}\n}\n\ntype mockRoleDiscoveryClient struct {\n\tserverGroupsAndResources func() ([]*metav1.APIGroup, []*metav1.APIResourceList, error)\n}\n\nfunc (dc *mockRoleDiscoveryClient) ServerGroupsAndResources() ([]*metav1.APIGroup, []*metav1.APIResourceList, error) {\n\treturn dc.serverGroupsAndResources()\n}\n\nfunc simpleGroupList() []*metav1.APIGroup {\n\treturn []*metav1.APIGroup{\n\t\t{\n\t\t\tName: \"example\",\n\t\t},\n\t\t{\n\t\t\tName: \"example2\",\n\t\t},\n\t}\n}\n\nfunc simpleResourcesList() []*metav1.APIResourceList {\n\treturn []*metav1.APIResourceList{\n\t\t{\n\t\t\tGroupVersion: \"v1\",\n\t\t\tAPIResources: []metav1.APIResource{\n\t\t\t\t{\n\t\t\t\t\tName:       \"namespaces\",\n\t\t\t\t\tKind:       \"Namespace\",\n\t\t\t\t\tNamespaced: false,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tName:       \"pods\",\n\t\t\t\t\tKind:       \"Pod\",\n\t\t\t\t\tNamespaced: true,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n}\n\ntype roleScaffoldTestCase struct {\n\tname                   string\n\tchart                  *chart.Chart\n\texpectSkipDefaultRules bool\n\texpectLenCustomRules   int\n}\n\nfunc failChart() *chart.Chart {\n\treturn &chart.Chart{\n\t\tMetadata: &chart.Metadata{\n\t\t\tName: \"broken\",\n\t\t},\n\t\tTemplates: []*chart.File{\n\t\t\t{Name: \"broken1.yaml\", Data: []byte(`invalid {{ template`)},\n\t\t},\n\t}\n}\n\nfunc unknownAPIChart() *chart.Chart {\n\treturn &chart.Chart{\n\t\tMetadata: &chart.Metadata{\n\t\t\tName: \"unknown\",\n\t\t},\n\t\tTemplates: []*chart.File{\n\t\t\t{Name: \"unknown1.yaml\", Data: testUnknownData(\"unknown1\")},\n\t\t\t{Name: \"pod1.yaml\", Data: testPodData(\"pod1\")},\n\t\t},\n\t}\n}\n\nfunc namespacedChart() *chart.Chart {\n\treturn &chart.Chart{\n\t\tMetadata: &chart.Metadata{\n\t\t\tName: \"namespaced\",\n\t\t},\n\t\tTemplates: []*chart.File{\n\t\t\t{Name: \"pod1.yaml\", Data: testPodData(\"pod1\")},\n\t\t\t{Name: \"pod2.yaml\", Data: testPodData(\"pod2\")},\n\t\t},\n\t}\n}\n\nfunc clusterScopedChart() *chart.Chart {\n\treturn &chart.Chart{\n\t\tMetadata: &chart.Metadata{\n\t\t\tName: \"clusterscoped\",\n\t\t},\n\t\tTemplates: []*chart.File{\n\t\t\t{Name: \"pod1.yaml\", Data: testPodData(\"pod1\")},\n\t\t\t{Name: \"pod2.yaml\", Data: testPodData(\"pod2\")},\n\t\t\t{Name: \"ns1.yaml\", Data: testNamespaceData(\"ns1\")},\n\t\t\t{Name: \"ns2.yaml\", Data: testNamespaceData(\"ns2\")},\n\t\t},\n\t}\n}\n\nfunc testUnknownData(name string) []byte {\n\treturn []byte(fmt.Sprintf(`apiVersion: my-test-unknown.unknown.com/v1alpha1\nkind: UnknownKind\nmetadata:\n  name: %s`, name),\n\t)\n}\n\nfunc testPodData(name string) []byte {\n\treturn []byte(fmt.Sprintf(`apiVersion: v1\nkind: Pod\nmetadata:\n  name: %s\nspec:\n  containers:\n  - name: test\n    image: test`, name),\n\t)\n}\n\nfunc testNamespaceData(name string) []byte {\n\treturn []byte(fmt.Sprintf(`apiVersion: v1\nkind: Namespace\nmetadata:\n  name: %s`, name),\n\t)\n}\n"
  },
  {
    "path": "internal/plugins/helm/v1/scaffolds/internal/templates/config/samples/custom_resource.go",
    "content": "/*\nCopyright 2018 The Kubernetes Authors.\nModifications copyright 2020 The Operator-SDK Authors\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage samples\n\nimport (\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"text/template\"\n\n\t\"helm.sh/helm/v3/pkg/chart\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/machinery\"\n\t\"sigs.k8s.io/yaml\"\n)\n\nvar (\n\t_ machinery.Template         = &CustomResource{}\n\t_ machinery.UseCustomFuncMap = &CustomResource{}\n)\n\n// CustomResource scaffolds a custom resource sample manifest.\ntype CustomResource struct {\n\tmachinery.TemplateMixin\n\tmachinery.ResourceMixin\n\n\tChartPath string\n\tChart     *chart.Chart\n\tSpec      string\n}\n\n// SetTemplateDefaults implements machinery.Template\nfunc (f *CustomResource) SetTemplateDefaults() error {\n\tif f.Path == \"\" {\n\t\tf.Path = filepath.Join(\"config\", \"samples\", \"%[group]_%[version]_%[kind].yaml\")\n\t}\n\tf.Path = f.Resource.Replacer().Replace(f.Path)\n\n\tf.IfExistsAction = machinery.OverwriteFile\n\n\tif len(f.Spec) == 0 {\n\t\tf.Spec = defaultSpecTemplate\n\t\tif f.Chart != nil {\n\t\t\tspec, err := yaml.Marshal(f.Chart.Values)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to get chart values: %v\", err)\n\t\t\t}\n\t\t\tcomment := \"\"\n\t\t\tif len(f.ChartPath) != 0 {\n\t\t\t\tcomment = fmt.Sprintf(\"# Default values copied from <project_dir>/%s/values.yaml\\n\", f.ChartPath)\n\t\t\t}\n\t\t\tf.Spec = fmt.Sprintf(\"%s%s\\n\", comment, string(spec))\n\t\t}\n\t}\n\n\tf.TemplateBody = customResourceTemplate\n\treturn nil\n}\n\nfunc indent(spaces int, v string) string {\n\tpad := strings.Repeat(\" \", spaces)\n\treturn pad + strings.ReplaceAll(v, \"\\n\", \"\\n\"+pad)\n}\n\n// GetFuncMap implements machinery.UseCustomFuncMap\nfunc (f *CustomResource) GetFuncMap() template.FuncMap {\n\tfm := machinery.DefaultFuncMap()\n\tfm[\"indent\"] = indent\n\treturn fm\n}\n\nconst defaultSpecTemplate = `# TODO(user): Add fields here\n`\n\nconst customResourceTemplate = `apiVersion: {{ .Resource.QualifiedGroup }}/{{ .Resource.Version }}\nkind: {{ .Resource.Kind }}\nmetadata:\n  name: {{ lower .Resource.Kind }}-sample\nspec:\n{{ .Spec | indent 2 }}\n`\n"
  },
  {
    "path": "internal/plugins/helm/v1/scaffolds/internal/templates/dockerfile.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage templates\n\nimport (\n\t\"errors\"\n\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/machinery\"\n)\n\nvar _ machinery.Template = &Dockerfile{}\n\n// Dockerfile scaffolds a Dockerfile for building a main\ntype Dockerfile struct {\n\tmachinery.TemplateMixin\n\n\t// HelmOperatorVersion is the version of the Dockerfile's base image.\n\tHelmOperatorVersion string\n}\n\n// SetTemplateDefaults implements machinery.Template\nfunc (f *Dockerfile) SetTemplateDefaults() error {\n\tif f.Path == \"\" {\n\t\tf.Path = \"Dockerfile\"\n\t}\n\n\tf.TemplateBody = dockerfileTemplate\n\n\tif f.HelmOperatorVersion == \"\" {\n\t\treturn errors.New(\"helm-operator version is required in scaffold\")\n\t}\n\n\treturn nil\n}\n\nconst dockerfileTemplate = `# Build the manager binary\nFROM quay.io/operator-framework/helm-operator:{{.HelmOperatorVersion}}\n\nENV HOME=/opt/helm\nCOPY watches.yaml ${HOME}/watches.yaml\nCOPY helm-charts  ${HOME}/helm-charts\nWORKDIR ${HOME}\n`\n"
  },
  {
    "path": "internal/plugins/helm/v1/scaffolds/internal/templates/gitignore.go",
    "content": "/*\nCopyright 2018 The Kubernetes Authors.\nModifications copyright 2020 The Operator-SDK Authors\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage templates\n\nimport (\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/machinery\"\n)\n\nvar _ machinery.Template = &GitIgnore{}\n\n// GitIgnore scaffolds the .gitignore file\ntype GitIgnore struct {\n\tmachinery.TemplateMixin\n}\n\n// SetTemplateDefaults implements machinery.Template\nfunc (f *GitIgnore) SetTemplateDefaults() error {\n\tif f.Path == \"\" {\n\t\tf.Path = \".gitignore\"\n\t}\n\n\tf.TemplateBody = gitignoreTemplate\n\n\treturn nil\n}\n\nconst gitignoreTemplate = `\n# Binaries for programs and plugins\n*.exe\n*.exe~\n*.dll\n*.so\n*.dylib\nbin\n\n# editor and IDE paraphernalia\n.idea\n*.swp\n*.swo\n*~\n`\n"
  },
  {
    "path": "internal/plugins/helm/v1/scaffolds/internal/templates/makefile.go",
    "content": "/*\nCopyright 2019 The Kubernetes Authors.\nModifications copyright 2020 The Operator-SDK Authors\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage templates\n\nimport (\n\t\"errors\"\n\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/machinery\"\n)\n\nvar _ machinery.Template = &Makefile{}\n\n// Makefile scaffolds the Makefile\ntype Makefile struct {\n\tmachinery.TemplateMixin\n\n\t// Image is controller manager image name\n\tImage string\n\n\t// Kustomize version to use in the project\n\tKustomizeVersion string\n\n\t// HelmOperatorVersion is the version of the helm-operator binary downloaded by the Makefile.\n\tHelmOperatorVersion string\n}\n\n// SetTemplateDefaults implements machinery.Template\nfunc (f *Makefile) SetTemplateDefaults() error {\n\tif f.Path == \"\" {\n\t\tf.Path = \"Makefile\"\n\t}\n\n\tf.TemplateBody = makefileTemplate\n\n\tf.IfExistsAction = machinery.Error\n\n\tif f.Image == \"\" {\n\t\tf.Image = \"controller:latest\"\n\t}\n\n\tif f.KustomizeVersion == \"\" {\n\t\treturn errors.New(\"kustomize version is required in scaffold\")\n\t}\n\n\tif f.HelmOperatorVersion == \"\" {\n\t\treturn errors.New(\"helm-operator version is required in scaffold\")\n\t}\n\n\treturn nil\n}\n\nconst makefileTemplate = `\n# Container tool to use for building and pushing images\nCONTAINER_TOOL ?= docker\n\n# Image URL to use all building/pushing image targets\nIMG ?= {{ .Image }}\n\n.PHONY: all\nall: docker-build\n\n##@ General\n\n# The help target prints out all targets with their descriptions organized\n# beneath their categories. The categories are represented by '##@' and the\n# target descriptions by '##'. The awk commands is responsible for reading the\n# entire set of makefiles included in this invocation, looking for lines of the\n# file as xyz: ## something, and then pretty-format the target and help. Then,\n# if there's a line with ##@ something, that gets pretty-printed as a category.\n# More info on the usage of ANSI control characters for terminal formatting:\n# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters\n# More info on the awk command:\n# http://linuxcommand.org/lc3_adv_awk.php\n\n.PHONY: help\nhelp: ## Display this help.\n\t@awk 'BEGIN {FS = \":.*##\"; printf \"\\nUsage:\\n  make \\033[36m<target>\\033[0m\\n\"} /^[a-zA-Z_0-9-]+:.*?##/ { printf \"  \\033[36m%-15s\\033[0m %s\\n\", $$1, $$2 } /^##@/ { printf \"\\n\\033[1m%s\\033[0m\\n\", substr($$0, 5) } ' $(MAKEFILE_LIST)\n\n##@ Build\n\n.PHONY: run\nrun: helm-operator ## Run against the configured Kubernetes cluster in ~/.kube/config\n\t$(HELM_OPERATOR) run\n\n.PHONY: docker-build\ndocker-build: ## Build docker image with the manager.\n\t$(CONTAINER_TOOL) build -t ${IMG} .\n\n.PHONY: docker-push\ndocker-push: ## Push docker image with the manager.\n\t$(CONTAINER_TOOL) push ${IMG}\n\n# PLATFORMS defines the target platforms for  the manager image be build to provide support to multiple\n# architectures. (i.e. make docker-buildx IMG=myregistry/mypoperator:0.0.1). To use this option you need to:\n# - able to use docker buildx . More info: https://docs.docker.com/build/buildx/\n# - have enable BuildKit, More info: https://docs.docker.com/develop/develop-images/build_enhancements/\n# - be able to push the image for your registry (i.e. if you do not inform a valid value via IMG=<myregistry/image:<tag>> than the export will fail)\n# To properly provided solutions that supports more than one platform you should use this option.\nPLATFORMS ?= linux/arm64,linux/amd64,linux/s390x,linux/ppc64le\n.PHONY: docker-buildx\ndocker-buildx: ## Build and push docker image for the manager for cross-platform support\n\t- $(CONTAINER_TOOL) buildx create --name project-v3-builder\n\t$(CONTAINER_TOOL) buildx use project-v3-builder\n\t- $(CONTAINER_TOOL) buildx build --push --platform=$(PLATFORMS) --tag ${IMG} -f Dockerfile .\n\t- $(CONTAINER_TOOL) buildx rm project-v3-builder\n\n##@ Deployment\n\n.PHONY: install\ninstall: kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config.\n\t$(KUSTOMIZE) build config/crd | kubectl apply -f -\n\n.PHONY: uninstall\nuninstall: kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config.\n\t$(KUSTOMIZE) build config/crd | kubectl delete -f -\n\n.PHONY: deploy\ndeploy: kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.\n\tcd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}\n\t$(KUSTOMIZE) build config/default | kubectl apply -f -\n\n.PHONY: undeploy\nundeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config.\n\t$(KUSTOMIZE) build config/default | kubectl delete -f -\n\nOS := $(shell uname -s | tr '[:upper:]' '[:lower:]')\nARCH := $(shell uname -m | sed 's/x86_64/amd64/' | sed 's/aarch64/arm64/')\n\n.PHONY: kustomize\nKUSTOMIZE = $(shell pwd)/bin/kustomize\nkustomize: ## Download kustomize locally if necessary.\nifeq (,$(wildcard $(KUSTOMIZE)))\nifeq (,$(shell which kustomize 2>/dev/null))\n\t@{ \\\n\tset -e ;\\\n\tmkdir -p $(dir $(KUSTOMIZE)) ;\\\n\tcurl -sSLo - https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/{{ .KustomizeVersion }}/kustomize_{{ .KustomizeVersion }}_$(OS)_$(ARCH).tar.gz | \\\n\ttar xzf - -C bin/ ;\\\n\t}\nelse\nKUSTOMIZE = $(shell which kustomize)\nendif\nendif\n\n.PHONY: helm-operator\nHELM_OPERATOR = $(shell pwd)/bin/helm-operator\nhelm-operator: ## Download helm-operator locally if necessary, preferring the $(pwd)/bin path over global if both exist.\nifeq (,$(wildcard $(HELM_OPERATOR)))\nifeq (,$(shell which helm-operator 2>/dev/null))\n\t@{ \\\n\tset -e ;\\\n\tmkdir -p $(dir $(HELM_OPERATOR)) ;\\\n\tcurl -sSLo $(HELM_OPERATOR) https://github.com/operator-framework/operator-sdk/releases/download/{{ .HelmOperatorVersion }}/helm-operator_$(OS)_$(ARCH) ;\\\n\tchmod +x $(HELM_OPERATOR) ;\\\n\t}\nelse\nHELM_OPERATOR = $(shell which helm-operator)\nendif\nendif\n`\n"
  },
  {
    "path": "internal/plugins/helm/v1/scaffolds/internal/templates/watches.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage templates\n\nimport (\n\t\"fmt\"\n\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/machinery\"\n)\n\nvar _ machinery.Template = &Watches{}\n\nconst defaultWatchesFile = \"watches.yaml\"\n\n// Watches scaffolds the watches.yaml file\ntype Watches struct {\n\tmachinery.TemplateMixin\n}\n\n// SetTemplateDefaults implements machinery.Template\nfunc (f *Watches) SetTemplateDefaults() error {\n\tif f.Path == \"\" {\n\t\tf.Path = defaultWatchesFile\n\t}\n\n\tf.TemplateBody = fmt.Sprintf(watchesTemplate,\n\t\tmachinery.NewMarkerFor(f.Path, watchMarker),\n\t)\n\treturn nil\n}\n\nvar _ machinery.Inserter = &WatchesUpdater{}\n\ntype WatchesUpdater struct {\n\tmachinery.ResourceMixin\n\n\tChartPath string\n}\n\nfunc (*WatchesUpdater) GetPath() string {\n\treturn defaultWatchesFile\n}\n\nfunc (*WatchesUpdater) GetIfExistsAction() machinery.IfExistsAction {\n\treturn machinery.OverwriteFile\n}\n\nconst (\n\twatchMarker = \"watch\"\n)\n\nfunc (f *WatchesUpdater) GetMarkers() []machinery.Marker {\n\treturn []machinery.Marker{\n\t\tmachinery.NewMarkerFor(defaultWatchesFile, watchMarker),\n\t}\n}\n\nfunc (f *WatchesUpdater) GetCodeFragments() machinery.CodeFragmentsMap {\n\tfragments := make(machinery.CodeFragmentsMap, 1)\n\n\t// If resource is not being provided we are creating the file, not updating it\n\tif f.Resource == nil {\n\t\treturn fragments\n\t}\n\n\t// Generate watch fragments\n\twatches := make([]string, 0)\n\twatches = append(watches,\n\t\tfmt.Sprintf(watchFragment, f.Resource.QualifiedGroup(), f.Resource.Version, f.Resource.Kind, f.ChartPath))\n\n\tif len(watches) != 0 {\n\t\tfragments[machinery.NewMarkerFor(defaultWatchesFile, watchMarker)] = watches\n\t}\n\treturn fragments\n}\n\nconst watchFragment = `- group: %s\n  version: %s\n  kind: %s\n  chart: %s\n`\n\nconst watchesTemplate = `# Use the 'create api' subcommand to add watches to this file.\n%s\n`\n"
  },
  {
    "path": "internal/plugins/manifests/v2/api.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage v2\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/config\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/machinery\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/model/resource\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/plugin\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/plugins/manifests/v2/templates/config/samples\"\n\t\"github.com/operator-framework/operator-sdk/internal/plugins/util\"\n)\n\nvar _ plugin.CreateAPISubcommand = &createAPISubcommand{}\n\ntype createAPISubcommand struct {\n\tconfig   config.Config\n\tresource *resource.Resource\n}\n\nfunc (s *createAPISubcommand) InjectConfig(c config.Config) error {\n\ts.config = c\n\n\t// Try to retrieve the plugin config\n\tif err := s.config.DecodePluginConfig(pluginKey, &Config{}); errors.As(err, &config.PluginKeyNotFoundError{}) {\n\t\tif util.UpdateIfLegacyKey(s.config) {\n\t\t\treturn nil\n\t\t}\n\t\t// If we couldn't find it, it means we are not using this plugin, so we skip remaining hooks\n\t\t// This scenario could happen if the project was initialized with kubebuilder which doesn't have this plugin\n\t\treturn plugin.ExitError{\n\t\t\tPlugin: pluginKey,\n\t\t\tReason: \"plugin not used in this project\",\n\t\t}\n\t} else if err != nil && !errors.As(err, &config.UnsupportedFieldError{}) {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc (s *createAPISubcommand) InjectResource(res *resource.Resource) error {\n\ts.resource = res\n\n\treturn nil\n}\n\nfunc (s *createAPISubcommand) Scaffold(fs machinery.Filesystem) error {\n\t// Initialize the machinery.Scaffold that will write the files to disk\n\tscaffold := machinery.NewScaffold(fs,\n\t\t// NOTE: kubebuilder's default permissions are only for root users\n\t\tmachinery.WithDirectoryPermissions(0755),\n\t\tmachinery.WithFilePermissions(0644),\n\t\tmachinery.WithConfig(s.config),\n\t\tmachinery.WithResource(s.resource),\n\t)\n\n\t// If the gvk is non-empty\n\tif s.resource.Group != \"\" || s.resource.Version != \"\" || s.resource.Kind != \"\" {\n\t\tif err := scaffold.Execute(&samples.Kustomization{}); err != nil {\n\t\t\treturn fmt.Errorf(\"error scaffolding manifests: %v\", err)\n\t\t}\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "internal/plugins/manifests/v2/init.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage v2\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/plugin/util\"\n\n\t\"github.com/spf13/afero\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/config\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/machinery\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/plugin\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/plugins/manifests/v2/templates/config/manifests\"\n\t\"github.com/operator-framework/operator-sdk/internal/util/projutil\"\n\t\"github.com/operator-framework/operator-sdk/internal/version\"\n)\n\n// Version of `opm` to download and use for building index images.\n// This version's release artifacts *must* contain a binary for multiple arches; certain releases do not.\nconst opmVersion = \"v1.55.0\"\n\nconst filePath = \"Makefile\"\n\nvar _ plugin.InitSubcommand = &initSubcommand{}\n\ntype initSubcommand struct {\n\tconfig config.Config\n}\n\nfunc (s *initSubcommand) InjectConfig(c config.Config) error {\n\ts.config = c\n\n\treturn nil\n}\n\nfunc (s *initSubcommand) Scaffold(fs machinery.Filesystem) error {\n\toperatorType := projutil.PluginChainToOperatorType(s.config.GetPluginChain())\n\tif operatorType == projutil.OperatorTypeUnknown {\n\t\treturn fmt.Errorf(\"none of the required plugins detected in %q\", s.config.GetPluginChain())\n\t}\n\n\tmakefileBytes, err := afero.ReadFile(fs.FS, filePath)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Prepend bundle variables.\n\tprojectName := s.config.GetProjectName()\n\tif projectName == \"\" {\n\t\tdir, err := os.Getwd()\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error getting current directory: %w\", err)\n\t\t}\n\t\tprojectName = strings.ToLower(filepath.Base(dir))\n\t}\n\tmakefileBytes = append([]byte(fmt.Sprintf(makefileBundleVarFragment, s.config.GetDomain(), projectName, strings.Trim(version.Version, \"+git\"))), makefileBytes...)\n\n\t// Append SDK recipes.\n\tswitch operatorType {\n\tcase projutil.OperatorTypeGo:\n\t\tmakefileBytes = append(makefileBytes, []byte(makefileSDKFragmentGo)...)\n\tdefault:\n\t\tmakefileBytes = append(makefileBytes, []byte(makefileSDKFragmentNonGo)...)\n\t}\n\n\t// Append bundle recipes.\n\tswitch operatorType {\n\tcase projutil.OperatorTypeGo:\n\t\tmakefileBytes = append(makefileBytes, []byte(makefileBundleFragmentGo)...)\n\tdefault:\n\t\tmakefileBytes = append(makefileBytes, []byte(makefileBundleFragmentNonGo)...)\n\t}\n\tmakefileBytes = append(makefileBytes, []byte(makefileBundleBuildPushFragment)...)\n\n\t// Append catalog recipes.\n\tswitch operatorType {\n\tcase projutil.OperatorTypeGo:\n\t\tmakefileBytes = append(makefileBytes, []byte(fmt.Sprintf(makefileOPMFragmentGo, opmVersion))...)\n\tdefault:\n\t\tmakefileBytes = append(makefileBytes, []byte(fmt.Sprintf(makefileOPMFragmentNonGo, opmVersion))...)\n\t}\n\tmakefileBytes = append(makefileBytes, []byte(makefileCatalogBuildFragment)...)\n\n\tvar mode os.FileMode = 0644\n\tif info, err := fs.FS.Stat(filePath); err == nil {\n\t\tmode = info.Mode()\n\t}\n\tif err := afero.WriteFile(fs.FS, filePath, makefileBytes, mode); err != nil {\n\t\treturn fmt.Errorf(\"error updating Makefile: %w\", err)\n\t}\n\n\t// Initialize the machinery.Scaffold that will write the files to disk\n\tscaffold := machinery.NewScaffold(fs,\n\t\t// NOTE: kubebuilder's default permissions are only for root users\n\t\tmachinery.WithDirectoryPermissions(0755),\n\t\tmachinery.WithFilePermissions(0644),\n\t\tmachinery.WithConfig(s.config),\n\t)\n\n\tif err := scaffold.Execute(\n\t\t&manifests.Kustomization{\n\t\t\tSupportsKustomizeV4: HasSupportForKustomizeV4(s.config),\n\t\t\tSupportsWebhooks:    operatorType == projutil.OperatorTypeGo},\n\t); err != nil {\n\t\treturn fmt.Errorf(\"error scaffolding manifests: %w\", err)\n\t}\n\n\tif err := s.config.EncodePluginConfig(pluginKey, Config{}); err != nil && !errors.As(err, &config.UnsupportedFieldError{}) {\n\t\treturn err\n\t}\n\n\t// TODO: remove this when we bump kubebuilder to v5.x\n\t// Not adopt changes introduced by mistake in the default Makefile of kubebuilder v4.x.\n\tif operatorType == projutil.OperatorTypeGo {\n\t\terr = util.ReplaceInFile(\"Makefile\", \"$(KIND) create cluster --name $(KIND_CLUSTER)\", makefileTestFix)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error replacing Makefile: %w\", err)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// Makefile fragments to add to the base Makefile.\nconst (\n\tmakefileBundleVarFragment = `# VERSION defines the project version for the bundle.\n# Update this value when you upgrade the version of your project.\n# To re-generate a bundle for another specific version without changing the standard setup, you can:\n# - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2)\n# - use environment variables to overwrite this value (e.g export VERSION=0.0.2)\nVERSION ?= 0.0.1\n\n# CHANNELS define the bundle channels used in the bundle.\n# Add a new line here if you would like to change its default config. (E.g CHANNELS = \"candidate,fast,stable\")\n# To re-generate a bundle for other specific channels without changing the standard setup, you can:\n# - use the CHANNELS as arg of the bundle target (e.g make bundle CHANNELS=candidate,fast,stable)\n# - use environment variables to overwrite this value (e.g export CHANNELS=\"candidate,fast,stable\")\nifneq ($(origin CHANNELS), undefined)\nBUNDLE_CHANNELS := --channels=$(CHANNELS)\nendif\n\n# DEFAULT_CHANNEL defines the default channel used in the bundle.\n# Add a new line here if you would like to change its default config. (E.g DEFAULT_CHANNEL = \"stable\")\n# To re-generate a bundle for any other default channel without changing the default setup, you can:\n# - use the DEFAULT_CHANNEL as arg of the bundle target (e.g make bundle DEFAULT_CHANNEL=stable)\n# - use environment variables to overwrite this value (e.g export DEFAULT_CHANNEL=\"stable\")\nifneq ($(origin DEFAULT_CHANNEL), undefined)\nBUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL)\nendif\nBUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL)\n\n# IMAGE_TAG_BASE defines the docker.io namespace and part of the image name for remote images.\n# This variable is used to construct full image tags for bundle and catalog images.\n#\n# For example, running 'make bundle-build bundle-push catalog-build catalog-push' will build and push both\n# %[1]s/%[2]s-bundle:$VERSION and %[1]s/%[2]s-catalog:$VERSION.\nIMAGE_TAG_BASE ?= %[1]s/%[2]s\n\n# BUNDLE_IMG defines the image:tag used for the bundle.\n# You can use it as an arg. (E.g make bundle-build BUNDLE_IMG=<some-registry>/<project-name-bundle>:<tag>)\nBUNDLE_IMG ?= $(IMAGE_TAG_BASE)-bundle:v$(VERSION)\n\n# BUNDLE_GEN_FLAGS are the flags passed to the operator-sdk generate bundle command\nBUNDLE_GEN_FLAGS ?= -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS)\n\n# USE_IMAGE_DIGESTS defines if images are resolved via tags or digests\n# You can enable this value if you would like to use SHA Based Digests\n# To enable set flag to true\nUSE_IMAGE_DIGESTS ?= false\nifeq ($(USE_IMAGE_DIGESTS), true)\n\tBUNDLE_GEN_FLAGS += --use-image-digests\nendif\n\n# Set the Operator SDK version to use. By default, what is installed on the system is used.\n# This is useful for CI or a project to utilize a specific version of the operator-sdk toolkit.\nOPERATOR_SDK_VERSION ?= %[3]s\n`\n\n\tmakefileSDKFragmentGo = `\n.PHONY: operator-sdk\nOPERATOR_SDK ?= $(LOCALBIN)/operator-sdk\noperator-sdk: ## Download operator-sdk locally if necessary.\nifeq (,$(wildcard $(OPERATOR_SDK)))\nifeq (, $(shell which operator-sdk 2>/dev/null))\n\t@{ \\\n\tset -e ;\\\n\tmkdir -p $(dir $(OPERATOR_SDK)) ;\\\n\tOS=$(shell go env GOOS) && ARCH=$(shell go env GOARCH) && \\\n\tcurl -sSLo $(OPERATOR_SDK) https://github.com/operator-framework/operator-sdk/releases/download/$(OPERATOR_SDK_VERSION)/operator-sdk_$${OS}_$${ARCH} ;\\\n\tchmod +x $(OPERATOR_SDK) ;\\\n\t}\nelse\nOPERATOR_SDK = $(shell which operator-sdk)\nendif\nendif\n`\n\n\tmakefileSDKFragmentNonGo = `\n.PHONY: operator-sdk\nOPERATOR_SDK ?= $(LOCALBIN)/operator-sdk\noperator-sdk: ## Download operator-sdk locally if necessary.\nifeq (,$(wildcard $(OPERATOR_SDK)))\nifeq (, $(shell which operator-sdk 2>/dev/null))\n\t@{ \\\n\tset -e ;\\\n\tmkdir -p $(dir $(OPERATOR_SDK)) ;\\\n\tcurl -sSLo $(OPERATOR_SDK) https://github.com/operator-framework/operator-sdk/releases/download/$(OPERATOR_SDK_VERSION)/operator-sdk_$(OS)_$(ARCH) ;\\\n\tchmod +x $(OPERATOR_SDK) ;\\\n\t}\nelse\nOPERATOR_SDK = $(shell which operator-sdk)\nendif\nendif\n`\n\n\tmakefileBundleFragmentGo = `\n.PHONY: bundle\nbundle: manifests kustomize operator-sdk ## Generate bundle manifests and metadata, then validate generated files.\n\t$(OPERATOR_SDK) generate kustomize manifests -q\n\tcd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG)\n\t$(KUSTOMIZE) build config/manifests | $(OPERATOR_SDK) generate bundle $(BUNDLE_GEN_FLAGS)\n\t$(OPERATOR_SDK) bundle validate ./bundle\n`\n\n\tmakefileBundleFragmentNonGo = `\n\n.PHONY: bundle\nbundle: kustomize operator-sdk ## Generate bundle manifests and metadata, then validate generated files.\n\t$(OPERATOR_SDK) generate kustomize manifests -q\n\tcd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG)\n\t$(KUSTOMIZE) build config/manifests | $(OPERATOR_SDK) generate bundle $(BUNDLE_GEN_FLAGS)\n\t$(OPERATOR_SDK) bundle validate ./bundle\n`\n\n\tmakefileBundleBuildPushFragment = `\n.PHONY: bundle-build\nbundle-build: ## Build the bundle image.\n\t$(CONTAINER_TOOL) build -f bundle.Dockerfile -t $(BUNDLE_IMG) .\n\n.PHONY: bundle-push\nbundle-push: ## Push the bundle image.\n\t$(MAKE) docker-push IMG=$(BUNDLE_IMG)\n`\n\n\tmakefileOPMFragmentGo = `\n.PHONY: opm\nOPM = $(LOCALBIN)/opm\nopm: ## Download opm locally if necessary.\nifeq (,$(wildcard $(OPM)))\nifeq (,$(shell which opm 2>/dev/null))\n\t@{ \\\n\tset -e ;\\\n\tmkdir -p $(dir $(OPM)) ;\\\n\tOS=$(shell go env GOOS) && ARCH=$(shell go env GOARCH) && \\\n\tcurl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/%[1]s/$${OS}-$${ARCH}-opm ;\\\n\tchmod +x $(OPM) ;\\\n\t}\nelse\nOPM = $(shell which opm)\nendif\nendif\n`\n\n\tmakefileOPMFragmentNonGo = `\n.PHONY: opm\nOPM = $(LOCALBIN)/opm\nopm: ## Download opm locally if necessary.\nifeq (,$(wildcard $(OPM)))\nifeq (,$(shell which opm 2>/dev/null))\n\t@{ \\\n\tset -e ;\\\n\tmkdir -p $(dir $(OPM)) ;\\\n\tcurl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/%[1]s/$(OS)-$(ARCH)-opm ;\\\n\tchmod +x $(OPM) ;\\\n\t}\nelse\nOPM = $(shell which opm)\nendif\nendif\n`\n\n\tmakefileCatalogBuildFragment = `\n# A comma-separated list of bundle images (e.g. make catalog-build BUNDLE_IMGS=example.com/operator-bundle:v0.1.0,example.com/operator-bundle:v0.2.0).\n# These images MUST exist in a registry and be pull-able.\nBUNDLE_IMGS ?= $(BUNDLE_IMG)\n\n# The image tag given to the resulting catalog image (e.g. make catalog-build CATALOG_IMG=example.com/operator-catalog:v0.2.0).\nCATALOG_IMG ?= $(IMAGE_TAG_BASE)-catalog:v$(VERSION)\n\n# Set CATALOG_BASE_IMG to an existing catalog image tag to add $BUNDLE_IMGS to that image.\nifneq ($(origin CATALOG_BASE_IMG), undefined)\nFROM_INDEX_OPT := --from-index $(CATALOG_BASE_IMG)\nendif\n\n# Build a catalog image by adding bundle images to an empty catalog using the operator package manager tool, 'opm'.\n# This recipe invokes 'opm' in 'semver' bundle add mode. For more information on add modes, see:\n# https://github.com/operator-framework/community-operators/blob/7f1438c/docs/packaging-operator.md#updating-your-existing-operator\n.PHONY: catalog-build\ncatalog-build: opm ## Build a catalog image.\n\t$(OPM) index add --container-tool $(CONTAINER_TOOL) --mode semver --tag $(CATALOG_IMG) --bundles $(BUNDLE_IMGS) $(FROM_INDEX_OPT)\n\n# Push the catalog image.\n.PHONY: catalog-push\ncatalog-push: ## Push a catalog image.\n\t$(MAKE) docker-push IMG=$(CATALOG_IMG)\n`\n\n\t// TODO: remove it when we bump kubebuilder to v4.x\n\t// We will not adopt this change since it did not work and was a bug introduced in the\n\t// default Makefile of kubebuilder v4.x.\n\tmakefileTestFix = `@case \"$$($(KIND) get clusters)\" in \\\n\t\t*\"$(KIND_CLUSTER)\"*) \\\n\t\t\techo \"Kind cluster '$(KIND_CLUSTER)' already exists. Skipping creation.\" ;; \\\n\t\t*) \\\n\t\t\techo \"Creating Kind cluster '$(KIND_CLUSTER)'...\"; \\\n\t\t\t$(KIND) create cluster --name $(KIND_CLUSTER) ;; \\\n\tesac`\n)\n"
  },
  {
    "path": "internal/plugins/manifests/v2/plugin.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage v2\n\nimport (\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/config\"\n\tcfgv3 \"sigs.k8s.io/kubebuilder/v4/pkg/config/v3\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/plugin\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/plugins\"\n)\n\nconst pluginName = \"manifests\" + plugins.DefaultNameQualifier\n\nvar (\n\tpluginVersion            = plugin.Version{Number: 2}\n\tsupportedProjectVersions = []config.Version{cfgv3.Version}\n\tpluginKey                = plugin.KeyFor(Plugin{})\n)\n\nvar (\n\t_ plugin.Plugin    = Plugin{}\n\t_ plugin.Init      = Plugin{}\n\t_ plugin.CreateAPI = Plugin{}\n)\n\ntype Plugin struct {\n\tinitSubcommand\n\tcreateAPISubcommand\n}\n\nfunc (Plugin) Name() string                                         { return pluginName }\nfunc (Plugin) Version() plugin.Version                              { return pluginVersion }\nfunc (Plugin) SupportedProjectVersions() []config.Version           { return supportedProjectVersions }\nfunc (p Plugin) GetInitSubcommand() plugin.InitSubcommand           { return &p.initSubcommand }\nfunc (p Plugin) GetCreateAPISubcommand() plugin.CreateAPISubcommand { return &p.createAPISubcommand }\n\ntype Config struct{}\n"
  },
  {
    "path": "internal/plugins/manifests/v2/templates/config/manifests/kustomization.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage manifests\n\nimport (\n\t\"path/filepath\"\n\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/machinery\"\n)\n\nvar _ machinery.Template = &Kustomization{}\n\n// Kustomization scaffolds a kustomization.yaml for the manifests overlay folder.\ntype Kustomization struct {\n\tmachinery.TemplateMixin\n\tmachinery.ProjectNameMixin\n\n\t// SupportsKustomizeV4 is true for the projects that are\n\t// scaffold using the kustomize/v2-aplha plugin and\n\t// the major bump for it 4x\n\t// Previous versions uses 3x\n\tSupportsKustomizeV4 bool\n\n\tSupportsWebhooks bool\n}\n\n// SetTemplateDefaults implements machinery.Template\nfunc (f *Kustomization) SetTemplateDefaults() error {\n\tif f.Path == \"\" {\n\t\tf.Path = filepath.Join(\"config\", \"manifests\", \"kustomization.yaml\")\n\t}\n\n\t// We cannot overwiting the file after it be created because\n\t// it might contain user changes (i.e to work with Kustomize 4.x\n\t// the target /spec/template/spec/containers/1/volumeMounts/0\n\t// needs to be replaced with /spec/template/spec/containers/0/volumeMounts/0\n\tf.IfExistsAction = machinery.SkipFile\n\n\tf.TemplateBody = kustomizationTemplate\n\n\treturn nil\n}\n\nconst kustomizationTemplate = `# These resources constitute the fully configured set of manifests\n# used to generate the 'manifests/' directory in a bundle.\nresources:\n- bases/{{ .ProjectName }}.clusterserviceversion.yaml\n- ../default\n- ../samples\n- ../scorecard\n{{ if .SupportsWebhooks }}\n# [WEBHOOK] To enable webhooks, uncomment all the sections with [WEBHOOK] prefix.\n# Do NOT uncomment sections with prefix [CERTMANAGER], as OLM does not support cert-manager.\n# These patches remove the unnecessary \"cert\" volume and its manager container volumeMount.\n#patches:\n#- target:\n#    group: apps\n#    version: v1\n#    kind: Deployment\n#    name: controller-manager\n#    namespace: system\n#  patch: |-\n#    # Remove the manager container's \"cert\" volumeMount, since OLM will create and mount a set of certs.\n#    # Update the indices in this path if adding or removing containers/volumeMounts in the manager's Deployment.\n#    - op: remove\n{{ if .SupportsKustomizeV4 }}\n#      path: /spec/template/spec/containers/0/volumeMounts/0\n{{ else -}} \n#      path: /spec/template/spec/containers/1/volumeMounts/0\n{{ end -}}\n#    # Remove the \"cert\" volume, since OLM will create and mount a set of certs.\n#    # Update the indices in this path if adding or removing volumes in the manager's Deployment.\n#    - op: remove\n#      path: /spec/template/spec/volumes/0\n{{ end -}}\n`\n"
  },
  {
    "path": "internal/plugins/manifests/v2/templates/config/samples/kustomization.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage samples\n\nimport (\n\t\"fmt\"\n\t\"path/filepath\"\n\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/machinery\"\n)\n\nvar (\n\t_ machinery.Template = &Kustomization{}\n\t_ machinery.Inserter = &Kustomization{}\n)\n\n// Kustomization scaffolds a kustomization.yaml for the manifests overlay folder.\ntype Kustomization struct {\n\tmachinery.TemplateMixin\n\tmachinery.ResourceMixin\n}\n\n// SetTemplateDefaults implements machinery.Template\nfunc (f *Kustomization) SetTemplateDefaults() error {\n\tif f.Path == \"\" {\n\t\tf.Path = filepath.Join(\"config\", \"samples\", \"kustomization.yaml\")\n\t}\n\tf.Path = f.Resource.Replacer().Replace(f.Path)\n\n\tf.TemplateBody = fmt.Sprintf(kustomizationTemplate, machinery.NewMarkerFor(f.Path, samplesMarker))\n\n\treturn nil\n}\n\nconst (\n\tsamplesMarker = \"manifestskustomizesamples\"\n)\n\n// GetMarkers implements file.Inserter\nfunc (f *Kustomization) GetMarkers() []machinery.Marker {\n\treturn []machinery.Marker{machinery.NewMarkerFor(f.Path, samplesMarker)}\n}\n\nconst samplesCodeFragment = `- %s\n`\n\n// makeCRFileName returns a Custom Resource example file name in the same format\n// as kubebuilder's CreateAPI plugin for a gvk.\nfunc (f Kustomization) makeCRFileName() string {\n\treturn f.Resource.Replacer().Replace(\"%[group]_%[version]_%[kind].yaml\")\n}\n\n// GetCodeFragments implements file.Inserter\nfunc (f *Kustomization) GetCodeFragments() machinery.CodeFragmentsMap {\n\treturn machinery.CodeFragmentsMap{\n\t\tmachinery.NewMarkerFor(f.Path, samplesMarker): []string{fmt.Sprintf(samplesCodeFragment, f.makeCRFileName())},\n\t}\n}\n\nconst kustomizationTemplate = `## Append samples you want in your CSV to this file as resources ##\nresources:\n%s\n`\n"
  },
  {
    "path": "internal/plugins/manifests/v2/utils.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage v2\n\nimport (\n\t\"errors\"\n\t\"strings\"\n\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/config\"\n)\n\nconst (\n\tgoV3APluginKey         = \"go.sdk.operatorframework.io/v3\"\n\tlegacyGoPluginKey      = \"go.sdk.operatorframework.io/v2\"\n\tlegacyGoPluginAlphaKey = \"go.sdk.operatorframework.io/v2-alpha\"\n\tkubebuilderGoV3        = \"go.kubebuilder.io/v3\"\n\tkubebuilderGoV2        = \"go.kubebuilder.io/v2\"\n)\n\n// HasSupportForKustomizeV4 will return true when we can do the scaffolds\n// using kustomize version\nfunc HasSupportForKustomizeV4(c config.Config) bool {\n\n\t// When we are creating the project with the Bundle Plugin\n\t// we have data only into the pluginChain\n\tfor _, pluginKey := range c.GetPluginChain() {\n\t\tif strings.HasPrefix(pluginKey, \"go\") {\n\t\t\tswitch pluginKey {\n\t\t\tcase kubebuilderGoV3:\n\t\t\t\treturn false\n\t\t\tcase kubebuilderGoV2:\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t}\n\n\t// If we call the implementation afterwords as we do\n\t// via the subCommand \"operator-sdk generate kustomize\"\n\t// we have the PROJECT file and the plugin layout\n\terr := c.DecodePluginConfig(goV3APluginKey, struct{}{})\n\tif err == nil || !errors.As(err, &config.PluginKeyNotFoundError{}) {\n\t\treturn false\n\t}\n\n\terr = c.DecodePluginConfig(legacyGoPluginKey, struct{}{})\n\tif err == nil || !errors.As(err, &config.PluginKeyNotFoundError{}) {\n\t\treturn false\n\t}\n\n\terr = c.DecodePluginConfig(legacyGoPluginAlphaKey, struct{}{})\n\tif err == nil || !errors.As(err, &config.PluginKeyNotFoundError{}) {\n\t\treturn false\n\t}\n\n\terr = c.DecodePluginConfig(kubebuilderGoV2, struct{}{})\n\tif err == nil || !errors.As(err, &config.PluginKeyNotFoundError{}) {\n\t\treturn false\n\t}\n\n\terr = c.DecodePluginConfig(kubebuilderGoV3, struct{}{})\n\tif err == nil || !errors.As(err, &config.PluginKeyNotFoundError{}) {\n\t\treturn false\n\t}\n\n\treturn true\n}\n"
  },
  {
    "path": "internal/plugins/plugins.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage plugins\n\n// DefaultNameQualifier is the Operator SDK plugin name suffix. Appending\n// this suffix to a short name, ex. \"go\", makes it fully qualified.\nconst DefaultNameQualifier = \".sdk.operatorframework.io\"\n"
  },
  {
    "path": "internal/plugins/scorecard/v2/init.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage v2\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"path/filepath\"\n\n\t\"github.com/spf13/afero\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/config\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/machinery\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/plugin\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/scorecard\"\n\t\"github.com/operator-framework/operator-sdk/internal/version\"\n)\n\nvar (\n\t// defaultTestImageTag points to the latest released scorecard-test image.\n\tdefaultTestImageTag = fmt.Sprintf(\"quay.io/operator-framework/scorecard-test:%s\", version.ImageVersion)\n\n\t// Directories\n\toutputDir  = filepath.Join(\"config\", \"scorecard\")\n\tbasesDir   = filepath.Join(outputDir, \"bases\")\n\tpatchesDir = filepath.Join(outputDir, \"patches\")\n)\n\nvar _ plugin.InitSubcommand = &initSubcommand{}\n\ntype initSubcommand struct {\n\tconfig config.Config\n}\n\nfunc (s *initSubcommand) InjectConfig(c config.Config) error {\n\ts.config = c\n\n\treturn nil\n}\n\nfunc (s *initSubcommand) Scaffold(fs machinery.Filesystem) error {\n\t// TODO: convert all these files to templates\n\n\t// Create the directories\n\tfor _, dir := range []string{basesDir, patchesDir} {\n\t\tif err := fs.FS.MkdirAll(dir, 0755); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// Write the scorecard config base.\n\tif err := afero.WriteFile(fs.FS, filepath.Join(basesDir, scorecard.ConfigFileName), []byte(configBaseFile), 0666); err != nil {\n\t\treturn fmt.Errorf(\"error writing default scorecard config: %w\", err)\n\t}\n\n\t// Write a \"<key>.config.yaml\" for each patch in patchSet.\n\tpatchSet := map[string]string{\n\t\t\"basic\": fmt.Sprintf(basicPatchFile, defaultTestImageTag),\n\t\t\"olm\":   fmt.Sprintf(olmPatchFile, defaultTestImageTag),\n\t}\n\tfor name, patchStr := range patchSet {\n\t\tif err := afero.WriteFile(fs.FS, filepath.Join(patchesDir, fmt.Sprintf(\"%s.config.yaml\", name)), []byte(patchStr), 0666); err != nil {\n\t\t\treturn fmt.Errorf(\"error writing %s scorecard config patch: %w\", name, err)\n\t\t}\n\t}\n\n\t// Write \"kustomization.yaml\".\n\tkustomizeContent := fmt.Sprintf(scorecardKustomizationFile, machinery.NewMarkerFor(\"kustomization.yaml\", patchesMarker))\n\tif err := afero.WriteFile(fs.FS, filepath.Join(outputDir, \"kustomization.yaml\"), []byte(kustomizeContent), 0666); err != nil {\n\t\treturn fmt.Errorf(\"error writing scorecard kustomization.yaml: %w\", err)\n\t}\n\n\tif err := s.config.EncodePluginConfig(pluginKey, Config{}); err != nil && !errors.As(err, &config.UnsupportedFieldError{}) {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nconst (\n\t// scorecardKustomizationFile is a kustomization.yaml file for the scorecard componentconfig.\n\t// This should always be written to config/scorecard/kustomization.yaml.\n\tscorecardKustomizationFile = `resources:\n- bases/config.yaml\napiVersion: kustomize.config.k8s.io/v1beta1\nkind: Kustomization\npatches:\n- path: patches/basic.config.yaml\n  target:\n    group: scorecard.operatorframework.io\n    kind: Configuration\n    name: config\n    version: v1alpha3\n- path: patches/olm.config.yaml\n  target:\n    group: scorecard.operatorframework.io\n    kind: Configuration\n    name: config\n    version: v1alpha3\n%[1]s\n`\n\n\t// YAML file marker to append to kustomization.yaml files.\n\tpatchesMarker = \"patches\"\n\n\t// configBaseFile is an empty scorecard componentconfig with parallel stages.\n\tconfigBaseFile = `apiVersion: scorecard.operatorframework.io/v1alpha3\nkind: Configuration\nmetadata:\n  name: config\nstages:\n- parallel: true\n  tests: []\n`\n\n\t// basicPatchFile contains all default \"basic\" test configurations.\n\tbasicPatchFile = `- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - scorecard-test\n    - basic-check-spec\n    image: %[1]s\n    labels:\n      suite: basic\n      test: basic-check-spec-test\n`\n\n\t// olmPatchFile contains all default \"olm\" test configurations.\n\tolmPatchFile = `- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - scorecard-test\n    - olm-bundle-validation\n    image: %[1]s\n    labels:\n      suite: olm\n      test: olm-bundle-validation-test\n- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - scorecard-test\n    - olm-crds-have-validation\n    image: %[1]s\n    labels:\n      suite: olm\n      test: olm-crds-have-validation-test\n- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - scorecard-test\n    - olm-crds-have-resources\n    image: %[1]s\n    labels:\n      suite: olm\n      test: olm-crds-have-resources-test\n- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - scorecard-test\n    - olm-spec-descriptors\n    image: %[1]s\n    labels:\n      suite: olm\n      test: olm-spec-descriptors-test\n- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - scorecard-test\n    - olm-status-descriptors\n    image: %[1]s\n    labels:\n      suite: olm\n      test: olm-status-descriptors-test\n`\n)\n"
  },
  {
    "path": "internal/plugins/scorecard/v2/plugin.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage v2\n\nimport (\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/config\"\n\tcfgv3 \"sigs.k8s.io/kubebuilder/v4/pkg/config/v3\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/plugin\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/plugins\"\n)\n\nconst pluginName = \"scorecard\" + plugins.DefaultNameQualifier\n\nvar (\n\tpluginVersion            = plugin.Version{Number: 2}\n\tsupportedProjectVersions = []config.Version{cfgv3.Version}\n\tpluginKey                = plugin.KeyFor(Plugin{})\n)\n\nvar (\n\t_ plugin.Plugin = Plugin{}\n\t_ plugin.Init   = Plugin{}\n)\n\ntype Plugin struct {\n\tinitSubcommand\n}\n\nfunc (Plugin) Name() string                               { return pluginName }\nfunc (Plugin) Version() plugin.Version                    { return pluginVersion }\nfunc (Plugin) SupportedProjectVersions() []config.Version { return supportedProjectVersions }\nfunc (p Plugin) GetInitSubcommand() plugin.InitSubcommand { return &p.initSubcommand }\n\ntype Config struct{}\n"
  },
  {
    "path": "internal/plugins/util/cleanup.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage util\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\n\tkbutil \"sigs.k8s.io/kubebuilder/v4/pkg/plugin/util\"\n\n\tlog \"github.com/sirupsen/logrus\"\n)\n\n// RemoveKustomizeCRDManifests removes items in config/crd relating to CRD conversion webhooks.\nfunc RemoveKustomizeCRDManifests() error {\n\n\tpathsToRemove := []string{\n\t\tfilepath.Join(\"config\", \"crd\", \"kustomizeconfig.yaml\"),\n\t}\n\tconfigPatchesDir := filepath.Join(\"config\", \"crd\", \"patches\")\n\twebhookPatchMatches, err := filepath.Glob(filepath.Join(configPatchesDir, \"webhook_in_*.yaml\"))\n\tif err != nil {\n\t\treturn err\n\t}\n\tpathsToRemove = append(pathsToRemove, webhookPatchMatches...)\n\tcainjectionPatchMatches, err := filepath.Glob(filepath.Join(configPatchesDir, \"cainjection_in_*.yaml\"))\n\tif err != nil {\n\t\treturn err\n\t}\n\tpathsToRemove = append(pathsToRemove, cainjectionPatchMatches...)\n\tfor _, p := range pathsToRemove {\n\t\tif err := os.RemoveAll(p); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tchildren, err := os.ReadDir(configPatchesDir)\n\tif err == nil && len(children) == 0 {\n\t\tif err := os.RemoveAll(configPatchesDir); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\n// UpdateKustomizationsInit updates certain parts of or removes entire kustomization.yaml files\n// that are either not used by certain Init plugins or are created by preceding Init plugins.\nfunc UpdateKustomizationsInit() error {\n\n\tdefaultKFile := filepath.Join(\"config\", \"default\", \"kustomization.yaml\")\n\tif err := kbutil.ReplaceInFile(defaultKFile,\n\t\t`\n# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in\n# crd/kustomization.yaml\n#- ../webhook\n# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required.\n#- ../certmanager`, \"\"); err != nil {\n\t\treturn fmt.Errorf(\"remove %s resources: %v\", defaultKFile, err)\n\t}\n\n\tif err := kbutil.ReplaceInFile(defaultKFile,\n\t\t`# Uncomment the patches line if you enable Metrics and CertManager\n# [METRICS-WITH-CERTS] To enable metrics protected with certManager, uncomment the following line.\n# This patch will protect the metrics with certManager self-signed certs.\n#- path: cert_metrics_manager_patch.yaml\n#  target:\n#    kind: Deployment`, \"\"); err != nil {\n\t\treturn fmt.Errorf(\"remove %s resources: %v\", defaultKFile, err)\n\t}\n\n\t// Remove the file not used for Helm projects since we do not scaffold the cert-manager\n\tcertPatchPath := filepath.Join(\"config\", \"default\", \"cert_metrics_manager_patch.yaml\")\n\tif err := os.Remove(certPatchPath); err != nil && !os.IsNotExist(err) {\n\t\treturn fmt.Errorf(\"failed to remove unused file %s: %v\", certPatchPath, err)\n\t}\n\n\t// Remove the file not used for Helm projects since we do not scaffold the cert-manager\n\tmonitorTLSPatchPath := filepath.Join(\"config\", \"prometheus\", \"monitor_tls_patch.yaml\")\n\tif err := os.Remove(monitorTLSPatchPath); err != nil && !os.IsNotExist(err) {\n\t\treturn fmt.Errorf(\"failed to remove unused file %s: %v\", monitorTLSPatchPath, err)\n\t}\n\n\tprometheusKustomize := filepath.Join(\"config\", \"prometheus\", \"kustomization.yaml\")\n\tif err := kbutil.ReplaceInFile(prometheusKustomize,\n\t\t`# [PROMETHEUS-WITH-CERTS] The following patch configures the ServiceMonitor in ../prometheus\n# to securely reference certificates created and managed by cert-manager.\n# Additionally, ensure that you uncomment the [METRICS WITH CERTMANAGER] patch under config/default/kustomization.yaml\n# to mount the \"metrics-server-cert\" secret in the Manager Deployment.\n#patches:\n#  - path: monitor_tls_patch.yaml\n#    target:\n#      kind: ServiceMonitor`, \"\"); err != nil {\n\t\treturn fmt.Errorf(\"remove %s resources: %v\", defaultKFile, err)\n\t}\n\n\tif err := kbutil.ReplaceInFile(defaultKFile,\n\t\t`\n# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in\n# crd/kustomization.yaml\n#- path: manager_webhook_patch.yaml\n#  target:\n#    kind: Deployment\n\n# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix.\n# Uncomment the following replacements to add the cert-manager CA injection annotations\n#replacements:\n# - source: # Uncomment the following block to enable certificates for metrics\n#     kind: Service\n#     version: v1\n#     name: controller-manager-metrics-service\n#     fieldPath: metadata.name\n#   targets:\n#     - select:\n#         kind: Certificate\n#         group: cert-manager.io\n#         version: v1\n#         name: metrics-certs\n#       fieldPaths:\n#         - spec.dnsNames.0\n#         - spec.dnsNames.1\n#       options:\n#         delimiter: '.'\n#         index: 0\n#         create: true\n#     - select: # Uncomment the following to set the Service name for TLS config in Prometheus ServiceMonitor\n#         kind: ServiceMonitor\n#         group: monitoring.coreos.com\n#         version: v1\n#         name: controller-manager-metrics-monitor\n#       fieldPaths:\n#         - spec.endpoints.0.tlsConfig.serverName\n#       options:\n#         delimiter: '.'\n#         index: 0\n#         create: true\n#\n# - source:\n#     kind: Service\n#     version: v1\n#     name: controller-manager-metrics-service\n#     fieldPath: metadata.namespace\n#   targets:\n#     - select:\n#         kind: Certificate\n#         group: cert-manager.io\n#         version: v1\n#         name: metrics-certs\n#       fieldPaths:\n#         - spec.dnsNames.0\n#         - spec.dnsNames.1\n#       options:\n#         delimiter: '.'\n#         index: 1\n#         create: true\n#     - select: # Uncomment the following to set the Service namespace for TLS in Prometheus ServiceMonitor\n#         kind: ServiceMonitor\n#         group: monitoring.coreos.com\n#         version: v1\n#         name: controller-manager-metrics-monitor\n#       fieldPaths:\n#         - spec.endpoints.0.tlsConfig.serverName\n#       options:\n#         delimiter: '.'\n#         index: 1\n#         create: true\n#\n# - source: # Uncomment the following block if you have any webhook\n#     kind: Service\n#     version: v1\n#     name: webhook-service\n#     fieldPath: .metadata.name # Name of the service\n#   targets:\n#     - select:\n#         kind: Certificate\n#         group: cert-manager.io\n#         version: v1\n#         name: serving-cert\n#       fieldPaths:\n#         - .spec.dnsNames.0\n#         - .spec.dnsNames.1\n#       options:\n#         delimiter: '.'\n#         index: 0\n#         create: true\n# - source:\n#     kind: Service\n#     version: v1\n#     name: webhook-service\n#     fieldPath: .metadata.namespace # Namespace of the service\n#   targets:\n#     - select:\n#         kind: Certificate\n#         group: cert-manager.io\n#         version: v1\n#         name: serving-cert\n#       fieldPaths:\n#         - .spec.dnsNames.0\n#         - .spec.dnsNames.1\n#       options:\n#         delimiter: '.'\n#         index: 1\n#         create: true\n#\n# - source: # Uncomment the following block if you have a ValidatingWebhook (--programmatic-validation)\n#     kind: Certificate\n#     group: cert-manager.io\n#     version: v1\n#     name: serving-cert # This name should match the one in certificate.yaml\n#     fieldPath: .metadata.namespace # Namespace of the certificate CR\n#   targets:\n#     - select:\n#         kind: ValidatingWebhookConfiguration\n#       fieldPaths:\n#         - .metadata.annotations.[cert-manager.io/inject-ca-from]\n#       options:\n#         delimiter: '/'\n#         index: 0\n#         create: true\n# - source:\n#     kind: Certificate\n#     group: cert-manager.io\n#     version: v1\n#     name: serving-cert\n#     fieldPath: .metadata.name\n#   targets:\n#     - select:\n#         kind: ValidatingWebhookConfiguration\n#       fieldPaths:\n#         - .metadata.annotations.[cert-manager.io/inject-ca-from]\n#       options:\n#         delimiter: '/'\n#         index: 1\n#         create: true\n#\n# - source: # Uncomment the following block if you have a DefaultingWebhook (--defaulting )\n#     kind: Certificate\n#     group: cert-manager.io\n#     version: v1\n#     name: serving-cert\n#     fieldPath: .metadata.namespace # Namespace of the certificate CR\n#   targets:\n#     - select:\n#         kind: MutatingWebhookConfiguration\n#       fieldPaths:\n#         - .metadata.annotations.[cert-manager.io/inject-ca-from]\n#       options:\n#         delimiter: '/'\n#         index: 0\n#         create: true\n# - source:\n#     kind: Certificate\n#     group: cert-manager.io\n#     version: v1\n#     name: serving-cert\n#     fieldPath: .metadata.name\n#   targets:\n#     - select:\n#         kind: MutatingWebhookConfiguration\n#       fieldPaths:\n#         - .metadata.annotations.[cert-manager.io/inject-ca-from]\n#       options:\n#         delimiter: '/'\n#         index: 1\n#         create: true\n#\n# - source: # Uncomment the following block if you have a ConversionWebhook (--conversion)\n#     kind: Certificate\n#     group: cert-manager.io\n#     version: v1\n#     name: serving-cert\n#     fieldPath: .metadata.namespace # Namespace of the certificate CR\n#   targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD.\n# +kubebuilder:scaffold:crdkustomizecainjectionns\n# - source:\n#     kind: Certificate\n#     group: cert-manager.io\n#     version: v1\n#     name: serving-cert\n#     fieldPath: .metadata.name\n#   targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD.\n# +kubebuilder:scaffold:crdkustomizecainjectionname\n`, \"\"); err != nil {\n\t\treturn fmt.Errorf(\"remove %s patch and vars blocks: %v\", defaultKFile, err)\n\t}\n\n\treturn nil\n}\n\n// UpdateKustomizationsCreateAPI updates certain parts of or removes entire kustomization.yaml files\n// that are either not used by certain CreateAPI plugins or are created by preceding CreateAPI plugins.\nfunc UpdateKustomizationsCreateAPI() error {\n\n\tcrdKFile := filepath.Join(\"config\", \"crd\", \"kustomization.yaml\")\n\tif crdKBytes, err := os.ReadFile(crdKFile); err != nil && !errors.Is(err, os.ErrNotExist) {\n\t\tlog.Debugf(\"Error reading kustomization for substitution: %v\", err)\n\t} else if err == nil {\n\t\tif bytes.Contains(crdKBytes, []byte(\"[WEBHOOK]\")) || bytes.Contains(crdKBytes, []byte(\"[CERTMANAGER]\")) {\n\t\t\tif err := os.RemoveAll(crdKFile); err != nil {\n\t\t\t\tlog.Debugf(\"Error removing file prior to scaffold: %v\", err)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "internal/plugins/util/legacy_keys.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage util\n\nimport (\n\t\"errors\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\tgofunk \"github.com/thoas/go-funk\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/config\"\n\tcfgv3 \"sigs.k8s.io/kubebuilder/v4/pkg/config/v3\"\n)\n\nconst (\n\t// The catch-all plugin key for the go/v2+manifests+scorecard plugins.\n\t// Should still be accepted for backwards-compat.\n\tlegacyGoPluginKey      = \"go.sdk.operatorframework.io/v2-alpha\"\n\tlegacyGoPluginAlphaKey = \"go.sdk.operatorframework.io/v2-alpha\"\n\n\t// Hard-code the latest manifests and scorecard keys here to avoid a circular import.\n\tmanifestsKey = \"manifests.sdk.operatorframework.io/v2\"\n\tscorecardKey = \"scorecard.sdk.operatorframework.io/v2\"\n)\n\n// Plugin keys that existed when manifests/scorecard keys did not.\nvar acceptedLayoutKeys = []string{\n\t\"ansible.sdk.operatorframework.io/v1\",\n\t\"helm.sdk.operatorframework.io/v1\",\n}\n\n// UpdateIfLegacyKey returns true if c's \"plugins\" map or \"layout\" value contains\n// a legacy key that may require this plugin be executed, even if the \"manifests\" key\n// isn't in \"plugins\".\nfunc UpdateIfLegacyKey(c config.Config) bool {\n\tif c.GetVersion().Compare(cfgv3.Version) < 0 {\n\t\treturn false\n\t}\n\n\tif IsGolangLegacyLayout(c) {\n\t\treturn true\n\t}\n\n\tchain := c.GetPluginChain()\n\tfor _, key := range acceptedLayoutKeys {\n\t\tif gofunk.ContainsString(chain, key) {\n\t\t\t// Encode missing plugin keys.\n\t\t\tif !gofunk.ContainsString(chain, manifestsKey) {\n\t\t\t\tif err := c.EncodePluginConfig(manifestsKey, struct{}{}); err != nil {\n\t\t\t\t\tlog.Error(err)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif !gofunk.ContainsString(chain, scorecardKey) {\n\t\t\t\tif err := c.EncodePluginConfig(scorecardKey, struct{}{}); err != nil {\n\t\t\t\t\tlog.Error(err)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// IsGolangLegacyLayout returns true if c's does not have the plugins\n// configuration.\nfunc IsGolangLegacyLayout(c config.Config) bool {\n\terr := c.DecodePluginConfig(legacyGoPluginKey, struct{}{})\n\tif err == nil || !errors.As(err, &config.PluginKeyNotFoundError{}) {\n\t\t// There is no way to remove keys from \"plugins\", so print a warning.\n\t\tlog.Warnf(\"Plugin key %q is deprecated. Replace this key with %q and %q on separate lines.\",\n\t\t\tlegacyGoPluginKey, manifestsKey, scorecardKey)\n\t\treturn true\n\t}\n\n\terr = c.DecodePluginConfig(legacyGoPluginAlphaKey, struct{}{})\n\tif err == nil || !errors.As(err, &config.PluginKeyNotFoundError{}) {\n\t\treturn true\n\t}\n\n\treturn false\n}\n"
  },
  {
    "path": "internal/plugins/util/message.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage util\n\nconst WarnMessageRemovalV1beta1 = \"The v1beta1 API version for CRDs and Webhooks is deprecated and is no longer offered since \" +\n\t\"Kubernetes 1.22. This flag will be removed in a future release. We \" +\n\t\"recommend that you no longer use the v1beta1 API version\" +\n\t\"More info: https://kubernetes.io/docs/reference/using-api/deprecation-guide/#v1-22\"\n"
  },
  {
    "path": "internal/registry/image.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage registry\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\n\tregistryimage \"github.com/operator-framework/operator-registry/pkg/image\"\n\t\"github.com/operator-framework/operator-registry/pkg/image/containerdregistry\"\n\tlog \"github.com/sirupsen/logrus\"\n)\n\n// ExtractBundleImage returns a bundle directory containing files extracted\n// from image. If local is true, the image will not be pulled.\nfunc ExtractBundleImage(ctx context.Context, logger *log.Entry, image string, local bool, skipTLSVerify bool, useHTTP bool) (string, error) {\n\tif logger == nil {\n\t\tlogger = DiscardLogger()\n\t}\n\t// Use a temp directory for bundle files. This will likely be removed by\n\t// the caller.\n\twd, err := os.Getwd()\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tbundleDir, err := os.MkdirTemp(wd, \"bundle-\")\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\t// This should always work, but if it doesn't bundleDir is still valid.\n\tif dir, err := filepath.Rel(wd, bundleDir); err == nil {\n\t\tbundleDir = dir\n\t}\n\n\t// Export the image into bundleDir.\n\tlogger = logger.WithFields(log.Fields{\"dir\": bundleDir})\n\n\t// Use a containerd registry instead of shelling out to a container tool.\n\treg, err := containerdregistry.NewRegistry(\n\t\tcontainerdregistry.WithLog(logger),\n\t\tcontainerdregistry.SkipTLSVerify(skipTLSVerify),\n\t\tcontainerdregistry.WithPlainHTTP(useHTTP))\n\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tdefer func() {\n\t\tif err := reg.Destroy(); err != nil {\n\t\t\tlogger.WithError(err).Warn(\"Error destroying local cache\")\n\t\t}\n\t}()\n\n\t// Pull the image if it isn't present locally.\n\tif !local {\n\t\tif err := reg.Pull(ctx, registryimage.SimpleReference(image)); err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"error pulling image %s: %v\", image, err)\n\t\t}\n\t}\n\n\t// Unpack the image's contents.\n\tif err := reg.Unpack(ctx, registryimage.SimpleReference(image), bundleDir); err != nil {\n\t\treturn \"\", fmt.Errorf(\"error unpacking image %s: %v\", image, err)\n\t}\n\n\treturn bundleDir, nil\n}\n\n// GetImageLabels returns the set of labels on image.\nfunc GetImageLabels(ctx context.Context, logger *log.Entry, image string, local bool) (map[string]string, error) {\n\tif logger == nil {\n\t\tlogger = DiscardLogger()\n\t}\n\n\t// Create a containerd registry for socket-less image layer reading.\n\treg, err := containerdregistry.NewRegistry(containerdregistry.WithLog(logger))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error creating new image registry: %v\", err)\n\t}\n\tdefer func() {\n\t\tif err := reg.Destroy(); err != nil {\n\t\t\tlogger.WithError(err).Warn(\"Error destroying local cache\")\n\t\t}\n\t}()\n\n\t// Pull the image if it isn't present locally.\n\tif !local {\n\t\tif err := reg.Pull(ctx, registryimage.SimpleReference(image)); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error pulling image %s: %v\", image, err)\n\t\t}\n\t}\n\n\t// Query the image reference for its labels.\n\tlabels, err := reg.Labels(ctx, registryimage.SimpleReference(image))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error reading image %s labels: %v\", image, err)\n\t}\n\n\treturn labels, err\n}\n"
  },
  {
    "path": "internal/registry/labels.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage registry\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\tregistrybundle \"github.com/operator-framework/operator-registry/pkg/lib/bundle\"\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/afero\"\n\t\"sigs.k8s.io/yaml\"\n)\n\ntype MetadataNotFoundError string\n\nfunc (e MetadataNotFoundError) Error() string {\n\treturn fmt.Sprintf(\"metadata not found in %s\", string(e))\n}\n\n// Labels is a set of key:value labels from an operator-registry object.\ntype LabelsMap map[string]string\n\n// GetManifestsDir returns the manifests directory name in ls using\n// a predefined key, or false if it does not exist.\nfunc (ls LabelsMap) GetManifestsDir() (string, bool) {\n\tvalue, hasKey := ls[registrybundle.ManifestsLabel]\n\treturn filepath.Clean(value), hasKey\n}\n\n// FindBundleMetadata walks bundleRoot searching for metadata (ex. annotations.yaml),\n// and returns metadata and its path if found. If one is not found, an error is returned.\nfunc FindBundleMetadata(bundleRoot string) (LabelsMap, string, error) {\n\treturn findBundleMetadata(afero.NewOsFs(), bundleRoot)\n}\n\nfunc findBundleMetadata(fs afero.Fs, bundleRoot string) (LabelsMap, string, error) {\n\t// Check the default path first, and return annotations if they were found or an error if that error\n\t// is not because the path does not exist (it exists or there was an unmarshalling error).\n\tannotationsPath := filepath.Join(bundleRoot, registrybundle.MetadataDir, registrybundle.AnnotationsFile)\n\tannotations, err := readAnnotations(fs, annotationsPath)\n\tif (err == nil && len(annotations) != 0) || (err != nil && !errors.Is(err, os.ErrNotExist)) {\n\t\treturn annotations, annotationsPath, err\n\t}\n\n\t// Annotations are not at the default path, so search recursively.\n\tannotations = make(LabelsMap)\n\tannotationsPath = \"\"\n\terr = afero.Walk(fs, bundleRoot, func(path string, info os.FileInfo, err error) error {\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\t// Skip directories and hidden files, or if annotations were already found.\n\t\tif len(annotations) != 0 || info.IsDir() || strings.HasPrefix(path, \".\") {\n\t\t\treturn nil\n\t\t}\n\n\t\tannotationsPath = path\n\t\t// Ignore this error, since we only care if any annotations are returned.\n\t\tif annotations, err = readAnnotations(fs, path); err != nil {\n\t\t\tlog.Debug(err)\n\t\t}\n\t\treturn nil\n\t})\n\tif err != nil {\n\t\treturn nil, \"\", err\n\t}\n\n\tif len(annotations) == 0 {\n\t\treturn nil, \"\", MetadataNotFoundError(bundleRoot)\n\t}\n\n\treturn annotations, annotationsPath, nil\n}\n\n// readAnnotations reads annotations from file(s) in bundleRoot and returns them as Labels.\nfunc readAnnotations(fs afero.Fs, annotationsPath string) (LabelsMap, error) {\n\t// The annotations file is well-defined.\n\tb, err := afero.ReadFile(fs, annotationsPath)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Use the arbitrarily-labelled bundle representation of the annotations file\n\t// for forwards and backwards compatibility.\n\tannotations := registrybundle.AnnotationMetadata{\n\t\tAnnotations: make(LabelsMap),\n\t}\n\tif err = yaml.Unmarshal(b, &annotations); err != nil {\n\t\treturn nil, fmt.Errorf(\"error unmarshalling potential bundle metadata %s: %v\", annotationsPath, err)\n\t}\n\n\treturn annotations.Annotations, nil\n}\n"
  },
  {
    "path": "internal/registry/labels_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage registry\n\nimport (\n\t\"fmt\"\n\t\"path/filepath\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\t\"github.com/spf13/afero\"\n)\n\nvar _ = Describe(\"Labels\", func() {\n\tDescribe(\"FindBundleMetadata\", func() {\n\t\tvar (\n\t\t\tfs          afero.Fs\n\t\t\terr         error\n\t\t\tdefaultPath = \"/bundle/metadata/annotations.yaml\"\n\t\t)\n\n\t\tContext(\"with valid annotations contents\", func() {\n\t\t\tvar (\n\t\t\t\tmetadata      LabelsMap\n\t\t\t\tpath, expPath string\n\t\t\t)\n\t\t\tBeforeEach(func() {\n\t\t\t\tfs = afero.NewMemMapFs()\n\t\t\t})\n\n\t\t\t// Location\n\t\t\tIt(\"finds registry metadata in the default location\", func() {\n\t\t\t\texpPath = defaultPath\n\t\t\t\twriteMetadataHelper(fs, expPath, annotationsStringValidV1)\n\t\t\t\tmetadata, path, err = findBundleMetadata(fs, \"/bundle\")\n\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\tExpect(path).To(Equal(expPath))\n\t\t\t\tExpect(metadata).To(BeEquivalentTo(annotationsValidV1))\n\t\t\t})\n\t\t\tIt(\"finds registry metadata in the a custom file name\", func() {\n\t\t\t\texpPath = \"/bundle/metadata/my-metadata.yaml\"\n\t\t\t\twriteMetadataHelper(fs, expPath, annotationsStringValidV1)\n\t\t\t\tmetadata, path, err = findBundleMetadata(fs, \"/bundle\")\n\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\tExpect(path).To(Equal(expPath))\n\t\t\t\tExpect(metadata).To(BeEquivalentTo(annotationsValidV1))\n\t\t\t})\n\t\t\tIt(\"finds registry metadata in a custom single-depth location\", func() {\n\t\t\t\texpPath = \"/bundle/my-dir/my-metadata.yaml\"\n\t\t\t\twriteMetadataHelper(fs, expPath, annotationsStringValidV1)\n\t\t\t\tmetadata, path, err = findBundleMetadata(fs, \"/bundle\")\n\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\tExpect(path).To(Equal(expPath))\n\t\t\t\tExpect(metadata).To(BeEquivalentTo(annotationsValidV1))\n\t\t\t})\n\t\t\tIt(\"finds registry metadata in a custom multi-depth location\", func() {\n\t\t\t\texpPath = \"/bundle/my-parent-dir/my-dir/annotations.yaml\"\n\t\t\t\twriteMetadataHelper(fs, expPath, annotationsStringValidV1)\n\t\t\t\tmetadata, path, err = findBundleMetadata(fs, \"/bundle\")\n\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\tExpect(path).To(Equal(expPath))\n\t\t\t\tExpect(metadata).To(BeEquivalentTo(annotationsValidV1))\n\t\t\t})\n\t\t\tIt(\"returns registry metadata from default path when metadata is also in another location\", func() {\n\t\t\t\texpPath = defaultPath\n\t\t\t\twriteMetadataHelper(fs, expPath, annotationsStringValidV1)\n\t\t\t\twriteMetadataHelper(fs, \"/bundle/other-metadata/annotations.yaml\", annotationsStringValidNoRegLabels)\n\t\t\t\tmetadata, path, err = findBundleMetadata(fs, \"/bundle\")\n\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\tExpect(path).To(Equal(expPath))\n\t\t\t\tExpect(metadata).To(BeEquivalentTo(annotationsValidV1))\n\t\t\t})\n\t\t\tIt(\"returns registry metadata from the first path, when metadata is also in another location\", func() {\n\t\t\t\texpPath = \"/bundle/custom1/annotations.yaml\"\n\t\t\t\twriteMetadataHelper(fs, expPath, annotationsStringValidV1)\n\t\t\t\twriteMetadataHelper(fs, \"/bundle/custom2/annotations.yaml\", annotationsStringValidNoRegLabels)\n\t\t\t\tmetadata, path, err = findBundleMetadata(fs, \"/bundle\")\n\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\tExpect(path).To(Equal(expPath))\n\t\t\t\tExpect(metadata).To(BeEquivalentTo(annotationsValidV1))\n\t\t\t})\n\n\t\t\t// Format\n\t\t\tIt(\"finds non-registry metadata\", func() {\n\t\t\t\texpPath = defaultPath\n\t\t\t\twriteMetadataHelper(fs, defaultPath, annotationsStringValidNoRegLabels)\n\t\t\t\tmetadata, path, err = findBundleMetadata(fs, \"/bundle\")\n\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\tExpect(path).To(Equal(expPath))\n\t\t\t\tExpect(metadata).To(BeEquivalentTo(annotationsValidNoRegLabels))\n\t\t\t})\n\t\t})\n\n\t\tContext(\"with invalid annotations contents\", func() {\n\t\t\tBeforeEach(func() {\n\t\t\t\tfs = afero.NewMemMapFs()\n\t\t\t})\n\n\t\t\tIt(\"returns a YAML error\", func() {\n\t\t\t\twriteMetadataHelper(fs, defaultPath, annotationsStringInvalidBadIndent)\n\t\t\t\t_, _, err = findBundleMetadata(fs, \"/bundle\")\n\t\t\t\t// err should contain both of the following parts.\n\t\t\t\tExpect(err.Error()).To(ContainSubstring(fmt.Sprintf(\"error unmarshalling potential bundle metadata %s: \", defaultPath)))\n\t\t\t\tExpect(err.Error()).To(ContainSubstring(\"yaml: line 2: found character that cannot start any token\"))\n\t\t\t})\n\t\t\tIt(\"returns an error for no metadata file (empty file)\", func() {\n\t\t\t\twriteMetadataHelper(fs, defaultPath, annotationsStringInvalidEmpty)\n\t\t\t\t_, _, err = findBundleMetadata(fs, \"/bundle\")\n\t\t\t\tExpect(err).To(MatchError(\"metadata not found in /bundle\"))\n\t\t\t})\n\t\t\tIt(\"returns an error for no metadata file (invalid top-level key)\", func() {\n\t\t\t\twriteMetadataHelper(fs, defaultPath, annotationsStringInvalidTopKey)\n\t\t\t\t_, _, err = findBundleMetadata(fs, \"/bundle\")\n\t\t\t\tExpect(err).To(MatchError(\"metadata not found in /bundle\"))\n\t\t\t})\n\t\t\tIt(\"returns an error for no labels in a metadata file\", func() {\n\t\t\t\twriteMetadataHelper(fs, defaultPath, annotationsStringInvalidNoLabels)\n\t\t\t\t_, _, err = findBundleMetadata(fs, \"/bundle\")\n\t\t\t\tExpect(err).To(MatchError(\"metadata not found in /bundle\"))\n\t\t\t})\n\t\t})\n\t})\n\n})\n\nfunc writeMetadataHelper(fs afero.Fs, path, contents string) {\n\tExpectWithOffset(1, fs.MkdirAll(filepath.Dir(path), 0755)).Should(Succeed())\n\tExpectWithOffset(1, afero.WriteFile(fs, path, []byte(contents), 0666)).Should(Succeed())\n}\n\nvar annotationsValidV1 = LabelsMap{\n\t\"operators.operatorframework.io.bundle.mediatype.v1\": \"registry+v1\",\n\t\"operators.operatorframework.io.bundle.metadata.v1\":  \"metadata/\",\n\t\"foo\": \"bar\",\n}\n\nconst annotationsStringValidV1 = `annotations:\n  operators.operatorframework.io.bundle.mediatype.v1: registry+v1\n  operators.operatorframework.io.bundle.metadata.v1: metadata/\n  foo: bar\n`\n\nvar annotationsValidNoRegLabels = LabelsMap{\n\t\"foo\": \"bar\",\n\t\"baz\": \"buf\",\n}\n\nconst annotationsStringValidNoRegLabels = `annotations:\n  foo: bar\n  baz: buf\n`\n\nconst annotationsStringInvalidBadIndent = `annotations:\n\toperators.operatorframework.io.bundle.mediatype.v1: registry+v1\n`\n\nconst annotationsStringInvalidEmpty = ``\n\nconst annotationsStringInvalidNoLabels = `annotations:\n`\n\nconst annotationsStringInvalidTopKey = `not-annotations:\n  operators.operatorframework.io.bundle.mediatype.v1: registry+v1\n  operators.operatorframework.io.bundle.metadata.v1: metadata/\n  foo: bar\n`\n"
  },
  {
    "path": "internal/registry/logger.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage registry\n\nimport (\n\t\"io\"\n\n\tlog \"github.com/sirupsen/logrus\"\n)\n\n// DiscardLogger returns a logger that throws away input.\nfunc DiscardLogger() *log.Entry {\n\tlogger := log.New()\n\tlogger.SetOutput(io.Discard)\n\treturn log.NewEntry(logger)\n}\n"
  },
  {
    "path": "internal/registry/registry_suite_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage registry\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nfunc TestRegistry(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"Registry Suite\")\n}\n"
  },
  {
    "path": "internal/registry/validate.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage registry\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\n\tapimanifests \"github.com/operator-framework/api/pkg/manifests\"\n\tapivalidation \"github.com/operator-framework/api/pkg/validation\"\n\tapierrors \"github.com/operator-framework/api/pkg/validation/errors\"\n\tregistrybundle \"github.com/operator-framework/operator-registry/pkg/lib/bundle\"\n\tlog \"github.com/sirupsen/logrus\"\n\tk8svalidation \"k8s.io/apimachinery/pkg/api/validation\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/util/validation/field\"\n\t\"sigs.k8s.io/yaml\"\n)\n\n// ValidateBundleContent confirms that the CSV and CRD files inside the bundle\n// directory are valid and can be installed in a cluster. Other GVK types are\n// also validated to confirm if they are \"kubectl-able\" to a cluster meaning\n// if they can be applied to a cluster using `kubectl` provided users have all\n// necessary permissions and configurations.\nfunc ValidateBundleContent(logger *log.Entry, bundle *apimanifests.Bundle, mediaType string) []apierrors.ManifestResult {\n\tif logger == nil {\n\t\tlogger = DiscardLogger()\n\t}\n\n\t// Use errs to collect bundle-level validation errors.\n\terrs := apierrors.ManifestResult{\n\t\tName: bundle.Name,\n\t}\n\n\tlogger.Debug(\"Validating bundle contents\")\n\n\t// helm+vX media types are not supported by this validation function.\n\tswitch mediaType {\n\tcase registrybundle.HelmType:\n\t\treturn []apierrors.ManifestResult{errs}\n\t}\n\n\tfor _, u := range bundle.Objects {\n\t\t// CSVs and CRDs will be validated separately.\n\t\tgvk := u.GetObjectKind().GroupVersionKind()\n\t\tif gvk.Kind == \"ClusterServiceVersion\" || gvk.Kind == \"CustomResourceDefinition\" {\n\t\t\tcontinue\n\t\t}\n\n\t\tlogger.Debugf(\"Validating %s %q\", gvk, u.GetName())\n\n\t\t// Verify if the object kind is supported for registry+v1 format.\n\t\tsupported, _ := registrybundle.IsSupported(gvk.Kind)\n\t\tif mediaType == registrybundle.RegistryV1Type && !supported {\n\t\t\terrs.Add(apierrors.ErrInvalidBundle(fmt.Sprintf(\"unsupported media type %s for bundle object\", mediaType), gvk))\n\t\t\tcontinue\n\t\t}\n\n\t\tif err := validateObject(metav1.Object(u)); err != nil {\n\t\t\terrs.Add(apierrors.ErrFailedValidation(err.Error(), u.GetName()))\n\t\t}\n\t}\n\n\t// Validate bundle itself.\n\tresults := apivalidation.BundleValidator.Validate(bundle)\n\n\t// All bundles must have a CSV currently.\n\tif bundle.CSV != nil {\n\t\tresults = append(results, apivalidation.ClusterServiceVersionValidator.Validate(bundle.CSV)...)\n\t} else {\n\t\terrs.Add(apierrors.ErrInvalidBundle(\"no ClusterServiceVersion in bundle\", bundle.Name))\n\t}\n\n\t// Validate all CRD versions in the bundle together.\n\tvar crds []any\n\tfor _, crd := range bundle.V1beta1CRDs {\n\t\tcrds = append(crds, crd)\n\t}\n\tfor _, crd := range bundle.V1CRDs {\n\t\tcrds = append(crds, crd)\n\t}\n\tif len(crds) != 0 {\n\t\tresults = append(results, apivalidation.CustomResourceDefinitionValidator.Validate(crds...)...)\n\t}\n\n\t// Add all other results/errors to the bundle validation results.\n\tresults = appendResult(results, errs)\n\n\treturn results\n}\n\n// validateObject validates an arbitrary metav1.Object's metadata.\nfunc validateObject(obj metav1.Object) error {\n\tf := func(string, bool) []string { return nil }\n\terrs := k8svalidation.ValidateObjectMetaAccessor(obj, false, f, field.NewPath(\"metadata\"))\n\tif len(errs) > 0 {\n\t\treturn fmt.Errorf(\"error validating object: %s. %v\", errs.ToAggregate(), obj)\n\t}\n\treturn nil\n}\n\n// appendResult attempts to find a result in results that matches r.Name, and\n// if found appends errors and warnings to that result. Otherwise r is added\n// to the end of results.\nfunc appendResult(results []apierrors.ManifestResult, r apierrors.ManifestResult) []apierrors.ManifestResult {\n\tresultIdx := -1\n\tfor i, result := range results {\n\t\tif result.Name == r.Name {\n\t\t\tresultIdx = i\n\t\t\tbreak\n\t\t}\n\t}\n\tif resultIdx < 0 {\n\t\tresults = append(results, r)\n\t} else {\n\t\tresults[resultIdx].Add(r.Errors...)\n\t\tresults[resultIdx].Add(r.Warnings...)\n\t}\n\n\treturn results\n}\n\n// RewriteAnnotationsYaml unmarshalls the specified yaml file, appends the content and\n// converts it again to yaml.\nfunc RewriteAnnotationsYaml(filename string, content map[string]string) error {\n\n\tmetadata, err := getAnnotationFileContents(filename)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Append the contents to annotationsYaml\n\tfor key, val := range content {\n\t\tmetadata.Annotations[key] = val\n\t}\n\n\terr = writeAnnotationFile(filename, metadata)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc getAnnotationFileContents(filename string) (*registrybundle.AnnotationMetadata, error) {\n\tf, err := os.ReadFile(filename)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tannotationsYaml := &registrybundle.AnnotationMetadata{}\n\tif err := yaml.Unmarshal(f, annotationsYaml); err != nil {\n\t\treturn nil, fmt.Errorf(\"error parsing annotations file: %v\", err)\n\t}\n\treturn annotationsYaml, nil\n}\n\nfunc writeAnnotationFile(filename string, annotation *registrybundle.AnnotationMetadata) error {\n\tfile, err := yaml.Marshal(annotation)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tmode := os.FileMode(0666)\n\tif info, err := os.Stat(filename); err == nil {\n\t\tmode = info.Mode()\n\t}\n\n\terr = os.WriteFile(filename, file, mode)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error writing modified contents to annotations file, %v\", err)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "internal/scorecard/bundle.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage scorecard\n\nimport (\n\t\"archive/tar\"\n\t\"bytes\"\n\t\"compress/gzip\"\n\t\"fmt\"\n\t\"os\"\n\n\tlog \"github.com/sirupsen/logrus\"\n)\n\n// getBundleData tars up the contents of a bundle from a path, and returns that tar file in []byte\nfunc (r PodTestRunner) getBundleData() (bundleData []byte, err error) {\n\n\t// make sure the bundle exists on disk\n\t_, err = os.Stat(r.BundlePath)\n\tif err != nil && os.IsNotExist(err) {\n\t\treturn nil, fmt.Errorf(\"bundle path does not exist: %w\", err)\n\t}\n\n\t// Write the tarball in-memory.\n\tbuf := &bytes.Buffer{}\n\tgz := gzip.NewWriter(buf)\n\tw := tar.NewWriter(gz)\n\t// Both tar and gzip writer Close() methods write some data that is\n\t// required when reading the result, so we must close these without a defer.\n\tclosers := closeFuncs{w.Close, gz.Close}\n\n\t// Write the bundle to a tarball.\n\tpaths := []string{r.BundlePath}\n\tif err = WritePathsToTar(w, paths); err != nil {\n\t\treturn nil, fmt.Errorf(\"error writing bundle tar: %w\", err)\n\t}\n\n\tclosers.close()\n\treturn buf.Bytes(), nil\n}\n\ntype closeFuncs []func() error\n\nfunc (fs closeFuncs) close() {\n\tfor _, f := range fs {\n\t\tif err := f(); err != nil {\n\t\t\tlog.Error(err)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/scorecard/bundle_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage scorecard\n\nimport (\n\t\"archive/tar\"\n\t\"bytes\"\n\t\"compress/gzip\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/registry\"\n)\n\nvar _ = Describe(\"Tarring a bundle\", func() {\n\tDescribe(\"getBundleData\", func() {\n\n\t\tvar (\n\t\t\tr          PodTestRunner\n\t\t\terr        error\n\t\t\texpTarPath = filepath.Join(\"testdata\", \"bundle.tar.gz\")\n\t\t\texpTarball []byte\n\t\t)\n\n\t\tBeforeEach(func() {\n\t\t\tr = PodTestRunner{}\n\t\t\texpTarball, err = os.ReadFile(expTarPath)\n\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t})\n\n\t\tContext(\"with a valid on-disk bundle\", func() {\n\t\t\tvar (\n\t\t\t\tvalidBundlePath = filepath.Join(\"testdata\", \"bundle\")\n\t\t\t)\n\n\t\t\tIt(\"creates a tarball successfully\", func() {\n\t\t\t\tr.BundlePath = validBundlePath\n\t\t\t\tr.BundleMetadata, _, err = registry.FindBundleMetadata(validBundlePath)\n\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\ttarredBundleData, err := r.getBundleData()\n\t\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\t\tcmpTarFilesHelper(expTarball, tarredBundleData)\n\t\t\t})\n\t\t})\n\n\t\tContext(\"with an invalid on-disk bundle\", func() {\n\t\t\tIt(\"returns an error\", func() {\n\t\t\t\t_, err = r.getBundleData()\n\t\t\t\tExpect(err).To(HaveOccurred())\n\t\t\t})\n\t\t})\n\t})\n\n})\n\n// cmpTarFilesHelper compares the byte representation of two tarballs,\n// by contents per matching header name and for non-intersecting header names.\nfunc cmpTarFilesHelper(c1, c2 []byte) {\n\tr1, r2 := bytes.NewBuffer(c1), bytes.NewBuffer(c2)\n\tset1, err := untarToFileSet(r1)\n\tExpectWithOffset(1, err).ToNot(HaveOccurred())\n\tset2, err := untarToFileSet(r2)\n\tExpectWithOffset(1, err).ToNot(HaveOccurred())\n\n\tfor fileName, contents1 := range set1 {\n\t\tcontents2, hasFileName := set2[fileName]\n\t\tExpectWithOffset(1, hasFileName).To(BeTrue(), \"second tarball does not have file %s\", fileName)\n\t\tExpectWithOffset(1, contents1.String()).To(Equal(contents2.String()),\n\t\t\t\"contents of file %s differ in first and second tarballs\", fileName)\n\t\tdelete(set2, fileName)\n\t}\n\tExpectWithOffset(1, set2).To(BeEmpty(), \"second tarball has files not in the first\")\n}\n\n// untarToFileSet reads a gizpped tarball from r and writes each object's bytes to a set, keyed by header name.\nfunc untarToFileSet(r io.Reader) (map[string]*bytes.Buffer, error) {\n\tgz, err := gzip.NewReader(r)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer func() {\n\t\tif err := gz.Close(); err != nil {\n\t\t\tfmt.Fprintln(GinkgoWriter, \"warning: error closing tarball reader:\", err)\n\t\t}\n\t}()\n\ttr := tar.NewReader(gz)\n\tfileSet := make(map[string]*bytes.Buffer)\n\n\tfor {\n\t\thdr, err := tr.Next()\n\t\tif err == io.EOF {\n\t\t\tbreak\n\t\t}\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tbuf := &bytes.Buffer{}\n\t\tn, err := io.Copy(buf, tr)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif n != hdr.Size {\n\t\t\treturn nil, fmt.Errorf(\"unexpected bytes written: wrote %d, want %d\", n, hdr.Size)\n\t\t}\n\t\tfileSet[path.Clean(hdr.Name)] = buf\n\t}\n\n\treturn fileSet, nil\n}\n"
  },
  {
    "path": "internal/scorecard/config.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage scorecard\n\nimport (\n\t\"os\"\n\n\t\"github.com/operator-framework/api/pkg/apis/scorecard/v1alpha3\"\n\t\"sigs.k8s.io/yaml\"\n)\n\nconst (\n\t// ConfigFileName is the scorecard's hard-coded config file name.\n\tConfigFileName = \"config.yaml\"\n\t// DefaultConfigDir is the default scorecard path within a bundle.\n\tDefaultConfigDir = \"tests/scorecard/\"\n)\n\n// LoadConfig will find and return the scorecard config, the config file\n// is found from a bundle location (TODO bundle image)\n// scorecard config.yaml is expected to be in the bundle at the following\n// location:  tests/scorecard/config.yaml\n// the user can override this location using the --config CLI flag\n// TODO: version this.\nfunc LoadConfig(configFilePath string) (v1alpha3.Configuration, error) {\n\tc := v1alpha3.Configuration{}\n\n\tyamlFile, err := os.ReadFile(configFilePath)\n\tif err != nil {\n\t\treturn c, err\n\t}\n\n\terr = yaml.Unmarshal(yamlFile, &c)\n\treturn c, err\n}\n"
  },
  {
    "path": "internal/scorecard/config_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage scorecard\n\nimport (\n\t\"testing\"\n)\n\nfunc TestInvalidConfigPath(t *testing.T) {\n\n\tcases := []struct {\n\t\tconfigPathValue string\n\t\twantError       bool\n\t}{\n\t\t{\"\", true},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(c.configPathValue, func(t *testing.T) {\n\t\t\t_, err := LoadConfig(c.configPathValue)\n\t\t\tif err == nil && c.wantError {\n\t\t\t\tt.Fatalf(\"Wanted error but got no error\")\n\t\t\t} else if err != nil {\n\t\t\t\tif !c.wantError {\n\t\t\t\t\tt.Fatalf(\"Wanted result but got error: %v\", err)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\n\t\t})\n\n\t}\n}\n"
  },
  {
    "path": "internal/scorecard/formatting.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage scorecard\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\n\t\"github.com/operator-framework/api/pkg/apis/scorecard/v1alpha3\"\n\tv1 \"k8s.io/api/core/v1\"\n)\n\n// getTestResult fetches the test pod log and converts it into\n// Test format\nfunc (r PodTestRunner) getTestStatus(ctx context.Context, p *v1.Pod) (output *v1alpha3.TestStatus) {\n\tlogBytes, err := getPodLog(ctx, r.Client, p)\n\tif err != nil {\n\t\treturn convertErrorToStatus(err, string(logBytes))\n\t}\n\t// marshal pod log into TestResult\n\terr = json.Unmarshal(logBytes, &output)\n\tif err != nil {\n\t\treturn convertErrorToStatus(err, string(logBytes))\n\t}\n\treturn output\n}\n\n// List lists the scorecard tests as configured that would be\n// run based on user selection\nfunc (o Scorecard) List() v1alpha3.TestList {\n\toutput := v1alpha3.NewTestList()\n\tfor _, stage := range o.Config.Stages {\n\t\ttests := o.selectTests(stage)\n\t\tfor _, test := range tests {\n\t\t\titem := v1alpha3.NewTest()\n\t\t\titem.Spec = test\n\t\t\toutput.Items = append(output.Items, item)\n\t\t}\n\t}\n\treturn output\n}\n"
  },
  {
    "path": "internal/scorecard/formatting_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage scorecard\n\nimport (\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"k8s.io/apimachinery/pkg/labels\"\n)\n\nfunc TestList(t *testing.T) {\n\n\tcases := []struct {\n\t\tbundlePathValue string\n\t\tselector        string\n\t\tresultCount     int\n\t}{\n\t\t{\"testdata/bundle\", \"suite=basic\", 1},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(c.bundlePathValue, func(t *testing.T) {\n\t\t\to := Scorecard{}\n\t\t\trunner := PodTestRunner{}\n\t\t\tvar err error\n\t\t\tconfigPath := filepath.Join(c.bundlePathValue, \"tests\", \"scorecard\", \"config.yaml\")\n\n\t\t\to.Config, err = LoadConfig(configPath)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"Unexpected error %v\", err)\n\t\t\t}\n\t\t\to.Selector, err = labels.Parse(c.selector)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"Unexpected error %v\", err)\n\t\t\t}\n\t\t\trunner.BundlePath = c.bundlePathValue\n\t\t\to.TestRunner = &runner\n\t\t\toutput := o.List()\n\t\t\tactualResultCount := len(output.Items)\n\t\t\tif c.resultCount != actualResultCount {\n\t\t\t\tt.Fatalf(\"Wanted result count %d but got : %d\", c.resultCount, actualResultCount)\n\t\t\t}\n\n\t\t})\n\n\t}\n}\n"
  },
  {
    "path": "internal/scorecard/kubeclient.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage scorecard\n\nimport (\n\t\"os\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/util/k8sutil\"\n\t\"k8s.io/client-go/kubernetes\"\n\t\"k8s.io/client-go/rest\"\n\t\"k8s.io/client-go/tools/clientcmd\"\n\tcruntime \"sigs.k8s.io/controller-runtime/pkg/client/config\"\n)\n\n// GetKubeClient will get a kubernetes client from the following sources:\n//   - a path to the kubeconfig file passed on the command line (--kubeconfig)\n//   - an environment variable that specifies the path (export KUBECONFIG)\n//   - the user's $HOME/.kube/config file\n//   - in-cluster connection for when the sdk is run within a cluster instead of\n//     the command line\n//\n// TODO(joelanford): migrate scorecard use `internal/operator.Configuration`\nfunc GetKubeClient(kubeconfig string) (client kubernetes.Interface, config *rest.Config, err error) {\n\n\tif kubeconfig != \"\" {\n\t\tos.Setenv(k8sutil.KubeConfigEnvVar, kubeconfig)\n\t}\n\n\tconfig, err = cruntime.GetConfig()\n\tif err != nil {\n\t\treturn client, config, err\n\t}\n\n\t// create the clientset\n\tclientset, err := kubernetes.NewForConfig(config)\n\tif err != nil {\n\t\treturn client, config, err\n\t}\n\n\treturn clientset, config, err\n}\n\n// GetKubeNamespace returns the kubernetes namespace to use\n// for scorecard pod creation\n// the order of how the namespace is determined is as follows:\n// - a namespace command line argument\n// - a namespace determined from the kubeconfig file\n// - the kubeconfig file is determined in the following order:\n//   - from the kubeconfig flag if set\n//   - from the KUBECONFIG env var if set\n//   - from the $HOME/.kube/config path if exists\n//   - returns 'default' as the namespace if not set in the kubeconfig\n//\n// TODO(joelanford): migrate scorecard to use `internal/operator.Configuration`\nfunc GetKubeNamespace(kubeconfigPath, namespace string) string {\n\n\tif namespace != \"\" {\n\t\treturn namespace\n\t}\n\n\trules := clientcmd.NewDefaultClientConfigLoadingRules()\n\n\tif kubeconfigPath != \"\" {\n\t\trules.ExplicitPath = kubeconfigPath\n\t}\n\n\tkubeConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(rules, &clientcmd.ConfigOverrides{})\n\n\tns, _, err := kubeConfig.Namespace()\n\tif err != nil {\n\t\treturn \"default\"\n\t}\n\treturn ns\n\n}\n"
  },
  {
    "path": "internal/scorecard/kubeclient_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage scorecard\n\nimport (\n\t\"log\"\n\t\"os\"\n\t\"testing\"\n)\n\nfunc TestGetKubeNamespace(t *testing.T) {\n\n\t// create temp kubeconfig file\n\tfile, err := os.CreateTemp(\"/tmp\", \"\")\n\tif err != nil {\n\t\tt.Fatal(err.Error())\n\t}\n\tdefer os.Remove(file.Name())\n\n\tdata := []byte(testKubeconfig)\n\terr = os.WriteFile(file.Name(), data, 0644)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tcases := []struct {\n\t\tkubeconfigPath string\n\t\tnamespace      string\n\t\texpectedValue  string\n\t}{\n\t\t{\"\", \"userspecified\", \"userspecified\"},\n\t\t{\"/tmp/doesnotexist\", \"\", \"default\"},\n\t\t{file.Name(), \"\", \"goo\"},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(c.kubeconfigPath, func(t *testing.T) {\n\n\t\t\toNamespace := GetKubeNamespace(c.kubeconfigPath, c.namespace)\n\t\t\tif oNamespace != c.expectedValue {\n\t\t\t\tt.Errorf(\"Wanted namespace %s, got: %s\", c.expectedValue, oNamespace)\n\t\t\t}\n\t\t})\n\n\t}\n}\n\nfunc TestGetKubeNamespaceEnvVar(t *testing.T) {\n\n\t// create temp kubeconfig file\n\tfile, err := os.CreateTemp(\"/tmp\", \"\")\n\tif err != nil {\n\t\tt.Fatal(err.Error())\n\t}\n\tdefer os.Remove(file.Name())\n\n\tdata := []byte(testKubeconfig)\n\terr = os.WriteFile(file.Name(), data, 0644)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// set KUBECONFIG env var\n\terr = os.Setenv(\"KUBECONFIG\", file.Name())\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tcases := []struct {\n\t\tkubeconfigPath string\n\t\tnamespace      string\n\t\texpectedValue  string\n\t}{\n\t\t{\"\", \"\", \"goo\"},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(c.kubeconfigPath, func(t *testing.T) {\n\t\t\toNamespace := GetKubeNamespace(c.kubeconfigPath, c.namespace)\n\t\t\tif oNamespace != c.expectedValue {\n\t\t\t\tt.Errorf(\"Wanted namespace %s, got: %s\", c.expectedValue, oNamespace)\n\t\t\t}\n\t\t})\n\n\t}\n}\n\nconst testKubeconfig = `\napiVersion: v1\nclusters:\n- cluster:\n    server: https://192.168.0.130:6443\n  name: kubernetes\ncontexts:\n- context:\n    cluster: kubernetes\n    namespace: foo\n    user: kubernetes-admin\n  name: dev\n- context:\n    cluster: kubernetes\n    user: kubernetes-admin\n  name: kubernetes-admin@kubernetes\n- context:\n    cluster: kubernetes\n    namespace: goo\n    user: kubernetes-admin\n  name: prod\ncurrent-context: prod\nkind: Config\npreferences: {}\nusers:\n- name: kubernetes-admin\n  user:\n`\n"
  },
  {
    "path": "internal/scorecard/labels_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage scorecard\n\nimport (\n\t\"testing\"\n\n\t\"github.com/operator-framework/api/pkg/apis/scorecard/v1alpha3\"\n\t\"k8s.io/apimachinery/pkg/labels\"\n)\n\nfunc TestEmptySelector(t *testing.T) {\n\n\tcases := []struct {\n\t\tselectorValue string\n\t\ttestsSelected int\n\t\tconfig        v1alpha3.Configuration\n\t\twantError     bool\n\t}{\n\t\t{\"\", 7, testConfig, false},\n\t\t{\"suite in (kuttl)\", 1, testConfig, false},\n\t\t{\"test=basic-check-spec-test\", 1, testConfig, false},\n\t\t{\"testXwriteintocr\", 0, testConfig, false},\n\t\t{\"test X writeintocr\", 0, testConfig, true},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(c.selectorValue, func(t *testing.T) {\n\t\t\to := Scorecard{}\n\t\t\to.Config = c.config\n\n\t\t\tvar err error\n\t\t\to.Selector, err = labels.Parse(c.selectorValue)\n\t\t\tif err == nil && c.wantError {\n\t\t\t\tt.Fatalf(\"Wanted error but got no error\")\n\t\t\t} else if err != nil {\n\t\t\t\tif !c.wantError {\n\t\t\t\t\tt.Fatalf(\"Wanted result but got error: %v\", err)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\ttests := o.selectTests(o.Config.Stages[0])\n\t\t\ttestsSelected := len(tests)\n\t\t\tif testsSelected != c.testsSelected {\n\t\t\t\tt.Errorf(\"Wanted testsSelected %d, got: %d\", c.testsSelected, testsSelected)\n\t\t\t}\n\t\t})\n\n\t}\n}\n\nvar testConfig = v1alpha3.Configuration{\n\tStages: []v1alpha3.StageConfiguration{\n\t\t{\n\t\t\tTests: []v1alpha3.TestConfiguration{\n\t\t\t\t{Image: \"quay.io/someuser/customtest1:v0.0.1\",\n\t\t\t\t\tEntrypoint: []string{\n\t\t\t\t\t\t\"custom-test\",\n\t\t\t\t\t},\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\t\"suite\": \"custom\",\n\t\t\t\t\t\t\"test\":  \"customtest1\",\n\t\t\t\t\t},\n\t\t\t\t},\n\n\t\t\t\t{Image: \"quay.io/someuser/customtest2:v0.0.1\",\n\t\t\t\t\tEntrypoint: []string{\n\t\t\t\t\t\t\"custom-test\",\n\t\t\t\t\t},\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\t\"suite\": \"custom\",\n\t\t\t\t\t\t\"test\":  \"customtest2\",\n\t\t\t\t\t},\n\t\t\t\t},\n\n\t\t\t\t{Image: \"quay.io/redhat/basictests:v0.0.1\",\n\t\t\t\t\tEntrypoint: []string{\n\t\t\t\t\t\t\"scorecard-test\",\n\t\t\t\t\t\t\"basic-check-spec\",\n\t\t\t\t\t},\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\t\"suite\": \"basic\",\n\t\t\t\t\t\t\"test\":  \"basic-check-spec-test\",\n\t\t\t\t\t},\n\t\t\t\t},\n\n\t\t\t\t{Image: \"quay.io/redhat/basictests:v0.0.1\",\n\t\t\t\t\tEntrypoint: []string{\n\t\t\t\t\t\t\"scorecard-test\",\n\t\t\t\t\t\t\"basic-check-status\",\n\t\t\t\t\t},\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\t\"suite\": \"basic\",\n\t\t\t\t\t\t\"test\":  \"basic-check-status-test\",\n\t\t\t\t\t},\n\t\t\t\t},\n\n\t\t\t\t{Image: \"quay.io/redhat/olmtests:v0.0.1\",\n\t\t\t\t\tEntrypoint: []string{\n\t\t\t\t\t\t\"scorecard-test\",\n\t\t\t\t\t\t\"olm-bundle-validation\",\n\t\t\t\t\t},\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\t\"suite\": \"olm\",\n\t\t\t\t\t\t\"test\":  \"olm-bundle-validation-test\",\n\t\t\t\t\t},\n\t\t\t\t},\n\n\t\t\t\t{Image: \"quay.io/redhat/olmtests:v0.0.1\",\n\t\t\t\t\tEntrypoint: []string{\n\t\t\t\t\t\t\"scorecard-test\",\n\t\t\t\t\t\t\"olm-crds-have-validation\",\n\t\t\t\t\t},\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\t\"suite\": \"olm\",\n\t\t\t\t\t\t\"test\":  \"olm-crds-have-validation-test\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{Image: \"quay.io/redhat/kuttltests:v0.0.1\",\n\t\t\t\t\tEntrypoint: []string{\n\t\t\t\t\t\t\"kuttl-test\",\n\t\t\t\t\t\t\"olm-status-descriptors\",\n\t\t\t\t\t},\n\t\t\t\t\tLabels: map[string]string{\n\t\t\t\t\t\t\"suite\": \"kuttl\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n}\n"
  },
  {
    "path": "internal/scorecard/run_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage scorecard\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"path/filepath\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/operator-framework/api/pkg/apis/scorecard/v1alpha3\"\n\t\"k8s.io/apimachinery/pkg/labels\"\n)\n\n// TODO(joelanford): rewrite to use ginkgo/gomega\nfunc TestRun(t *testing.T) {\n\tcases := []struct {\n\t\tname            string\n\t\tconfigPathValue string\n\t\tselector        string\n\t\ttimeout         time.Duration\n\t\twantedError     error\n\t\ttestRunner      FakeTestRunner\n\t\texpectedState   v1alpha3.State\n\t}{\n\t\t{\n\t\t\tname:            \"should execute 1 fake test successfully\",\n\t\t\tconfigPathValue: \"testdata/bundle\",\n\t\t\tselector:        \"suite=basic\",\n\t\t\ttimeout:         time.Second * 7,\n\t\t\ttestRunner:      FakeTestRunner{},\n\t\t\texpectedState:   v1alpha3.PassState,\n\t\t},\n\t\t{\n\t\t\tname:            \"should fail to execute 1 test with short timeout\",\n\t\t\tconfigPathValue: \"testdata/bundle\",\n\t\t\tselector:        \"suite=basic\",\n\t\t\ttimeout:         time.Second * 0,\n\t\t\twantedError:     context.DeadlineExceeded,\n\t\t\ttestRunner:      FakeTestRunner{},\n\t\t\texpectedState:   v1alpha3.PassState,\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(c.configPathValue, func(t *testing.T) {\n\t\t\to := Scorecard{}\n\t\t\tvar err error\n\t\t\tconfigPath := filepath.Join(c.configPathValue, \"tests\", \"scorecard\", \"config.yaml\")\n\t\t\to.Config, err = LoadConfig(configPath)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"Unexpected error loading config %v\", err)\n\t\t\t}\n\t\t\to.Selector, err = labels.Parse(c.selector)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"Unexpected error parsing selector %v\", err)\n\t\t\t}\n\t\t\to.SkipCleanup = true\n\n\t\t\tmockResult := v1alpha3.TestResult{}\n\t\t\tmockResult.Name = \"mocked test\"\n\t\t\tmockResult.State = v1alpha3.PassState\n\t\t\tmockResult.Errors = make([]string, 0)\n\t\t\tmockResult.Suggestions = make([]string, 0)\n\t\t\tmockStatus := v1alpha3.TestStatus{Results: []v1alpha3.TestResult{mockResult}}\n\n\t\t\tc.testRunner.TestStatus = &mockStatus\n\t\t\to.TestRunner = c.testRunner\n\n\t\t\tctx, cancel := context.WithTimeout(context.Background(), c.timeout)\n\t\t\tdefer cancel()\n\n\t\t\tscorecardOutput, err := o.Run(ctx)\n\t\t\tif err == nil {\n\t\t\t\tif c.wantedError != nil {\n\t\t\t\t\tt.Errorf(\"Wanted error %s but got no error\", c.wantedError)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif scorecardOutput.Items[0].Status.Results[0].State != c.expectedState {\n\t\t\t\t\tt.Errorf(\"Wanted state %v, got %v\", c.expectedState, scorecardOutput.Items[0].Status.Results[0].State)\n\t\t\t\t}\n\t\t\t} else if err != nil {\n\t\t\t\tif c.wantedError == nil {\n\t\t\t\t\tt.Errorf(\"Wanted result but got error %v\", err)\n\t\t\t\t} else if !errors.Is(err, c.wantedError) {\n\t\t\t\t\tt.Errorf(\"Wanted error %v but got error %v\", c.wantedError, err)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\n\t}\n}\n\n// TODO(joelanford): rewrite to use ginkgo/gomega\nfunc TestRunParallelPass(t *testing.T) {\n\tscorecard := getFakeScorecard(true)\n\tctx, cancel := context.WithTimeout(context.Background(), 70*time.Millisecond)\n\tdefer cancel()\n\n\ttests, err := scorecard.Run(ctx)\n\tif err != nil {\n\t\tt.Fatalf(\"Expected no error, got error: %v\", err)\n\t}\n\tif len(tests.Items) != 2 {\n\t\tt.Fatalf(\"Expected 2 tests, got %d\", len(tests.Items))\n\t}\n\tfor _, test := range tests.Items {\n\t\texpectPass(t, test)\n\t}\n}\n\n// TODO(joelanford): rewrite to use ginkgo/gomega\nfunc TestRunSequentialPass(t *testing.T) {\n\tscorecard := getFakeScorecard(false)\n\tctx, cancel := context.WithTimeout(context.Background(), 120*time.Millisecond)\n\tdefer cancel()\n\n\ttests, err := scorecard.Run(ctx)\n\tif err != nil {\n\t\tt.Fatalf(\"Expected no error, got error: %v\", err)\n\t}\n\tif len(tests.Items) != 2 {\n\t\tt.Fatalf(\"Expected 2 tests, got %d\", len(tests.Items))\n\t}\n\tfor _, test := range tests.Items {\n\t\texpectPass(t, test)\n\t}\n}\n\n// TODO(joelanford): rewrite to use ginkgo/gomega\nfunc TestRunSequentialFail(t *testing.T) {\n\tscorecard := getFakeScorecard(false)\n\n\tctx, cancel := context.WithTimeout(context.Background(), 70*time.Millisecond)\n\tdefer cancel()\n\n\t_, err := scorecard.Run(ctx)\n\tif !errors.Is(err, context.DeadlineExceeded) {\n\t\tt.Fatalf(\"Expected deadline exceeded error, got:  %v\", err)\n\t}\n}\n\nfunc getFakeScorecard(parallel bool) Scorecard {\n\treturn Scorecard{\n\t\tConfig: v1alpha3.Configuration{\n\t\t\tStages: []v1alpha3.StageConfiguration{\n\t\t\t\t{\n\t\t\t\t\tParallel: parallel,\n\t\t\t\t\tTests: []v1alpha3.TestConfiguration{\n\t\t\t\t\t\t{},\n\t\t\t\t\t\t{},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tTestRunner: FakeTestRunner{\n\t\t\tSleep: 50 * time.Millisecond,\n\t\t\tTestStatus: &v1alpha3.TestStatus{\n\t\t\t\tResults: []v1alpha3.TestResult{\n\t\t\t\t\t{\n\t\t\t\t\t\tState: v1alpha3.PassState,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n}\n\nfunc expectPass(t *testing.T, test v1alpha3.Test) {\n\tif len(test.Status.Results) != 1 {\n\t\tt.Fatalf(\"Expected 1 results, got %d\", len(test.Status.Results))\n\t}\n\tfor _, r := range test.Status.Results {\n\t\tif len(r.Errors) > 0 {\n\t\t\tt.Fatalf(\"Expected no errors, got %v\", r.Errors)\n\t\t}\n\t\tif r.State != v1alpha3.PassState {\n\t\t\tt.Fatalf(\"Expected result state %q, got %q\", v1alpha3.PassState, r.State)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/scorecard/scorecard.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage scorecard\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/operator-framework/api/pkg/apis/scorecard/v1alpha3\"\n\tv1 \"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/labels\"\n\t\"k8s.io/apimachinery/pkg/util/wait\"\n\t\"k8s.io/client-go/kubernetes\"\n\t\"k8s.io/client-go/rest\"\n\n\tregistryutil \"github.com/operator-framework/operator-sdk/internal/registry\"\n)\n\ntype TestRunner interface {\n\tInitialize(context.Context) error\n\tRunTest(context.Context, v1alpha3.TestConfiguration, bool) (*v1alpha3.TestStatus, error)\n\tCleanup(context.Context) error\n}\n\ntype Scorecard struct {\n\tConfig      v1alpha3.Configuration\n\tSelector    labels.Selector\n\tTestRunner  TestRunner\n\tSkipCleanup bool\n\tPodSecurity bool\n}\n\ntype PodTestRunner struct {\n\tNamespace      string\n\tServiceAccount string\n\tBundlePath     string\n\tTestOutput     string\n\tBundleMetadata registryutil.LabelsMap\n\tClient         kubernetes.Interface\n\tRESTConfig     *rest.Config\n\tStorageImage   string\n\tUntarImage     string\n\n\tconfigMapName string\n\tPodSecurity   bool\n}\n\ntype FakeTestRunner struct {\n\tSleep      time.Duration\n\tTestStatus *v1alpha3.TestStatus\n\tError      error\n}\n\n// cleanupTimeout is the time given to clean up resources, regardless of how long ctx's deadline is.\nvar cleanupTimeout = time.Second * 30\n\n// Run executes the scorecard tests as configured\nfunc (o Scorecard) Run(ctx context.Context) (testOutput v1alpha3.TestList, err error) {\n\ttestOutput = v1alpha3.NewTestList()\n\n\tif err := o.TestRunner.Initialize(ctx); err != nil {\n\t\treturn testOutput, err\n\t}\n\n\tfor _, stage := range o.Config.Stages {\n\t\ttests := o.selectTests(stage)\n\t\tif len(tests) == 0 {\n\t\t\tcontinue\n\t\t}\n\t\ttests = o.setTestDefaults(tests)\n\n\t\toutput := make(chan v1alpha3.Test, len(tests))\n\t\tif stage.Parallel {\n\t\t\to.runStageParallel(ctx, tests, output)\n\t\t} else {\n\t\t\to.runStageSequential(ctx, tests, output)\n\t\t}\n\t\tclose(output)\n\t\tfor o := range output {\n\t\t\ttestOutput.Items = append(testOutput.Items, o)\n\t\t}\n\t}\n\n\t// Get timeout error, if any, before calling Cleanup() so deletes don't cause a timeout.\n\tselect {\n\tcase <-ctx.Done():\n\t\terr = ctx.Err()\n\tdefault:\n\t}\n\n\tif !o.SkipCleanup {\n\t\t// Use a separate context for cleanup, which needs to run regardless of a prior timeout.\n\t\tclctx, cancel := context.WithTimeout(context.Background(), cleanupTimeout)\n\t\tdefer cancel()\n\t\tif err := o.TestRunner.Cleanup(clctx); err != nil {\n\t\t\treturn testOutput, err\n\t\t}\n\t}\n\n\treturn testOutput, err\n}\n\nfunc (o Scorecard) setTestDefaults(tests []v1alpha3.TestConfiguration) []v1alpha3.TestConfiguration {\n\tfor i := range tests {\n\t\tif len(tests[i].Storage.Spec.MountPath.Path) == 0 {\n\t\t\ttests[i].Storage.Spec.MountPath.Path = o.Config.Storage.Spec.MountPath.Path\n\t\t}\n\t}\n\treturn tests\n}\n\nfunc (o Scorecard) runStageParallel(ctx context.Context, tests []v1alpha3.TestConfiguration, results chan<- v1alpha3.Test) {\n\tvar wg sync.WaitGroup\n\tfor _, t := range tests {\n\t\twg.Add(1)\n\t\tgo func(test v1alpha3.TestConfiguration) {\n\t\t\tresults <- o.runTest(ctx, test)\n\t\t\twg.Done()\n\t\t}(t)\n\t}\n\twg.Wait()\n}\n\nfunc (o Scorecard) runStageSequential(ctx context.Context, tests []v1alpha3.TestConfiguration, results chan<- v1alpha3.Test) {\n\tfor _, test := range tests {\n\t\tresults <- o.runTest(ctx, test)\n\t}\n}\n\nfunc (o Scorecard) runTest(ctx context.Context, test v1alpha3.TestConfiguration) v1alpha3.Test {\n\tresult, err := o.TestRunner.RunTest(ctx, test, o.PodSecurity)\n\tif err != nil {\n\t\tresult = convertErrorToStatus(err, \"\")\n\t}\n\n\tout := v1alpha3.NewTest()\n\t//TODO: Add timestamp to result when API version updates\n\t//out.Tstamp = time.Now().Format(time.RFC850)\n\tout.Spec = test\n\tout.Status = *result\n\treturn out\n}\n\n// selectTests applies an optionally passed selector expression\n// against the configured set of tests, returning the selected tests\nfunc (o *Scorecard) selectTests(stage v1alpha3.StageConfiguration) []v1alpha3.TestConfiguration {\n\tselected := make([]v1alpha3.TestConfiguration, 0)\n\tfor _, test := range stage.Tests {\n\t\tif o.Selector == nil || o.Selector.String() == \"\" || o.Selector.Matches(labels.Set(test.Labels)) {\n\t\t\t// TODO olm manifests check\n\t\t\tselected = append(selected, test)\n\t\t}\n\t}\n\treturn selected\n}\n\nfunc (r FakeTestRunner) Initialize(ctx context.Context) error {\n\tselect {\n\tcase <-ctx.Done():\n\t\treturn ctx.Err()\n\tdefault:\n\t\treturn nil\n\t}\n}\n\n// Initialize sets up the bundle configmap for tests\nfunc (r *PodTestRunner) Initialize(ctx context.Context) error {\n\tbundleData, err := r.getBundleData()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error getting bundle data %w\", err)\n\t}\n\n\tr.configMapName, err = r.CreateConfigMap(ctx, bundleData)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error creating ConfigMap %w\", err)\n\t}\n\n\treturn nil\n\n}\n\nfunc (r FakeTestRunner) Cleanup(ctx context.Context) error {\n\tselect {\n\tcase <-ctx.Done():\n\t\treturn ctx.Err()\n\tdefault:\n\t\treturn nil\n\t}\n}\n\n// Cleanup deletes pods and configmap resources from this test run\nfunc (r PodTestRunner) Cleanup(ctx context.Context) (err error) {\n\n\terr = r.deletePods(ctx, r.configMapName)\n\tif err != nil {\n\t\treturn err\n\t}\n\terr = r.deleteConfigMap(ctx, r.configMapName)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\n// RunTest executes a single test\nfunc (r PodTestRunner) RunTest(ctx context.Context, test v1alpha3.TestConfiguration, podSec bool) (*v1alpha3.TestStatus, error) {\n\n\t// Create a Pod to run the test\n\tpodDef := getPodDefinition(r.configMapName, test, r)\n\tif podSec {\n\t\t// creating a pod security context to support running in default namespace\n\t\tpodSecCtx := v1.PodSecurityContext{}\n\t\tpodSecCtx.RunAsNonRoot = &podSec\n\t\tpodSecCtx.SeccompProfile = &v1.SeccompProfile{\n\t\t\tType: v1.SeccompProfileTypeRuntimeDefault,\n\t\t}\n\n\t\t// creating a security context to be used by all containers in the pod\n\t\tsecCtx := v1.SecurityContext{}\n\t\tsecCtx.RunAsNonRoot = &podSec\n\t\tsecCtx.AllowPrivilegeEscalation = &[]bool{false}[0]\n\t\tsecCtx.Capabilities = &v1.Capabilities{\n\t\t\tDrop: []v1.Capability{\n\t\t\t\t\"ALL\",\n\t\t\t},\n\t\t}\n\n\t\tpodDef.Spec.SecurityContext = &podSecCtx\n\n\t\tpodDef.Spec.Containers[0].SecurityContext = &secCtx\n\t\tpodDef.Spec.InitContainers[0].SecurityContext = &secCtx\n\t}\n\n\tif test.Storage.Spec.MountPath.Path != \"\" {\n\t\taddStorageToPod(podDef, test.Storage.Spec.MountPath.Path, r.StorageImage)\n\t}\n\n\tpod, err := r.Client.CoreV1().Pods(r.Namespace).Create(ctx, podDef, metav1.CreateOptions{})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\terr = r.waitForTestToComplete(ctx, pod)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// gather test output if necessary\n\tif test.Storage.Spec.MountPath.Path != \"\" {\n\t\terr := gatherTestOutput(r, test.Labels[\"suite\"], test.Labels[\"test\"], pod.Name, test.Storage.Spec.MountPath.Path)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\treturn r.getTestStatus(ctx, pod), nil\n}\n\n// RunTest executes a single test\nfunc (r FakeTestRunner) RunTest(ctx context.Context, _ v1alpha3.TestConfiguration, _ bool) (result *v1alpha3.TestStatus, err error) {\n\tselect {\n\tcase <-time.After(r.Sleep):\n\t\treturn r.TestStatus, r.Error\n\tcase <-ctx.Done():\n\t\treturn nil, ctx.Err()\n\t}\n}\n\nfunc ConfigDocLink() string {\n\treturn \"https://sdk.operatorframework.io/docs/scorecard/\"\n}\n\n// waitForTestToComplete waits for a fixed amount of time while\n// checking for a test pod to complete\nfunc (r PodTestRunner) waitForTestToComplete(ctx context.Context, p *v1.Pod) (err error) {\n\n\tpodCheck := wait.ConditionWithContextFunc(func(pctx context.Context) (done bool, err error) {\n\t\tvar tmp *v1.Pod\n\t\ttmp, err = r.Client.CoreV1().Pods(p.Namespace).Get(pctx, p.Name, metav1.GetOptions{})\n\t\tif err != nil {\n\t\t\treturn true, fmt.Errorf(\"error getting pod %s %w\", p.Name, err)\n\t\t}\n\t\tfor _, s := range tmp.Status.ContainerStatuses {\n\t\t\tif s.Name == \"scorecard-test\" {\n\t\t\t\tif s.State.Terminated != nil {\n\t\t\t\t\treturn true, nil\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn false, nil\n\t})\n\n\terr = wait.PollUntilContextCancel(ctx, 1*time.Second, false, podCheck)\n\treturn err\n\n}\n\nfunc convertErrorToStatus(err error, log string) *v1alpha3.TestStatus {\n\tresult := v1alpha3.TestResult{}\n\tresult.State = v1alpha3.FailState\n\tresult.Errors = []string{err.Error()}\n\tresult.Log = log\n\treturn &v1alpha3.TestStatus{\n\t\tResults: []v1alpha3.TestResult{result},\n\t}\n}\n"
  },
  {
    "path": "internal/scorecard/scorecard_suite_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage scorecard_test\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nfunc TestScorecard(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"Scorecard Suite\")\n}\n"
  },
  {
    "path": "internal/scorecard/storage.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage scorecard\n\nimport (\n\t\"archive/tar\"\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\tv1 \"k8s.io/api/core/v1\"\n\t\"k8s.io/client-go/tools/remotecommand\"\n\t\"k8s.io/kubectl/pkg/scheme\"\n)\n\nconst (\n\tStorageSidecarContainer = \"scorecard-gather\"\n)\n\nfunc (r PodTestRunner) execInPod(podName, mountPath, containerName string) (io.Reader, io.Reader, error) {\n\tcmd := []string{\n\t\t\"tar\",\n\t\t\"cf\",\n\t\t\"-\",\n\t\tmountPath,\n\t}\n\n\tstdoutReader, outStream := io.Pipe()\n\tstderrReader, errStream := io.Pipe()\n\tconst tty = false\n\treq := r.Client.CoreV1().RESTClient().Post().\n\t\tResource(\"pods\").\n\t\tName(podName).\n\t\tNamespace(r.Namespace).SubResource(\"exec\").Param(\"container\", containerName)\n\treq.VersionedParams(\n\t\t&v1.PodExecOptions{\n\t\t\tCommand: cmd,\n\t\t\tStdin:   false,\n\t\t\tStdout:  true,\n\t\t\tStderr:  true,\n\t\t\tTTY:     tty,\n\t\t},\n\t\tscheme.ParameterCodec,\n\t)\n\n\texec, err := remotecommand.NewSPDYExecutor(r.RESTConfig, \"POST\", req.URL())\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tgo func() {\n\t\tdefer outStream.Close()\n\t\tdefer errStream.Close()\n\t\terr = exec.StreamWithContext(context.TODO(), remotecommand.StreamOptions{\n\t\t\tStdin:  nil,\n\t\t\tStdout: outStream,\n\t\t\tStderr: errStream,\n\t\t})\n\t\tif err != nil {\n\t\t\tlog.Error(err)\n\t\t}\n\t}()\n\treturn stdoutReader, stderrReader, err\n}\n\nfunc getStoragePrefix(file string) string {\n\treturn strings.TrimLeft(file, \"/\")\n}\n\nfunc untarAll(reader io.Reader, destDir, prefix string) error {\n\ttarReader := tar.NewReader(reader)\n\tfor {\n\t\theader, err := tarReader.Next()\n\t\tif err != nil {\n\t\t\tif err != io.EOF {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\n\t\tif !strings.HasPrefix(header.Name, prefix) {\n\t\t\treturn fmt.Errorf(\"tar contents corrupted\")\n\t\t}\n\n\t\tmode := header.FileInfo().Mode()\n\t\tdestFileName := filepath.Join(destDir, header.Name[len(prefix):])\n\n\t\tbaseName := filepath.Dir(destFileName)\n\t\tif err := os.MkdirAll(baseName, 0755); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif header.FileInfo().IsDir() {\n\t\t\tif err := os.MkdirAll(destFileName, 0755); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\tif mode&os.ModeSymlink != 0 {\n\t\t\tlinkname := header.Linkname\n\n\t\t\tif err := os.Symlink(linkname, destFileName); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t} else {\n\t\t\toutFile, err := os.Create(destFileName)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tdefer outFile.Close()\n\t\t\tif _, err := io.Copy(outFile, tarReader); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif err := outFile.Close(); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc addStorageToPod(podDef *v1.Pod, mountPath string, storageImage string) {\n\n\t// add the emptyDir volume for storage to the test Pod\n\tnewVolume := v1.Volume{}\n\tnewVolume.Name = \"scorecard-storage\"\n\tnewVolume.VolumeSource = v1.VolumeSource{}\n\n\tpodDef.Spec.Volumes = append(podDef.Spec.Volumes, newVolume)\n\n\t// add the storage sidecar container\n\tstorageContainer := v1.Container{\n\t\tName:            StorageSidecarContainer,\n\t\tImage:           storageImage,\n\t\tImagePullPolicy: v1.PullIfNotPresent,\n\t\tArgs: []string{\n\t\t\t\"/bin/sh\",\n\t\t\t\"-c\",\n\t\t\t//\"trap 'echo TERM;exit 0' TERM;tail -f /dev/null\",\n\t\t\t\"sleep 1000\",\n\t\t},\n\t\tVolumeMounts: []v1.VolumeMount{\n\t\t\t{\n\t\t\t\tMountPath: mountPath,\n\t\t\t\tName:      \"scorecard-storage\",\n\t\t\t\tReadOnly:  true,\n\t\t\t},\n\t\t},\n\t}\n\n\tpodDef.Spec.Containers = append(podDef.Spec.Containers, storageContainer)\n\n\t// add the storage emptyDir volume into the test container\n\n\tvMount := v1.VolumeMount{\n\t\tMountPath: mountPath,\n\t\tName:      \"scorecard-storage\",\n\t\tReadOnly:  false,\n\t}\n\tpodDef.Spec.Containers[0].VolumeMounts = append(podDef.Spec.Containers[0].VolumeMounts, vMount)\n\n\t// add mountPath to Env\n\tmountPathEnv := v1.EnvVar{\n\t\tName:  \"SCORECARD_STORAGE\",\n\t\tValue: mountPath,\n\t}\n\tpodDef.Spec.Containers[0].Env = append(podDef.Spec.Containers[0].Env, mountPathEnv)\n\n}\n\nfunc gatherTestOutput(r PodTestRunner, suiteName, testName, podName, mountPath string) error {\n\n\t//exec into sidecar container, run tar,  get reader\n\tcontainerName := StorageSidecarContainer\n\tstdoutReader, stderrReader, err := r.execInPod(podName, mountPath, containerName)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tsrcPath := mountPath\n\tprefix := getStoragePrefix(srcPath)\n\tprefix = path.Clean(prefix)\n\tdestPath := getDestPath(r.TestOutput, suiteName, testName)\n\terr = untarAll(stdoutReader, destPath, prefix)\n\tif err != nil {\n\t\treturn err\n\t}\n\tstderr, err := io.ReadAll(stderrReader)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(stderr) > 0 {\n\t\tdestFileName := filepath.Join(destPath, \"tar_stderr\")\n\t\terr = os.WriteFile(destFileName, stderr, 0644)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc getDestPath(baseDir, suiteName, testName string) (destPath string) {\n\tdestPath = baseDir + string(os.PathSeparator)\n\tif suiteName != \"\" {\n\t\tdestPath = destPath + suiteName + string(os.PathSeparator)\n\t}\n\tdestPath = destPath + testName\n\treturn destPath\n}\n"
  },
  {
    "path": "internal/scorecard/tar.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage scorecard\n\nimport (\n\t\"archive/tar\"\n\t\"compress/gzip\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\tlog \"github.com/sirupsen/logrus\"\n)\n\nfunc WriteToTar(tw *tar.Writer, r io.Reader, hdr *tar.Header) error {\n\tif err := tw.WriteHeader(hdr); err != nil {\n\t\treturn err\n\t}\n\t_, err := io.Copy(tw, r)\n\treturn err\n}\n\n// WritePathsToTar walks paths to create tar file tarName\nfunc WritePathsToTar(tw *tar.Writer, paths []string) (err error) {\n\t// walk each specified path and add encountered file to tar\n\tfor _, path := range paths {\n\t\tpath = filepath.Clean(path)\n\n\t\twalker := func(file string, finfo os.FileInfo, err error) error {\n\t\t\tif err != nil || file == path {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\t// fill in header info using func FileInfoHeader\n\t\t\thdr, err := tar.FileInfoHeader(finfo, finfo.Name())\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\trelFilePath := file\n\t\t\tif filepath.IsAbs(path) {\n\t\t\t\trelFilePath, err = filepath.Rel(path, file)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\t\t// ensure header has relative file path\n\t\t\thdr.Name = strings.TrimPrefix(relFilePath, path+string(filepath.Separator))\n\t\t\tif err := tw.WriteHeader(hdr); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\t// if path is a dir, dont continue\n\t\t\tif finfo.IsDir() {\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\t// add file to tar\n\t\t\tsrcFile, err := os.Open(file)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\t_, err = io.Copy(tw, srcFile)\n\t\t\tif err := srcFile.Close(); err != nil {\n\t\t\t\tlog.Error(err)\n\t\t\t}\n\t\t\treturn err\n\t\t}\n\n\t\t// build tar\n\t\terr = filepath.Walk(path, walker)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to add %s to tar: %w\", path, err)\n\t\t}\n\t}\n\treturn nil\n}\n\n// untar a file into a location\nfunc UntarFile(tarName, target string) (err error) {\n\ttarFile, err := os.Open(tarName)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer func() {\n\t\tif err := tarFile.Close(); err != nil {\n\t\t\tlog.Error(err)\n\t\t}\n\t}()\n\n\tabsPath, err := filepath.Abs(target)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tvar tr *tar.Reader\n\tif isFileGzipped(tarName) {\n\t\tgz, err := gzip.NewReader(tarFile)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tdefer func() {\n\t\t\tif err := gz.Close(); err != nil {\n\t\t\t\tlog.Error(err)\n\t\t\t}\n\t\t}()\n\t\ttr = tar.NewReader(gz)\n\t} else {\n\t\ttr = tar.NewReader(tarFile)\n\t}\n\n\t// untar each segment\n\tfor {\n\t\thdr, err := tr.Next()\n\t\tif err == io.EOF {\n\t\t\tbreak\n\t\t}\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// determine proper file path info\n\t\tfinfo := hdr.FileInfo()\n\t\tfileName := hdr.Name\n\t\tif filepath.IsAbs(fileName) {\n\t\t\tfileName, err = filepath.Rel(\"/\", fileName)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\n\t\t// nolint\n\t\tabsFileName := filepath.Join(absPath, fileName)\n\n\t\tif finfo.Mode().IsDir() {\n\t\t\tif err := os.MkdirAll(absFileName, 0755); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// create new file with original file mode\n\t\tfile, err := os.OpenFile(absFileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, finfo.Mode().Perm())\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tn, cpErr := io.Copy(file, tr)\n\t\tif closeErr := file.Close(); closeErr != nil { // close file immediately\n\t\t\treturn err\n\t\t}\n\t\tif cpErr != nil {\n\t\t\treturn cpErr\n\t\t}\n\t\tif n != finfo.Size() {\n\t\t\treturn fmt.Errorf(\"unexpected bytes written: wrote %d, want %d\", n, finfo.Size())\n\t\t}\n\t}\n\treturn nil\n\n}\n\n// isFileGzipped returns true if file is compressed with gzip.\nfunc isFileGzipped(file string) bool {\n\treturn strings.HasSuffix(file, \".gz\") || strings.HasSuffix(file, \".gzip\")\n}\n"
  },
  {
    "path": "internal/scorecard/testconfigmap.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage scorecard\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\tv1 \"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/util/rand\"\n)\n\n// CreateConfigMap creates a ConfigMap that will hold the bundle\n// contents to be mounted into the test Pods\nfunc (r PodTestRunner) CreateConfigMap(ctx context.Context, bundleData []byte) (configMapName string, err error) {\n\tcfg := getConfigMapDefinition(r.Namespace, bundleData)\n\tconfigMap, err := r.Client.CoreV1().ConfigMaps(r.Namespace).Create(ctx, cfg, metav1.CreateOptions{})\n\tif err != nil {\n\t\treturn configMapName, err\n\t}\n\treturn configMap.Name, nil\n}\n\n// getConfigMapDefinition returns a ConfigMap definition that\n// will hold the bundle contents and eventually will be mounted\n// into each test Pod\nfunc getConfigMapDefinition(namespace string, bundleData []byte) *v1.ConfigMap {\n\tconfigMapName := fmt.Sprintf(\"scorecard-test-%s\", rand.String(4))\n\tdata := make(map[string][]byte)\n\tdata[\"bundle.tar.gz\"] = bundleData\n\treturn &v1.ConfigMap{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      configMapName,\n\t\t\tNamespace: namespace,\n\t\t\tLabels: map[string]string{\n\t\t\t\t\"app\": \"scorecard-test\",\n\t\t\t},\n\t\t},\n\t\tBinaryData: data,\n\t}\n}\n\n// deleteConfigMap deletes the test bundle ConfigMap and is called\n// as part of the test run cleanup\nfunc (r PodTestRunner) deleteConfigMap(ctx context.Context, configMapName string) error {\n\terr := r.Client.CoreV1().ConfigMaps(r.Namespace).Delete(ctx, configMapName, metav1.DeleteOptions{})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error deleting configMap %s %w\", configMapName, err)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "internal/scorecard/testdata/bundle/manifests/cache.example.com_memcacheds_crd.yaml",
    "content": "apiVersion: apiextensions.k8s.io/v1\nkind: CustomResourceDefinition\nmetadata:\n  name: memcacheds.cache.example.com\nspec:\n  group: cache.example.com\n  names:\n    kind: Memcached\n    listKind: MemcachedList\n    plural: memcacheds\n    singular: memcached\n  scope: Namespaced\n  subresources:\n    status: {}\n  validation:\n    openAPIV3Schema:\n      description: Memcached is the Schema for the memcacheds API\n      properties:\n        apiVersion:\n          description: 'APIVersion defines the versioned schema of this representation\n            of an object. Servers should convert recognized schemas to the latest\n            internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'\n          type: string\n        kind:\n          description: 'Kind is a string value representing the REST resource this\n            object represents. Servers may infer this from the endpoint the client\n            submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'\n          type: string\n        metadata:\n          type: object\n        spec:\n          description: MemcachedSpec defines the desired state of Memcached\n          properties:\n            size:\n              description: 'INSERT ADDITIONAL SPEC FIELDS - desired state of cluster\n                Important: Run \"operator-sdk generate k8s\" to regenerate code after\n                modifying this file Add custom validation using kubebuilder tags:\n                https://book-v1.book.kubebuilder.io/beyond_basics/generating_crd.html\n                Size is the size of the memcached deployment'\n              format: int32\n              type: integer\n          required:\n          - size\n          type: object\n        status:\n          description: MemcachedStatus defines the observed state of Memcached\n          properties:\n            nodes:\n              description: 'INSERT ADDITIONAL STATUS FIELD - define observed state\n                of cluster Important: Run \"operator-sdk generate k8s\" to regenerate\n                code after modifying this file Add custom validation using kubebuilder\n                tags: https://book-v1.book.kubebuilder.io/beyond_basics/generating_crd.html\n                Nodes are the names of the memcached pods'\n              items:\n                type: string\n              type: array\n          required:\n          - nodes\n          type: object\n      type: object\n  version: v1alpha1\n  versions:\n  - name: v1alpha1\n    served: true\n    storage: true\n"
  },
  {
    "path": "internal/scorecard/testdata/bundle/manifests/memcached-operator.clusterserviceversion.yaml",
    "content": "apiVersion: operators.coreos.com/v1alpha1\nkind: ClusterServiceVersion\nmetadata:\n  annotations:\n    alm-examples: |-\n      [\n        {\n          \"apiVersion\": \"cache.example.com/v1alpha1\",\n          \"kind\": \"Memcached\",\n          \"metadata\": {\n            \"name\": \"example-memcached\"\n          },\n          \"spec\": {\n            \"size\": 3\n          },\n          \"status\": {\n            \"nodes\": null\n          }\n        }\n      ]\n    capabilities: Basic Install\n  name: memcached-operator.v0.0.1\n  namespace: placeholder\nspec:\n  apiservicedefinitions: {}\n  customresourcedefinitions:\n    owned:\n    - description: Memcached is the Schema for the memcacheds API\n      kind: Memcached\n      name: memcacheds.cache.example.com\n      version: v1alpha1\n      specDescriptors:\n      - description: The desired number of memcached instances to deploy.\n        displayName: Size\n        path: size\n        x-descriptors:\n        - 'urn:alm:descriptor:com.tectonic.ui:podCount'\n      resources:\n      - kind: Pod\n        version: v1\n      statusDescriptors:\n      - description: Nodes are the names of the memcached pods\n        displayName: Nodes\n        path: nodes\n        x-descriptors:\n        - 'urn:alm:descriptor:com.tectonic.ui:nodes'\n  description: Placeholder description\n  displayName: Memcached Operator\n  icon:\n  - base64data: \"\"\n    mediatype: \"\"\n  install:\n    spec:\n      deployments:\n      - name: memcached-operator\n        spec:\n          replicas: 1\n          selector:\n            matchLabels:\n              name: memcached-operator\n          strategy: {}\n          template:\n            metadata:\n              labels:\n                name: memcached-operator\n            spec:\n              containers:\n              - command:\n                - memcached-operator\n                env:\n                - name: WATCH_NAMESPACE\n                  valueFrom:\n                    fieldRef:\n                      fieldPath: metadata.annotations['olm.targetNamespaces']\n                - name: POD_NAME\n                  valueFrom:\n                    fieldRef:\n                      fieldPath: metadata.name\n                - name: OPERATOR_NAME\n                  value: memcached-operator\n                image: REPLACE_IMAGE\n                imagePullPolicy: Always\n                name: memcached-operator\n                resources: {}\n              serviceAccountName: memcached-operator\n      permissions:\n      - rules:\n        - apiGroups:\n          - \"\"\n          resources:\n          - pods\n          - services\n          - services/finalizers\n          - endpoints\n          - persistentvolumeclaims\n          - events\n          - configmaps\n          - secrets\n          verbs:\n          - create\n          - delete\n          - get\n          - list\n          - patch\n          - update\n          - watch\n        - apiGroups:\n          - apps\n          resources:\n          - deployments\n          - daemonsets\n          - replicasets\n          - statefulsets\n          verbs:\n          - create\n          - delete\n          - get\n          - list\n          - patch\n          - update\n          - watch\n        - apiGroups:\n          - monitoring.coreos.com\n          resources:\n          - servicemonitors\n          verbs:\n          - get\n          - create\n        - apiGroups:\n          - apps\n          resourceNames:\n          - memcached-operator\n          resources:\n          - deployments/finalizers\n          verbs:\n          - update\n        - apiGroups:\n          - \"\"\n          resources:\n          - pods\n          verbs:\n          - get\n        - apiGroups:\n          - apps\n          resources:\n          - replicasets\n          - deployments\n          verbs:\n          - get\n        - apiGroups:\n          - cache.example.com\n          resources:\n          - '*'\n          verbs:\n          - create\n          - delete\n          - get\n          - list\n          - patch\n          - update\n          - watch\n        serviceAccountName: memcached-operator\n    strategy: deployment\n  installModes:\n  - supported: false\n    type: OwnNamespace\n  - supported: false\n    type: SingleNamespace\n  - supported: false\n    type: MultiNamespace\n  - supported: true\n    type: AllNamespaces\n  keywords:\n  - \"\"\n  maintainers:\n  - {}\n  maturity: alpha\n  provider: {}\n  version: 0.0.1\n"
  },
  {
    "path": "internal/scorecard/testdata/bundle/metadata/annotations.yaml",
    "content": "annotations:\n  operators.operatorframework.io.bundle.mediatype.v1: registry+v1\n  operators.operatorframework.io.bundle.manifests.v1: manifests/\n  operators.operatorframework.io.bundle.metadata.v1: metadata/\n  operators.operatorframework.io.bundle.package.v1: memcached-operator\n  operators.operatorframework.io.bundle.channels.v1: alpha,stable\n  operators.operatorframework.io.bundle.channel.default.v1: stable\n  operators.operatorframework.io.test.mediatype.v1: scorecard+v1\n  operators.operatorframework.io.test.config.v1: tests/scorecard/\n"
  },
  {
    "path": "internal/scorecard/testdata/bundle/tests/scorecard/config.yaml",
    "content": "kind: Configuration\napiversion: scorecard.operatorframework.io/v1alpha3\nmetadata:\n  name: config\nstages:\n- parallel: true\n  tests:\n  - image: quay.io/operator-framework/scorecard-test:dev\n    entrypoint:\n    - scorecard-test\n    - basic-check-spec\n    labels:\n      suite: basic\n      test: basic-check-spec-test\n  - image: quay.io/operator-framework/scorecard-test:dev\n    entrypoint:\n    - scorecard-test\n    - olm-bundle-validation\n    labels:\n      suite: olm\n      test: olm-bundle-validation-test\n  - image: quay.io/operator-framework/scorecard-test:dev\n    entrypoint:\n    - scorecard-test\n    - olm-crds-have-validation\n    labels:\n      suite: olm\n      test: olm-crds-have-validation-test\n  - image: quay.io/operator-framework/scorecard-test:dev\n    entrypoint:\n    - scorecard-test\n    - olm-crds-have-resources\n    labels:\n      suite: olm\n      test: olm-crds-have-resources-test\n  - image: quay.io/operator-framework/scorecard-test:dev\n    entrypoint:\n    - scorecard-test\n    - olm-spec-descriptors\n    labels:\n      suite: olm\n      test: olm-spec-descriptors-test\n  - image: quay.io/operator-framework/scorecard-test:dev\n    entrypoint:\n    - scorecard-test\n    - olm-status-descriptors\n    labels:\n      suite: olm\n      test: olm-status-descriptors-test\n"
  },
  {
    "path": "internal/scorecard/testdata/bundle/tests/scorecard/kuttl/kuttl-test.yaml",
    "content": "apiVersion: kudo.dev/v1beta1\nkind: TestSuite\nparallel: 4\ntimeout: 120\nstartControlPlane: false\nsuppressLog: events\n"
  },
  {
    "path": "internal/scorecard/testdata/bundle/tests/scorecard/kuttl/list-pods/00-assert.yaml",
    "content": "apiVersion: v1\nkind: Pod\nmetadata:\n  labels:\n    app: nginx\nspec:\n  containers:\n  - name: nginx\n    image: nginx:1.7.9\n"
  },
  {
    "path": "internal/scorecard/testdata/bundle/tests/scorecard/kuttl/list-pods/00-pod.yaml",
    "content": "apiVersion: v1\nkind: Pod\nmetadata:\n  name: pod-1\n  labels:\n    app: nginx\nspec:\n  containers:\n  - name: nginx\n    image: nginx:1.7.9\n"
  },
  {
    "path": "internal/scorecard/testdata/generate-bundle-tarball.sh",
    "content": "#!/usr/bin/env bash\n\nset -eu\n\nDIR=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" >/dev/null 2>&1 && pwd )\"\n\npushd \"${DIR}/bundle\"\ntar zcvf \"${DIR}/bundle.tar.gz\" *\npopd\n"
  },
  {
    "path": "internal/scorecard/testdata/pod.yaml",
    "content": "apiVersion: v1\nkind: Pod\nmetadata:\n  name: scorecard-test\n  namespace: default\nspec:\n  containers:\n  - env:\n    - name: NAMESPACE\n      valueFrom:\n        fieldRef:\n          apiVersion: v1\n          fieldPath: metadata.namespace\n    image: quay.io/operator-framework/scorecard-test:dev \n    imagePullPolicy: Always\n    name: scorecard-test\n    command: [\"/usr/local/bin/scorecard-test\"]\n    args: [\"basic-check-spec\"]\n    resources: {}\n    volumeMounts:\n    - mountPath: /scorecard\n      name: scorecard-bundle\n      readOnly: true\n  dnsPolicy: ClusterFirst\n  restartPolicy: Never\n  securityContext: {}\n  serviceAccount: default\n  serviceAccountName: default\n  volumes:\n  - name: scorecard-bundle\n    configMap:\n      name: scorecard-bundle\n"
  },
  {
    "path": "internal/scorecard/testpod.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage scorecard\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\n\t\"github.com/operator-framework/api/pkg/apis/scorecard/v1alpha3\"\n\tv1 \"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/util/rand\"\n\t\"k8s.io/client-go/kubernetes\"\n)\n\nconst (\n\t// PodBundleRoot is the directory containing all bundle data within a test pod.\n\tPodBundleRoot = \"/bundle\"\n)\n\n// getPodDefinition fills out a Pod definition based on\n// information from the test\nfunc getPodDefinition(configMapName string, test v1alpha3.TestConfiguration, r PodTestRunner) *v1.Pod {\n\n\treturn &v1.Pod{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      fmt.Sprintf(\"scorecard-test-%s\", rand.String(4)),\n\t\t\tNamespace: r.Namespace,\n\t\t\tLabels: map[string]string{\n\t\t\t\t\"app\":     \"scorecard-test\",\n\t\t\t\t\"testrun\": configMapName,\n\t\t\t},\n\t\t},\n\t\tSpec: v1.PodSpec{\n\t\t\tServiceAccountName: r.ServiceAccount,\n\t\t\tRestartPolicy:      v1.RestartPolicyNever,\n\t\t\tContainers: []v1.Container{\n\t\t\t\t{\n\t\t\t\t\tName:            \"scorecard-test\",\n\t\t\t\t\tImage:           test.Image,\n\t\t\t\t\tImagePullPolicy: v1.PullIfNotPresent,\n\t\t\t\t\tCommand:         test.Entrypoint,\n\t\t\t\t\tVolumeMounts: []v1.VolumeMount{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tMountPath: PodBundleRoot,\n\t\t\t\t\t\t\tName:      \"scorecard-untar\",\n\t\t\t\t\t\t\tReadOnly:  true,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tEnv: []v1.EnvVar{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tName: \"SCORECARD_NAMESPACE\",\n\t\t\t\t\t\t\tValueFrom: &v1.EnvVarSource{\n\t\t\t\t\t\t\t\tFieldRef: &v1.ObjectFieldSelector{\n\t\t\t\t\t\t\t\t\tFieldPath: \"metadata.namespace\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tInitContainers: []v1.Container{\n\t\t\t\t{\n\t\t\t\t\tName:            \"scorecard-untar\",\n\t\t\t\t\tImage:           r.UntarImage,\n\t\t\t\t\tImagePullPolicy: v1.PullIfNotPresent,\n\t\t\t\t\tArgs: []string{\n\t\t\t\t\t\t\"tar\",\n\t\t\t\t\t\t\"xvzf\",\n\t\t\t\t\t\t\"/scorecard/bundle.tar.gz\",\n\t\t\t\t\t\t\"-C\",\n\t\t\t\t\t\t\"/scorecard-bundle\",\n\t\t\t\t\t},\n\t\t\t\t\tVolumeMounts: []v1.VolumeMount{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tMountPath: \"/scorecard\",\n\t\t\t\t\t\t\tName:      \"scorecard-bundle\",\n\t\t\t\t\t\t\tReadOnly:  true,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tMountPath: \"/scorecard-bundle\",\n\t\t\t\t\t\t\tName:      \"scorecard-untar\",\n\t\t\t\t\t\t\tReadOnly:  false,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tVolumes: []v1.Volume{\n\t\t\t\t{\n\t\t\t\t\tName: \"scorecard-bundle\",\n\t\t\t\t\tVolumeSource: v1.VolumeSource{\n\t\t\t\t\t\tConfigMap: &v1.ConfigMapVolumeSource{\n\t\t\t\t\t\t\tLocalObjectReference: v1.LocalObjectReference{\n\t\t\t\t\t\t\t\tName: configMapName,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tName: \"scorecard-untar\",\n\t\t\t\t\tVolumeSource: v1.VolumeSource{\n\t\t\t\t\t\tEmptyDir: &v1.EmptyDirVolumeSource{},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n}\n\n// getPodLog fetches the test results which are found in the pod log\nfunc getPodLog(ctx context.Context, client kubernetes.Interface, pod *v1.Pod) ([]byte, error) {\n\tpodLogOptions := v1.PodLogOptions{\n\t\tContainer: \"scorecard-test\",\n\t}\n\n\treq := client.CoreV1().Pods(pod.Namespace).GetLogs(pod.Name, &podLogOptions)\n\tpodLogs, err := req.Stream(ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer podLogs.Close()\n\n\tbuf := new(bytes.Buffer)\n\t_, err = io.Copy(buf, podLogs)\n\treturn buf.Bytes(), err\n}\n\n// deletePods deletes a collection of pods that match a predefined selector value\nfunc (r PodTestRunner) deletePods(ctx context.Context, configMapName string) error {\n\tdo := metav1.DeleteOptions{}\n\tselector := fmt.Sprintf(\"testrun=%s\", configMapName)\n\tlo := metav1.ListOptions{LabelSelector: selector}\n\terr := r.Client.CoreV1().Pods(r.Namespace).DeleteCollection(ctx, do, lo)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error deleting pods (label selector %q): %w\", selector, err)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "internal/scorecard/tests/basic.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage tests\n\nimport (\n\t\"fmt\"\n\n\tscapiv1alpha3 \"github.com/operator-framework/api/pkg/apis/scorecard/v1alpha3\"\n\tapimanifests \"github.com/operator-framework/api/pkg/manifests\"\n\t\"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured\"\n)\n\nconst (\n\tBasicCheckSpecTest = \"basic-check-spec\"\n)\n\n// CheckSpecTest verifies that CRs have a spec block\nfunc CheckSpecTest(bundle *apimanifests.Bundle) scapiv1alpha3.TestStatus {\n\tr := scapiv1alpha3.TestResult{\n\t\tName:        BasicCheckSpecTest,\n\t\tState:       scapiv1alpha3.PassState,\n\t\tErrors:      make([]string, 0),\n\t\tSuggestions: make([]string, 0),\n\t}\n\n\tcrSet, err := GetCRs(bundle)\n\tif err != nil {\n\t\tr.Errors = append(r.Errors, fmt.Sprintf(\"error getting custom resources: %s\", err))\n\t\tr.State = scapiv1alpha3.FailState\n\t}\n\n\treturn scapiv1alpha3.TestStatus{\n\t\tResults: []scapiv1alpha3.TestResult{checkSpec(crSet, r)},\n\t}\n}\n\nfunc checkSpec(crSet []unstructured.Unstructured,\n\tres scapiv1alpha3.TestResult) scapiv1alpha3.TestResult {\n\tfor _, cr := range crSet {\n\t\tif cr.Object[\"spec\"] == nil {\n\t\t\tres.State = scapiv1alpha3.PassState\n\t\t\tres.Suggestions = append(res.Suggestions, fmt.Sprintf(\"spec missing from [%+v]\", cr.GetName()))\n\t\t\treturn res\n\t\t}\n\t}\n\treturn res\n}\n"
  },
  {
    "path": "internal/scorecard/tests/bundle_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage tests\n\nimport (\n\t\"path/filepath\"\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\tscapiv1alpha3 \"github.com/operator-framework/api/pkg/apis/scorecard/v1alpha3\"\n\tapimanifests \"github.com/operator-framework/api/pkg/manifests\"\n\toperatorsv1alpha1 \"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\tapiextv1 \"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1\"\n\t\"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured\"\n\t\"k8s.io/apimachinery/pkg/runtime/schema\"\n\n\tregistryutil \"github.com/operator-framework/operator-sdk/internal/registry\"\n)\n\nvar _ = Describe(\"Basic and OLM tests\", func() {\n\tvar (\n\t\ttestBundle = filepath.Join(\"..\", \"testdata\", \"bundle\")\n\t\tstatus     scapiv1alpha3.TestStatus\n\t\tresult     scapiv1alpha3.TestResult\n\t)\n\n\tBeforeEach(func() {\n\t\tresult = scapiv1alpha3.TestResult{\n\t\t\tName:   \"Scorecard result struct\",\n\t\t\tState:  scapiv1alpha3.PassState,\n\t\t\tErrors: make([]string, 0),\n\t\t}\n\t\tstatus = scapiv1alpha3.TestStatus{\n\t\t\tResults: []scapiv1alpha3.TestResult{result}}\n\t})\n\n\tDescribe(\"Test Bundle CRs\", func() {\n\t\tvar (\n\t\t\tbundle  *apimanifests.Bundle\n\t\t\terr     error\n\t\t\tcrCount int\n\t\t\tcrList  []unstructured.Unstructured\n\t\t)\n\n\t\tIt(\"Check Bundle CRs\", func() {\n\t\t\tcrCount = 1\n\n\t\t\tbundle, err = apimanifests.GetBundleFromDir(testBundle)\n\n\t\t\tExpect(err).ToNot(HaveOccurred())\n\n\t\t\tcrList, err = GetCRs(bundle)\n\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t\tExpect(crCount).To(Equal(len(crList)))\n\t\t})\n\t})\n\n\tDescribe(\"Testing Basic and OLM tests\", func() {\n\t\tvar (\n\t\t\tbundle *apimanifests.Bundle\n\t\t\terr    error\n\t\t)\n\n\t\tBeforeEach(func() {\n\t\t\tbundle, err = apimanifests.GetBundleFromDir(testBundle)\n\t\t\tExpect(err).ToNot(HaveOccurred())\n\t\t})\n\n\t\tContext(\"CheckSpecTest\", func() {\n\t\t\tIt(\"returns a pass state when Spec field exists\", func() {\n\t\t\t\tstatus = CheckSpecTest(bundle)\n\t\t\t\tExpect(status.Results[0].State).To(Equal(scapiv1alpha3.PassState))\n\t\t\t})\n\t\t})\n\n\t\tContext(\"CRDsHaveValidationTest\", func() {\n\t\t\tIt(\"returns a pass state when CRDs have validations\", func() {\n\t\t\t\tstatus = CRDsHaveValidationTest(bundle)\n\t\t\t\tExpect(status.Results[0].State).To(Equal(scapiv1alpha3.PassState))\n\t\t\t})\n\t\t})\n\n\t\tContext(\"CRDsHaveResourcesTest\", func() {\n\t\t\tIt(\"returns a pass state when CRDs have resources\", func() {\n\t\t\t\tstatus = CRDsHaveResourcesTest(bundle)\n\t\t\t\tExpect(status.Results[0].State).To(Equal(scapiv1alpha3.PassState))\n\t\t\t})\n\t\t})\n\n\t\tContext(\"SpecDescriptorsTest\", func() {\n\t\t\tIt(\"returns a pass state then spec descriptors are present\", func() {\n\t\t\t\tstatus = SpecDescriptorsTest(bundle)\n\t\t\t\tExpect(status.Results[0].State).To(Equal(scapiv1alpha3.PassState))\n\t\t\t})\n\t\t})\n\n\t\tContext(\"StatusDescriptorsTest\", func() {\n\t\t\tIt(\"returns a pass state then status descriptors are present\", func() {\n\t\t\t\tstatus = StatusDescriptorsTest(bundle)\n\t\t\t\tExpect(status.Results[0].State).To(Equal(scapiv1alpha3.PassState))\n\t\t\t})\n\t\t})\n\t})\n\n\tDescribe(\"Testing OLM Bundle\", func() {\n\t\tIt(\"should pass when test bundle is at the desired location\", func() {\n\t\t\tmetadata, _, err := registryutil.FindBundleMetadata(testBundle)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\tstatus = BundleValidationTest(testBundle, metadata)\n\t\t\tExpect(status.Results[0].State).To(Equal(scapiv1alpha3.PassState))\n\t\t})\n\t})\n\n\tDescribe(\"OLM Tests\", func() {\n\n\t\tDescribe(\"Test Status and Spec Descriptors\", func() {\n\t\t\tcsv := operatorsv1alpha1.ClusterServiceVersion{\n\t\t\t\tSpec: operatorsv1alpha1.ClusterServiceVersionSpec{\n\t\t\t\t\tCustomResourceDefinitions: operatorsv1alpha1.CustomResourceDefinitions{\n\t\t\t\t\t\tOwned: []operatorsv1alpha1.CRDDescription{\n\t\t\t\t\t\t\toperatorsv1alpha1.CRDDescription{\n\t\t\t\t\t\t\t\tName:    \"Test\",\n\t\t\t\t\t\t\t\tVersion: \"v2\",\n\t\t\t\t\t\t\t\tKind:    \"TestKind\",\n\t\t\t\t\t\t\t\tStatusDescriptors: []operatorsv1alpha1.StatusDescriptor{\n\t\t\t\t\t\t\t\t\toperatorsv1alpha1.StatusDescriptor{\n\t\t\t\t\t\t\t\t\t\tPath: \"newStatus\",\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tSpecDescriptors: []operatorsv1alpha1.SpecDescriptor{\n\t\t\t\t\t\t\t\t\toperatorsv1alpha1.SpecDescriptor{\n\t\t\t\t\t\t\t\t\t\tPath: \"newSpec\",\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\toperatorsv1alpha1.CRDDescription{\n\t\t\t\t\t\t\t\tName:    \"Test\",\n\t\t\t\t\t\t\t\tVersion: \"v1\",\n\t\t\t\t\t\t\t\tKind:    \"TestKind\",\n\t\t\t\t\t\t\t\tStatusDescriptors: []operatorsv1alpha1.StatusDescriptor{\n\t\t\t\t\t\t\t\t\toperatorsv1alpha1.StatusDescriptor{\n\t\t\t\t\t\t\t\t\t\tPath: \"status\",\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tSpecDescriptors: []operatorsv1alpha1.SpecDescriptor{\n\t\t\t\t\t\t\t\t\toperatorsv1alpha1.SpecDescriptor{\n\t\t\t\t\t\t\t\t\t\tPath: \"spec\",\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\n\t\t\tIt(\"should pass when CR Object Descriptor is nil\", func() {\n\t\t\t\tcr := unstructured.Unstructured{\n\t\t\t\t\tObject: nil,\n\t\t\t\t}\n\t\t\t\tcr.SetGroupVersionKind(schema.GroupVersionKind{\n\t\t\t\t\tKind:    \"TestKind\",\n\t\t\t\t\tGroup:   \"test.example.com\",\n\t\t\t\t\tVersion: \"v1\",\n\t\t\t\t})\n\n\t\t\t\tresult = checkOwnedCSVStatusDescriptor(cr, &csv, result)\n\t\t\t\tExpect(result.State).To(Equal(scapiv1alpha3.PassState))\n\t\t\t})\n\n\t\t\tIt(\"should pass when status descriptor field is present in CR\", func() {\n\t\t\t\tcr := unstructured.Unstructured{\n\t\t\t\t\tObject: map[string]any{\n\t\t\t\t\t\t\"status\": map[string]any{\n\t\t\t\t\t\t\t\"status\": \"val\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"spec\": map[string]any{\n\t\t\t\t\t\t\t\"spec\": \"val\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t\tcr.SetGroupVersionKind(schema.GroupVersionKind{\n\t\t\t\t\tKind:    \"TestKind\",\n\t\t\t\t\tGroup:   \"test.example.com\",\n\t\t\t\t\tVersion: \"v1\",\n\t\t\t\t})\n\n\t\t\t\tresult = checkOwnedCSVStatusDescriptor(cr, &csv, result)\n\t\t\t\tExpect(result.State).To(Equal(scapiv1alpha3.PassState))\n\t\t\t})\n\n\t\t\tIt(\"should pass when required spec descriptor field is present in CR\", func() {\n\t\t\t\tcr := unstructured.Unstructured{\n\t\t\t\t\tObject: map[string]any{\n\t\t\t\t\t\t\"status\": map[string]any{\n\t\t\t\t\t\t\t\"status\": \"val\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"spec\": map[string]any{\n\t\t\t\t\t\t\t\"spec\": \"val\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t\tcr.SetGroupVersionKind(schema.GroupVersionKind{\n\t\t\t\t\tKind:    \"TestKind\",\n\t\t\t\t\tGroup:   \"test.example.com\",\n\t\t\t\t\tVersion: \"v1\",\n\t\t\t\t})\n\n\t\t\t\tresult = checkOwnedCSVSpecDescriptors(cr, &csv, result)\n\t\t\t\tExpect(result.State).To(Equal(scapiv1alpha3.PassState))\n\t\t\t})\n\n\t\t\tIt(\"should pass with warning when no status descriptor field is present in CR\", func() {\n\t\t\t\tcr := unstructured.Unstructured{\n\t\t\t\t\tObject: map[string]any{\n\t\t\t\t\t\t\"spec\": map[string]any{\n\t\t\t\t\t\t\t\"spec\": \"val\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t\tcr.SetGroupVersionKind(schema.GroupVersionKind{\n\t\t\t\t\tKind:    \"TestKind\",\n\t\t\t\t\tGroup:   \"test.example.com\",\n\t\t\t\t\tVersion: \"v1\",\n\t\t\t\t})\n\n\t\t\t\tresult = checkOwnedCSVStatusDescriptor(cr, &csv, result)\n\t\t\t\tExpect(result.Suggestions).To(HaveLen(1))\n\t\t\t\tExpect(result.State).To(Equal(scapiv1alpha3.PassState))\n\t\t\t})\n\n\t\t\tIt(\"should fail CRD with given GVK cannot be found\", func() {\n\t\t\t\tcr := unstructured.Unstructured{\n\t\t\t\t\tObject: map[string]any{\n\t\t\t\t\t\t\"status\": map[string]any{\n\t\t\t\t\t\t\t\"status\": \"val\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"spec\": map[string]any{\n\t\t\t\t\t\t\t\"spec\": \"val\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t\tcr.SetGroupVersionKind(schema.GroupVersionKind{\n\t\t\t\t\tKind:    \"TestKindNotPresent\",\n\t\t\t\t\tGroup:   \"testnotpresent.example.com\",\n\t\t\t\t\tVersion: \"unknown\",\n\t\t\t\t})\n\n\t\t\t\tresult = checkOwnedCSVStatusDescriptor(cr, &csv, result)\n\t\t\t\tExpect(result.State).To(Equal(scapiv1alpha3.FailState))\n\t\t\t})\n\n\t\t\tIt(\"should fail when CR does not have GVK set\", func() {\n\t\t\t\tcr := unstructured.Unstructured{\n\t\t\t\t\tObject: map[string]any{\n\t\t\t\t\t\t\"status\": map[string]any{\n\t\t\t\t\t\t\t\"status\": \"val\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t}\n\n\t\t\t\tresult = checkOwnedCSVStatusDescriptor(cr, &csv, result)\n\t\t\t\tExpect(result.State).To(Equal(scapiv1alpha3.FailState))\n\t\t\t})\n\n\t\t\tIt(\"should fail when required spec descriptor field is not present in CR\", func() {\n\t\t\t\tcr := unstructured.Unstructured{\n\t\t\t\t\tObject: map[string]any{\n\t\t\t\t\t\t\"spec\": map[string]any{\n\t\t\t\t\t\t\t\"node\": \"val\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t\tcr.SetGroupVersionKind(schema.GroupVersionKind{\n\t\t\t\t\tKind:    \"TestKind\",\n\t\t\t\t\tGroup:   \"test.example.com\",\n\t\t\t\t\tVersion: \"v1\",\n\t\t\t\t})\n\n\t\t\t\tresult = checkOwnedCSVSpecDescriptors(cr, &csv, result)\n\t\t\t\tExpect(result.State).To(Equal(scapiv1alpha3.FailState))\n\t\t\t})\n\n\t\t\tIt(\"should pass when CRs have spec field specified\", func() {\n\t\t\t\tcr := []unstructured.Unstructured{\n\t\t\t\t\t{\n\t\t\t\t\t\tObject: map[string]any{\n\t\t\t\t\t\t\t\"spec\": map[string]any{\n\t\t\t\t\t\t\t\t\"spec\": \"val\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t\tresult = checkSpec(cr, result)\n\t\t\t\tExpect(result.State).To(Equal(scapiv1alpha3.PassState))\n\t\t\t})\n\n\t\t\tIt(\"should pass with warning when CRs do not have spec field specified\", func() {\n\t\t\t\tcr := []unstructured.Unstructured{\n\t\t\t\t\t{\n\t\t\t\t\t\tObject: map[string]any{},\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t\tresult = checkSpec(cr, result)\n\t\t\t\tExpect(result.State).To(Equal(scapiv1alpha3.PassState))\n\t\t\t\tExpect(result.Suggestions).To(HaveLen(1))\n\t\t\t})\n\n\t\t})\n\n\t})\n\n\tDescribe(\"CRDs have validation test\", func() {\n\t\tvar (\n\t\t\tcr  unstructured.Unstructured\n\t\t\tcrd []*apiextv1.CustomResourceDefinition\n\t\t)\n\n\t\tcrd = []*apiextv1.CustomResourceDefinition{\n\t\t\t&apiextv1.CustomResourceDefinition{\n\t\t\t\tSpec: apiextv1.CustomResourceDefinitionSpec{\n\t\t\t\t\tVersions: []apiextv1.CustomResourceDefinitionVersion{\n\t\t\t\t\t\tapiextv1.CustomResourceDefinitionVersion{\n\t\t\t\t\t\t\tName: \"v1\",\n\t\t\t\t\t\t\tSchema: &apiextv1.CustomResourceValidation{\n\t\t\t\t\t\t\t\tOpenAPIV3Schema: &apiextv1.JSONSchemaProps{\n\t\t\t\t\t\t\t\t\tID:          \"Test\",\n\t\t\t\t\t\t\t\t\tSchema:      \"URL\",\n\t\t\t\t\t\t\t\t\tDescription: \"Schema for test\",\n\t\t\t\t\t\t\t\t\tProperties: map[string]apiextv1.JSONSchemaProps{\n\t\t\t\t\t\t\t\t\t\t\"spec\": apiextv1.JSONSchemaProps{\n\t\t\t\t\t\t\t\t\t\t\tProperties: map[string]apiextv1.JSONSchemaProps{\n\t\t\t\t\t\t\t\t\t\t\t\t\"node\": apiextv1.JSONSchemaProps{\n\t\t\t\t\t\t\t\t\t\t\t\t\tID: \"node\",\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tNames: apiextv1.CustomResourceDefinitionNames{\n\t\t\t\t\t\tKind: \"TestKind\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\n\t\tIt(\"should pass when CR has Spec field\", func() {\n\t\t\tcr = unstructured.Unstructured{\n\t\t\t\tObject: map[string]any{\n\t\t\t\t\t\"spec\": map[string]any{\n\t\t\t\t\t\t\"node\": \"val\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t\tcr.SetGroupVersionKind(schema.GroupVersionKind{\n\t\t\t\tKind:    \"TestKind\",\n\t\t\t\tGroup:   \"test.example.com\",\n\t\t\t\tVersion: \"v1\",\n\t\t\t})\n\n\t\t\tresult = isCRFromCRDApi(cr, crd, result)\n\t\t\tExpect(result.State).To(Equal(scapiv1alpha3.PassState))\n\n\t\t})\n\n\t\tIt(\"should fail when cr does not have required fields in Spec\", func() {\n\t\t\tcr = unstructured.Unstructured{\n\t\t\t\tObject: map[string]any{\n\t\t\t\t\t\"spec\": map[string]any{\n\t\t\t\t\t\t\"items\": \"val\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t\tcr.SetGroupVersionKind(schema.GroupVersionKind{\n\t\t\t\tKind:    \"TestKind\",\n\t\t\t\tGroup:   \"test.example.com\",\n\t\t\t\tVersion: \"v1\",\n\t\t\t})\n\n\t\t\tresult = isCRFromCRDApi(cr, crd, result)\n\t\t\tExpect(result.State).To(Equal(scapiv1alpha3.FailState))\n\n\t\t})\n\n\t\tIt(\"should skip and pass when version/kind does not match for CR with CRD\", func() {\n\t\t\tcr = unstructured.Unstructured{\n\t\t\t\tObject: map[string]any{\n\t\t\t\t\t\"spec\": map[string]any{\n\t\t\t\t\t\t\"node\": \"val\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t\tcr.SetGroupVersionKind(schema.GroupVersionKind{\n\t\t\t\tKind:    \"MemcachedKind\",\n\t\t\t\tGroup:   \"Cache\",\n\t\t\t\tVersion: \"v2\",\n\t\t\t})\n\n\t\t\tresult = isCRFromCRDApi(cr, crd, result)\n\t\t\tExpect(result.State).To(Equal(scapiv1alpha3.PassState))\n\n\t\t})\n\n\t})\n\n\tDescribe(\"Check CRDs for resources\", func() {\n\t\tvar (\n\t\t\tcrd operatorsv1alpha1.CustomResourceDefinitions\n\t\t)\n\n\t\tIt(\"Should pass when CSV has Owned CRD's with resources\", func() {\n\t\t\tcrd = operatorsv1alpha1.CustomResourceDefinitions{\n\t\t\t\tOwned: []operatorsv1alpha1.CRDDescription{\n\t\t\t\t\toperatorsv1alpha1.CRDDescription{\n\t\t\t\t\t\tName:              \"Test\",\n\t\t\t\t\t\tVersion:           \"v1\",\n\t\t\t\t\t\tKind:              \"Test\",\n\t\t\t\t\t\tStatusDescriptors: make([]operatorsv1alpha1.StatusDescriptor, 0),\n\t\t\t\t\t\tResources: []operatorsv1alpha1.APIResourceReference{\n\t\t\t\t\t\t\toperatorsv1alpha1.APIResourceReference{\n\t\t\t\t\t\t\t\tName:    \"operator\",\n\t\t\t\t\t\t\t\tKind:    \"Test\",\n\t\t\t\t\t\t\t\tVersion: \"v1\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t\tresult = CheckResources(crd, result)\n\t\t\tExpect(result.State).To(Equal(scapiv1alpha3.PassState))\n\t\t})\n\n\t\tIt(\"Should fail when CSV does not have Owned CRD's with resources\", func() {\n\n\t\t\tcrd = operatorsv1alpha1.CustomResourceDefinitions{\n\t\t\t\tOwned: []operatorsv1alpha1.CRDDescription{\n\t\t\t\t\toperatorsv1alpha1.CRDDescription{\n\t\t\t\t\t\tName:              \"Test\",\n\t\t\t\t\t\tVersion:           \"v1\",\n\t\t\t\t\t\tKind:              \"Test\",\n\t\t\t\t\t\tStatusDescriptors: make([]operatorsv1alpha1.StatusDescriptor, 0),\n\t\t\t\t\t\tResources:         make([]operatorsv1alpha1.APIResourceReference, 0),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t\tresult = CheckResources(crd, result)\n\t\t\tExpect(result.State).To(Equal(scapiv1alpha3.FailState))\n\t\t})\n\t})\n\n})\n\nfunc TestScorecard(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"Scorecard Basic and OLM Tests\")\n}\n"
  },
  {
    "path": "internal/scorecard/tests/crhelper.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage tests\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\n\tapimanifests \"github.com/operator-framework/api/pkg/manifests\"\n\t\"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured\"\n)\n\n// GetCRs parses a Bundle's CSV for CRs\nfunc GetCRs(bundle *apimanifests.Bundle) (crList []unstructured.Unstructured, err error) {\n\tif bundle.CSV.GetAnnotations() == nil {\n\t\treturn crList, nil\n\t}\n\n\t// get CRs from CSV's alm-examples annotation, assume single bundle\n\talmExamples := bundle.CSV.GetAnnotations()[\"alm-examples\"]\n\tif almExamples == \"\" {\n\t\treturn crList, nil\n\t}\n\n\terr = json.Unmarshal([]byte(almExamples), &crList)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse alm-examples annotation: %v\", err)\n\t}\n\treturn crList, nil\n}\n"
  },
  {
    "path": "internal/scorecard/tests/olm.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage tests\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\tscapiv1alpha3 \"github.com/operator-framework/api/pkg/apis/scorecard/v1alpha3\"\n\tapimanifests \"github.com/operator-framework/api/pkg/manifests\"\n\toperatorsv1alpha1 \"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\tapivalidation \"github.com/operator-framework/api/pkg/validation\"\n\t\"github.com/operator-framework/operator-registry/pkg/containertools\"\n\t\"github.com/operator-framework/operator-registry/pkg/image/execregistry\"\n\tregistrybundle \"github.com/operator-framework/operator-registry/pkg/lib/bundle\"\n\t\"github.com/sirupsen/logrus\"\n\tapiextv1 \"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1\"\n\t\"k8s.io/apimachinery/pkg/api/meta\"\n\t\"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured\"\n\n\tregistryutil \"github.com/operator-framework/operator-sdk/internal/registry\"\n\t\"github.com/operator-framework/operator-sdk/internal/util/k8sutil\"\n)\n\nconst (\n\tOLMBundleValidationTest   = \"olm-bundle-validation\"\n\tOLMCRDsHaveValidationTest = \"olm-crds-have-validation\"\n\tOLMCRDsHaveResourcesTest  = \"olm-crds-have-resources\"\n\tOLMSpecDescriptorsTest    = \"olm-spec-descriptors\"\n\tOLMStatusDescriptorsTest  = \"olm-status-descriptors\"\n\tstatusDescriptor          = \"status\"\n\tspecDescriptor            = \"spec\"\n)\n\n// BundleValidationTest validates an on-disk bundle\nfunc BundleValidationTest(bundleRoot string, metadata registryutil.LabelsMap) scapiv1alpha3.TestStatus {\n\tr := scapiv1alpha3.TestResult{}\n\tr.Name = OLMBundleValidationTest\n\tr.State = scapiv1alpha3.PassState\n\tr.Errors = []string{}\n\tr.Suggestions = []string{}\n\n\tdefaultOutput := logrus.StandardLogger().Out\n\tdefer logrus.SetOutput(defaultOutput)\n\n\t// Log output from the test will be captured in this buffer\n\tbuf := &bytes.Buffer{}\n\tlogger := logrus.WithField(\"name\", \"bundle-test\")\n\tlogrus.SetLevel(logrus.DebugLevel)\n\tlogrus.SetOutput(buf)\n\n\t// Despite NewRegistry appearing to create a docker image registry, all this function does is return a type\n\t// that shells out to the docker client binary. Since BundleValidationTest only ever calls ValidateBundleFormat,\n\t// which does not use the underlying registry, we can use this object as a dummy registry. We shouldn't\n\t// use the containerd registry because that actually creates an underlying registry.\n\t// NB(estroz): previously NewImageValidator constructed a docker registry internally, which is what we've done\n\t// here. However it might be nice to create a mock registry that returns an error if any method is called.\n\treg, err := execregistry.NewRegistry(containertools.DockerTool, logger)\n\tif err != nil {\n\t\t// This function should never return an error since it's wrapping the docker client binary in a struct.\n\t\tlogger.Fatalf(\"Scorecard: this docker registry error should never occur: %v\", err)\n\t}\n\tval := registrybundle.NewImageValidator(reg, logger)\n\n\t// Validate bundle format.\n\tif err := val.ValidateBundleFormat(bundleRoot); err != nil {\n\t\tr.State = scapiv1alpha3.FailState\n\t\tr.Errors = append(r.Errors, err.Error())\n\t}\n\n\t// Since a custom manifests directory may be used, check metadata for its base\n\t// path. Use the default base path if that label doesn't exist.\n\tmanifestsDir := registrybundle.ManifestsDir\n\tif value, hasKey := metadata.GetManifestsDir(); hasKey {\n\t\tmanifestsDir = value\n\t}\n\n\t// Validate bundle content.\n\tbundle, err := apimanifests.GetBundleFromDir(filepath.Join(bundleRoot, manifestsDir))\n\tif err != nil {\n\t\tr.State = scapiv1alpha3.FailState\n\t\tr.Errors = append(r.Errors, err.Error())\n\t\tr.Log = buf.String()\n\t\treturn wrapResult(r)\n\t}\n\n\tobjs := []any{bundle, bundle.CSV}\n\tfor _, crd := range bundle.V1CRDs {\n\t\tobjs = append(objs, crd)\n\t}\n\tfor _, crd := range bundle.V1beta1CRDs {\n\t\tobjs = append(objs, crd)\n\t}\n\tvalidationResults := apivalidation.DefaultBundleValidators.Validate(objs...)\n\tfor _, result := range validationResults {\n\t\tfor _, e := range result.Errors {\n\t\t\tr.Errors = append(r.Errors, e.Error())\n\t\t\tr.State = scapiv1alpha3.FailState\n\t\t}\n\n\t\tfor _, w := range result.Warnings {\n\t\t\tr.Suggestions = append(r.Suggestions, w.Error())\n\t\t}\n\t}\n\n\tr.Log = buf.String()\n\treturn wrapResult(r)\n}\n\n// CRDsHaveValidationTest verifies all CRDs have a validation section\nfunc CRDsHaveValidationTest(bundle *apimanifests.Bundle) scapiv1alpha3.TestStatus {\n\tr := scapiv1alpha3.TestResult{}\n\tr.Name = OLMCRDsHaveValidationTest\n\tr.State = scapiv1alpha3.PassState\n\tr.Errors = make([]string, 0)\n\tr.Suggestions = make([]string, 0)\n\n\tcrs, err := GetCRs(bundle)\n\tif err != nil {\n\t\tr.Errors = append(r.Errors, err.Error())\n\t\tr.State = scapiv1alpha3.ErrorState\n\t\treturn wrapResult(r)\n\t}\n\tr.Log += fmt.Sprintf(\"Loaded %d Custom Resources from alm-examples\\n\", len(crs))\n\n\tvar crds []*apiextv1.CustomResourceDefinition\n\tfor _, crd := range bundle.V1CRDs {\n\t\tcrds = append(crds, crd.DeepCopy())\n\t}\n\tfor _, crd := range bundle.V1beta1CRDs {\n\t\tout, err := k8sutil.Convertv1beta1Tov1CustomResourceDefinition(crd)\n\t\tif err != nil {\n\t\t\tr.Errors = append(r.Errors, err.Error())\n\t\t\tr.State = scapiv1alpha3.ErrorState\n\t\t\treturn wrapResult(r)\n\t\t}\n\t\tcrds = append(crds, out)\n\t}\n\tr.Log += fmt.Sprintf(\"Loaded CustomresourceDefinitions: %s\\n\", crds)\n\n\tfor _, cr := range crs {\n\t\tr = isCRFromCRDApi(cr, crds, r)\n\t}\n\treturn wrapResult(r)\n}\n\n// CRDsHaveResourcesTest verifies CRDs have resources listed in its owned CRDs section\nfunc CRDsHaveResourcesTest(bundle *apimanifests.Bundle) scapiv1alpha3.TestStatus {\n\tr := scapiv1alpha3.TestResult{}\n\tr.Name = OLMCRDsHaveResourcesTest\n\tr.State = scapiv1alpha3.PassState\n\tr.Errors = make([]string, 0)\n\tr.Suggestions = make([]string, 0)\n\n\tr.Log += fmt.Sprintf(\"Loaded ClusterServiceVersion: %s\\n\", bundle.CSV.GetName())\n\n\treturn wrapResult(CheckResources(bundle.CSV.Spec.CustomResourceDefinitions, r))\n}\n\n// CheckResources verified if the owned CRDs have the resources field.\nfunc CheckResources(crd operatorsv1alpha1.CustomResourceDefinitions,\n\tr scapiv1alpha3.TestResult) scapiv1alpha3.TestResult {\n\tfor _, description := range crd.Owned {\n\t\tif len(description.Resources) == 0 {\n\t\t\tr.State = scapiv1alpha3.FailState\n\t\t\tr.Errors = append(r.Errors, \"Owned CRDs do not have resources specified\")\n\t\t\treturn r\n\t\t}\n\t}\n\treturn r\n}\n\n// SpecDescriptorsTest verifies all spec fields have descriptors\nfunc SpecDescriptorsTest(bundle *apimanifests.Bundle) scapiv1alpha3.TestStatus {\n\tr := scapiv1alpha3.TestResult{}\n\tr.Name = OLMSpecDescriptorsTest\n\tr.State = scapiv1alpha3.PassState\n\tr.Errors = make([]string, 0)\n\tr.Suggestions = make([]string, 0)\n\tr = checkCSVDescriptors(bundle, r, specDescriptor)\n\treturn wrapResult(r)\n}\n\n// StatusDescriptorsTest verifies all CRDs have status descriptors\nfunc StatusDescriptorsTest(bundle *apimanifests.Bundle) scapiv1alpha3.TestStatus {\n\tr := scapiv1alpha3.TestResult{}\n\tr.Name = OLMStatusDescriptorsTest\n\tr.State = scapiv1alpha3.PassState\n\tr.Errors = make([]string, 0)\n\tr.Suggestions = make([]string, 0)\n\tr = checkCSVDescriptors(bundle, r, statusDescriptor)\n\treturn wrapResult(r)\n}\n\nfunc checkCSVDescriptors(bundle *apimanifests.Bundle, r scapiv1alpha3.TestResult,\n\tdescriptor string) scapiv1alpha3.TestResult {\n\n\tr.Log += fmt.Sprintf(\"Loaded ClusterServiceVersion: %s\\n\", bundle.CSV.GetName())\n\n\tcrs, err := GetCRs(bundle)\n\tif err != nil {\n\t\tr.Errors = append(r.Errors, err.Error())\n\t\tr.State = scapiv1alpha3.ErrorState\n\t\treturn r\n\t}\n\tr.Log += fmt.Sprintf(\"Loaded %d Custom Resources from alm-examples\\n\", len(crs))\n\n\t// if the descriptor is status then check the status\n\t// otherwise check the spec\n\tfor _, cr := range crs {\n\t\tif descriptor == statusDescriptor {\n\t\t\tr = checkOwnedCSVStatusDescriptor(cr, bundle.CSV, r)\n\t\t} else {\n\t\t\tr = checkOwnedCSVSpecDescriptors(cr, bundle.CSV, r)\n\t\t}\n\t}\n\treturn r\n}\n\nfunc checkOwnedCSVStatusDescriptor(cr unstructured.Unstructured, csv *operatorsv1alpha1.ClusterServiceVersion,\n\tr scapiv1alpha3.TestResult) scapiv1alpha3.TestResult {\n\n\tvar crdDescription *operatorsv1alpha1.CRDDescription\n\n\tfor _, owned := range csv.Spec.CustomResourceDefinitions.Owned {\n\t\tif owned.Kind == cr.GetKind() && owned.Version == cr.GroupVersionKind().Version {\n\t\t\tcrdDescription = &owned\n\t\t\tbreak\n\t\t}\n\t}\n\n\tif crdDescription == nil {\n\t\tmsg := fmt.Sprintf(\"Failed to find an owned CRD for CR %s with GVK %s\", cr.GetName(), cr.GroupVersionKind().String())\n\t\tr.Errors = append(r.Errors, msg)\n\t\tr.State = scapiv1alpha3.FailState\n\t\treturn r\n\t}\n\n\thasStatusDefinition := false\n\tif cr.Object[\"status\"] != nil {\n\t\t// Ensure that has no empty keys\n\t\thasStatusDefinition = len(cr.Object[\"status\"].(map[string]any)) > 0\n\t}\n\n\tif !hasStatusDefinition {\n\t\tr.Suggestions = append(r.Suggestions, fmt.Sprintf(\"%s does not have status spec. Note that \"+\n\t\t\t\"all objects that represent a physical resource whose state may vary from the user's desired \"+\n\t\t\t\"intent SHOULD have a spec and a status. \"+\n\t\t\t\"More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status\", crdDescription.Name))\n\t}\n\n\tif hasStatusDefinition && len(crdDescription.StatusDescriptors) == 0 {\n\t\tr.Errors = append(r.Errors, fmt.Sprintf(\"%s does not have a status descriptor\", crdDescription.Name))\n\t\tr.Suggestions = append(r.Suggestions, fmt.Sprintf(\"add status descriptor for the crd %s. \"+\n\t\t\t\"If your project is built using Golang you can use the csv markers. \"+\n\t\t\t\"More info: https://sdk.operatorframework.io/docs/building-operators/golang/references/markers/\", crdDescription.Name))\n\t\tr.State = scapiv1alpha3.FailState\n\t}\n\n\treturn r\n}\n\n// TODO This is the validation we did in v1, but it looks like it only validates fields that\n// are in the example CRs, if you have a field in your CRD that isn't present in one of your examples,\n// I don't think it will be validated.\nfunc checkOwnedCSVSpecDescriptors(cr unstructured.Unstructured, csv *operatorsv1alpha1.ClusterServiceVersion,\n\tr scapiv1alpha3.TestResult) scapiv1alpha3.TestResult {\n\tif cr.Object[specDescriptor] == nil {\n\t\tr.State = scapiv1alpha3.FailState\n\t\treturn r\n\t}\n\n\tblock := cr.Object[specDescriptor].(map[string]any)\n\n\tvar crd *operatorsv1alpha1.CRDDescription\n\tfor _, owned := range csv.Spec.CustomResourceDefinitions.Owned {\n\t\tif owned.Kind == cr.GetKind() && owned.Version == cr.GroupVersionKind().Version {\n\t\t\tcrd = &owned\n\t\t\tbreak\n\t\t}\n\t}\n\n\tif crd == nil {\n\t\tmsg := fmt.Sprintf(\"Failed to find an owned CRD for CR %s with GVK %s\", cr.GetName(), cr.GroupVersionKind().String())\n\t\tr.Errors = append(r.Errors, msg)\n\t\tr.State = scapiv1alpha3.FailState\n\t\treturn r\n\t}\n\n\tfor key := range block {\n\t\tfor _, specDesc := range crd.SpecDescriptors {\n\t\t\tif specDesc.Path == key {\n\t\t\t\tdelete(block, key)\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\tfor key := range block {\n\t\tr.Errors = append(r.Errors, fmt.Sprintf(\"%s does not have a %s descriptor\", key, specDescriptor))\n\t\tr.Suggestions = append(r.Suggestions, fmt.Sprintf(\"Add a %s descriptor for %s\", specDescriptor, key))\n\t\tr.State = scapiv1alpha3.FailState\n\t}\n\treturn r\n}\n\n// hasVersion checks if a CRD contains a specified version in a case insensitive manner\nfunc hasVersion(version string, crdVersion apiextv1.CustomResourceDefinitionVersion) bool {\n\treturn strings.EqualFold(version, crdVersion.Name)\n}\n\nfunc hasKind(kind1, kind2 string, r scapiv1alpha3.TestResult) bool {\n\n\tvar restMapper meta.DefaultRESTMapper\n\tsingularKind1, err := restMapper.ResourceSingularizer(kind1)\n\tif err != nil {\n\t\tsingularKind1 = kind1\n\t\tr.Suggestions = append(r.Suggestions, fmt.Sprintf(\"could not find singular version of %s\", kind1))\n\t}\n\tsingularKind2, err := restMapper.ResourceSingularizer(kind2)\n\tif err != nil {\n\t\tsingularKind2 = kind2\n\t\tr.Suggestions = append(r.Suggestions, fmt.Sprintf(\"could not find singular version of %s\", kind2))\n\t}\n\treturn strings.EqualFold(singularKind1, singularKind2)\n}\n\nfunc isCRFromCRDApi(cr unstructured.Unstructured, crds []*apiextv1.CustomResourceDefinition,\n\tr scapiv1alpha3.TestResult) scapiv1alpha3.TestResult {\n\n\t// check if the CRD matches the testing CR\n\tfor _, crd := range crds {\n\t\tgvk := cr.GroupVersionKind()\n\t\t// Only check the validation block if the CRD and CR have the same Kind and Version\n\t\tfor _, version := range crd.Spec.Versions {\n\n\t\t\tif !hasVersion(gvk.Version, version) || !hasKind(gvk.Kind, crd.Spec.Names.Kind, r) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif version.Schema == nil {\n\t\t\t\tr.Suggestions = append(r.Suggestions, fmt.Sprintf(\"Add CRD validation for %s/%s\",\n\t\t\t\t\tcrd.Spec.Names.Kind, version.Name))\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfailed := false\n\t\t\tif cr.Object[\"spec\"] != nil {\n\t\t\t\tspec := cr.Object[\"spec\"].(map[string]any)\n\t\t\t\tfor key := range spec {\n\t\t\t\t\tif _, ok := version.Schema.OpenAPIV3Schema.Properties[\"spec\"].Properties[key]; !ok {\n\t\t\t\t\t\tfailed = true\n\t\t\t\t\t\tr.Suggestions = append(r.Suggestions,\n\t\t\t\t\t\t\tfmt.Sprintf(\"Add CRD validation for spec field `%s` in %s/%s\",\n\t\t\t\t\t\t\t\tkey, gvk.Kind, gvk.Version))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif cr.Object[\"status\"] != nil {\n\t\t\t\tstatus := cr.Object[\"status\"].(map[string]any)\n\t\t\t\tfor key := range status {\n\t\t\t\t\tif _, ok := version.Schema.OpenAPIV3Schema.Properties[\"status\"].Properties[key]; !ok {\n\t\t\t\t\t\tfailed = true\n\t\t\t\t\t\tr.Suggestions = append(r.Suggestions, fmt.Sprintf(\"Add CRD validation for status\"+\n\t\t\t\t\t\t\t\" field `%s` in %s/%s\", key, gvk.Kind, gvk.Version))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif failed {\n\t\t\t\tr.State = scapiv1alpha3.FailState\n\t\t\t\treturn r\n\t\t\t}\n\t\t}\n\t}\n\treturn r\n}\n\nfunc wrapResult(r scapiv1alpha3.TestResult) scapiv1alpha3.TestStatus {\n\treturn scapiv1alpha3.TestStatus{\n\t\tResults: []scapiv1alpha3.TestResult{r},\n\t}\n}\n"
  },
  {
    "path": "internal/testutils/olm.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage testutils\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\n\t_ \"sigs.k8s.io/kubebuilder/v4/pkg/config/v3\" // Register config/v3 for `config.New`\n\n\t\"github.com/operator-framework/operator-sdk/internal/util/projutil\"\n)\n\nconst (\n\tOlmVersionForTestSuite = \"0.28.0\"\n)\n\nvar makefilePackagemanifestsFragment = `\n# Options for \"packagemanifests\".\nifneq ($(origin FROM_VERSION), undefined)\nPKG_FROM_VERSION := --from-version=$(FROM_VERSION)\nendif\nifneq ($(origin CHANNEL), undefined)\nPKG_CHANNELS := --channel=$(CHANNEL)\nendif\nifeq ($(IS_CHANNEL_DEFAULT), 1)\nPKG_IS_DEFAULT_CHANNEL := --default-channel\nendif\nPKG_MAN_OPTS ?= $(PKG_FROM_VERSION) $(PKG_CHANNELS) $(PKG_IS_DEFAULT_CHANNEL)\n\n# Generate package manifests.\npackagemanifests: kustomize %s\n\t$(OPERATOR_SDK) generate kustomize manifests -q --interactive=false\n\tcd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG)\n\t$(KUSTOMIZE) build config/manifests | $(OPERATOR_SDK) generate packagemanifests -q --version $(VERSION) $(PKG_MAN_OPTS)\n`\n\n// AddPackagemanifestsTarget will append the packagemanifests target to the makefile\n// in order to test the steps described in the docs.\n// More info:  https://v1-0-x.sdk.operatorframework.io/docs/olm-integration/generation/#package-manifests-formats\nfunc (tc TestContext) AddPackagemanifestsTarget(operatorType projutil.OperatorType) error {\n\tmakefileBytes, err := os.ReadFile(filepath.Join(tc.Dir, \"Makefile\"))\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// add the manifests target when is a Go project.\n\treplaceTarget := \"\"\n\tif operatorType == projutil.OperatorTypeGo {\n\t\treplaceTarget = \"manifests\"\n\t}\n\tmakefilePackagemanifestsFragment = fmt.Sprintf(makefilePackagemanifestsFragment, replaceTarget)\n\n\t// update makefile by adding the packagemanifests target\n\tmakefileBytes = append([]byte(makefilePackagemanifestsFragment), makefileBytes...)\n\terr = os.WriteFile(filepath.Join(tc.Dir, \"Makefile\"), makefileBytes, 0644)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// DisableManifestsInteractiveMode will update the Makefile to disable the interactive mode\nfunc (tc TestContext) DisableManifestsInteractiveMode() error {\n\t// Todo: check if we cannot improve it since the replace/content will exists in the\n\t// pkgmanifest target if it be scaffolded before this call\n\tcontent := \"$(OPERATOR_SDK) generate kustomize manifests\"\n\treplace := content + \" --interactive=false\"\n\treturn ReplaceInFile(filepath.Join(tc.Dir, \"Makefile\"), content, replace)\n}\n\n// GenerateBundle runs all commands to create an operator bundle.\nfunc (tc TestContext) GenerateBundle() error {\n\tif err := tc.DisableManifestsInteractiveMode(); err != nil {\n\t\treturn err\n\t}\n\n\treturn tc.Make(\"bundle\", \"IMG=\"+tc.ImageName)\n}\n"
  },
  {
    "path": "internal/testutils/scorecard.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Modified from https://github.com/kubernetes-sigs/kubebuilder/tree/39224f0/test/e2e/v3\n\npackage testutils\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\n\tkbutil \"sigs.k8s.io/kubebuilder/v4/pkg/plugin/util\"\n)\n\nconst scorecardImage = \"quay.io/operator-framework/scorecard-test:.*\"\nconst scorecardImageReplace = \"quay.io/operator-framework/scorecard-test:dev\"\n\nconst customScorecardPatch = `\n- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - custom-scorecard-tests\n    - customtest1\n    image: quay.io/operator-framework/custom-scorecard-tests:dev\n    labels:\n      suite: custom\n      test: customtest1\n- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - custom-scorecard-tests\n    - customtest2\n    image: quay.io/operator-framework/custom-scorecard-tests:dev\n    labels:\n      suite: custom\n      test: customtest2\n`\n\nconst customScorecardKustomize = `\n- path: patches/custom.config.yaml\n  target:\n    group: scorecard.operatorframework.io\n    version: v1alpha3\n    kind: Configuration\n    name: config\n`\n\nfunc (tc TestContext) AddScorecardCustomPatchFile() error {\n\t// drop in the patch file\n\tcustomScorecardPatchFile := filepath.Join(tc.Dir, \"config\", \"scorecard\", \"patches\", \"custom.config.yaml\")\n\tpatchBytes := []byte(customScorecardPatch)\n\terr := os.WriteFile(customScorecardPatchFile, patchBytes, 0777)\n\tif err != nil {\n\t\tfmt.Printf(\"can not write %s %s\\n\", customScorecardPatchFile, err.Error())\n\t\treturn err\n\t}\n\n\t// append to config/scorecard/kustomization.yaml\n\tkustomizeFile := filepath.Join(tc.Dir, \"config\", \"scorecard\", \"kustomization.yaml\")\n\tf, err := os.OpenFile(kustomizeFile, os.O_APPEND|os.O_WRONLY, 0777)\n\tif err != nil {\n\t\tfmt.Printf(\"error in opening scorecard kustomization.yaml file %s\\n\", err.Error())\n\t\treturn err\n\t}\n\tdefer f.Close()\n\tif _, err := f.WriteString(customScorecardKustomize); err != nil {\n\t\tfmt.Printf(\"error in append to scorecard kustomization.yaml %s\\n\", err.Error())\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// ReplaceScorecardImagesForDev will replaces the scorecard images in the manifests per dev tag which is built\n// in the CI based on the code changes made.\nfunc (tc TestContext) ReplaceScorecardImagesForDev() error {\n\terr := kbutil.ReplaceRegexInFile(\n\t\tfilepath.Join(tc.Dir, \"config\", \"scorecard\", \"patches\", \"basic.config.yaml\"),\n\t\tscorecardImage, scorecardImageReplace,\n\t)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\terr = kbutil.ReplaceRegexInFile(\n\t\tfilepath.Join(tc.Dir, \"config\", \"scorecard\", \"patches\", \"olm.config.yaml\"),\n\t\tscorecardImage, scorecardImageReplace,\n\t)\n\treturn err\n}\n"
  },
  {
    "path": "internal/testutils/utils.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage testutils\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"time\"\n\n\t. \"github.com/onsi/ginkgo/v2\" //nolint:staticcheck\n\t. \"github.com/onsi/gomega\"    //nolint:staticcheck\n\tkbutil \"sigs.k8s.io/kubebuilder/v4/pkg/plugin/util\"\n\tkbtestutils \"sigs.k8s.io/kubebuilder/v4/test/e2e/utils\"\n)\n\nconst BinaryName = \"operator-sdk\"\n\n// TestContext wraps kubebuilder's e2e TestContext.\ntype TestContext struct {\n\t*kbtestutils.TestContext\n\t// BundleImageName store the image to use to build the bundle\n\tBundleImageName string\n\t// ProjectName store the project name\n\tProjectName string\n\t// isPrometheusManagedBySuite is true when the suite tests is installing/uninstalling the Prometheus\n\tisPrometheusManagedBySuite bool\n\t// isOLMManagedBySuite is true when the suite tests is installing/uninstalling the OLM\n\tisOLMManagedBySuite bool\n}\n\n// NewTestContext returns a TestContext containing a new kubebuilder TestContext.\n// Construct if your environment is connected to a live cluster, ex. for e2e tests.\nfunc NewTestContext(binaryName string, env ...string) (tc TestContext, err error) {\n\tif tc.TestContext, err = kbtestutils.NewTestContext(binaryName, env...); err != nil {\n\t\treturn tc, err\n\t}\n\ttc.ProjectName = strings.ToLower(filepath.Base(tc.Dir))\n\ttc.ImageName = makeImageName(tc.ProjectName)\n\ttc.BundleImageName = makeBundleImageName(tc.ProjectName)\n\ttc.isOLMManagedBySuite = true\n\ttc.isPrometheusManagedBySuite = true\n\treturn tc, nil\n}\n\n// NewPartialTestContext returns a TestContext containing a partial kubebuilder TestContext.\n// This object needs to be populated with GVK information. The underlying TestContext is\n// created directly rather than through a constructor so cluster-based setup is skipped.\nfunc NewPartialTestContext(binaryName, dir string, env ...string) (tc TestContext, err error) {\n\tcc := &kbtestutils.CmdContext{\n\t\tEnv: env,\n\t}\n\tif cc.Dir, err = filepath.Abs(dir); err != nil {\n\t\treturn tc, err\n\t}\n\tprojectName := strings.ToLower(filepath.Base(dir))\n\n\treturn TestContext{\n\t\tTestContext: &kbtestutils.TestContext{\n\t\t\tCmdContext: cc,\n\t\t\tBinaryName: binaryName,\n\t\t\tImageName:  makeImageName(projectName),\n\t\t},\n\t\tProjectName:     projectName,\n\t\tBundleImageName: makeBundleImageName(projectName),\n\t}, nil\n}\n\nfunc makeImageName(projectName string) string {\n\treturn fmt.Sprintf(\"quay.io/example/%s:v0.0.1\", projectName)\n}\n\nfunc makeBundleImageName(projectName string) string {\n\treturn fmt.Sprintf(\"quay.io/example/%s-bundle:v0.0.1\", projectName)\n}\n\n// InstallOLMVersion runs 'operator-sdk olm install' for specific version\n// and returns any errors emitted by that command.\nfunc (tc TestContext) InstallOLMVersion(version string) error {\n\tcmd := exec.Command(tc.BinaryName, \"olm\", \"install\", \"--version\", version, \"--timeout\", \"4m\")\n\t_, err := tc.Run(cmd)\n\treturn err\n}\n\n// UninstallOLM runs 'operator-sdk olm uninstall' and logs any errors emitted by that command.\nfunc (tc TestContext) UninstallOLM() {\n\tcmd := exec.Command(tc.BinaryName, \"olm\", \"uninstall\")\n\tif _, err := tc.Run(cmd); err != nil {\n\t\tfmt.Fprintln(GinkgoWriter, \"warning: error when uninstalling OLM:\", err)\n\t}\n}\n\n// ReplaceInFile replaces all instances of old with new in the file at path.\n// todo(camilamacedo86): this func can be pushed to upstream/kb\nfunc ReplaceInFile(path, o, n string) error {\n\tinfo, err := os.Stat(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\tb, err := os.ReadFile(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif !strings.Contains(string(b), o) {\n\t\treturn errors.New(\"unable to find the content to be replaced\")\n\t}\n\ts := strings.ReplaceAll(string(b), o, n)\n\terr = os.WriteFile(path, []byte(s), info.Mode())\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\n// LoadImageToKindClusterWithName loads a local docker image with the name informed to the kind cluster\nfunc (tc TestContext) LoadImageToKindClusterWithName(image string) error {\n\tcluster := \"kind\"\n\tif v, ok := os.LookupEnv(\"KIND_CLUSTER\"); ok {\n\t\tcluster = v\n\t}\n\tkindOptions := []string{\"load\", \"docker-image\", \"--name\", cluster, image}\n\tcmd := exec.Command(\"kind\", kindOptions...)\n\t_, err := tc.Run(cmd)\n\treturn err\n}\n\n// InstallPrerequisites will install OLM and Prometheus\n// when the cluster kind is Kind and when they are not present on the Cluster\nfunc (tc TestContext) InstallPrerequisites() {\n\tBy(\"checking API resources applied on Cluster\")\n\toutput, err := tc.Kubectl.Command(\"api-resources\")\n\tExpect(err).NotTo(HaveOccurred())\n\tif strings.Contains(output, \"servicemonitors\") {\n\t\ttc.isPrometheusManagedBySuite = false\n\t}\n\tif strings.Contains(output, \"clusterserviceversions\") {\n\t\ttc.isOLMManagedBySuite = false\n\t}\n\n\tif tc.isPrometheusManagedBySuite {\n\t\tBy(\"installing Prometheus\")\n\t\tExpect(tc.InstallPrometheusOperManager()).To(Succeed())\n\n\t\tBy(\"ensuring provisioned Prometheus Manager Service\")\n\t\tEventually(func() error {\n\t\t\t_, err := tc.Kubectl.Get(\n\t\t\t\tfalse,\n\t\t\t\t\"Service\", \"prometheus-operator\")\n\t\t\treturn err\n\t\t}, 3*time.Minute, time.Second).Should(Succeed())\n\t}\n\n\tif tc.isOLMManagedBySuite {\n\t\tBy(\"installing OLM\")\n\t\tExpect(tc.InstallOLMVersion(OlmVersionForTestSuite)).To(Succeed())\n\t}\n}\n\n// IsRunningOnKind returns true when the tests are executed in a Kind Cluster\nfunc (tc TestContext) IsRunningOnKind() (bool, error) {\n\tkubectx, err := tc.Kubectl.Command(\"config\", \"current-context\")\n\tif err != nil {\n\t\treturn false, err\n\t}\n\treturn strings.Contains(kubectx, \"kind\"), nil\n}\n\n// UninstallPrerequisites will uninstall all prerequisites installed via InstallPrerequisites()\nfunc (tc TestContext) UninstallPrerequisites() {\n\tif tc.isPrometheusManagedBySuite {\n\t\tBy(\"uninstalling Prometheus\")\n\t\ttc.UninstallPrometheusOperManager()\n\t}\n\tif tc.isOLMManagedBySuite {\n\t\tBy(\"uninstalling OLM\")\n\t\ttc.UninstallOLM()\n\t}\n}\n\n// WrapWarnOutput is a one-liner to wrap an error from a command that returns (string, error) in a warning.\nfunc WrapWarnOutput(_ string, err error) {\n\tif err != nil {\n\t\tfmt.Fprintf(GinkgoWriter, \"warning: %s\", err)\n\t}\n}\n\n// WrapWarn is a one-liner to wrap an error from a command that returns (error) in a warning.\nfunc WrapWarn(err error) {\n\tWrapWarnOutput(\"\", err)\n}\n\nfunc (tc TestContext) UncommentRestrictivePodStandards() error {\n\tconfigManager := filepath.Join(tc.Dir, \"config\", \"manager\", \"manager.yaml\")\n\n\tif err := kbutil.ReplaceInFile(configManager, `# TODO(user): For common cases that do not require escalating privileges\n        # it is recommended to ensure that all your Pods/Containers are restrictive.\n        # More info: https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted\n        # Please uncomment the following code if your project does NOT have to work on old Kubernetes\n        # versions < 1.19 or on vendors versions which do NOT support this field by default (i.e. Openshift < 4.11 ).\n        # seccompProfile:\n        #   type: RuntimeDefault`, `seccompProfile:\n          type: RuntimeDefault`); err == nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "internal/util/bundleutil/bundleutil.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage bundleutil\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strings\"\n\t\"text/template\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/viper\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/flags\"\n\t\"github.com/operator-framework/operator-sdk/internal/util/projutil\"\n)\n\nvar (\n\tdefaultMetadataDir          = \"metadata\"\n\tdefaultManifestDir          = \"manifests\"\n\tdefaultBundleDockerfilePath = \"bundle.Dockerfile\"\n)\n\n// BundleMetaData contains the required metadata to build bundles and images.\ntype BundleMetaData struct {\n\t// BundleDir refers to the directory where generated bundles are to be written.\n\tBundleDir string\n\n\t// The PackageName of the operator bundle.\n\tPackageName string\n\n\t// Channels and DefaultChannel the operator should be subscribed to.\n\tChannels       string\n\tDefaultChannel string\n\n\t// BaseImage name to build bundle image.\n\tBaseImage string\n\n\t// BuildCommand to run while building image.\n\tBuildCommand string\n\n\t// PackageManifestPath where the input manifests are present.\n\tPkgmanifestPath string\n\n\t// IsScoreConfigPresent when set to true includes scorecard config annotations\n\t// in bundle metadata.\n\tIsScoreConfigPresent bool\n\n\t// Other labels to be added in CSV.\n\tOtherLabels map[string]string\n}\n\n// values to populate bundle metadata/Dockerfile.\ntype annotationsValues struct {\n\tBundleDir                string\n\tPackageName              string\n\tChannels                 string\n\tDefaultChannel           string\n\tOtherLabels              []string\n\tIsScorecardConfigPresent bool\n}\n\n// GenerateMetadata scaffolds annotations.yaml and bundle.Dockerfile with the provided\n// annotation values.\nfunc (meta *BundleMetaData) GenerateMetadata() error {\n\t// Create output directory\n\tif err := os.MkdirAll(meta.BundleDir, projutil.DirMode); err != nil {\n\t\treturn err\n\t}\n\n\t// Create annotation values for both bundle.Dockerfile and annotations.yaml, which should\n\t// hold the same set of values always.\n\tvalues := annotationsValues{\n\t\tBundleDir:                meta.BundleDir,\n\t\tPackageName:              meta.PackageName,\n\t\tChannels:                 meta.Channels,\n\t\tDefaultChannel:           meta.DefaultChannel,\n\t\tIsScorecardConfigPresent: meta.IsScoreConfigPresent,\n\t}\n\n\tfor k, v := range meta.OtherLabels {\n\t\tvalues.OtherLabels = append(values.OtherLabels, fmt.Sprintf(\"%s=%s\", k, v))\n\t}\n\tsort.Strings(values.OtherLabels)\n\n\t// Write each file\n\tmetadataDir := filepath.Join(meta.BundleDir, defaultMetadataDir)\n\tif err := os.MkdirAll(metadataDir, projutil.DirMode); err != nil {\n\t\treturn err\n\t}\n\n\tdockerfilePath := defaultBundleDockerfilePath\n\t// If migrating from packagemanifests to bundle, bundle.Dockerfile is present\n\t// inside bundleDir, else it's in the project directory. Hence, dockerfile\n\t// should have the path specified with respect to output directory of resulting bundles.\n\t// Remove this, when pkgman-to-bundle migrate command is removed.\n\tif len(meta.PkgmanifestPath) != 0 {\n\t\tdockerfilePath = filepath.Join(filepath.Dir(meta.BundleDir), \"bundle.Dockerfile\")\n\t\tvalues.BundleDir = filepath.Base(meta.BundleDir)\n\t}\n\n\ttemplateMap := map[string]*template.Template{\n\t\tdockerfilePath: dockerfileTemplate,\n\t\tfilepath.Join(metadataDir, \"annotations.yaml\"): annotationsTemplate,\n\t}\n\n\tfor path, tmpl := range templateMap {\n\t\tlog.Info(fmt.Sprintf(\"Creating %s\", path))\n\t\tf, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tdefer func() {\n\t\t\tif err := f.Close(); err != nil {\n\t\t\t\tlog.Error(err)\n\t\t\t}\n\t\t}()\n\t\tif err = tmpl.Execute(f, values); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tlog.Infof(\"Bundle metadata generated successfully\")\n\treturn nil\n}\n\n// CopyOperatorManifests copies packagemanifestsDir/manifests to bundleDir/manifests.\nfunc (meta *BundleMetaData) CopyOperatorManifests() error {\n\treturn copyOperatorManifests(meta.PkgmanifestPath, filepath.Join(meta.BundleDir, defaultManifestDir))\n}\n\nfunc copyOperatorManifests(src, dest string) error {\n\tsrcInfo, err := os.Stat(src)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error reading source directory %v\", err)\n\t}\n\n\tif err := os.MkdirAll(dest, srcInfo.Mode()); err != nil {\n\t\treturn err\n\t}\n\n\tsrcFiles, err := os.ReadDir(src)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfor _, f := range srcFiles {\n\t\tsrcPath := filepath.Join(src, f.Name())\n\t\tdestPath := filepath.Join(dest, f.Name())\n\n\t\tif f.IsDir() {\n\t\t\t// TODO(verify): we may have to log an error here instead of recursively copying\n\t\t\t// if there are no sub-folders allowed under manifests dir of a packagemanifest.\n\t\t\tif err = copyOperatorManifests(srcPath, destPath); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t} else {\n\t\t\tsrcFile, err := os.Open(srcPath)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tdefer srcFile.Close()\n\n\t\t\tdestFile, err := os.Create(destPath)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tdefer destFile.Close()\n\n\t\t\t_, err = io.Copy(destFile, srcFile)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// BuildBundleImage builds the bundle image with the provided command or using\n// docker build command.\nfunc (meta *BundleMetaData) BuildBundleImage(tag string) error {\n\n\timg := fmt.Sprintf(\"%s:%s\", meta.BaseImage, tag)\n\n\t// switch back to current working directory, so that subsequent\n\t// bundle version images can be built.\n\tcwd, err := os.Getwd()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tdefer func() {\n\t\tif err := os.Chdir(cwd); err != nil {\n\t\t\tlog.Error(cwd)\n\t\t}\n\t}()\n\n\tif err := os.Chdir(filepath.Dir(meta.BundleDir)); err != nil {\n\t\treturn err\n\t}\n\n\tif len(meta.BuildCommand) != 0 {\n\t\t// TODO(varsha): Make this more user friendly by accepting a template which\n\t\t// can executed in each bundle subdirectory.\n\t\tlog.Infof(\"Using the specified command to build image\")\n\t\tcommandArg := strings.Split(meta.BuildCommand, \" \")\n\n\t\t// append the tag and build context to the command\n\t\tcmd := exec.Command(commandArg[0], append(commandArg[1:], img)...)\n\t\toutput, err := cmd.CombinedOutput()\n\t\tif err != nil || viper.GetBool(flags.VerboseOpt) {\n\t\t\tfmt.Println(string(output))\n\t\t}\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\toutput, err := exec.Command(\"docker\", \"build\", \"-f\", \"bundle.Dockerfile\", \"-t\", img, \".\").CombinedOutput()\n\t\tif err != nil || viper.GetBool(flags.VerboseOpt) {\n\t\t\tfmt.Println(string(output))\n\t\t}\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\tlog.Infof(\"Successfully built image %s\", img)\n\treturn nil\n}\n\n// WriteScorecardConfig creates the scorecard directory in the bundle and copies the\n// configuration yaml to bundle.\nfunc (meta *BundleMetaData) WriteScorecardConfig(inputConfigPath string) error {\n\t// If the config is already copied as a part of the manifest directory\n\t// then ensure that it is deleted to remove duplicates.\n\t_, filename := filepath.Split(inputConfigPath)\n\tif err := deleteExistingScorecardConfig(meta.BundleDir, filename); err != nil {\n\t\treturn err\n\t}\n\n\tscorecardDir := filepath.Join(meta.BundleDir, \"tests\", \"scorecard\")\n\n\t// Create directory for scorecard config\n\tif err := os.MkdirAll(scorecardDir, projutil.DirMode); err != nil {\n\t\treturn err\n\t}\n\n\tlog.Info(fmt.Sprintf(\"Writing scorecard config in %s\", scorecardDir))\n\tb, err := os.ReadFile(inputConfigPath)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\terr = os.WriteFile(filepath.Join(scorecardDir, \"config.yaml\"), b, 0644)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error writing scorecard config %v\", err)\n\t}\n\treturn nil\n}\n\n// deleteExistingScorecardConfig checks if there is an existing scorecard config file\n// in manifests/ folder, if present it deletes it.\nfunc deleteExistingScorecardConfig(bundleDir, filename string) error {\n\tscorecardConfigPath := filepath.Join(bundleDir, defaultManifestDir, filename)\n\treturn os.RemoveAll(scorecardConfigPath)\n}\n"
  },
  {
    "path": "internal/util/bundleutil/template.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage bundleutil\n\nimport (\n\t\"strings\"\n\t\"text/template\"\n)\n\n// Transform a Dockerfile label to a YAML kv.\nvar funcs = template.FuncMap{\n\t\"toYAML\": func(s string) string { return strings.ReplaceAll(s, \"=\", \": \") },\n}\n\n// Template for bundle.Dockerfile, containing scorecard labels.\nvar dockerfileTemplate = template.Must(template.New(\"\").Funcs(funcs).Parse(`FROM scratch\n\n# Core bundle labels.\nLABEL operators.operatorframework.io.bundle.mediatype.v1=registry+v1\nLABEL operators.operatorframework.io.bundle.manifests.v1=manifests/\nLABEL operators.operatorframework.io.bundle.metadata.v1=metadata/\nLABEL operators.operatorframework.io.bundle.package.v1={{ .PackageName }}\nLABEL operators.operatorframework.io.bundle.channels.v1={{ .Channels }}\n{{- if .DefaultChannel }}\nLABEL operators.operatorframework.io.bundle.channel.default.v1={{ .DefaultChannel }}\n{{- end }}\n{{- range $i, $l := .OtherLabels }}\nLABEL {{ $l }}\n{{- end }}\n\n{{- if .IsScorecardConfigPresent }}\n\n# Labels for testing.\nLABEL operators.operatorframework.io.test.mediatype.v1=scorecard+v1\nLABEL operators.operatorframework.io.test.config.v1=tests/scorecard/\n{{- end }}\n\n# Copy files to locations specified by labels.\nCOPY {{ .BundleDir }}/manifests /manifests/\nCOPY {{ .BundleDir }}/metadata /metadata/\n{{- if .IsScorecardConfigPresent }}\nCOPY {{ .BundleDir }}/tests/scorecard /tests/scorecard/\n{{- end }}\n`))\n\n// Template for annotations.yaml, containing scorecard labels.\nvar annotationsTemplate = template.Must(template.New(\"\").Funcs(funcs).Parse(`annotations:\n  # Core bundle annotations.\n  operators.operatorframework.io.bundle.mediatype.v1: registry+v1\n  operators.operatorframework.io.bundle.manifests.v1: manifests/\n  operators.operatorframework.io.bundle.metadata.v1: metadata/\n  operators.operatorframework.io.bundle.package.v1: {{ .PackageName }}\n  operators.operatorframework.io.bundle.channels.v1: {{ .Channels }}\n  {{- if .DefaultChannel }}\n  operators.operatorframework.io.bundle.channel.default.v1: {{ .DefaultChannel }}\n  {{- end }}\n  {{- range $i, $l := .OtherLabels }}\n  {{ toYAML $l }}\n  {{- end }}\n\n  {{- if .IsScorecardConfigPresent }}\n\n  # Annotations for testing.\n  operators.operatorframework.io.test.mediatype.v1: scorecard+v1\n  operators.operatorframework.io.test.config.v1: tests/scorecard/\n  {{- end }}\n`))\n"
  },
  {
    "path": "internal/util/k8sutil/api.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage k8sutil\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\n\t\"github.com/operator-framework/operator-registry/pkg/registry\"\n\tlog \"github.com/sirupsen/logrus\"\n\tapiext \"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions\"\n\tapiextv1 \"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1\"\n\tapiextv1beta1 \"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1\"\n\t\"k8s.io/apimachinery/pkg/runtime/schema\"\n\t\"k8s.io/apimachinery/pkg/version\"\n\t\"sigs.k8s.io/yaml\"\n)\n\n// GetCustomResourceDefinitions returns all CRD manifests of both v1 and v1beta1\n// versions in the directory crdsDir. If a duplicate object with different API\n// versions is found, and error is returned.\nfunc GetCustomResourceDefinitions(crdsDir string) (\n\tv1crds []apiextv1.CustomResourceDefinition,\n\tv1beta1crds []apiextv1beta1.CustomResourceDefinition,\n\terr error) {\n\n\tinfos, err := os.ReadDir(crdsDir)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\t// The set of all custom resource GVKs in found CRDs.\n\tcrGVKSet := map[schema.GroupVersionKind]struct{}{}\n\tfor _, info := range infos {\n\t\tpath := filepath.Join(crdsDir, info.Name())\n\n\t\tif info.IsDir() {\n\t\t\tlog.Debugf(\"Skipping dir: %s\", path)\n\t\t\tcontinue\n\t\t}\n\n\t\tb, err := os.ReadFile(path)\n\t\tif err != nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"error reading manifest %s: %w\", path, err)\n\t\t}\n\n\t\tscanner := NewYAMLScanner(bytes.NewBuffer(b))\n\t\tfor scanner.Scan() {\n\t\t\tmanifest := scanner.Bytes()\n\t\t\ttypeMeta, err := GetTypeMetaFromBytes(manifest)\n\t\t\tif err != nil {\n\t\t\t\tlog.Debugf(\"Skipping manifest in %s: %v\", path, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif typeMeta.Kind != \"CustomResourceDefinition\" {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Unmarshal based on CRD version.\n\t\t\tvar crGVKs []schema.GroupVersionKind\n\t\t\tswitch gvk := typeMeta.GroupVersionKind(); gvk.Version {\n\t\t\tcase apiextv1.SchemeGroupVersion.Version:\n\t\t\t\tcrd := apiextv1.CustomResourceDefinition{}\n\t\t\t\tif err = yaml.Unmarshal(manifest, &crd); err != nil {\n\t\t\t\t\treturn nil, nil, err\n\t\t\t\t}\n\t\t\t\tv1crds = append(v1crds, crd)\n\t\t\t\tcrGVKs = append(crGVKs, GVKsForV1CustomResourceDefinitions(crd)...)\n\t\t\tcase apiextv1beta1.SchemeGroupVersion.Version:\n\t\t\t\tcrd := apiextv1beta1.CustomResourceDefinition{}\n\t\t\t\tif err := yaml.Unmarshal(manifest, &crd); err != nil {\n\t\t\t\t\treturn nil, nil, err\n\t\t\t\t}\n\t\t\t\tv1beta1crds = append(v1beta1crds, crd)\n\t\t\t\tcrGVKs = append(crGVKs, GVKsForV1beta1CustomResourceDefinitions(crd)...)\n\t\t\tdefault:\n\t\t\t\treturn nil, nil, fmt.Errorf(\"unrecognized CustomResourceDefinition version %q\", gvk.Version)\n\t\t\t}\n\n\t\t\t// Check if any GVK in crd is a duplicate.\n\t\t\tfor _, gvk := range crGVKs {\n\t\t\t\tif _, hasGVK := crGVKSet[gvk]; hasGVK {\n\t\t\t\t\treturn nil, nil, fmt.Errorf(\"duplicate custom resource GVK %s in %s\", gvk, path)\n\t\t\t\t}\n\t\t\t\tcrGVKSet[gvk] = struct{}{}\n\t\t\t}\n\n\t\t}\n\t\tif err = scanner.Err(); err != nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"error scanning %s: %w\", path, err)\n\t\t}\n\t}\n\treturn v1crds, v1beta1crds, nil\n}\n\n// DefinitionsForV1CustomResourceDefinitions returns definition keys for all\n// custom resource versions in each crd in crds.\nfunc DefinitionsForV1CustomResourceDefinitions(crds ...apiextv1.CustomResourceDefinition) (keys []registry.DefinitionKey) {\n\tfor _, crd := range crds {\n\t\tfor _, ver := range crd.Spec.Versions {\n\t\t\tif !ver.Served {\n\t\t\t\tlog.Debugf(\"Not adding unserved CRD %q version %q to set of owned keys\", crd.GetName(), ver.Name)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tkeys = append(keys, registry.DefinitionKey{\n\t\t\t\tName:    crd.GetName(),\n\t\t\t\tGroup:   crd.Spec.Group,\n\t\t\t\tVersion: ver.Name,\n\t\t\t\tKind:    crd.Spec.Names.Kind,\n\t\t\t})\n\t\t}\n\t}\n\treturn keys\n}\n\n// DefinitionsForV1beta1CustomResourceDefinitions returns definition keys for all\n// custom resource versions in each crd in crds.\nfunc DefinitionsForV1beta1CustomResourceDefinitions(crds ...apiextv1beta1.CustomResourceDefinition) (keys []registry.DefinitionKey) {\n\tfor _, crd := range crds {\n\t\tif len(crd.Spec.Versions) == 0 {\n\t\t\tkeys = append(keys, registry.DefinitionKey{\n\t\t\t\tName:    crd.GetName(),\n\t\t\t\tGroup:   crd.Spec.Group,\n\t\t\t\tVersion: crd.Spec.Version,\n\t\t\t\tKind:    crd.Spec.Names.Kind,\n\t\t\t})\n\t\t}\n\t\tfor _, ver := range crd.Spec.Versions {\n\t\t\tif !ver.Served {\n\t\t\t\tlog.Debugf(\"Not adding unserved CRD %q version %q to set of owned keys\", crd.GetName(), ver.Name)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tkeys = append(keys, registry.DefinitionKey{\n\t\t\t\tName:    crd.GetName(),\n\t\t\t\tGroup:   crd.Spec.Group,\n\t\t\t\tVersion: ver.Name,\n\t\t\t\tKind:    crd.Spec.Names.Kind,\n\t\t\t})\n\t\t}\n\t}\n\treturn keys\n}\n\n// GVKsForV1CustomResourceDefinitions returns GroupVersionKind's for all\n// custom resource versions in each crd in crds.\nfunc GVKsForV1CustomResourceDefinitions(crds ...apiextv1.CustomResourceDefinition) (gvks []schema.GroupVersionKind) {\n\tfor _, key := range DefinitionsForV1CustomResourceDefinitions(crds...) {\n\t\tgvks = append(gvks, schema.GroupVersionKind{\n\t\t\tGroup:   key.Group,\n\t\t\tVersion: key.Version,\n\t\t\tKind:    key.Kind,\n\t\t})\n\t}\n\treturn gvks\n}\n\n// GVKsForV1beta1CustomResourceDefinitions returns GroupVersionKind's for all\n// custom resource versions in each crd in crds.\nfunc GVKsForV1beta1CustomResourceDefinitions(crds ...apiextv1beta1.CustomResourceDefinition) (gvks []schema.GroupVersionKind) {\n\tfor _, key := range DefinitionsForV1beta1CustomResourceDefinitions(crds...) {\n\t\tgvks = append(gvks, schema.GroupVersionKind{\n\t\t\tGroup:   key.Group,\n\t\t\tVersion: key.Version,\n\t\t\tKind:    key.Kind,\n\t\t})\n\t}\n\treturn gvks\n}\n\ntype CRDVersions []apiextv1beta1.CustomResourceDefinitionVersion\n\nfunc (vs CRDVersions) Len() int { return len(vs) }\nfunc (vs CRDVersions) Less(i, j int) bool {\n\treturn version.CompareKubeAwareVersionStrings(vs[i].Name, vs[j].Name) > 0\n}\nfunc (vs CRDVersions) Swap(i, j int) { vs[i], vs[j] = vs[j], vs[i] }\n\nfunc Convertv1beta1Tov1CustomResourceDefinition(in *apiextv1beta1.CustomResourceDefinition) (*apiextv1.CustomResourceDefinition, error) {\n\tvar unversioned apiext.CustomResourceDefinition\n\tif err := apiextv1beta1.Convert_v1beta1_CustomResourceDefinition_To_apiextensions_CustomResourceDefinition(in, &unversioned, nil); err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar out apiextv1.CustomResourceDefinition\n\tout.APIVersion = apiextv1.SchemeGroupVersion.String()\n\tout.Kind = \"CustomResourceDefinition\"\n\tif err := apiextv1.Convert_apiextensions_CustomResourceDefinition_To_v1_CustomResourceDefinition(&unversioned, &out, nil); err != nil {\n\t\treturn nil, err\n\t}\n\treturn &out, nil\n}\n"
  },
  {
    "path": "internal/util/k8sutil/api_test.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage k8sutil\n\nimport (\n\t\"reflect\"\n\t\"sort\"\n\t\"testing\"\n\n\tapiextv1beta1 \"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1\"\n)\n\nfunc TestSortVersions(t *testing.T) {\n\tcases := []struct {\n\t\tinputVersions []string\n\t\texpected      []string\n\t}{\n\t\t{[]string{\"\"}, []string{\"\"}},\n\t\t{[]string{\"v1\"}, []string{\"v1\"}},\n\t\t{[]string{\"v1alpha1\"}, []string{\"v1alpha1\"}},\n\t\t{[]string{\"v1alpha1\", \"v1\"}, []string{\"v1\", \"v1alpha1\"}},\n\t\t{\n\t\t\t[]string{\"foo1\", \"foo10\", \"foo2\", \"foo13\", \"foo52\", \"foo23\", \"foo32\", \"foo33\", \"foo100\"},\n\t\t\t[]string{\"foo1\", \"foo10\", \"foo100\", \"foo13\", \"foo2\", \"foo23\", \"foo32\", \"foo33\", \"foo52\"},\n\t\t},\n\t\t{\n\t\t\t[]string{\"v1alpha10\", \"v1alpha1\", \"v1alpha2000\", \"v1alpha3\", \"v1alpha2\", \"v1alpha300\"},\n\t\t\t[]string{\"v1alpha2000\", \"v1alpha300\", \"v1alpha10\", \"v1alpha3\", \"v1alpha2\", \"v1alpha1\"},\n\t\t},\n\t\t{\n\t\t\t[]string{\"v3beta1\", \"v12alpha1\", \"v12alpha2\", \"v10beta3\", \"v1\", \"v11alpha2\", \"foo1\", \"v10\",\n\t\t\t\t\"v2\", \"foo10\", \"v11beta2\"},\n\t\t\t[]string{\"v10\", \"v2\", \"v1\", \"v11beta2\", \"v10beta3\", \"v3beta1\", \"v12alpha2\", \"v12alpha1\",\n\t\t\t\t\"v11alpha2\", \"foo1\", \"foo10\"},\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\tcvs := stringsToCRDVersions(c.inputVersions)\n\t\tsort.Sort(cvs)\n\t\tvs := crdVersionsToStrings(cvs)\n\t\tif !reflect.DeepEqual(vs, c.expected) {\n\t\t\tt.Errorf(\"Output not sorted as expected:\\noutput:   %+q\\nexpected: %+q\", vs, c.expected)\n\t\t}\n\t}\n}\n\nfunc stringsToCRDVersions(vs []string) (cvs CRDVersions) {\n\tfor _, v := range vs {\n\t\tcvs = append(cvs, apiextv1beta1.CustomResourceDefinitionVersion{\n\t\t\tName: v,\n\t\t})\n\t}\n\treturn cvs\n}\n\nfunc crdVersionsToStrings(cvs []apiextv1beta1.CustomResourceDefinitionVersion) (vs []string) {\n\tfor _, v := range cvs {\n\t\tvs = append(vs, v.Name)\n\t}\n\treturn vs\n}\n"
  },
  {
    "path": "internal/util/k8sutil/constants.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage k8sutil\n\nconst (\n\t// KubeConfigEnvVar defines the env variable KUBECONFIG which\n\t// contains the kubeconfig file path.\n\tKubeConfigEnvVar = \"KUBECONFIG\"\n\n\t// WatchNamespaceEnvVar is the constant for env variable WATCH_NAMESPACE\n\t// which is the namespace where the watch activity happens.\n\t// this value is empty if the operator is running with clusterScope.\n\tWatchNamespaceEnvVar = \"WATCH_NAMESPACE\"\n)\n"
  },
  {
    "path": "internal/util/k8sutil/k8sutil.go",
    "content": "// Copyright 2018 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage k8sutil\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"regexp\"\n\t\"strings\"\n\t\"unicode\"\n\n\t\"golang.org/x/text/cases\"\n\t\"golang.org/x/text/language\"\n\t\"k8s.io/apimachinery/pkg/api/meta\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\t\"k8s.io/apimachinery/pkg/util/validation\"\n\t\"k8s.io/apimachinery/pkg/util/yaml\"\n)\n\n// GetDisplayName turns a project dir name in any of {snake, chain, camel}\n// cases, hierarchical dot structure, or space-delimited into a\n// space-delimited, title'd display name.\n// Ex. \"another-_AppOperator_againTwiceThrice More\"\n// ->  \"Another App Operator Again Twice Thrice More\"\nfunc GetDisplayName(name string) string {\n\tfor _, sep := range \".-_ \" {\n\t\tsplitName := strings.Split(name, string(sep))\n\t\tfor i := 0; i < len(splitName); i++ {\n\t\t\tif splitName[i] == \"\" {\n\t\t\t\tsplitName = append(splitName[:i], splitName[i+1:]...)\n\t\t\t\ti--\n\t\t\t} else {\n\t\t\t\tsplitName[i] = strings.TrimSpace(splitName[i])\n\t\t\t}\n\t\t}\n\t\tname = strings.Join(splitName, \" \")\n\t}\n\tsplitName := strings.Split(name, \" \")\n\tfor i, word := range splitName {\n\t\ttemp := word\n\t\to := 0\n\t\tfor j, r := range word {\n\t\t\tif unicode.IsUpper(r) {\n\t\t\t\tif j > 0 && !unicode.IsUpper(rune(word[j-1])) {\n\t\t\t\t\tindex := j + o\n\t\t\t\t\ttemp = temp[0:index] + \" \" + temp[index:]\n\t\t\t\t\to++\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tsplitName[i] = temp\n\t}\n\tcaser := cases.Title(language.AmericanEnglish, cases.NoLower)\n\treturn strings.TrimSpace(caser.String(strings.Join(splitName, \" \")))\n}\n\n// GetTypeMetaFromBytes gets the type and object metadata from b. b is assumed\n// to be a single Kubernetes resource manifest.\nfunc GetTypeMetaFromBytes(b []byte) (t metav1.TypeMeta, err error) {\n\tu := unstructured.Unstructured{}\n\tr := bytes.NewReader(b)\n\tdec := yaml.NewYAMLOrJSONDecoder(r, 8)\n\t// There is only one YAML doc if there are no more bytes to be read or EOF\n\t// is hit.\n\tif err := dec.Decode(&u); err == nil && r.Len() != 0 {\n\t\treturn t, errors.New(\"error getting TypeMeta from bytes: more than one manifest in file\")\n\t} else if err != nil && err != io.EOF {\n\t\treturn t, fmt.Errorf(\"error getting TypeMeta from bytes: %v\", err)\n\t}\n\treturn metav1.TypeMeta{\n\t\tAPIVersion: u.GetAPIVersion(),\n\t\tKind:       u.GetKind(),\n\t}, nil\n}\n\n// dns1123LabelRegexp defines the character set allowed in a DNS 1123 label.\nvar dns1123LabelRegexp = regexp.MustCompile(\"[^a-zA-Z0-9]+\")\n\n// FormatOperatorNameDNS1123 ensures name is DNS1123 label-compliant by\n// replacing all non-compliant UTF-8 characters with \"-\".\nfunc FormatOperatorNameDNS1123(name string) string {\n\tif len(validation.IsDNS1123Label(name)) != 0 {\n\t\t// Use - for any of the non-matching characters\n\t\tn := dns1123LabelRegexp.ReplaceAllString(name, \"-\")\n\n\t\t// Now let's remove any leading or trailing -\n\t\treturn strings.ToLower(strings.Trim(n, \"-\"))\n\t}\n\treturn name\n}\n\n// TrimDNS1123Label trims a label to meet the DNS 1123 label length requirement\n// by removing characters from the beginning of label such that len(label) <= 63.\nfunc TrimDNS1123Label(label string) string {\n\tif len(label) > validation.DNS1123LabelMaxLength {\n\t\treturn strings.Trim(label[len(label)-validation.DNS1123LabelMaxLength:], \"-\")\n\t}\n\treturn label\n}\n\n// SupportsOwnerReference checks whether a given dependent supports owner references, based on the owner.\n// The namespace of the dependent resource can either be passed in explicitly, otherwise it will be\n// extracted from the dependent runtime.Object.\n// This function performs following checks:\n//\n//\t-- True: Owner is cluster-scoped.\n//\t-- True: Both Owner and dependent are Namespaced with in same namespace.\n//\t-- False: Owner is Namespaced and dependent is Cluster-scoped.\n//\t-- False: Both Owner and dependent are Namespaced with different namespaces.\nfunc SupportsOwnerReference(restMapper meta.RESTMapper, owner, dependent runtime.Object, depNamespace string) (bool, error) {\n\townerGVK := owner.GetObjectKind().GroupVersionKind()\n\townerMapping, err := restMapper.RESTMapping(ownerGVK.GroupKind(), ownerGVK.Version)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\tmOwner, err := meta.Accessor(owner)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\tdepGVK := dependent.GetObjectKind().GroupVersionKind()\n\tdepMapping, err := restMapper.RESTMapping(depGVK.GroupKind(), depGVK.Version)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\tmDep, err := meta.Accessor(dependent)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\townerClusterScoped := ownerMapping.Scope.Name() == meta.RESTScopeNameRoot\n\townerNamespace := mOwner.GetNamespace()\n\tdepClusterScoped := depMapping.Scope.Name() == meta.RESTScopeNameRoot\n\tif depNamespace == \"\" {\n\t\tdepNamespace = mDep.GetNamespace()\n\t}\n\n\tif ownerClusterScoped {\n\t\treturn true, nil\n\t}\n\n\tif depClusterScoped {\n\t\treturn false, nil\n\t}\n\n\tif ownerNamespace != depNamespace {\n\t\treturn false, nil\n\t}\n\t// Both owner and dependent are namespace-scoped and in the same namespace.\n\treturn true, nil\n}\n"
  },
  {
    "path": "internal/util/k8sutil/k8sutil_test.go",
    "content": "// Copyright 2018 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage k8sutil\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"k8s.io/apimachinery/pkg/api/meta\"\n\t\"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\t\"k8s.io/apimachinery/pkg/runtime/schema\"\n)\n\nfunc TestGetDisplayName(t *testing.T) {\n\tcases := []struct {\n\t\tinput, wanted string\n\t}{\n\t\t{\"Appoperator\", \"Appoperator\"},\n\t\t{\"appoperator\", \"Appoperator\"},\n\t\t{\"appoperatoR\", \"Appoperato R\"},\n\t\t{\"AppOperator\", \"App Operator\"},\n\t\t{\"appOperator\", \"App Operator\"},\n\t\t{\"app-operator\", \"App Operator\"},\n\t\t{\"app-_operator\", \"App Operator\"},\n\t\t{\"App-operator\", \"App Operator\"},\n\t\t{\"app-_Operator\", \"App Operator\"},\n\t\t{\"app--Operator\", \"App Operator\"},\n\t\t{\"app--_Operator\", \"App Operator\"},\n\t\t{\"APP\", \"APP\"},\n\t\t{\"another-AppOperator_againTwiceThrice More\", \"Another App Operator Again Twice Thrice More\"},\n\t}\n\n\tfor _, c := range cases {\n\t\tdn := GetDisplayName(c.input)\n\t\tif dn != c.wanted {\n\t\t\tt.Errorf(\"Wanted %s, got %s\", c.wanted, dn)\n\t\t}\n\t}\n}\n\nfunc TestSupportsOwnerReference(t *testing.T) {\n\ttype testcase struct {\n\t\tname         string\n\t\trestMapper   meta.RESTMapper\n\t\towner        runtime.Object\n\t\tdependent    runtime.Object\n\t\tresult       bool\n\t\tdepNamespace string\n\t}\n\n\tvar defaultVersion []schema.GroupVersion\n\trestMapper := meta.NewDefaultRESTMapper(defaultVersion)\n\n\tGVK1 := schema.GroupVersionKind{\n\t\tGroup:   \"apps\",\n\t\tVersion: \"v1alpha1\",\n\t\tKind:    \"MyNamespaceKind\",\n\t}\n\tGVK2 := schema.GroupVersionKind{\n\t\tGroup:   \"rbac\",\n\t\tVersion: \"v1alpha1\",\n\t\tKind:    \"MyClusterKind\",\n\t}\n\n\trestMapper.Add(GVK1, meta.RESTScopeNamespace)\n\trestMapper.Add(GVK2, meta.RESTScopeRoot)\n\n\tcases := []testcase{\n\t\t{\n\t\t\tname:       \"Returns false when owner is Namespaced and dependent resource is Clusterscoped.\",\n\t\t\trestMapper: restMapper,\n\t\t\towner: &unstructured.Unstructured{\n\t\t\t\tObject: map[string]any{\n\t\t\t\t\t\"kind\":       \"MyNamespaceKind\",\n\t\t\t\t\t\"apiVersion\": \"apps/v1alpha1\",\n\t\t\t\t\t\"metadata\": map[string]any{\n\t\t\t\t\t\t\"name\":      \"example-nginx-controller\",\n\t\t\t\t\t\t\"namespace\": \"ns\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdependent: &unstructured.Unstructured{\n\t\t\t\tObject: map[string]any{\n\t\t\t\t\t\"kind\":       \"MyClusterKind\",\n\t\t\t\t\t\"apiVersion\": \"rbac/v1alpha1\",\n\t\t\t\t\t\"metadata\": map[string]any{\n\t\t\t\t\t\t\"name\":      \"example-nginx-role\",\n\t\t\t\t\t\t\"namespace\": \"ns\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tresult: false,\n\t\t},\n\t\t{\n\t\t\tname:       \"Returns true for owner and dependant are both ClusterScoped.\",\n\t\t\trestMapper: restMapper,\n\t\t\towner: &unstructured.Unstructured{\n\t\t\t\tObject: map[string]any{\n\t\t\t\t\t\"kind\":       \"MyClusterKind\",\n\t\t\t\t\t\"apiVersion\": \"rbac/v1alpha1\",\n\t\t\t\t\t\"metadata\": map[string]any{\n\t\t\t\t\t\t\"name\":      \"example-nginx-controller\",\n\t\t\t\t\t\t\"namespace\": \"ns\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdependent: &unstructured.Unstructured{\n\t\t\t\tObject: map[string]any{\n\t\t\t\t\t\"kind\":       \"MyClusterKind\",\n\t\t\t\t\t\"apiVersion\": \"rbac/v1alpha1\",\n\t\t\t\t\t\"metadata\": map[string]any{\n\t\t\t\t\t\t\"name\":      \"example-nginx-role\",\n\t\t\t\t\t\t\"namespace\": \"ns\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tresult: true,\n\t\t},\n\t\t{\n\t\t\tname:       \"Returns true when owner and dependant are Namespaced with in same namespace.\",\n\t\t\trestMapper: restMapper,\n\t\t\towner: &unstructured.Unstructured{\n\t\t\t\tObject: map[string]any{\n\t\t\t\t\t\"kind\":       \"MyNamespaceKind\",\n\t\t\t\t\t\"apiVersion\": \"apps/v1alpha1\",\n\t\t\t\t\t\"metadata\": map[string]any{\n\t\t\t\t\t\t\"name\":      \"example-nginx-controller\",\n\t\t\t\t\t\t\"namespace\": \"ns\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdependent: &unstructured.Unstructured{\n\t\t\t\tObject: map[string]any{\n\t\t\t\t\t\"kind\":       \"MyNamespaceKind\",\n\t\t\t\t\t\"apiVersion\": \"apps/v1alpha1\",\n\t\t\t\t\t\"metadata\": map[string]any{\n\t\t\t\t\t\t\"name\":      \"example-nginx-role\",\n\t\t\t\t\t\t\"namespace\": \"ns\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tresult: true,\n\t\t},\n\t\t{\n\t\t\tname:       \"Returns false when owner,and dependant are Namespaced, with different namespaces.\",\n\t\t\trestMapper: restMapper,\n\t\t\towner: &unstructured.Unstructured{\n\t\t\t\tObject: map[string]any{\n\t\t\t\t\t\"kind\":       \"MyNamespaceKind\",\n\t\t\t\t\t\"apiVersion\": \"apps/v1alpha1\",\n\t\t\t\t\t\"metadata\": map[string]any{\n\t\t\t\t\t\t\"name\":      \"example-nginx-controller\",\n\t\t\t\t\t\t\"namespace\": \"ns1\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdependent: &unstructured.Unstructured{\n\t\t\t\tObject: map[string]any{\n\t\t\t\t\t\"kind\":       \"MyNamespaceKind\",\n\t\t\t\t\t\"apiVersion\": \"apps/v1alpha1\",\n\t\t\t\t\t\"metadata\": map[string]any{\n\t\t\t\t\t\t\"name\":      \"example-nginx-role\",\n\t\t\t\t\t\t\"namespace\": \"ns\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tresult: false,\n\t\t},\n\t\t{\n\t\t\tname:       \"Returns false for invalid Owner Kind.\",\n\t\t\trestMapper: restMapper,\n\t\t\towner: &unstructured.Unstructured{\n\t\t\t\tObject: map[string]any{\n\t\t\t\t\t\"kind\":       \"Dummy\",\n\t\t\t\t\t\"apiVersion\": \"apps/v1alpha1\",\n\t\t\t\t\t\"metadata\": map[string]any{\n\t\t\t\t\t\t\"name\":      \"example-nginx-controller\",\n\t\t\t\t\t\t\"namespace\": \"ns1\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdependent: &unstructured.Unstructured{\n\t\t\t\tObject: map[string]any{\n\t\t\t\t\t\"kind\":       \"MyNamespaceKind\",\n\t\t\t\t\t\"apiVersion\": \"apps/v1alpha1\",\n\t\t\t\t\t\"metadata\": map[string]any{\n\t\t\t\t\t\t\"name\":      \"example-nginx-role\",\n\t\t\t\t\t\t\"namespace\": \"ns\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tresult: false,\n\t\t},\n\t\t{\n\t\t\tname:       \"Returns false for invalid dependant Kind.\",\n\t\t\trestMapper: restMapper,\n\t\t\towner: &unstructured.Unstructured{\n\t\t\t\tObject: map[string]any{\n\t\t\t\t\t\"kind\":       \"MyNamespaceKind\",\n\t\t\t\t\t\"apiVersion\": \"apps/v1alpha1\",\n\t\t\t\t\t\"metadata\": map[string]any{\n\t\t\t\t\t\t\"name\":      \"example-nginx-controller\",\n\t\t\t\t\t\t\"namespace\": \"ns1\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdependent: &unstructured.Unstructured{\n\t\t\t\tObject: map[string]any{\n\t\t\t\t\t\"kind\":       \"Dummy\",\n\t\t\t\t\t\"apiVersion\": \"apps/v1alpha1\",\n\t\t\t\t\t\"metadata\": map[string]any{\n\t\t\t\t\t\t\"name\":      \"example-nginx-role\",\n\t\t\t\t\t\t\"namespace\": \"ns\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tresult: false,\n\t\t},\n\t\t{\n\t\t\tname:         \"Returns true if depNamespace provided and matches.\",\n\t\t\trestMapper:   restMapper,\n\t\t\tdepNamespace: \"ns\",\n\t\t\towner: &unstructured.Unstructured{\n\t\t\t\tObject: map[string]any{\n\t\t\t\t\t\"kind\":       \"MyNamespaceKind\",\n\t\t\t\t\t\"apiVersion\": \"apps/v1alpha1\",\n\t\t\t\t\t\"metadata\": map[string]any{\n\t\t\t\t\t\t\"name\":      \"example-nginx-controller\",\n\t\t\t\t\t\t\"namespace\": \"ns\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdependent: &unstructured.Unstructured{\n\t\t\t\tObject: map[string]any{\n\t\t\t\t\t\"kind\":       \"MyNamespaceKind\",\n\t\t\t\t\t\"apiVersion\": \"apps/v1alpha1\",\n\t\t\t\t\t\"metadata\": map[string]any{\n\t\t\t\t\t\t\"name\": \"example-nginx-role\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tresult: true,\n\t\t},\n\t\t{\n\t\t\tname:         \"Returns false if depNamespace provided and doesn't match.\",\n\t\t\trestMapper:   restMapper,\n\t\t\tdepNamespace: \"ns1\",\n\t\t\towner: &unstructured.Unstructured{\n\t\t\t\tObject: map[string]any{\n\t\t\t\t\t\"kind\":       \"MyNamespaceKind\",\n\t\t\t\t\t\"apiVersion\": \"apps/v1alpha1\",\n\t\t\t\t\t\"metadata\": map[string]any{\n\t\t\t\t\t\t\"name\":      \"example-nginx-controller\",\n\t\t\t\t\t\t\"namespace\": \"ns\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tdependent: &unstructured.Unstructured{\n\t\t\t\tObject: map[string]any{\n\t\t\t\t\t\"kind\":       \"MyNamespaceKind\",\n\t\t\t\t\t\"apiVersion\": \"apps/v1alpha1\",\n\t\t\t\t\t\"metadata\": map[string]any{\n\t\t\t\t\t\t\"name\": \"example-nginx-role\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tresult: false,\n\t\t},\n\t}\n\n\tfor _, c := range cases {\n\t\tt.Run(c.name, func(t *testing.T) {\n\t\t\tuseOwner, err := SupportsOwnerReference(c.restMapper, c.owner, c.dependent, c.depNamespace)\n\t\t\tif err != nil {\n\t\t\t\tassert.Error(t, err)\n\t\t\t}\n\t\t\tassert.Equal(t, c.result, useOwner)\n\t\t})\n\t}\n}\n\nfunc TestTrimDNS1123Label(t *testing.T) {\n\ttype testcase struct {\n\t\tname     string\n\t\tlabel    string\n\t\texpected string\n\t}\n\ttestcases := []testcase{\n\t\t{\n\t\t\tname:     \"return valid truncated values\",\n\t\t\tlabel:    \"quay-io-raffaelespazzoli-proactive-node-scaling-operator-bundle-latest\",\n\t\t\texpected: \"raffaelespazzoli-proactive-node-scaling-operator-bundle-latest\",\n\t\t},\n\t\t{\n\t\t\tname:     \"valid labels with proper length are noops\",\n\t\t\tlabel:    \"raffaelespazzoli-proactive-node-scaling-operator-bundle-latest\",\n\t\t\texpected: \"raffaelespazzoli-proactive-node-scaling-operator-bundle-latest\",\n\t\t},\n\t\t{\n\t\t\tname:     \"short invalid labels are left alone\",\n\t\t\tlabel:    \"-$*@*#fixed-invalid(__$)@+==-name-#$($\",\n\t\t\texpected: \"-$*@*#fixed-invalid(__$)@+==-name-#$($\",\n\t\t},\n\t}\n\tfor _, tc := range testcases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tresult := TrimDNS1123Label(tc.label)\n\t\t\tassert.Equal(t, tc.expected, result)\n\t\t})\n\t}\n}\n\nfunc TestFormatOperatorNameDNS1123(t *testing.T) {\n\ttype testcase struct {\n\t\tname     string\n\t\tlabel    string\n\t\texpected string\n\t}\n\ttestcases := []testcase{\n\t\t{\n\t\t\tname:     \"should not start with -\",\n\t\t\tlabel:    \"-doesnot-start-with-hyphen\",\n\t\t\texpected: \"doesnot-start-with-hyphen\",\n\t\t},\n\t\t{\n\t\t\tname:     \"should not start with non-alphanumeric\",\n\t\t\tlabel:    \"$@*#(@does-notstart-garbage\",\n\t\t\texpected: \"does-notstart-garbage\",\n\t\t},\n\t\t{\n\t\t\tname:     \"should not have non-alphanumeric\",\n\t\t\tlabel:    \"sample-1234$@*#(@does-notstart-garbage\",\n\t\t\texpected: \"sample-1234-does-notstart-garbage\",\n\t\t},\n\t\t{\n\t\t\tname:     \"should not end with non-alphanumeric\",\n\t\t\tlabel:    \"sample-1234-does-notstart-garbage#$*@#*($_!-_@(\",\n\t\t\texpected: \"sample-1234-does-notstart-garbage\",\n\t\t},\n\t\t{\n\t\t\tname:     \"should not start or end with hyphen\",\n\t\t\tlabel:    \"-does-not-start-or-end-with-hyphen---\",\n\t\t\texpected: \"does-not-start-or-end-with-hyphen\",\n\t\t},\n\t\t{\n\t\t\tname:     \"empty string is a noop\",\n\t\t\tlabel:    \"\",\n\t\t\texpected: \"\",\n\t\t},\n\t\t{\n\t\t\tname:     \"string of invalid characters results in empty string\",\n\t\t\tlabel:    \"@#@#)$*!!_$#*$*!@\",\n\t\t\texpected: \"\",\n\t\t},\n\t\t{\n\t\t\tname:     \"valid long names are not trimmed\",\n\t\t\tlabel:    \"quay-io-raffaelespazzoli-proactive-node-scaling-operator-bundle-latest\",\n\t\t\texpected: \"quay-io-raffaelespazzoli-proactive-node-scaling-operator-bundle-latest\",\n\t\t},\n\t\t{\n\t\t\tname:     \"should not contain capital letters\",\n\t\t\tlabel:    \"QUAY-IO-gobble-gobBLE\",\n\t\t\texpected: \"quay-io-gobble-gobble\",\n\t\t},\n\t}\n\tfor _, tc := range testcases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tresult := FormatOperatorNameDNS1123(tc.label)\n\t\t\tassert.Equal(t, tc.expected, result)\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "internal/util/k8sutil/object.go",
    "content": "// Copyright 2019 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage k8sutil\n\nimport (\n\t\"k8s.io/apimachinery/pkg/runtime\"\n)\n\ntype MarshalFunc func(any) ([]byte, error)\n\n// GetObjectBytes marshalls an object with m and removes runtime-managed fields:\n// 'status', 'creationTimestamp'\nfunc GetObjectBytes(obj any, m MarshalFunc) ([]byte, error) {\n\tu, err := runtime.DefaultUnstructuredConverter.ToUnstructured(obj)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdeleteKeys := []string{\"status\", \"creationTimestamp\"}\n\tfor _, dk := range deleteKeys {\n\t\tdeleteKeyFromUnstructured(u, dk)\n\t}\n\treturn m(u)\n}\n\nfunc deleteKeyFromUnstructured(u map[string]any, key string) {\n\tif _, ok := u[key]; ok {\n\t\tdelete(u, key)\n\t\treturn\n\t}\n\n\tfor _, v := range u {\n\t\tswitch t := v.(type) {\n\t\tcase map[string]any:\n\t\t\tdeleteKeyFromUnstructured(t, key)\n\t\tcase []any:\n\t\t\tfor _, ti := range t {\n\t\t\t\tif m, ok := ti.(map[string]any); ok {\n\t\t\t\t\tdeleteKeyFromUnstructured(m, key)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "internal/util/k8sutil/scan.go",
    "content": "// Copyright 2018 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage k8sutil\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"io\"\n\n\tk8syaml \"k8s.io/apimachinery/pkg/util/yaml\"\n)\n\nconst maxExecutiveEmpties = 100\n\n// Scanner scans a yaml manifest file for manifest tokens delimited by \"---\".\n// See bufio.Scanner for semantics.\ntype Scanner struct {\n\treader  *k8syaml.YAMLReader\n\ttoken   []byte // Last token returned by split.\n\terr     error  // Sticky error.\n\tempties int    // Count of successive empty tokens.\n\tdone    bool   // Scan has finished.\n}\n\nfunc NewYAMLScanner(r io.Reader) *Scanner {\n\treturn &Scanner{reader: k8syaml.NewYAMLReader(bufio.NewReader(r))}\n}\n\nfunc (s *Scanner) Err() error {\n\tif s.err == io.EOF {\n\t\treturn nil\n\t}\n\treturn s.err\n}\n\nfunc (s *Scanner) Scan() bool {\n\tif s.done {\n\t\treturn false\n\t}\n\n\tvar (\n\t\ttok []byte\n\t\terr error\n\t)\n\n\tfor {\n\t\ttok, err = s.reader.Read()\n\t\tif err != nil {\n\t\t\tif err == io.EOF {\n\t\t\t\ts.done = true\n\t\t\t}\n\t\t\ts.err = err\n\t\t\treturn false\n\t\t}\n\t\tif len(bytes.TrimSpace(tok)) == 0 {\n\t\t\ts.empties++\n\t\t\tif s.empties > maxExecutiveEmpties {\n\t\t\t\tpanic(\"yaml.Scan: too many empty tokens without progressing\")\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\ts.empties = 0\n\t\ts.token = tok\n\t\treturn true\n\t}\n}\n\nfunc (s *Scanner) Text() string {\n\treturn string(s.token)\n}\n\nfunc (s *Scanner) Bytes() []byte {\n\treturn s.token\n}\n"
  },
  {
    "path": "internal/util/projutil/interactive_promt_util.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage projutil\n\nimport (\n\t\"bufio\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\t\"strings\"\n)\n\n// InteractiveLevel captures the user preference on the generation of interactive\n// commands.\ntype InteractiveLevel int\n\nconst (\n\t// User has not turned interactive mode on or off, default to off.\n\tInteractiveSoftOff InteractiveLevel = iota\n\t// User has explicitly turned interactive mode off.\n\tInteractiveHardOff\n\t// User only explicitly turned interactive mode on.\n\tInteractiveOnAll\n)\n\nfunc printMessage(msg string, isOptional bool) {\n\tfmt.Println()\n\tif isOptional {\n\t\tfmt.Print(strings.TrimSpace(msg) + \" (optional): \" + \"\\n\" + \"> \")\n\t} else {\n\t\tfmt.Print(strings.TrimSpace(msg) + \" (required): \" + \"\\n\" + \"> \")\n\t}\n}\n\nfunc GetRequiredInput(msg string) string {\n\treturn getRequiredInput(os.Stdin, msg)\n}\n\nfunc getRequiredInput(rd io.Reader, msg string) string {\n\treader := bufio.NewReader(rd)\n\n\tfor {\n\t\tprintMessage(msg, false)\n\t\tvalue := readInput(reader)\n\t\tif value != \"\" {\n\t\t\treturn value\n\t\t}\n\t\tfmt.Printf(\"Input is required. \")\n\t}\n}\n\nfunc GetOptionalInput(msg string) string {\n\tprintMessage(msg, true)\n\tvalue := readInput(bufio.NewReader(os.Stdin))\n\treturn value\n}\n\nfunc GetStringArray(msg string) []string {\n\treturn getStringArray(os.Stdin, msg)\n}\n\nfunc getStringArray(rd io.Reader, msg string) []string {\n\treader := bufio.NewReader(rd)\n\tfor {\n\t\tprintMessage(msg, false)\n\t\tvalue := readArray(reader)\n\t\tif len(value) != 0 && len(value[0]) != 0 {\n\t\t\treturn value\n\t\t}\n\t\tfmt.Printf(\"No list provided. \")\n\t}\n}\n\n// readstdin reads a line from stdin and returns the value.\nfunc readLine(reader *bufio.Reader) string {\n\ttext, err := reader.ReadString('\\n')\n\tif err != nil {\n\t\tlog.Fatalf(\"Error when reading input: %v\", err)\n\t}\n\treturn strings.Trim(strings.TrimSpace(text), \"`'\\\"\")\n}\n\nfunc readInput(reader *bufio.Reader) string {\n\tfor {\n\t\ttext := readLine(reader)\n\t\treturn text\n\t}\n}\n\n// readArray parses the line from stdin, returns an array\n// of words.\nfunc readArray(reader *bufio.Reader) []string {\n\tarr := make([]string, 0)\n\ttext := readLine(reader)\n\n\tfor words := range strings.SplitSeq(text, \",\") {\n\t\tarr = append(arr, strings.TrimSpace(words))\n\t}\n\treturn arr\n}\n"
  },
  {
    "path": "internal/util/projutil/interactive_promt_util_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage projutil\n\nimport (\n\t\"bytes\"\n\t\"reflect\"\n\t\"testing\"\n)\n\nfunc TestUserInput(t *testing.T) {\n\ttype args struct {\n\t\tmsg     string\n\t\tcontent []byte\n\t}\n\n\ttests := []struct {\n\t\tname string\n\t\targs args\n\t\twant string\n\t}{\n\t\t{\n\t\t\tname: \"test when user provides input to the command\",\n\t\t\targs: args{\n\t\t\t\tmsg:     \"Enter a word: \",\n\t\t\t\tcontent: []byte(\"Memcached Operator\\n\"),\n\t\t\t},\n\t\t\twant: \"Memcached Operator\",\n\t\t},\n\t\t{\n\t\t\tname: \"test when user does not provide input and prompt appears again\",\n\t\t\targs: args{\n\t\t\t\tmsg:     \"Enter a word: \",\n\t\t\t\tcontent: []byte(\"\\nMemcached Operator\\n\"),\n\t\t\t},\n\t\t\twant: \"Memcached Operator\",\n\t\t},\n\t\t{\n\t\t\tname: \"test when user provides quoted input to the command\",\n\t\t\targs: args{\n\t\t\t\tmsg:     \"Enter a word: \",\n\t\t\t\tcontent: []byte(\"'Memcached Operator'\\n\"),\n\t\t\t},\n\t\t\twant: \"Memcached Operator\",\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tif got := getRequiredInput(bytes.NewBuffer(tt.args.content), tt.args.msg); got != tt.want {\n\t\t\t\tt.Errorf(\"GetRequiredInput() = %v, want %v\", got, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestUserInputStringArray(t *testing.T) {\n\ttype args struct {\n\t\tmsg     string\n\t\tcontent []byte\n\t}\n\n\ttests := []struct {\n\t\tname string\n\t\targs args\n\t\twant []string\n\t}{\n\t\t{\n\t\t\tname: \"test when user provides input to the command\",\n\t\t\targs: args{\n\t\t\t\tmsg:     \"Enter list of words\",\n\t\t\t\tcontent: []byte(\"app, memcached-operator \\n\"),\n\t\t\t},\n\t\t\twant: []string{\"app\", \"memcached-operator\"},\n\t\t},\n\t\t{\n\t\t\tname: \"test when user does not provide input and prompt appears again\",\n\t\t\targs: args{\n\t\t\t\tmsg:     \"Enter list of words\",\n\t\t\t\tcontent: []byte(\"\\noperator, app\\n\"),\n\t\t\t},\n\t\t\twant: []string{\"operator\", \"app\"},\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tif got := getStringArray(bytes.NewBuffer(tt.args.content), tt.args.msg); !reflect.DeepEqual(got, tt.want) {\n\t\t\t\tt.Errorf(\"GetRequiredInput() = %v, want %v\", got, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "internal/util/projutil/project_util.go",
    "content": "// Copyright 2018 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage projutil\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"regexp\"\n\t\"strings\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/afero\"\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/config\"\n\tyamlstore \"sigs.k8s.io/kubebuilder/v4/pkg/config/store/yaml\"\n\t_ \"sigs.k8s.io/kubebuilder/v4/pkg/config/v3\" // Register config/v3 for `config.New`\n\t\"sigs.k8s.io/kubebuilder/v4/pkg/machinery\"\n)\n\nconst (\n\t// Useful file modes.\n\tDirMode      = 0755\n\tFileMode     = 0644\n\tExecFileMode = 0755\n)\n\nconst (\n\t// Go env vars.\n\tGoFlagsEnv = \"GOFLAGS\"\n)\n\n// Default config file path.\nconst configFile = \"PROJECT\"\n\n// OperatorType - the type of operator\ntype OperatorType = string\n\nconst (\n\t// OperatorTypeGo - golang type of operator.\n\tOperatorTypeGo OperatorType = \"go\"\n\t// OperatorTypeAnsible - ansible type of operator.\n\tOperatorTypeAnsible OperatorType = \"ansible\"\n\t// OperatorTypeHelm - helm type of operator.\n\tOperatorTypeHelm OperatorType = \"helm\"\n\t// OperatorTypeUnknown - unknown type of operator.\n\tOperatorTypeUnknown OperatorType = \"unknown\"\n)\n\ntype ErrUnknownOperatorType struct {\n\tType string\n}\n\nfunc (e ErrUnknownOperatorType) Error() string {\n\tif e.Type == \"\" {\n\t\treturn \"unknown operator type\"\n\t}\n\treturn fmt.Sprintf(`unknown operator type \"%v\"`, e.Type)\n}\n\n// HasProjectFile returns true if the project is configured as a kubebuilder\n// project.\nfunc HasProjectFile() bool {\n\t_, err := os.Stat(configFile)\n\tif err != nil {\n\t\tif os.IsNotExist(err) {\n\t\t\treturn false\n\t\t}\n\t\tlog.Fatalf(\"Failed to read PROJECT file to detect kubebuilder project: %v\", err)\n\t}\n\treturn true\n}\n\n// ReadConfig returns a configuration if a file containing one exists at the\n// default path (project root).\nfunc ReadConfig() (config.Config, error) {\n\tstore := yamlstore.New(machinery.Filesystem{FS: afero.NewOsFs()})\n\tif err := store.Load(); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn store.Config(), nil\n}\n\n// PluginChainToOperatorType converts a plugin chain to an operator project type.\n// TODO(estroz): this can probably be made more robust by checking known plugin keys directly.\nfunc PluginChainToOperatorType(pluginKeys []string) OperatorType {\n\tfor _, pluginKey := range pluginKeys {\n\t\tswitch {\n\t\tcase strings.HasPrefix(pluginKey, \"go\"):\n\t\t\treturn OperatorTypeGo\n\t\tcase strings.HasPrefix(pluginKey, \"helm\"):\n\t\t\treturn OperatorTypeHelm\n\t\tcase strings.HasPrefix(pluginKey, \"ansible\"):\n\t\t\treturn OperatorTypeAnsible\n\t\t}\n\t}\n\treturn OperatorTypeUnknown\n}\n\n// GetProjectLayout returns the `layout` field as a comma separated list.\nfunc GetProjectLayout(cfg config.Config) string {\n\treturn strings.Join(cfg.GetPluginChain(), \",\")\n}\n\nvar flagRe = regexp.MustCompile(\"(.* )?-v(.* )?\")\n\n// SetGoVerbose sets GOFLAGS=\"${GOFLAGS} -v\" if GOFLAGS does not\n// already contain \"-v\" to make \"go\" command output verbose.\nfunc SetGoVerbose() error {\n\tgf, ok := os.LookupEnv(GoFlagsEnv)\n\tif !ok || len(gf) == 0 {\n\t\treturn os.Setenv(GoFlagsEnv, \"-v\")\n\t}\n\tif !flagRe.MatchString(gf) {\n\t\treturn os.Setenv(GoFlagsEnv, gf+\" -v\")\n\t}\n\treturn nil\n}\n\n// RewriteFileContents adds newContent to the line after the last occurrence of target in filename's contents,\n// then writes the updated contents back to disk.\nfunc RewriteFileContents(filename, target, newContent string) error {\n\ttext, err := os.ReadFile(filename)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error in getting contents from the file, %v\", err)\n\t}\n\n\tmodifiedContent, err := appendContent(string(text), target, newContent)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\terr = os.WriteFile(filename, []byte(modifiedContent), FileMode)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error writing modified contents to file, %v\", err)\n\t}\n\n\treturn nil\n}\n\nfunc appendContent(fileContents, target, newContent string) (string, error) {\n\tlabelIndex := strings.LastIndex(fileContents, target)\n\tif labelIndex == -1 {\n\t\treturn \"\", fmt.Errorf(\"no prior string %s in newContent\", target)\n\t}\n\n\tseparationIndex := strings.Index(fileContents[labelIndex:], \"\\n\")\n\tif separationIndex == -1 {\n\t\treturn \"\", fmt.Errorf(\"no new line at the end of string %s\", fileContents[labelIndex:])\n\t}\n\n\tindex := labelIndex + separationIndex + 1\n\treturn fileContents[:index] + newContent + fileContents[index:], nil\n}\n"
  },
  {
    "path": "internal/util/projutil/projutil_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage projutil\n\nimport (\n\t\"errors\"\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nvar _ = Describe(\"Testing projutil helpers\", func() {\n\tDescribe(\"Testing RewriteFileContents\", func() {\n\t\tvar (\n\t\t\tfileContents   string\n\t\t\tinstruction    string\n\t\t\tcontent        string\n\t\t\texpectedOutput string\n\t\t)\n\t\tIt(\"Should pass when file has instruction\", func() {\n\t\t\tfileContents = \"LABEL operators.operatorframework.io.bundle.mediatype.v1=registry+v1 \\n\" +\n\t\t\t\t\"LABEL operators.operatorframework.io.bundle.manifests.v1=manifests/ \\n\" +\n\t\t\t\t\"LABEL operators.operatorframework.io.bundle.metadata.v1=metadata/ \\n\" +\n\t\t\t\t\"COPY deploy/olm-catalog/memcached-operator/manifests /manifests/ \\n\"\n\n\t\t\tinstruction = \"LABEL\"\n\n\t\t\tcontent = \"LABEL operators.operatorframework.io.bundle.tests.v1=tests/ \\n\"\n\n\t\t\texpectedOutput = \"LABEL operators.operatorframework.io.bundle.mediatype.v1=registry+v1 \\n\" +\n\t\t\t\t\"LABEL operators.operatorframework.io.bundle.manifests.v1=manifests/ \\n\" +\n\t\t\t\t\"LABEL operators.operatorframework.io.bundle.metadata.v1=metadata/ \\n\" +\n\t\t\t\t\"LABEL operators.operatorframework.io.bundle.tests.v1=tests/ \\n\" +\n\t\t\t\t\"COPY deploy/olm-catalog/memcached-operator/manifests /manifests/ \\n\"\n\n\t\t\tExpect(appendContent(fileContents, instruction, content)).To(Equal(expectedOutput))\n\t\t})\n\n\t\tIt(\"Should result in error when file does not have instruction\", func() {\n\t\t\tfileContents = \"LABEL operators.operatorframework.io.bundle.mediatype.v1=registry+v1 \\n\" +\n\t\t\t\t\"LABEL operators.operatorframework.io.bundle.manifests.v1=manifests/ \\n\" +\n\t\t\t\t\"LABEL operators.operatorframework.io.bundle.metadata.v1=metadata/ \\n\" +\n\t\t\t\t\"COPY deploy/olm-catalog/memcached-operator/manifests /manifests/ \\n\"\n\n\t\t\tinstruction = \"ADD\"\n\n\t\t\tcontent = \"ADD operators.operatorframework.io.bundle.tests.v1=tests/ \\n\"\n\n\t\t\texpectedOutput = \"LABEL operators.operatorframework.io.bundle.mediatype.v1=registry+v1 \\n\" +\n\t\t\t\t\"LABEL operators.operatorframework.io.bundle.manifests.v1=manifests/ \\n\" +\n\t\t\t\t\"LABEL operators.operatorframework.io.bundle.metadata.v1=metadata/ \\n\" +\n\t\t\t\t\"LABEL operators.operatorframework.io.bundle.tests.v1=tests/ \\n\" +\n\t\t\t\t\"COPY deploy/olm-catalog/memcached-operator/manifests /manifests/ \\n\"\n\n\t\t\t_, err := appendContent(fileContents, instruction, content)\n\n\t\t\tExpect(err).Should(MatchError(errors.New(\"no prior string ADD in newContent\")))\n\t\t})\n\n\t\tIt(\"Should result in error as no new line at the end of dockerfile command\", func() {\n\t\t\tfileContents = \"LABEL operators.operatorframework.io.bundle.mediatype.v1=registry+v1 \\n\" +\n\t\t\t\t\"LABEL operators.operatorframework.io.bundle.manifests.v1=manifests/ \\n\" +\n\t\t\t\t\"LABEL operators.operatorframework.io.bundle.metadata.v1=metadata/\"\n\n\t\t\tinstruction = \"LABEL\"\n\n\t\t\tcontent = \"LABEL operators.operatorframework.io.bundle.tests.v1=tests/ \\n\"\n\n\t\t\texpectedOutput = \"LABEL operators.operatorframework.io.bundle.mediatype.v1=registry+v1 \\n\" +\n\t\t\t\t\"LABEL operators.operatorframework.io.bundle.manifests.v1=manifests/ \\n\" +\n\t\t\t\t\"LABEL operators.operatorframework.io.bundle.metadata.v1=metadata/ \\n\" +\n\t\t\t\t\"LABEL operators.operatorframework.io.bundle.tests.v1=tests/ \\n\"\n\n\t\t\t_, err := appendContent(fileContents, instruction, content)\n\n\t\t\tExpect(err).ShouldNot((BeNil()))\n\t\t})\n\n\t})\n})\n\nfunc TestMetadata(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"Projutil Helpers suite\")\n}\n"
  },
  {
    "path": "internal/validate/external.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage validate\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\tapierrors \"github.com/operator-framework/api/pkg/validation/errors\"\n)\n\n// For mocking in tests.\nvar stderr io.Writer = os.Stderr\n\n// GetExternalValidatorEntrypoints returns a list of external validator entrypoints\n// retrieved from given entrypoints string. If not set or set to the empty string,\n// GetExternalValidatorEntrypoints returns false.\nfunc GetExternalValidatorEntrypoints(entrypoints string) ([]string, bool) {\n\tif strings.TrimSpace(entrypoints) == \"\" {\n\t\treturn nil, false\n\t}\n\treturn filepath.SplitList(entrypoints), true\n}\n\n// RunExternalValidators runs each entrypoint in entrypoint as a exec.Cmd with the\n// single argument bundleRoot. External validators are expected to parse the bundle\n// themselves with library APIs available in\n// https://pkg.go.dev/github.com/operator-framework/api/pkg/manifests.\nfunc RunExternalValidators(ctx context.Context, entrypoints []string, bundleRoot string) ([]apierrors.ManifestResult, error) {\n\tmanifestresults := make([]apierrors.ManifestResult, len(entrypoints))\n\tfor i, entrypoint := range entrypoints {\n\t\tcmd := exec.CommandContext(ctx, entrypoint, bundleRoot)\n\t\t// Let error text go to stderr.\n\t\tcmd.Stderr = stderr\n\n\t\t// The validator should only exit non-zero if the entrypoint itself failed to run,\n\t\t// not if the bundle failed validation.\n\t\tstdout, err := cmd.StdoutPipe()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif err := cmd.Start(); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\t// Ensure output conforms to the Output spec.\n\t\tdec := json.NewDecoder(stdout)\n\t\tdec.DisallowUnknownFields()\n\n\t\tdecodeErr := dec.Decode(&manifestresults[i])\n\t\t// Always wait for the command to finish to ensure stderr is fully written\n\t\t// and all goroutines complete before returning.\n\t\tif err := cmd.Wait(); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\t// Return decode error after waiting for command to complete\n\t\tif decodeErr != nil {\n\t\t\tfmt.Printf(\"decode failed: %v\\n\", decodeErr)\n\t\t\treturn nil, decodeErr\n\t\t}\n\t}\n\treturn manifestresults, nil\n}\n"
  },
  {
    "path": "internal/validate/external_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage validate\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"path/filepath\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\tapierrors \"github.com/operator-framework/api/pkg/validation/errors\"\n)\n\nvar _ = Describe(\"External\", func() {\n\tvar (\n\t\tctx context.Context\n\n\t\ttestdataDir = \"testdata\"\n\t)\n\n\tBeforeEach(func() {\n\t\tctx = context.Background()\n\t})\n\n\tDescribe(\"getexternalvalidatorentrypoints\", func() {\n\t\tIt(\"should return entrypoints\", func() {\n\t\t\tpaths := \"/path/to/validate1.sh:/path/to/validator2\"\n\t\t\tentrypoints, hasExternal := GetExternalValidatorEntrypoints(paths)\n\t\t\tExpect(hasExternal).To(BeTrue())\n\t\t\tExpect(entrypoints).To(HaveLen(2))\n\t\t\tExpect(entrypoints[0]).To(Equal(\"/path/to/validate1.sh\"))\n\t\t})\n\t\tIt(\"should return false\", func() {\n\t\t\tentrypoints, hasExternal := GetExternalValidatorEntrypoints(\"\")\n\t\t\tExpect(hasExternal).To(BeFalse())\n\t\t\tExpect(entrypoints).To(BeEmpty())\n\t\t})\n\t})\n\n\tContext(\"passing validator\", func() { //nolint:dupl\n\t\tIt(\"runs successfully\", func() {\n\t\t\tentrypoints, hasExternal := GetExternalValidatorEntrypoints(filepath.Join(testdataDir, \"passes.sh\"))\n\t\t\tExpect(hasExternal).To(BeTrue())\n\t\t\tresults, err := RunExternalValidators(ctx, entrypoints, \"foo/bar\")\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\tExpect(results).To(HaveLen(1))\n\t\t\tExpect(results[0].Name).To(Equal(\"passes-bundle\"))\n\t\t\tExpect(results[0].Errors).To(BeEmpty())\n\t\t})\n\t})\n\n\tContext(\"failing validator\", func() { //nolint:dupl\n\t\tIt(\"fails with one error\", func() {\n\t\t\tentrypoints, hasExternal := GetExternalValidatorEntrypoints(filepath.Join(testdataDir, \"fails.sh\"))\n\t\t\tExpect(hasExternal).To(BeTrue())\n\t\t\tresults, err := RunExternalValidators(ctx, entrypoints, \"foo/bar\")\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\tExpect(results).To(HaveLen(1))\n\t\t\tExpect(results[0].Name).To(Equal(\"fails-bundle\"))\n\t\t\tExpect(results[0].Errors).To(HaveLen(1))\n\t\t\tExpect(results[0].Errors[0].Type).To(Equal(apierrors.ErrorInvalidCSV))\n\t\t\tExpect(results[0].Errors[0].Detail).To(Equal(\"invalid field Pesce\"))\n\t\t})\n\t})\n\n\tContext(\"errored validator\", func() {\n\t\tIt(\"does not run\", func() {\n\t\t\tentrypoints, hasExternal := GetExternalValidatorEntrypoints(filepath.Join(testdataDir, \"errors.sh\"))\n\t\t\tExpect(hasExternal).To(BeTrue())\n\t\t\tstderrBuf := &bytes.Buffer{}\n\t\t\tstderr = stderrBuf\n\t\t\tresults, err := RunExternalValidators(ctx, entrypoints, \"foo/bar\")\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t\tExpect(stderrBuf.String()).To(Equal(\"validator runtime error\"))\n\t\t\tExpect(results).To(BeEmpty())\n\t\t})\n\t})\n\n})\n"
  },
  {
    "path": "internal/validate/result.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage validate\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\n\tapierrors \"github.com/operator-framework/api/pkg/validation/errors\"\n\tregistrybundle \"github.com/operator-framework/operator-registry/pkg/lib/bundle\"\n\t\"github.com/sirupsen/logrus\"\n)\n\n// TODO: might be nice to formalize this with apiVersion=sdk.operatorframework.io/v1alpha1, kind=ValidationResult.\n\nconst (\n\tJSONAlpha1Output = \"json-alpha1\"\n\tTextOutput       = \"text\"\n)\n\n// Result represents the final result\ntype Result struct {\n\tPassed  bool     `json:\"passed\"`\n\tOutputs []Output `json:\"outputs\"`\n}\n\n// Output represents the logs which are used to return the final result in the JSON format\ntype Output struct {\n\tType    string `json:\"type\"`\n\tMessage string `json:\"message\"`\n}\n\n// NewResult return a new result object which starts with passed == true since has no errors\nfunc NewResult() *Result {\n\treturn &Result{Passed: true}\n}\n\n// AddManifestResults adds warnings and errors in results to Results.\nfunc (r *Result) AddManifestResults(results ...apierrors.ManifestResult) {\n\tfor _, mr := range results {\n\t\tfor _, w := range mr.Warnings {\n\t\t\tr.AddWarn(w)\n\t\t}\n\t\tfor _, e := range mr.Errors {\n\t\t\tr.AddError(e)\n\t\t}\n\t}\n}\n\n// AddInfo will add a log to the result with the Info Level\nfunc (r *Result) AddInfo(msg string) {\n\tr.Outputs = append(r.Outputs, Output{\n\t\tType:    logrus.InfoLevel.String(),\n\t\tMessage: msg,\n\t})\n}\n\n// AddError will add a log to the result with the Error Level\nfunc (r *Result) AddError(err error) {\n\tverr := registrybundle.ValidationError{}\n\tif errors.As(err, &verr) {\n\t\tfor _, valErr := range verr.Errors {\n\t\t\tr.Outputs = append(r.Outputs, Output{\n\t\t\t\tType:    logrus.ErrorLevel.String(),\n\t\t\t\tMessage: valErr.Error(),\n\t\t\t})\n\t\t}\n\t} else {\n\t\tr.Outputs = append(r.Outputs, Output{\n\t\t\tType:    logrus.ErrorLevel.String(),\n\t\t\tMessage: err.Error(),\n\t\t})\n\t}\n\tr.Passed = false\n}\n\n// AddWarn will add a log to the result with the Warn Level\nfunc (r *Result) AddWarn(err error) {\n\tr.Outputs = append(r.Outputs, Output{\n\t\tType:    logrus.WarnLevel.String(),\n\t\tMessage: err.Error(),\n\t})\n}\n\n// Combine creates a new Result and calls Result.Combine(results).\nfunc Combine(results ...Result) (r Result, err error) {\n\terr = r.Combine(results...)\n\treturn r, err\n}\n\n// Combine combines results into r, setting r.Passed = false if\n// any Result in results has r.Passed == false.\nfunc (r *Result) Combine(results ...Result) error {\n\tfor _, result := range results {\n\t\tr.Outputs = append(r.Outputs, result.Outputs...)\n\t}\n\treturn r.prepare()\n}\n\n// prepare should be used when writing an Result to a non-log writer.\n// it will ensure that the passed boolean will properly set in the case of the setters were not properly used\nfunc (r *Result) prepare() error {\n\tr.Passed = true\n\tfor i, obj := range r.Outputs {\n\t\tlvl, err := logrus.ParseLevel(obj.Type)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif r.Passed && lvl == logrus.ErrorLevel {\n\t\t\tr.Passed = false\n\t\t}\n\t\tlvlBytes, _ := lvl.MarshalText()\n\t\tr.Outputs[i].Type = string(lvlBytes)\n\t}\n\treturn nil\n}\n\n// PrintWithFormat prints output to w in format, and exits if some object in output\n// is not in a passing state.\nfunc (r *Result) PrintWithFormat(format string) (failed bool, err error) {\n\treturn r.printWithFormat(os.Stdout, format)\n}\n\nfunc (r *Result) printWithFormat(w io.Writer, format string) (failed bool, err error) {\n\t// the prepare will ensure the result data if the setters were not used\n\tif err = r.prepare(); err != nil {\n\t\treturn failed, fmt.Errorf(\"error preparing output: %v\", err)\n\t}\n\n\tswitch format {\n\tcase JSONAlpha1Output:\n\t\terr = r.printJSON(w)\n\tcase TextOutput: // Text\n\t\t// Address all to the Stdout when the type is not JSON\n\t\tentry := logrus.NewEntry(newLoggerTo(w))\n\t\terr = r.printText(entry)\n\tdefault:\n\t\treturn failed, fmt.Errorf(\"invalid result format type: %s\", format)\n\t}\n\tif err == nil && !r.Passed {\n\t\tfailed = true\n\t}\n\n\treturn failed, err\n}\n\n// printText will print the Output in human readable format\nfunc (r *Result) printText(logger *logrus.Entry) error {\n\tfor _, obj := range r.Outputs {\n\t\tlvl, err := logrus.ParseLevel(obj.Type)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tswitch lvl {\n\t\tcase logrus.InfoLevel:\n\t\t\tlogger.Info(obj.Message)\n\t\tcase logrus.WarnLevel:\n\t\t\tlogger.Warn(obj.Message)\n\t\tcase logrus.ErrorLevel:\n\t\t\tlogger.Error(obj.Message)\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"unknown log output level %q\", obj.Type)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// printJSON will print the Output in JSON format\nfunc (r *Result) printJSON(w io.Writer) error {\n\tprettyJSON, err := json.MarshalIndent(r, \"\", \"    \")\n\tif err != nil {\n\t\treturn err\n\t}\n\tfmt.Fprintf(w, \"%s\\n\", string(prettyJSON))\n\treturn nil\n}\n\nfunc newLoggerTo(w io.Writer) *logrus.Logger {\n\tlogger := logrus.New()\n\tlogger.SetOutput(w)\n\treturn logger\n}\n"
  },
  {
    "path": "internal/validate/result_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage validate\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\tlog \"github.com/sirupsen/logrus\"\n)\n\nvar _ = Describe(\"Output Result\", func() {\n\tvar result *Result\n\n\tBeforeEach(func() {\n\t\tresult = NewResult()\n\t})\n\n\tDescribe(\"Result Model Manipulation\", func() {\n\t\tIt(\"should add the error with ErrorLevel and passed should be flagged with false\", func() {\n\t\t\tresult.AddError(errors.New(\"example of an error\"))\n\n\t\t\tExpect(result).NotTo(BeNil())\n\t\t\tExpect(result.Passed).To(BeFalse())\n\t\t\tExpect(result.Outputs[0].Type).To(Equal(log.ErrorLevel.String()))\n\t\t\tExpect(result.Outputs[0].Message).To(Equal(\"example of an error\"))\n\t\t})\n\n\t\tIt(\"should add the error with WarnLevel and passed should be flagged with true\", func() {\n\t\t\tresult.AddWarn(errors.New(\"example of a warn\"))\n\n\t\t\tExpect(result).NotTo(BeNil())\n\t\t\tExpect(result.Passed).To(BeTrue())\n\t\t\tExpect(result.Outputs[0].Type).To(Equal(log.WarnLevel.String()))\n\t\t\tExpect(result.Outputs[0].Message).To(Equal(\"example of a warn\"))\n\t\t})\n\n\t\tIt(\"should add msg with InfoLevel and passed should be flagged with true\", func() {\n\t\t\tresult.AddInfo(\"Example of an info\")\n\n\t\t\tExpect(result).NotTo(BeNil())\n\t\t\tExpect(result.Passed).To(BeTrue())\n\t\t\tExpect(result.Outputs[0].Type).To(Equal(log.InfoLevel.String()))\n\t\t\tExpect(result.Outputs[0].Message).To(Equal(\"Example of an info\"))\n\t\t})\n\n\t\tIt(\"should passed be flagged with false when has many outputs and an error\", func() {\n\t\t\tresult.AddError(errors.New(\"example of an error\"))\n\t\t\tresult.AddWarn(errors.New(\"example of a warn\"))\n\t\t\tresult.AddInfo(\"Example of an info\")\n\n\t\t\tExpect(result).NotTo(BeNil())\n\t\t\tExpect(result.Passed).To(BeFalse())\n\t\t\tExpect(result.Outputs).To(HaveLen(3))\n\t\t})\n\n\t})\n\n\tDescribe(\"PrintText\", func() {\n\t\tIt(\"should work successfully with valid log levels\", func() {\n\t\t\tlogger := log.NewEntry(newLoggerTo(os.Stderr))\n\t\t\tresult.AddError(errors.New(\"example of an error\"))\n\t\t\tresult.AddWarn(errors.New(\"example of a warn\"))\n\t\t\tresult.AddInfo(\"Example of an info\")\n\n\t\t\terr := result.printText(logger)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t})\n\n\t\tIt(\"should fail when an invalid log level is found\", func() {\n\t\t\t// This scenario can just occurs if the setters are not used\n\t\t\tlogger := log.NewEntry(newLoggerTo(os.Stderr))\n\t\t\tresult.Outputs = append(result.Outputs, Output{\n\t\t\t\tType:    log.TraceLevel.String(),\n\t\t\t\tMessage: \"invalid\",\n\t\t\t})\n\n\t\t\terr := result.printText(logger)\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t\tExpect(err.Error()).To(Equal(\"unknown log output level \\\"trace\\\"\"))\n\t\t})\n\n\t\tIt(\"should fail when is not possible parse the log level\", func() {\n\t\t\t// This scenario can just occurs if the setters are not used\n\t\t\tlogger := log.NewEntry(newLoggerTo(os.Stderr))\n\t\t\tresult.Outputs = append(result.Outputs, Output{\n\t\t\t\tType:    \"invalid\",\n\t\t\t\tMessage: \"invalid\",\n\t\t\t})\n\n\t\t\terr := result.printText(logger)\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t\tExpect(err.Error()).To(Equal(\"not a valid logrus Level: \\\"invalid\\\"\"))\n\t\t})\n\t})\n\n\tDescribe(\"prepare\", func() {\n\t\tIt(\"should finished with passed flagged with false when has an output with the ErrorLevel\", func() {\n\t\t\t// This scenario can just occurs if the setters are not used\n\t\t\tresult.Outputs = append(result.Outputs, Output{\n\t\t\t\tType:    log.ErrorLevel.String(),\n\t\t\t\tMessage: \"error\",\n\t\t\t})\n\n\t\t\tresult.Outputs = append(result.Outputs, Output{\n\t\t\t\tType:    log.InfoLevel.String(),\n\t\t\t\tMessage: \"info\",\n\t\t\t})\n\n\t\t\tresult.Outputs = append(result.Outputs, Output{\n\t\t\t\tType:    log.WarnLevel.String(),\n\t\t\t\tMessage: \"warn\",\n\t\t\t})\n\n\t\t\terr := result.prepare()\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\tExpect(result).NotTo(BeNil())\n\t\t\tExpect(result.Passed).To(BeFalse())\n\t\t\tExpect(result.Outputs).To(HaveLen(3))\n\t\t})\n\n\t\tIt(\"should fail when an invalid log level is found\", func() {\n\t\t\t// This scenario can just occurs if the setters are not used\n\t\t\tresult.Outputs = append(result.Outputs, Output{\n\t\t\t\tType:    \"invalid\",\n\t\t\t\tMessage: \"invalid\",\n\t\t\t})\n\n\t\t\terr := result.prepare()\n\t\t\tExpect(err).To(HaveOccurred())\n\t\t})\n\t})\n\n\tDescribe(\"PrintWithFormat\", func() {\n\t\tvar w *bytes.Buffer\n\t\tvar output []byte\n\t\tvar resJSON Result\n\t\tconst warnText = \"example of a warning\"\n\t\tconst errorText = \"example of an error\"\n\n\t\tBeforeEach(func() {\n\t\t\tw = &bytes.Buffer{}\n\t\t\tresJSON = Result{}\n\t\t})\n\n\t\tContext(\"json-alpha1 formatting\", func() {\n\t\t\tIt(\"prints a warning\", func() {\n\t\t\t\tresult.AddWarn(errors.New(warnText))\n\t\t\t\tfailed, err := result.printWithFormat(w, JSONAlpha1Output)\n\t\t\t\tExpect(failed).To(BeFalse())\n\t\t\t\tExpect(err).To(Succeed())\n\t\t\t\toutput = w.Bytes()\n\t\t\t\tExpect(json.Unmarshal(output, &resJSON)).To(Succeed(), string(output))\n\t\t\t\tExpect(resJSON.Passed).To(BeTrue())\n\t\t\t\tExpect(resJSON.Outputs).To(HaveLen(1))\n\t\t\t\tExpect(resJSON.Outputs[0].Type).To(Equal(\"warning\"))\n\t\t\t\tExpect(resJSON.Outputs[0].Message).To(Equal(warnText))\n\t\t\t})\n\n\t\t\tIt(\"prints an error\", func() {\n\t\t\t\tresult.AddError(errors.New(errorText))\n\t\t\t\tfailed, err := result.printWithFormat(w, JSONAlpha1Output)\n\t\t\t\tfmt.Println(failed)\n\t\t\t\tfmt.Println(err)\n\t\t\t\tExpect(failed).To(BeTrue())\n\t\t\t\tExpect(err).To(Succeed())\n\t\t\t\toutput = w.Bytes()\n\t\t\t\tExpect(json.Unmarshal(output, &resJSON)).To(Succeed(), string(output))\n\t\t\t\tExpect(resJSON.Passed).To(BeFalse())\n\t\t\t\tExpect(resJSON.Outputs).To(HaveLen(1))\n\t\t\t\tExpect(resJSON.Outputs[0].Type).To(Equal(\"error\"))\n\t\t\t\tExpect(resJSON.Outputs[0].Message).To(Equal(errorText))\n\t\t\t})\n\t\t})\n\n\t\tContext(\"text formatting\", func() {\n\t\t\tIt(\"prints a warning\", func() {\n\t\t\t\tresult.AddWarn(errors.New(warnText))\n\t\t\t\tfailed, err := result.printWithFormat(w, TextOutput)\n\t\t\t\tExpect(failed).To(BeFalse())\n\t\t\t\tExpect(err).To(Succeed())\n\t\t\t\toutput = w.Bytes()\n\t\t\t\tlines := bytes.Split(bytes.TrimSpace(output), []byte(\"\\n\"))\n\t\t\t\tExpect(lines).To(HaveLen(1))\n\t\t\t\tline := string(lines[0])\n\t\t\t\tExpect(line).To(ContainSubstring(\"level=warning\"), line)\n\t\t\t\tExpect(line).To(ContainSubstring(`msg=\"example of a warning\"`), line)\n\t\t\t})\n\n\t\t\tIt(\"prints an error\", func() {\n\t\t\t\tresult.AddError(errors.New(errorText))\n\t\t\t\tfailed, err := result.printWithFormat(w, TextOutput)\n\t\t\t\tExpect(failed).To(BeTrue())\n\t\t\t\tExpect(err).To(Succeed())\n\t\t\t\toutput = w.Bytes()\n\t\t\t\tlines := bytes.Split(bytes.TrimSpace(output), []byte(\"\\n\"))\n\t\t\t\tExpect(lines).To(HaveLen(1))\n\t\t\t\tline := string(lines[0])\n\t\t\t\tfmt.Println(line)\n\t\t\t\tExpect(line).To(ContainSubstring(\"level=error\"), line)\n\t\t\t\tExpect(line).To(ContainSubstring(`msg=\"example of an error\"`), line)\n\t\t\t})\n\t\t})\n\n\t\tContext(\"returns an error\", func() {\n\t\t\tIt(\"gets an invalid log level\", func() {\n\t\t\t\tresult.Outputs = append(result.Outputs, Output{\n\t\t\t\t\tType:    \"invalid\",\n\t\t\t\t\tMessage: \"invalid\",\n\t\t\t\t})\n\t\t\t\tfailed, err := result.printWithFormat(w, TextOutput)\n\t\t\t\tExpect(failed).To(BeFalse())\n\t\t\t\tExpect(err).NotTo(Succeed())\n\t\t\t})\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "internal/validate/suite_test.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage validate\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nfunc TestResult(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"Output Result Tests\")\n}\n"
  },
  {
    "path": "internal/validate/testdata/errors.sh",
    "content": "#!/usr/bin/env bash\n\n>&2 echo -n \"validator runtime error\"\nexit 1\n"
  },
  {
    "path": "internal/validate/testdata/fails.sh",
    "content": "#!/usr/bin/env bash\n\ncat <<EOF\n{\n    \"Name\": \"fails-bundle\",\n    \"Errors\": [\n        {\n            \"Type\": \"CSVFileNotValid\",\n            \"Level\": \"Error\",\n            \"Field\": \"\",\n            \"BadValue\": \"\",\n            \"Detail\": \"invalid field Pesce\"\n        }\n    ],\n    \"Warnings\": null\n}\nEOF\n"
  },
  {
    "path": "internal/validate/testdata/passes.sh",
    "content": "#!/usr/bin/env bash\n\ncat <<EOF\n{\n    \"Name\": \"passes-bundle\",\n    \"Errors\": null,\n    \"Warnings\": [\n        {\n            \"Type\": \"CSVFileNotValid\",\n            \"Level\": \"Warning\",\n            \"Field\": \"\",\n            \"BadValue\": \"\",\n            \"Detail\": \"(gatekeeper-operator.v0.2.0-rc.3) csv.Spec.minKubeVersion is not informed. It is recommended you provide this information. Otherwise, it would mean that your operator project can be distributed and installed in any cluster version available, which is not necessarily the case for all projects.\"\n        }\n    ]\n}\nEOF\n"
  },
  {
    "path": "internal/version/version.go",
    "content": "// Copyright 2018 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage version\n\n// var needs to be used instead of const for ldflags\nvar (\n\tVersion           = \"unknown\"\n\tGitVersion        = \"unknown\"\n\tGitCommit         = \"unknown\"\n\tKubernetesVersion = \"unknown\"\n\n\t// ImageVersion represents the ansible-operator, helm-operator, and scorecard subproject versions,\n\t// which is used in each plugin to specify binary and/or image versions. This is set to the\n\t// most recent operator-sdk release tag such that samples are generated with the correct versions\n\t// in a release commit. Once each element that uses this version is moved to a separate repo\n\t// and release process, this variable will be removed.\n\tImageVersion = \"unknown\"\n)\n"
  },
  {
    "path": "netlify.toml",
    "content": "# Hugo build configuration for Netlify\n# (https://gohugo.io/hosting-and-deployment/hosting-on-netlify/#configure-hugo-version-in-netlify)\n\n# Default build settings\n[build]\n  publish = \"public\"\n  base = \"website\"\n  command = \"\"\"\ngit submodule update -f --init --recursive themes/docsy && \\\nnpm install postcss@^8.0.0 postcss-cli@^8.0.0 autoprefixer@^9.0.0 && \\\n./scripts/set_menu_version.sh && \\\nhugo version && \\\nhugo\n\"\"\"\n\n# \"production\" environment specific build settings\n[build.environment]\n  HUGO_ENV = \"production\"\n  HUGO_VERSION = \"0.73.0\"\n"
  },
  {
    "path": "proposals/README.md",
    "content": "# Operator SDK Proposals\n\nThis directory contains design documents for accepted proposals. To\npropose a new feature use the [template document][template]. Note that\nif the proposal gets accepted whoever is the proposal implementation\nowner is expected to carry out the implementation, the implementation\nowner can be different to the proposal creator.\n\n[template]: ./TEMPLATE.md\n"
  },
  {
    "path": "proposals/TEMPLATE.md",
    "content": "---\ntitle: Neat-proposals-Idea\nauthors:\n  - \"@janedoe\"\nreviewers:\n  - TBD\n  - \"@alicedoe\"\napprovers:\n  - TBD\n  - \"@oscardoe\"\ncreation-date: yyyy-mm-dd\nlast-updated: yyyy-mm-dd\nstatus: provisional|implementable|implemented|deferred|rejected|withdrawn|replaced\nsee-also:\n  - \"/proposals/this-other-neat-thing.md\"  \nreplaces:\n  - \"/proposals/that-less-than-great-idea.md\"\nsuperseded-by:\n  - \"/proposals/our-past-effort.md\"\n---\n\n# Title\n\nThis is the title of the enhancement. Keep it simple and descriptive. A good\ntitle can help communicate what the enhancement is and should be considered as\npart of any review.\n\nTo get started with this template:\n1. **Pick a domain.** Find the appropriate domain to discuss your enhancement.\n1. **Make a copy of this template.** Copy this template into the directory for\n   the domain.\n1. **Fill out the \"overview\" sections.** This includes the Summary and\n   Motivation sections. These should be easy and explain why the community\n   should desire this enhancement.\n1. **Create a PR.** Assign it to folks with expertise in that domain to help\n   sponsor the process.\n1. **Merge at each milestone.** Merge when the design is able to transition to a\n   new status (provisional, implementable, implemented, etc.). View anything\n   marked as `provisional` as an idea worth exploring in the future, but not\n   accepted as ready to execute. Anything marked as `implementable` should\n   clearly communicate how an enhancement is coded up and delivered. If an\n   enhancement describes a new deployment topology or platform, include a\n   logical description for the deployment, and how it handles the unique aspects\n   of the platform. Aim for single topic PRs to keep discussions focused. If you\n   disagree with what is already in a document, open a new PR with suggested\n   changes.\n\nThe `Metadata` section above is intended to support the creation of tooling\naround the enhancement process.\n\n## Release Signoff Checklist\n\n- \\[ \\] Enhancement is `implementable`\n- \\[ \\] Design details are appropriately documented from clear requirements\n- \\[ \\] Test plan is defined\n- \\[ \\] Graduation criteria for dev preview, tech preview, GA\n- \\[ \\] User-facing documentation is created in [operator-sdk/doc][operator-sdk-doc]\n\n## Open Questions (optional)\n\nThis is where to call out areas of the design that require closure before deciding\nto implement the design.  For instance, \n > 1. This requires exposing previously private resources which contain sensitive\n  information.  Can we do this? \n\n## Summary\n\nThe `Summary` section is incredibly important for producing high quality\nuser-focused documentation such as release notes or a development roadmap. It\nshould be possible to collect this information before implementation begins in\norder to avoid requiring implementors to split their attention between writing\nrelease notes and implementing the feature itself. \n\nA good summary is probably at least a paragraph in length.\n\n## Motivation\n\nThis section is for explicitly listing the motivation, goals and non-goals of\nthis proposal. Describe why the change is important and the benefits to users.\n\n## Goals\n\nList the specific goals of the proposal. How will we know that this has succeeded?\n\n### Non-Goals\n\nWhat is out of scope for this proposal? Listing non-goals helps to focus discussion\nand make progress.\n\n## Proposal\n\nThis is where we get down to the nitty gritty of what the proposal actually is.\n\n### User Stories (optional)\n\nDetail the things that people will be able to do if this is implemented.\nInclude as much detail as possible so that people can understand the \"how\" of\nthe system. The goal here is to make this feel real for users without getting\nbogged down.\n\n#### Story 1\n\n#### Story 2\n\n### Implementation Details/Notes/Constraints (optional)\n\nWhat are the caveats to the implementation? What are some important details that\ndidn't come across above. Go in to as much detail as necessary here. This might\nbe a good place to talk about core concepts and how they releate.\n\n### Risks and Mitigations\n\nWhat are the risks of this proposal and how do we mitigate. Think broadly. For\nexample, consider both security and how this will impact the larger OKD\necosystem.\n\nHow will security be reviewed and by whom? How will UX be reviewed and by whom?\n\nConsider including folks that also work outside your immediate sub-project.\n\n## Design Details\n\n### Test Plan\n\n**Note:** *Section not required until targeted at a release.*\n\nConsider the following in developing a test plan for this enhancement:\n- Will there be e2e and integration tests, in addition to unit tests?\n- How will it be tested in isolation vs with other components?\n\nNo need to outline all of the test cases, just the general strategy. Anything\nthat would count as tricky in the implementation and anything particularly\nchallenging to test should be called out.\n\nAll code is expected to have adequate tests (eventually with coverage\nexpectations).\n\n### Graduation Criteria\n\n**Note:** *Section not required until targeted at a release.*\n\nDefine graduation milestones.\n\nThese may be defined in terms of API maturity, or as something else. Initial proposal\nshould keep this high-level with a focus on what signals will be looked at to\ndetermine graduation.\n\nConsider the following in developing the graduation criteria for this\nenhancement:\n- Maturity levels - `Dev Preview`, `Tech Preview`, `GA`\n- Deprecation\n\nClearly define what graduation means.\n\n#### Examples\n\nThese are generalized examples to consider, in addition to the aforementioned maturity levels(`Dev Preview`, `Tech Preview`, `GA`).\n\n##### Dev Preview -> Tech Preview\n\n- Ability to utilize the enhancement end to end\n- End user documentation, relative API stability\n- Sufficient test coverage\n- Gather feedback from users rather than just developers\n\n##### Tech Preview -> GA \n\n- More testing (upgrade, downgrade, scale)\n- Sufficient time for feedback\n- Available by default\n\n**For non-optional features moving to GA, the graduation criteria must include\nend to end tests.**\n\n##### Removing a deprecated feature\n\n- Announce deprecation and support policy of the existing feature\n- Deprecate the feature\n\n### Upgrade / Downgrade Strategy\n\nIf applicable, how will the component be upgraded and downgraded? Make sure this\nis in the test plan.\n\nConsider the following in developing an upgrade/downgrade strategy for this\nenhancement:\n- What changes (in invocations, configurations, API use, etc.) is an existing\n  cluster required to make on upgrade in order to keep previous behavior?\n- What changes (in invocations, configurations, API use, etc.) is an existing\n  cluster required to make on upgrade in order to make use of the enhancement?\n\n### Version Skew Strategy\n\nHow will the component handle version skew with other components?\nWhat are the guarantees? Make sure this is in the test plan.\n\nConsider the following in developing a version skew strategy for this\nenhancement:\n- During an upgrade, we will always have skew among components, how will this impact your work?\n- Does this enhancement involve coordinating behavior in the control plane and\n  in the kubelet? How does an n-2 kubelet without this feature available behave\n  when this feature is used?\n- Will any other components on the node change? For example, changes to CSI, CRI\n  or CNI may require updating that component before the kubelet.\n\n## Implementation History\n\nMajor milestones in the life cycle of a proposal should be tracked in `Implementation\nHistory`.\n\n## Drawbacks\n\nThe idea is to find the best form of an argument why this enhancement should _not_ be implemented.\n\n## Alternatives\n\nSimilar to the `Drawbacks` section the `Alternatives` section is used to\nhighlight and record other possible approaches to delivering the value proposed\nby an enhancement.\n\n## Infrastructure Needed (optional)\n\nUse this section if you need things from the project. Examples include a new\nsubproject, repos requested, github details, and/or testing infrastructure.\n\nListing these here allows the community to get the process for these resources\nstarted right away.\n\n[operator-sdk-doc]:  https://sdk.operatorframework.io/\n"
  },
  {
    "path": "proposals/ansible-helm-addapi.md",
    "content": "---\ntitle: Ansible/Helm add api command proposal for Operator SDK\nauthors:\n  - \"@bharathi-tenneti\"\nreviewers:\n  - \"@fabianvf\"\n  - \"@cmacedo\"\napprovers:\n  - \"@fabianvf\"\n  - \"@jlanford\"\n  - \"@dmesser\"\ncreation-date: 2020-03-10\nlast-updated: 2020-03-15\nstatus: implementable\n---\n\n\n# Ansible/Helm add API command proposal for Operator SDK\n\n\n## Release Signoff Checklist\n\n- \\[x\\] Enhancement is `implementable`\n- \\[x\\] Design details are appropriately documented from clear requirements\n- \\[ \\] Test plan is defined\n- \\[ \\] Accceptance criteria\n- \\[ \\] User-facing documentation is created\n\n\n\n## Summary\n\nThe proposal is to enable Ansible/Helm operator developers to create additional APIs, through SDK CLI.\n\n## Motivation\n\nAs of today, SDK CLI can be used only to add additional APIs for Go based Operators.\nAnsible/Helm operator developers are not able to create additional APIs via CLI, once the original project scaffolds. Today, developers have to manually add necessary files to the project scaffold.\n\n## Goals\n\n* Ansible/Helm operator developer can use existing SDK CLI commands to create additional APIs as needed.\n* Ansible/Helm operator developer should be able to use flags necessary for Ansible/Helm as used in `operator-sdk new`CLI. for adding additional APIs as well.\n* Ansible/Helm operator developer can find supported documentation for the same.\n\n## Non-Goals\n\n* Updating Molecule tests for additional APIs created for Anible based operators.<**TBD**>\n* Generating/Updating Playbook for additional APIs for Ansible based operators. <**TBD**>\n\n## Proposal\n\n### User Stories\n\n#### Story 1 - Ansible operator additional API\nAs an  Ansible operator developer, I would like to scaffold additional API, once the original Ansible operator project has been created. Goal is to use  following command, to create additional APIs.\n    `operator-sdk add api --kind <kind> --api-version <group/version> [flags]`\n\n##### Acceptance Criteria\n\n* Ansible operator developer should be able to scaffold all resources needed for the additional API with following command.\n    `operator-sdk add api --kind <kind> --api-version <group/version> [flags]`\n* Flags options available for `operator-sdk new`, should also be made available for `operator-sdk add api`, as shown below.\n```\n  --api-version string - CRD APIVersion in the format $GROUP_NAME/$VERSION (e.g app.example.com/v1alpha1)\n  --kind string - CRD Kind. (e.g AppService)\n  --generate-playbook - Generate a playbook skeleton. (Only used for --type ansible) [**TBD**]\n```\n* Documentation for [SDK CLI reference][sdkclidoc] is updated with steps to add additional APIs for Ansible based operator.\n* Documentation is updated for [operator-sdk add api][addapidoc] for ansible.\n\n\n#### Story 2 - Helm operator additional API\n\nAs Helm operator developer, I would like to scaffold additional API, once the original Helm operator project has been created, using following command.\n    `operator-sdk add api --kind <kind> --api-version <group/version> [flags]`\n\n##### Acceptance Criteria\n* Helm operator developer should be able to scaffold all resources needed for the additional API with any of below commands,\n      `operator-sdk add api --kind <kind> --api-version <group/version> [flags]`\n* Flags options available for `operator-sdk new`, should also be made available for `operator-sdk add api`\n```\n  --api-version string - CRD APIVersion in the format $GROUP_NAME/$VERSION (e.g app.example.com/v1alpha1)\n  --kind string - CRD Kind. (e.g AppService)\n  --helm-chart string - Initialize helm operator with existing helm chart (<URL>, <repo>/<name>, or local path)\n  --helm-chart-repo string - Chart repository URL for the requested helm chart\n  --helm-chart-version string - Specific version of the helm chart (default is latest version)\n  ```\n* Documentation for [SDK CLI reference][sdkclidoc] is updated with steps to add additional APIs for Helm based operator.\n* Documentation is updated for [operator-sdk add api][addapidoc] for helm.\n\n\n\n### Implementation Details/Notes/Constraints\n\n* The `operator-sdk new memcached-operator --api-version=cache.example.com/v1alpha1 --kind=Memcached --type=ansible` command scaffolds new ansible based operator for the user with given API.Please refer below logic being used to determine the type of operator:\n```go\n\tcase projutil.OperatorTypeAnsible:\n\t\tif err := doAnsibleScaffold(); err != nil {\n\t\t\treturn err\n\t\t}\n\tcase projutil.OperatorTypeHelm:\n\t\tif err := doHelmScaffold(); err != nil {\n\t\t\treturn err\n\t\t}\n```\nand subsequently [`func doAnsibleScaffold()`][doansible] or [`func doHelmScaffold()`][dohelm] is being called to perform the scaffold.\n\n Currently, `operator-sdk add api` only allows Go-based operators to create further APIs, after the original project is scaffolded. By posing restriction as shown [here][onlygorestriction].\n```go\n// Only Go projects can add apis.\n\tif err := projutil.CheckGoProjectCmd(cmd); err != nil {\n\t\treturn err\n\t}\n```\n* This proposal is to enhance [`func apiRun(cmd *cobra.Command, args []string)`][addapifunc] to add APIs for Ansible/Helm operators, by re-using pre-existing functions as shown above to check for `--type`, and perform necessary scaffolds for the new resource.\n\n* To this extent, PoCs have been done for both [Ansible][ansiblepoc] and [Helm][helmpoc] by manually adding necessary files in the scaffold. Please see below for project layout.\n  **NOTE**: To test/check the POCs locally used the makefile targets `make install` and `make uninstall`.\n\n  * Ansible roles scaffold after adding APIs:\n  ```\n  ── roles\n  │   ├── memcached\n  │   │   ├── README.md\n  │   │   ├── defaults\n  │   │   │   └── main.yml\n  │   │   ├── files\n  │   │   ├── handlers\n  │   │   │   └── main.yml\n  │   │   ├── meta\n  │   │   │   └── main.yml\n  │   │   ├── tasks\n  │   │   │   └── main.yml\n  │   │   ├── templates\n  │   │   └── vars\n  │   │       └── main.yml\n  │   ├── myapp\n  │   │   ├── README.md\n  │   │   ├── defaults\n  │   │   │   └── main.yml\n  │   │   ├── files\n  │   │   ├── handlers\n  │   │   │   └── main.yml\n  │   │   ├── meta\n  │   │   │   └── main.yml\n  │   │   ├── tasks\n  │   │   │   └── main.yml\n  │   │   ├── templates\n  │   │   └── vars\n  │   │       └── main.yml\n  ```\n\n  * Helm charts are scaffolded as shown below for new APIs:\n  ```bash\n  ├── helm-charts\n  │   ├── memcached\n  │   │   ├── Chart.yaml\n  │   │   ├── README.md\n  │   │   ├── templates\n  │   │   │   ├── NOTES.txt\n  │   │   │   ├── _helpers.tpl\n  │   │   │   ├── pdb.yaml\n  │   │   │   ├── statefulset.yaml\n  │   │   │   └── svc.yaml\n  │   │   └── values.yaml\n  │   ├── mongodb\n  │   │   ├── Chart.yaml\n  │   │   ├── OWNERS\n  │   │   ├── README.md\n  │   │   ├── files\n  │   │   │   └── docker-entrypoint-initdb.d\n  │   │   │       └── README.md\n  │   │   ├── templates\n  │   │   │   ├── NOTES.txt\n  │   │   │   ├── _helpers.tpl\n  │   │   │   ├── configmap.yaml\n  │   │   │   ├── deployment-standalone.yaml\n  │   │   │   ├── ingress.yaml\n  │   │   │   ├── initialization-configmap.yaml\n  │   │   │   ├── poddisruptionbudget-arbiter-rs.yaml\n  │   │   │   ├── poddisruptionbudget-secondary-rs.yaml\n  │   │   │   ├── prometheus-alerting-rule.yaml\n  │   │   │   ├── prometheus-service-monitor.yaml\n  │   │   │   ├── pvc-standalone.yaml\n  │   │   │   ├── secrets.yaml\n  │   │   │   ├── statefulset-arbiter-rs.yaml\n  │   │   │   ├── statefulset-primary-rs.yaml\n  │   │   │   ├── statefulset-secondary-rs.yaml\n  │   │   │   ├── svc-headless-rs.yaml\n  │   │   │   ├── svc-primary-rs.yaml\n  │   │   │   └── svc-standalone.yaml\n  │   │   ├── values-production.yaml\n  │   │   ├── values.schema.json\n  │   │   └── values.yaml\n  │   └── nginx\n  │       ├── Chart.yaml\n  │       ├── charts\n  │       ├── templates\n  │       │   ├── NOTES.txt\n  │       │   ├── _helpers.tpl\n  │       │   ├── deployment.yaml\n  │       │   ├── ingress.yaml\n  │       │   ├── service.yaml\n  │       │   ├── serviceaccount.yaml\n  │       │   └── tests\n  │       │       └── test-connection.yaml\n  │       └── values.yaml\n  ```\n  * Along with above changes,`/deploy/role.yaml` will be updated to reflect new apiGroups.\n  ``` yaml\n  - apiGroups:\n    - cache.example.com\n    resources:\n    - '*'\n    verbs:\n    - create\n    - delete\n    - get\n    - list\n    - patch\n    - update\n    - watch\n  - apiGroups:\n    - app.example.com\n    resources:\n    - '*'\n    verbs:\n    - create\n    - delete\n    - get\n    - list\n    - patch\n    - update\n    - watch\n  ```\n* CRD and CR files will be generated at `/deploy/crds`, as shown below.\n```\n── deploy\n│   ├── crds\n│   │   ├── cache.example.com_memcacheds_crd.yaml\n│   │   ├── cache.example.com_v1alpha1_memcached_cr.yaml\n│   │   ├── charts.helm.k8s.io_mongodbs_crd.yaml\n│   │   ├── charts.helm.k8s.io_v1alpha1_mongodb_cr.yaml\n│   │   ├── example.com_nginxes_crd.yaml\n│   │   └── example.com_v1alpha1_nginx_cr.yaml\n```\n* watches.yaml at `/watches.yaml` gets updated with new API resource as shown below.\n```yaml\n- version: v1alpha1\n  group: cache.example.com\n  kind: Memcached\n  role: /opt/ansible/roles/memcached\n\n- version: v1alpha1\n  group: cache.example.com\n  kind: Mykind\n  role: /opt/ansible/roles/mykind\n```\n[addapidoc]: https://v0-19-x.sdk.operatorframework.io/docs/cli/operator-sdk_add_api/\n[sdkclidoc]: https://v0-19-x.sdk.operatorframework.io/docs/cli/\n[onlygorestriction]:https://github.com/operator-framework/operator-sdk/blob/master/cmd/operator-sdk/add/api.go#L95\n[doansible]:https://github.com/operator-framework/operator-sdk/blob/master/cmd/operator-sdk/new/cmd.go#L228\n[dohelm]:https://github.com/operator-framework/operator-sdk/blob/master/cmd/operator-sdk/new/cmd.go#L320\n[addapifunc]:https://github.com/operator-framework/operator-sdk/blob/master/cmd/operator-sdk/add/api.go#L91\n[ansiblepoc]:https://github.com/bharathi-tenneti/memcached-ansible-demo\n[helmpoc]:https://github.com/bharathi-tenneti/helm-operator-demo\n"
  },
  {
    "path": "proposals/ansible-operator-devex.md",
    "content": "---\ntitle: Ansible Operator Developer Experience Improvements\nauthors:\n  - \"@fabianvf\"\nreviewers:\n  - TBD\napprovers:\n  - TBD\ncreation-date: 2019-12-18\nlast-updated: 2019-12-18\nstatus: implementable\nsee-also:\n  - https://github.com/operator-framework/operator-sdk/pull/2048\nreplaces: []\nsuperseded-by: []\n---\n\n# OpenShift 4.4: Ansible Operator Developer Experience Improvements\n\n## Release Signoff Checklist\n\n- \\[x\\] Enhancement is `implementable`\n- \\[x\\] Design details are appropriately documented from clear requirements\n- \\[ \\] Test plan is defined\n- \\[ \\] Graduation criteria for dev preview, tech preview, GA\n- \\[ \\] User-facing documentation is created in [operator-sdk/doc][operator-sdk-doc]\n\n## Open Questions (optional)\n\nThis is where to call out areas of the design that require closure before deciding\nto implement the design.  For instance,\n > 1. This requires exposing previously private resources which contain sensitive\n  information.  Can we do this?\n\n## Summary\n\nDuring the OpenShift 4.4 development timeframe, we plan to improve the developer\nexperience, focusing on a few key areas:\n\n1. Ease development/debugging friction by making it easier to debug and test\n    locally.\n2. Allow users to customize the behavior of the proxy, to allow them to work around\n    APIs that do not follow conventions rather than requiring additional logic in\n    the Golang controller.\n3. Update scaffolding and examples to take new tooling and best practices into\n    consideration.\n\n## Motivation\n\nThe motivation for these changes is to ease development friction and give more\npower to the users, shortening the development iteration loop and preventing them\nfrom being blocked by the Golang portion of the Ansible Operator due to\nKubernetes/OpenShift API inconsistencies or operator-sdk bugs/behaviors.\n\n## Goals\n\n1. Allow users to whitelist/blacklist resources to be passed through the cache\n2. Update Ansible scaffolding, test scenarios, and examples to make use of newer\n    Ansible features and best practices, including support for collections and\n    simpler and more flexible test scenarios.\n3. Readable logs without additional dependencies, and ideally without a sidecar\n    container.\n\n### Non-Goals\n\n- Perfection of the logging. We are trying to get incremental improvement for the\n    logs of the Ansible Operator, but there will likely be additional changes and\n    improvements that we make before a 1.0 release.\n- Significant changes to the tooling used for tests. We are aiming primarily to\n    remove/refactor unnecessarily complicated aspects of the scaffolded tests,\n    while making it easier for the user to get the behavior that they need without\n    needing to delve into some of the nittier aspects of the testing logic.\n\n## Proposal\n\nThis is where we get down to the nitty gritty of what the proposal actually is.\n\n### User Stories\n\n#### Story 1 - Use operator-sdk up local to run the Ansible-based Operator\n\nAs a user, I would like to be able to run `operator-sdk up local` to run my\nAnsible-based Operator without requiring additional work or options. Although\nit is currently possible to use `up local`, there are a variety of limitations\nthat make the experience inferior to deploying the operator to a real cluster.\n\n1. I would like to be able to run `up local`, and see both the operator logs as\n    well as the logs from the Ansible stdout. I would like both logs to be useful\n    and readable.\n1. I would like to be able to run `up local` and not need to change my\n    `watches.yaml` to reflect the different paths of my host vs the operator\n    container.\n\n#### Story 2 - Use the molecule scenarios to test in a variety of environments\n\nAs a user, I would like to be able to use the scaffolded molecule scenarios to\nrun the same set of tests against Kubernetes clusters in the following scenarios:\n\n1. An ephemeral cluster provisioned by molecule\n1. An existing cluster local to my machine\n1. An existing cluster in the cloud\n1. A cluster with OLM installed\n1. A cluster without OLM installed\n\n\n#### Story 3 - Customize the cache to work around API issues\n\nAs a user, if there are issues in the way the proxy/cache handles a certain resource,\nI should be able to work around those issues without needing to wait for bugfixes or\nfeatures in the operator-sdk, by preventing those resources from being passed through\nthe cache at all. For example, if I need to access an OpenShift Project resource (which\nis not cacheable, because it is not watchable), I should be able to specify that the\nProject resource skips the cache in my watches.yaml.\n\n\n#### Story 4 - Readable logs by default\n\nAs a user, I would like to be able to tail the log of the primary operator pod and be\nable to see both what the Golang process and the child Ansible processes are doing,\nin a human readable way.\n\n\n### Risks and Mitigations\n\nBecause these are primarily UX improvements, there isn't too much risk of breaking\ncompatibility or hitting unforeseen issues. The primary issue I could see is that\nif we begin parsing the event messages that Ansible gives us we become reliant on\ntheir structure, which is not guaranteed to remain static, so it could lead to a\nmarginally higher maintenance burden when changing Ansible versions.\n\n## Design Details\n\n### Test Plan\n\n1. We will add at least one test for each molecule scenario (when possible).\n1. We will add tests that make Ansible emit messages of each type that it supports,\n    to help ensure that we can easily catch changes to the messag format.\n1. We will add a test scenario that uses `up local`.\n\n### Graduation Criteria\n\nN/A\n\n### Upgrade / Downgrade Strategy\n\nN/A\n\n### Version Skew Strategy\n\nN/A\n\n## Implementation History\n\nMajor milestones in the life cycle of a proposal should be tracked in `Implementation\nHistory`.\n\n## Drawbacks\n\nNone\n\n## Alternatives\n\nNone\n\n[operator-sdk-doc]:  https://sdk.operatorframework.io/\n"
  },
  {
    "path": "proposals/ansible-operator-status.md",
    "content": "# Ansible-based Operator Status Proposal for Operator SDK\n\n> Status: **implemented**\n> \n> The operator can surface basic information from the Ansible code in a generic fashion - it can set the conditions and it can surface a failure message if the run failed. See documentation in the Developer Guide: [Custom Resource Status Management](https://sdk.operatorframework.io/docs/building-operators/ansible/development-tips/#custom-resource-status-management)\n\n- [Problem](#problem)\n- [Proposal](#proposal)\n- [Complications / Further Discussion](#complications--further-discussion)\n\n## Problem\n\nThere is currently no way to intentionally surface information to the status object from Ansible. If users want to surface custom information in their Custom Resource’s status field, they would need to change the Go code for the operator.\n\nThere are two main approaches we see for users wanting to manage the status:\n\n1. The user wants to change the status of the Custom Resource over the course of an Ansible reconciliation run, but still wants to make use of the operator's builtin status management utilities to set certain conditions and failure messages\n1. The user wants to manage the entire status manually from Ansible, and the Go-side of Ansible Operator does nothing with statuses\n\n\n## Proposal\n\nAdd a new field to the watches.yaml entry, which tells the operator whether or not it is allowed to manage status.\n\nAdd a new Ansible module, named `k8s_status` that is usable when running inside Ansible Operator.\n\nThe `k8s_status` module would take the apiVersion, kind, name, namespace as well as a status blob and list of conditions. It would then set the status on the specified resource using that blob. The conditions would be validated to conform to the [Kubernetes API conventions](https://github.com/kubernetes/community/blob/cbe9c8ac5f71a99179d7ffe4a008b9018830af72/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties). It would then take this status blob and call to update the status subresource for the specified resource (which should be the CR that is being reconciled).\\\n_**Note - likely this module would inherit from k8s_common, and include the same general authentication/etc options as the other k8s modules*_\n\nThe Go-side of the Ansible Operator would need two changes:\n1. It needs to not attempt to manage the status when the watches.yaml tells it not to\n1. It needs to `GET` the current state of the object before updating the status after an Ansible reconciliation run, so that it does not attempt to write a stale version of the object.\n\n\n\n## Complications / Further Discussion\n\nNot all clusters and Custom Resource Definitions have the status subresource enabled. In the case where the status subresource is not enabled for a CRD, we can do one of two things:\n\n1. Error out - if the user is attempting to manage the status of an object that doesn’t have the subresource enabled, we call it a misconfiguration and fail without attempting to update the status.\n2. If a resource doesn’t have the status subresource enabled, the status field can still be updated. Instead of updating the status subresource, you would `GET` the resource in its current state, update the status field manually, and `PUT` the whole object back.\n"
  },
  {
    "path": "proposals/ansible-operator-testing.md",
    "content": "# Ansible based-Operator Testing Proposal for Operator SDK\n\n> Status: **implemented**\n> \n> Ansible-based operators can be tested with Molecule. Please see the testing documentation: [Testing Ansible Operators with Molecule](https://sdk.operatorframework.io/docs/ansible/testing-guide/).\n\n- [Background](#background)\n- [Goals](#goals)\n- [Non-Goals](#non-goals)\n- [Solution](#solution)\n- [Discussion / Further Investigation](#discussion--further-investigation)\n\n## Background\nAll operators should fit into the e2e testing framework used by operator-sdk, including Ansible Operator.\n\n## Goals\n\n- Add support for the `test {local|cluster}` e2e testing subcommand with Ansible Operators\n- Integrate with existing Ansible test frameworks to provide a uniform experience across the Ansible ecosystem\n- Maintain the existing interface for the `test` subcommands\n\n## Non-Goals\n\n- Create a new testing framework for Ansible that plays nicely with operators\n- Allow Ansible users to write non-Ansible tests\n\n## Solution\n1. Update scaffolding to (optionally?) include [molecule](https://molecule.readthedocs.io/en/latest/) initialization\n    - Set up a molecule scenario for the e2e environment (may have different behavior between `local` and `cluster` scenarios)\n1. Create a [delegated driver](https://molecule.readthedocs.io/en/latest/configuration.html#delegated) for molecule that:\n    - In the `test local` case handles the creation of the necessary resources (namespace, CRDs, roles, rolebindings, operator deployment) in the Kubernetes cluster\n    - In the `test cluster` case does nothing\n1. Add a custom entrypoint for testing that will spin up the operator and then run the proper molecule scenario, which can be included in the\n   Ansible Operator image when it is built with the `--enable-tests` option\n1. Update the `test local` subcommand so that when it is run in the context of an Ansible Operator, it will trigger a molecule run of the proper scenario\n1. Update the `test cluster` subcommand so that when it is run in the context of an Ansible Operator, a deployment of the operator with the custom testing entrypoint\n   is created. The behavior here should approximate the Golang operator equivalent, in terms of reporting/termination\n\n## Discussion / Further Investigation\n- Should test scaffolding be optional, or should we always initialize tests?\n- Can we easily get access to the `deploy/` resources from our molecule test?\n- How do we distribute the custom molecule driver?\n- Should `test local` and `test cluster` be two different molecule scenarios?\n    - `test local` can run molecule at the permissions required to create CRDs, roles, SAs, etc\n        - What if it isn't? Maybe we should do a best effort here, and not crash the run if we hit permissions issues.\n    - `test cluster` will be run at normal operator permissions, and will require that the prerequisites be satisfied before invocation\n"
  },
  {
    "path": "proposals/ansible-operator.md",
    "content": "# Ansible based-Operator Proposal for Operator SDK\n\n> Status: **implemented**\n> \n> This proposal has been implemented, please see the [Ansible User Guide for Operator SDK](http://sdk.operatorframework.io/docs/ansible/) for current documentation.\n\n- [Background](#background)\n- [Goals](#goals)\n- [New Operator Type](#new-operator-type)\n- [Package Structure](#package-structure)\n- [Commands](#commands)\n\n## Background\n\nNot everyone is a golang developer, and therefore gaining adoption for the operator-sdk is capped by the number of golang developers. Also, tooling for Kubernetes in other languages is lacking support for things such as informers, caches, and listers.\n\nOperators purpose is to codify the operations of an application on Kubernetes. [Ansible](https://www.ansible.com/) is already an industry standard tool for automation and is a good fit for the kind of work that Kubernetes operators need to do. Adding the ability for users of the SDK to choose which between ansible and golang to follow will increase the number of potential users, and will grant existing users even more behavior.\n\n## Goals\n\nThe goal of the Ansible Operator will be to create a fully functional framework for Ansible developers to create operators. It will also expose a library for golang users to use ansible in their operator if they so choose. These two goals in conjunction will allow users to select the best technology for their project or skillset.\n\n## New Operator Type\n\nThis proposal creates a new type of operator called `ansible`.  The new type is used to tell the tooling to act on that type of operator.\n\n## Package Structure\nPackages will be added to the operator-sdk. These packages are designed to be usable by the end user if they choose to and should have a well documented public API. The proposed packages are:\n* /operator-sdk/pkg/ansible/controller\n  * Will contain the ansible operator controller.\n  * Will contain a exposed reconciler. But the default `Add` method will use this reconciler.\n* /operator-sdk/pkg/ansible/runner\n  * Contains the runner types and interfaces\n  * Implementation is behind an internal package (/operator-sdk/pkg/ansible/runner/internal)\n  * New Methods are exposed and are the main way a user interacts with the package\n  * Runner interface for running ansible from the operator.\n  * NewForWatchers - the method that returns a map of GVK to Runner types based on the watchers file.\n  * NewPlaybookRunner - the method that returns a new Runner for a playbook.\n  * NewRoleRunner - the method that returns a new Runner for a role.\n  * This contains the events API code and public methods. Implementation should probably be in the internal package. The events API is used for receiving events from ansible runner.\n\n* /operator-sdk/pkg/ansible/proxy\n  * This is a reverse proxy for the Kubernetes API that is used for owner reference injection.\n* /operator-sdk/pkg/ansible/proxy/kubeconfig\n  * Code needed to generate the kubeconfig for the proxy.\n* /operator-sdk/pkg/ansible/events\n  * Package for event handlers from ansible runner events.\n  * Default has only the event logger.\n\n\n## Commands\nWe are adding and updating existing commands to accommodate the ansible operator.  Changes to the `cmd` package as well as changes to the generator are needed.\n\n`operator-sdk new <project-name> --type ansible --kind <kind> --api-version <group/version>`  This will be a new generation command under the hood. We will:\n* Create a new ansible role in the roles directory\n* Create a new watchers file. The role and GVK are defaulted based on input to the command.\n* A CRD is generated. This CRD does not have any validations defined.\n* A dockerfile is created using the watchers file and the ansible role with the base image being the ansible operator base image.\n\nThe resulting structure should be\n```\n|- Dockerfile\n|\n|- roles\n\\ | - <kind>\n|  \\ | - generated ansible role\n|\n| - watchers.yaml\n|\n| - deploy\n\\  | - <kind>-CRD.yaml\n|  | - rbac.yaml\n|  | - operator.yaml\n|  | - cr.yaml\n```\n\n`operator-sdk generate crd <api-version> <kind> ` This will be used to generate new CRDs based on ansible code. The command helps when a user wants to watch more than one CRD for their operator.\nArgs:\nRequired kind - the kind for the object.\nRequired api-version - the <group>/<version> for the CRD.\nFlags:\nOptional: --defaults-file - A path to the defaults file to use to generate a new CRD.yaml. If this is not defined, then an empty CRD is created.\n\n`operator-sdk up local` - This should use the known structure and the ansible operator code to run the operator from this location. This will need to be changed to determine if it is an ansible operator or a golang operator. The command works by running the operator-sdk binary, which includes the ansible operator code, as the operator process. This is slightly different than the current up local command.\n\n`operator-sdk build <image-name>` - This builds the operator image. This will need to be changed to determine if ansbile operator or golang operator.\n\n\n"
  },
  {
    "path": "proposals/automating-releases.md",
    "content": "---\ntitle: automating-releases\nauthors:\n  - @estroz\nreviewers:\n  - @jmrodri\n  - @joelanford\n  - @theishah\napprovers:\n  - TBD\ncreation-date: 2020-09-19\nlast-updated: 2020-10-01\nstatus: implementable\n---\n\n# automating-releases\n\n## Release Signoff Checklist\n\n- \\[ \\] Enhancement is `implementable`\n- \\[ \\] Design details are appropriately documented from clear requirements\n- \\[ \\] Test plan is defined\n- \\[ \\] Graduation criteria for dev preview, tech preview, GA\n- \\[ \\] User-facing documentation is created [for the website][operator-sdk-doc]\n\n## Open Questions\n\n1. [RESOLVED] We currently build images for an architecture on machines of that architecture.\nThis is not a requirement for Go binaries themselves, but might be for Ansible/Helm\ndependencies since they install binaries for particular architectures. What are\nthese dependencies and can they be installed in a container during image build?\n1. This proposal encompasses all binaries/images currently built for an operator-sdk release.\nOnce Ansible- and Helm-related code are split into their respective repos, will\nthis release process follow?\n1. [RESOLVED] Continue using our [changelog generator][sdk-changelog-generator], or use goreleaser's\n[generator][goreleaser-changelog]?\n\n## Summary\n\nThis proposal outlines an automated release pipeline for the operator-sdk repository\nthat includes both binary and image builds. The [`goreleaser`][goreleaser] release tool\nwill replace the existing combination of the release script `release.sh`, manual `git`\nsteps, and manual release publishing with a one \"click\" solution. To users, no changes\nwill occur since the release artifacts are not changing. To developers, the release\nprocess will become much simpler, hopefully to the point where a new contributor can\nrun the release with little process knowledge.\n\n## Motivation\n\nReleasing the operator-sdk repo currently requires several steps that are mostly manual,\nwith some automation around building binaries for all architectures supported. Tools like\n[`goreleaser`][goreleaser] can automate this process entirely by tagging code, and building\nand publishing binaries and images with one \"click\".\n\n## Goals\n\n- Remove all manual steps from the release process\n- Centralize release configuration\n- One-click releasing\n\n### Non-Goals\n\n- Change the content or constituency of output release artifacts in any way\n- Change the testing process in any way\n- Change our CI provider\n\n## Proposal\n\n### User Stories\n\n#### Story 1 - Release the operator-sdk repo in one click\n\nAs a contributor I want to run the release in as few operations as possible.\nThis feature will enable new contributors to release the repo easily, instead\nof relying on a long onboarding document and the expertise of a few contributors.\n\n#### Story 2 - Easily modify release configuration\n\nAs a contributor I want to easily improve the release configuration whenever necessary,\nwhich includes adding new release architectures. Configuration should be documented,\ncomprehensible, and centralized.\n\n### Implementation Details/Notes/Constraints\n\nThe [`goreleaser`][goreleaser] release tool satisfies the above goals and user stories:\n- Release from semver code tags\n- Encapsulates most release process complexity in one command\n  - Builds [binaries][goreleaser-builds]\n    - Applies to `operator-sdk`, `ansible-operator`, and `helm-operator`\n  - Publishes GitHub releases\n- Centralized configuration and a well-documented [configuration spec][goreleaser-config]\n\n`goreleaser` configuration is CI-agnostic, so if we choose to switch CI systems in the future\nwe can bring our configuration with us verbatim.\n\nAdditionally it supports generating release notes from a [custom source][goreleaser-custom-changelog];\nwe currently use a custom changelog generator which we can continue using.\n\n#### Release steps\n\nThese new release steps delegate releasing completely to CI infrastructure.\n\n1. Commit to master:\n  - Regenerated `CHANGELOG.md`\n  - Removed fragments in `changelog/`\n  - New migration guide `website/content/en/docs/upgrading-sdk-version/vX.Y.Z.md`\n  - Updated version in `website/content/en/docs/installation/install-operator-sdk.md`\n1. `git tag vX.Y.Z && git push --tags`\n    1. CI runs tests on tag\n    1. CI runs `make release TAG=<tag>`\n\nCurrently the `make release` only builds binaries; this new rule will set up and run `goreleaser` to:\n- Build multi-arch binaries and images\n- Publish a Github release with binaries and signed SHA256 hashes for each binary\n  - We'll need to create a PGP key for CI\n- Push images to the remote registry.\n\n##### Binary builds\n\nBuilding `operator-sdk`, `ansible-operator`, and `helm-operator` binaries is straightforward because they\ncan be cross-compiled locally under their own [`builds`][goreleaser-builds] task. These binaries will\nbe published as they are now.\n\n##### Image builds\n\n`goreleaser` does not yet have support for multi-arch image builds. Instead, the release config will have a\npost-build hook for each task in `builds` that runs an image build script leveraging [`docker buildx`][docker-buildx],\na Docker plugin that can build an image for each arch of a multi-arch manifest list in one command.\n`buildx` should be available in almost every CI environment by default as it is built into\nthe `docker` CLI and server v19.03+.\n\nThis removes the need for our CI to create and push manifest lists from images built on machines of the target arch.\n\n###### Multi-stage builds\n\nCurrently our Dockerfiles require binaries be built externally with a specific name.\nWe should instead be encapsulating the full image build process in a multi-stage build,\nin which our Dockerfiles are set up such that they first build the desired binary in a builder image (`golang:alpine`)\nthen copy that binary into the final image (`ubi8/ubi-minimal:latest`).\n\n##### Publishing releases\n\nAll `goreleaser` requires to publish a release is a [Github access token][github-token] with the `repo` privilege,\nand a quay.io push-enabled token (Travis CI already has one).\n\n### Risks and Mitigations\n\n- Contributors need to learn a new configuration format. Luckily the goreleaser\n[config file format][goreleaser-config] is straightforward and has great documentation.\n- Release tool development is controlled by another organization, which can lead to undesirable bugs/changes.\nThis is a manageable risk because the project is open source, to which we can contribute.\n- [`docker buildx`][docker-buildx] is experimental and may not be easy to set up in CI.\n\n## Design Details\n\n### Test Plan\n\n1. Create a goreleaser configuration that creates the exact same release artifacts the current process does.\n1. Push configuration to a test repository.\n1. Run a [test release][goreleaser-dry-run].\n1. Ensure:\n    1. Tag is present remotely.\n    1. Release notes/binaries are published as expected.\n    1. Images are pullable and run on the desired architectures.\n\n### Graduation Criteria\n\nOnce test plan has been executed and passed, the goreleaser configuration can be pushed to the\noperator-sdk repo and unused release scripts/code removed.\n\n#### Examples\n\nN/A\n\n##### Dev Preview -> Tech Preview\n\nN/A\n\n##### Tech Preview -> GA\n\nN/A\n\n##### Removing a deprecated feature\n\nN/A\n\n### Upgrade / Downgrade Strategy\n\nN/A\n\n### Version Skew Strategy\n\nThe `goreleaser` binary will be updated whenever a new release containing a bug fix we want is available.\n\n## Implementation History\n\nCurrent release [script][sdk-release-script] and [documentation][sdk-release-doc].\n\n## Drawbacks\n\nSee [risks and mitigations](#risks-and-mitigations).\n\n## Alternatives\n\n- Combining native Github actions like [create-release](https://github.com/actions/create-release).\n  - Still requires glue code and multiple actions have different configs that are not documented as well.\n- A traditional build system like [Bazel][bazel]. While this could work, it is quite heavy-handed for\nwhat we need and would likely involve writing glue code.\n\n## Infrastructure Needed (optional)\n\nNone, this can continue using our current CI infrastructure.\n\n\n[operator-sdk-doc]:https://sdk.operatorframework.io/\n[sdk-changelog-generator]:https://github.com/operator-framework/operator-sdk/tree/v1.0.1/hack/generate/changelog\n[sdk-release-script]:https://github.com/operator-framework/operator-sdk/tree/v1.0.1/release.sh\n[sdk-release-doc]:https://v1-0-x.sdk.operatorframework.io/docs/contribution-guidelines/release/\n[goreleaser]:https://goreleaser.com/customization/\n[goreleaser-config]:https://goreleaser.com/customization/\n[goreleaser-builds]:https://goreleaser.com/customization/build/\n[goreleaser-docker]:https://goreleaser.com/customization/docker/\n[goreleaser-changelog]:https://goreleaser.com/customization/release/#customize-the-changelog\n[goreleaser-custom-changelog]:https://goreleaser.com/customization/release/#custom-release-notes\n[goreleaser-dry-run]:https://goreleaser.com/quick-start/#dry-run\n[bazel]:https://docs.bazel.build/versions/3.5.0/bazel-overview.html\n[github-token]:https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token\n[docker-buildx]:https://github.com/docker/buildx#building-multi-platform-images\n"
  },
  {
    "path": "proposals/cli-ux-phase1.md",
    "content": "# User Experience CLI Improvements | Phase 1 Proposal for Operator SDK\n\nImplementation Owner: @joelanford\n\n> Status: **implementable**\n\n- [Background](#background)\n- [Goal](#goal)\n- [Use cases](#use-cases)\n- [Proposed CLI commands](#proposed-cli-commands)\n  - [`operator-sdk alpha`](#operator-sdk-alpha)\n  - [`operator-sdk alpha olm init`](#operator-sdk-alpha-olm-init)\n    - [OCP/OKD](#ocpokd)\n    - [Upstream Kubernetes](#upstream-kubernetes)\n    - [Flags for `olm init`](#flags-for-olm-init)\n  - [`operator-sdk alpha olm up`](#operator-sdk-alpha-olm-up)\n    - [Prerequisites](#prerequisites)\n    - [Flags for `olm up`](#flags-for-olm-up)\n    - [Resources](#resources)\n- [References](#references)\n  - [Operator SDK](#operator-sdk)\n  - [Operator Registry](#operator-registry)\n  - [Operator Lifecycle Manager](#operator-lifecycle-manager)\n\n## Background\n\nThe SDK CLI is one of the primary tools in the Operator Framework for operator developers and\ndeployers. However, the current user experience (UX) leaves a lot to be desired. Currently, the\ntools and documentation that help a user create, develop, test, package, run, and publish an\noperator are spread among many different repositories, making for a steep learning curve for\nnewcomers.\n\n## Goal\n\nImplement a proof-of-concept with an initial set of CLI additions to support a simplified workflow for an Operator SDK user to run an Operator SDK-developed project in a cluster using the Operator Lifecyle Manager (OLM).\n\n## Use cases\n\n1. As an operator developer, I want to deploy OLM to a development cluster.\n2. As an operator developer, I want to create the resources necessary for running my operator via OLM.\n3. As an operator developer, I want to run my operator via OLM.\n\n## Proposed CLI commands\n\n### `operator-sdk alpha`\n\nMany other Kubernetes CLI projects (e.g. `kubebuilder`, `kubectl`, and `kubeadm`) have an `alpha` subcommand tree that is used to introduce new functionality to the CLI while giving users a cue that the functionality is subject to change. This gives maintainers flexibility while iterating on new CLI features.\n\nThe general idea is that new subcommand features should be introduced under the `alpha` subcommand (e.g. `operator-sdk alpha my-command`) and then moved to their own top-level commands once the implementation has matured (e.g. `operator-sdk my-command`).\n\n### `operator-sdk alpha olm init`\n\nChecks cluster facts based on the current kubeconfig context (e.g. cluster type, version, OLM status), and ensures OLM is running. Using this command with unsupported clusters results in a failure.\n\n#### OCP/OKD\n\nFor clusters where OLM is expected to be installed by default, this command will print OLM's current status and exit.\n\n#### Upstream Kubernetes\n\nFor other clusters that meet OLM's prerequisites, the command will check to see if OLM is already deployed. If so, it will print OLM's current status and exit. If not, it will deploy OLM using the `upstream` manifests from OLM's repository at the version specified by the `--olm-version` flag, based on the following URL pattern:\n\n`https://raw.githubusercontent.com/operator-framework/operator-lifecycle-manager/master/deploy/upstream/manifests/<olm-version>/`\n\nEach resource that is applied will be logged so that users can manually backout the OLM deployment if desired. Once the manifests have been applied, the command will wait until OLM is running (or until a specified timeout) and then print its status.\n\n#### Flags for `olm init`\n\n| Flag             | Type   | Description                                                                                     |\n|------------------|--------|-------------------------------------------------------------------------------------------------|\n| `--olm-version`  | string | The version of OLM to deploy (default `latest`)                                                 |\n| `--timeout`      | string | Timeout duration to wait for OLM to become ready before outputting status (default 60s)         |\n| `--kubeconfig`   | string | Path for custom Kubernetes client config file (overrides the default locations)                 |\n\n### `operator-sdk alpha olm up`\n\nCreates all necessary resources in the cluster to run the operator via OLM, waits for the operator to be deployed by OLM, and tails the operator log, similar to `operator-sdk up local`. When the user terminates the process or if a timeout or error occurs, all of the created resources will be cleaned up.\n\nDifferent clusters install OLM in different namespaces. Since `olm up` may need to create resources in these namespaces, the cluster fact collection used in `operator-sdk alpha olm init` should be used here as well to determine which OLM namespaces are in use. This cluster fact collection package should be maintained in a separate shared package within the SDK repo, such that it is decoupled and could be extracted into a separate `operator-framework-tools` (or similar) repo in the future.\n\n#### Prerequisites\n\n1. The operator container image referenced by the CSV is available to the cluster.\n2. An operator bundle on disk (created by `operator-sdk generate csv`).\n\n#### Flags for `olm up`\n\n| Flag             | Type   | Description                                                                                     |\n|------------------|--------|-------------------------------------------------------------------------------------------------|\n| `--bundle-dir`   | string | The directory containing the operator bundle (default `./deploy/olm-catalog/<operator-name>`)   |\n| `--install-mode` | string | The [`InstallMode`][olm_install_modes] to use when running the operator, one of `OwnNamespace`, `SingleNamespace`, `MultiNamespace`, or `AllNamespaces` (default `OwnNamespace`). If using `MultiNamespace`, users can define the `OperatorGroup` target namespaces with `--install-mode=MultiNamespace=ns1,ns2,nsN`  |\n| `--kubeconfig`   | string | Path for custom Kubernetes client config file (overrides the default locations)                 |\n| `--namespace`    | string | Namespace in which to deploy operator and RBAC rules (overrides namespace from current context). We'll verify this is compatible with the defined install mode. |\n\n#### Resources\n\nOLM uses Kubernetes APIs to learn about the set of operators that are available to be installed and to manage operator lifecycles (i.e. install, upgrade, uninstall). The following resources will be created in the cluster.\n\n| API Kind        | Description  |\n|-----------------|--------------|\n| `ConfigMap`     | Contains catalog data created from the on-disk operator bundle. |\n| `CatalogSource` | Tells OLM where to find operator catalog data. This will refer to the catalog `ConfigMap`. |\n| `OperatorGroup` | Tells OLM which namespaces the operator will have RBAC permissions for. We'll configure it based on the `--install-mode` and `--namespace` flags. |\n| `Subscription`  | Tells OLM to manage installation and upgrade of an operator in the namespace in which the `Subscription` is created. We'll create it based on the value of the `--namespace` flag. |\n\n**Open questions:**\n1. When the user aborts the process, should we handle cleanup for any of the InstallPlan, CSV, CRD, and CR resources? Which of these will be automatically garbage-collected?\n\n## References\n\n### Operator SDK\n\n* [GitHub][osdk_github]\n* [User Guide][osdk_user_guide]\n* [CLI Reference][osdk_cli]\n\n### Operator Registry\n\n* [GitHub][registry_github]\n* [Manifest format][registry_manifest_format]\n\n### Operator Lifecycle Manager\n\n* [GitHub][olm_github]\n* [Architecture][olm_arch]\n\n[osdk_github]: https://github.com/operator-framework/operator-sdk\n[osdk_user_guide]: https://github.com/operator-framework/operator-sdk/blob/master/doc/user-guide.md\n[osdk_cli]: https://github.com/operator-framework/operator-sdk/tree/master/doc/cli\n\n\n[registry_github]: https://github.com/operator-framework/operator-registry\n[registry_manifest_format]: https://github.com/operator-framework/operator-registry#manifest-format\n\n[olm_github]: https://github.com/operator-framework/operator-lifecycle-manager\n[olm_arch]: https://github.com/operator-framework/operator-lifecycle-manager/blob/master/doc/design/architecture.md\n[olm_install_modes]: https://github.com/operator-framework/operator-lifecycle-manager/blob/master/doc/design/operatorgroups.md#installmodes-and-supported-operatorgroups\n"
  },
  {
    "path": "proposals/helm-operator.md",
    "content": "# Helm based-Operator Proposal for Operator SDK\n\n> Status: **implemented**\n> \n> See also: [Helm documentation][helm_docs].\n\n- [Background](#background)\n- [Goals](#goals)\n- [New Operator Type](#new-operator-type)\n- [Package Structure](#package-structure)\n- [Commands](#commands)\n  - [New](#new)\n  - [Add](#add)\n  - [Up](#up)\n  - [Build](#build)\n  - [Test](#test)\n- [Base Image](#base-image)\n- [Observations and open questions](#observations-and-open-questions)\n\n### Background\n\nAs was mentioned in the [Ansible Operator Proposal](./ansible-operator.md), not everyone is a golang developer, so the SDK needs to support other types of operators to gain adoption across a wider community of users.\n\n[Helm](https://helm.sh/) is one of the most widely-used tools for Kubernetes application management, and it bills itself as the \"package manager for Kubernetes.\" Operators serve a nearly identical function, but they improve on Helm's concepts by incorporating an always-on reconciliation loop rather than relying on an imperative user-driven command line tool. By integrating Helm's templating engine and release management into an operator, the SDK will further increase the number of potential users by adding the ability to deploy Charts (e.g. from Helm's [large catalog of existing Charts](https://github.com/helm/charts)) as operators with very little extra effort.\n\n## Goals\n\nThe goal of the Helm Operator will be to create a fully functional framework for Helm Chart developers to create operators. It will also expose a library for golang users to use Helm in their operator if they so choose. These two goals in conjunction will allow users to select the best technology for their project or skillset.\n\n## New Operator Type\n\nThis proposal creates a new type of operator called `helm`. The new type is used to tell the tooling to act on that type of operator.\n\n## Package Structure\n\nPackages will be added to the operator-sdk. These packages are designed to be usable by the end user if they choose to and should have a well documented public API. The proposed packages are:\n\n* /operator-sdk/pkg/helm/client\n  * Will contain a helper function to create a Helm client from `controller-runtime` manager.\n\n* /operator-sdk/pkg/helm/controller\n  * Will contain an exported `HelmOperatorReconciler` that implements the `controller-runtime` `reconcile.Reconciler` interface.\n  * Will contain an exported `Add` function that creates a controller using the `HelmOperatorReconciler` and adds watches based on a set of watch options passed to the `Add` function.\n\n* /operator-sdk/pkg/helm/engine\n  * Will contain a Helm Engine implementation that adds owner references to generated Kubernetes resource assets, which is necessary for garbage collection of Helm chart resources.\n\n* /operator-sdk/pkg/helm/internal\n  * Will contain types and utilities used by other Helm packages in the SDK.\n\n* /operator-sdk/pkg/helm/release\n  * Will contain the `Manager` types and interfaces. A `Manager` is responsible for:\n    * Implementing Helm's Tiller functions that are necessary to install, update, and uninstall releases.\n    * Reconciling an existing release's resources.\n  * A default `Manager` implementation is provided in this package but is not exported.\n  * Package functions:\n    * `NewManager` - function that returns a new Manager for a provided helm chart.\n    * `NewManagersFromEnv` - function that returns a map of GVK to Manager types based on environment variables.\n    * `NewManagersFromFile` - function that returns a map of GVK to Manager types based on a provided config file.\n\n### Commands\n\nWe are adding and updating existing commands to accommodate the Helm operator.  Changes to the `cmd` package as well as changes to the generator are needed.\n\n#### New\n\nNew functionality will be updates to allow Helm operator developers to create a new boilerplate operator structure with everything necessary to get started developing and deploying a Helm operator with the SDK.\n\n```\noperator-sdk new <project-name> --type=helm --kind=<kind> --api-version=<group/version>\n```\n\nFlags:\n* `--type=helm` is required to create Helm operator project.\n* **Required:** --kind - the kind for the CRD.\n* **Required:** --api-version - the group/version for the CRD.\n\nThis will be new scaffolding for the above command under the hood. We will:\n* Create a `./<project-name>` directory.\n* Create a `./<project-name>/helm-charts` directory.\n* Generate a simple default chart at `./<project-name>/helm-charts/<kind>`.\n* Create a new watches file at `./<project-name>/watches.yaml`. The chart and GVK will be defaulted based on input to the `new` command.\n* Create a `./<project-name>/deploy` with the Kubernetes resource files necessary to run the operator.\n* Create a `./build/Dockerfile` that uses the watches file and the helm chart. It will use the Helm operator as its base image.\n\nThe resulting structure will be:\n\n```\n<project-name>\n|   watches.yaml\n|\n|-- build\n|   |   Dockerfile\n|\n|-- helm-charts\n|   |-- <kind>\n|       |   Chart.yaml\n|       |   ...\n|\n|-- deploy\n|   |   operator.yaml\n|   |   role_binding.yaml\n|   |   role.yaml\n|   |   service_account.yaml\n|   |\n|   |-- crds\n|       |   <full group>_<resource>_crd.yaml\n|       |   <full group>_<version>_<kind>_cr.yaml\n```\n\nThe SDK CLI will use the presence of the `helm-charts` directory to detect a `helm` type project.\n\n### Add\n\nAdd functionality will be updated to allow Helm operator developers to add new CRDs/CRs and to update the watches.yaml file for additional Helm charts. The command helps when a user wants to watch more than one CRD for their operator.\n\n```\noperator-sdk add crd --api-version=<group>/<version> --kind=<kind> --update-watches=<true|false>\n```\n\nFlags:\n* **Required:** --kind - the kind for the CRD.\n* **Required:** --api-version - the group/version for the CRD.\n* **Optional:** --update-watches - whether or not to update watches.yaml file (default: false).\n\n**NOTE:** `operator-sdk add` subcommands `api` and `controller` will not be supported, since they are only valid for Go operators. Running these subcommands in a Helm operator project will result in an error.\n\n### Up\n\nUp functionality will be updated to allow Helm operator developers to run their operator locally, using the `operator-sdk` binary's built-in helm operator implementation.\n\n```\noperator-sdk up local\n```\n\nThis should use the known structure and the helm operator code to run the operator from this location. The existing code will need to be updated with a new operator type check for `helm` (in addition to existing `go` and `ansible` types). The command works by running the operator-sdk binary, which includes the Helm operator code, as the operator process.\n\n### Build\n\nBuild functionality will be updated to support building a docker image from the Helm operator directory structure.\n\n```\noperator-sdk build <image-name>\n```\n\n### Test\n\nThe SDK `test` command currently only supports Go projects, so there will be no support for the `operator-sdk test` subcommand in the initial integration of the Helm operator.\n\n## Base Image\n\nThe SDK team will maintain a build job for the `helm-operator` base image with the following tagging methodology:\n* Builds on the master branch that pass nightly CI tests will be tagged with `:master`\n* Builds for tags that pass CI will be tagged with `:<tag>`. If the tag is also the greatest semantic version for the repository, the image will also be tagged with `:latest`.\n\nThe go binary included in the base image will be built with `GOOS=linux` and `GOARCH=amd64`.\n\nThe base image repository will be `quay.io/water-hole/helm-operator`.\n\n## Observations and open questions\n\n* There will be a large amount of overlap in the `operator-sdk` commands for the Ansible and Helm operators. We should take care to extract the reusable features of the Ansible operator commands into a shared library, usable by both Helm and Ansible commands.\n\n* There is a moderate amount of complexity already related to how operator types are handled between the `go` and `ansible` types. With the addition of a third type, there may need to be a larger design proposal for operator types. For example, do we need to define an `Operator` interface that each of the operator types can implement for flag verification, scaffolding, project detection, etc.?\n\n[helm_docs]: https://sdk.operatorframework.io/docs/helm/\n"
  },
  {
    "path": "proposals/hugo-doc-build.md",
    "content": "---\ntitle: Build and Host Documentation\nauthors:\n  - \"@asmacdo\"\nreviewers:\n  - TBD\napprovers:\n  - TBD\ncreation-date: 2019-10-29\nlast-updated: 2019-10-29\nstatus: TBD\n---\n\n# Build and Host Documentation\n\n## Release Signoff Checklist\n\n- \\[ \\] Enhancement is `implementable`\n- \\[ \\] Design details are appropriately documented from clear requirements\n- \\[ \\] Test plan is defined\n- \\[ \\] Graduation criteria for dev preview, tech preview, GA\n- \\[ \\] User-facing documentation is created in [operator-sdk/doc][operator-sdk-doc]\n\n## Motivation\n\nHosted documentation will improve the Operator SDK user experience by\nincreasing the visibility and accessibility of the content. \n\n## Summary\n\nThis enhancement proposes a technology stack that will be used to write,\nbuild, and host the documentation for the Operator SDK project.\n\nHugo will be used for static site generation from Markdown. Neflify will\nbe used to host the site. \n\nHighlights:\n  - Files will remain markdown, few syntax changes necessary.\n  - Stack is aligned with current Golang/Kubernetes community.\n  - Proof of concept: https://operator-sdk.netlify.com/\n\n## Open Questions (optional)\n\n- What domain should we use? Available options include operator-sdk.com,\n  operator-sdk.org, operator-framework.com, and operator-framework.org\n\n### Goals\n\n1. Implementation of this proposal will result in a website that hosts\n   the documentation that currently exists in the `doc` directory of\n   [the Operator SDK\n   project](https://github.com/operator-framework/operator-sdk/). \n1. A minimal landing page will be created.\n1. Docs will build automatically when code merges to master branch.\n\n### Non-Goals\n\n1. Content changes. Other than minor syntax changes for Hugo compliance,\n   the content should remain the same, including the content\n   organization.\n\n## Proposal\n\nDocs will be built with [Hugo](https://gohugo.io/). Highlights:\n - Static site generator\n - Files will remain markdown, with minor syntactical changes.\n - Fast builds\n - Commonly used for Golang projects, including Docker and Kubernetes. \n - Open source (Apache 2.0)\n - Multi-language support\n\nHugo can use themes to lower the barrier to entry.\n[Docsy](https://github.com/google/docsy) is a theme specifically\ndesigned for medium to large technical documentation sets, and supports\nmultiple content types (tutorials, reference docs, blog posts, and so\non). Docsy is used by other projects in the Kubernetes community,\nincluding Knative and Kubeflow.\n[kubernetes.io](https://github.com/kubernetes/website) is planning to\nswitch to docsy as well.\n\nKey features:\n - Auto-generated Navigation\n - Versioned documentation support\n - Search\n - GitHub integration for fixing or reporting issues.\n - Open source (Apache 2.0)\n\nDocs will be deployed with [Netlify](https://www.netlify.com/).\n\nKey Features:\n  - Free hosting with [Open Source Project\n      Plan](https://www.netlify.com/legal/open-source-policy/)\n  - Open source plan is equivalent to [Pro\n      plan](https://www.netlify.com/pricing/#teams)\n  - Simple GitHub integration\n  - \"Deploy Preview\" feature builds documentation for pull requests.\n\n### Risks and Mitigations\n\nIf the Docsy theme (or similar) does not work for our needs, customizing\nHugo templates can be time consuming to create and maintain. However,\nour documentation needs are not unique, we should be able to get most or\nall of what we need out of the box.\n\n## Drawbacks\n\nWebsite maintenance can be time consuming, even if everything goes\nwell. This stack seems like a relatively efficient way to host docs, but\nthere are even lighter weight solutions.\n\n## Alternatives\n\nBecause our documentation needs are not unique, there are many tool sets\nthat could meet our needs. A similar arrangement would be `.rst` files,\nrendered with `sphinx` and hosted with readthedocs, but that would\nrequire a more significant refactor.\n\n## Infrastructure Needed (optional)\n\n1. (optional) Domain registration\n1. SSL Cert via Let's Encrypt\n1. Installation of Netlify app for GitHub repository.\n\n[operator-sdk-doc]:  https://sdk.operatorframework.io/\n"
  },
  {
    "path": "proposals/improve-csv-cli.md",
    "content": "---\ntitle: Improve `generate csv` CLI\nauthors:\n  - \"@estroz\"\nreviewers:\n  - \"@joelanford\"\n  - \"@dmesser\"\n  - \"@robszumski\"\napprovers:\n  - \"@joelanford\"\n  - \"@dmesser\"\n  - \"@robszumski\"\ncreation-date: 2019-11-27\nlast-updated: 2019-11-27\nstatus: implementable\nsee-also:\n  - \"doc/user/olm-catalog/generating-a-csv.md\"  \n---\n\n# Improve `generate csv` CLI\n\n## Release Signoff Checklist\n\n- \\[x\\] Enhancement is `implementable`\n- \\[ \\] Design details are appropriately documented from clear requirements\n- \\[ \\] Test plan is defined\n- \\[ \\] Graduation criteria for dev preview, tech preview, GA\n- \\[ \\] User-facing documentation is created in [operator-sdk/doc][operator-sdk-doc]\n\n## Summary\n\nThe ClusterServiceVersion (CSV) generator's entry point, `operator-sdk generate csv`, currently uses a configuration file that points to several files required to generate a CSV manifest from an Operator project. This config was intended to allow Operators either of high complexity or a non-standard project structure to generate CSV manifests. The config file path can be passed to `generate csv` with `--csv-config=<path>`.\n\n## Motivation\n\nThe CSV manifest format is currently in `v1alpha1`, indicating that fields may be added, modified, or removed until stabilization. Perhaps certain SDK files are no longer or new files are required after a manifest format change. This implies that the config format will also change, so it must maintained by SDK authors and updated by SDK users when switching versions.\n\nAnother issue crops up when updating existing CSV manifests generated with a different set of Operator manifests. Say I have an existing CSV `my-operator.v0.1.0` that contains legacy Deployment and Role manifests (the project has released `v1.0.0` recently, and the current Deployment and Role will not work with Operator `0.1.0`). However this CSV manifest must be maintained because downstream users are still using version `0.1.0` of the Operator. This scenario requires the operator maintainer to do one of two things:\n\n- Update the CSV config just for this update, such that `operator-path` and `role-paths` point to the legacy Deployment and Role manifest files, respectively. They would then revert those changes once the update is complete.\n- Maintain a legacy config for `my-operator.v0.1.0` such that the current config does not need to be updated when updating legacy CSV manifests.\n\nNeither option is desirable. The first option is messy; config files should not have to be modified ad-hoc. The second option implies N configs for N Operator versions in the limit, which is not scalable. Plus each config would have to be modified when upgrading SDK versions if the config format changes, or use old SDK versions to update legacy CSV manifests.\n\nIn summary: a config file for CSV manifest generation is too heavy-handed, since it may change often in the future, only configures one `operator-sdk` generator, and adds overhead when migrating to new SDK versions. This file should be replaced by a streamlined CLI approach, which this document details.\n\n## Goals\n\n- I should be able to create/update a CSV manifest from a complex Operator SDK-based project structure.\n- I should be able to create/update a CSV manifest from a non-standard Operator project structure.\n- I should be able to configure CSV manifest generation for non-Go Operator projects (when this feature is implemented).\n- I should not have to rely on on-disk configuration to create/update a CSV manifest.\n\n### Non-Goals\n\n- Reduce the ability to configure the CSV manifest generator.\n- Implement CSV manifest generation for non-Go Operator projects.\n\n## Proposal\n\n### Implementation Details/Notes/Constraints\n\n`--inputs` will take a list of patterns, which will be matched against files in the Operator project using [`strings.HasPrefix()`](https://golang.org/pkg/strings/#HasPrefix).\n  - The default path for Go projects, if `--inputs` is not set, will be `deploy/`. This emulates current behavior.\n  - An error is returned if no matches are found for a pattern in the list.\n  - Future non-Go CSV generators can use `--inputs` easily, with new/additional defaults set by individual generators.\n\n### Risks and Mitigations\n\n- Removing `--csv-config` will break existing users that have complex Operator SDK-based or non-standard Operator project structures. A version upgrade guide section is required to migrate these users.\n\n## Design Details\n\nA general CLI option `--inputs` to configure the CSV generator handles either situation described above without changes required in future Operator SDK versions.\n\nThe `--inputs` option takes a list of patterns to include in the generation process. For example:\n\n```\n$ operator-sdk generate csv --csv-version 0.1.0 --inputs config,deploy/legacy/operator.yaml,deploy/legacy/role.yaml\n```\n\nwould pass all files in the `config/` dir, `deploy/legacy/operator.yaml`, and `deploy/legacy/role.yaml` to the CSV generator and update the legacy `0.1.0` CSV manifest.\n\n### Test Plan\n\nUnit tests will be implemented for scenarios described above.\n\n##### Removing a deprecated feature\n\n- `--csv-config` and all related code will be removed.\n\n### Upgrade / Downgrade Strategy\n\n- There will be a version upgrade guide section dedicated to transitioning users to the new CLI.\n\n## Alternatives\n\n- An `--exclude` flag to which a list of patterns that should be excluded from CSV generation is passed.\n  - This alternative would not easily support non-standard Operator project structures.\n\n[operator-sdk-doc]:  https://sdk.operatorframework.io/\n"
  },
  {
    "path": "proposals/improved-scorecard-config.md",
    "content": "# Improved Scorecard Config Proposal for Operator SDK\n\nImplementation Owner: AlexNPavel\n> Status: **implemented**\n>\n> See the [scorecard documentation](https://sdk.operatorframework.io/docs/scorecard/) for up-to-date information.\n\n- [Background](#background)\n- [Goals](#goals)\n- [Design overview](#design-overview)\n- [User facing usage](#user-facing-usage)\n\n## Background\n\nThe `scorecard` subcommand in the `operator-sdk` currently has ~15 different command line flags. This creates\nunnecessary complexity for users. Also, many of the config options only apply to the internal plugins, and\nthis may become confusing to users who use external plugins, as they may think that these config options\naffect their external plugins. Using a config file that configures plugins on an individual\nbasis can help clarify these differences as well as make configuration a lot cleaner\n\n## Goals\n\nDrastically reduce the amount of command line flags in the `scorecard` subcommand and define a configuration file\nformat that can allow for the simple configuration of both internal and external plugins.\n\n## Design overview\n\nThe configuration for the scorecard will be in a `scorecard` subsection of the config file. This will allow\nthe config file to continue working properly when the SDK adds global config file support for all subcommands.\nUnder the scorecard subsection there are configuration options that apply to the entire scorecard as well as\na section that allows for the configuration of both internal and external plugins. Here are the config options\nand what they do:\n\n- `kubeconfig` string - path to kubeconfig. This option sets the kubeconfig for internal plugins and sets the `KUBECONFIG` env var for external plugins\n- `output` string - sets output format. Valid values: `text` and `json`\n- `plugin-dir` string - path to scorecard plugin directory. This is the directory where the plugins are run from, and all executable files in a `bin` subdirectory of the `plugin-dir` are automtically run by default.\n- `plugins` - an array of objects that configure both internal and external scorecard plugins\n\nThe objects in the `plugins` configuration have 3 elements: `name`, `disable`, and either `basic`, `olm`, or `external`. The `name` is\nthe name of the plugin and `basic`, `olm`, and `external` are configuration blocks used if the plugin is the `basic`, `olm`, or an `external`\nplugin respectively. If any of `basic`, `olm`, or `external` are specified for the same plugin, the plugin is automatically marked as failed. The\n`disable` field is `false` by default, but can be set to `true` to disable tests that would be automatically run, such as the\n`basic` and `olm` tests and external plugins in `{plugin-dir}/bin`. For internal plugins, the `basic` or `olm` struct must be set in\nto identify the plugin and for external plugins the `command` field must be set in the `external` config block for the `disable`\nconfig to work properly.\n\nConfiguration for both `basic` and `olm` contains all of the original configuration options for the scorecard that pertained to internal plugins. They are:\n\n- `namespace`\n- `init-timeout`\n- `olm-deployed`\n- `csv-path`\n- `namespaced-manifest`\n- `global-manifest`\n- `cr-manifest`\n- `proxy-image`\n- `proxy-pull-policy`\n- `crds-dir`\n\nConfiguration for `external` contains 3 fields:\n\n- `command` string - path to the command being run. Can be relative or absolute. If an executable from `{plugin-dir}/bin` is specified in the `command` field, it will not be automatically run without configuration as it would be otherwise. The same command can be specified in multiple plugins if a user wishes to run the same plugin multiple times with different configurations.\n- `args` \\[\\]string - a string array consisting of args passed to the command\n- `env` - array of elements that contain 2 fields, `name` and `value`, that configure the environment variables that the command is run with. If a user specified a kubeconfig in the main `scorecard` config and also sets `KUBECONFIG` in this section, the `KUBECONFIG` environment variable in this section has priority. This allows a user to run certain plugins under a different Kubernetes environment if necessary\n\nHere is an example config:\n\n```yaml\nscorecard:\n  output: json\n  plugins:\n    - name: Basic Tests\n      basic:\n        cr-manifest:\n          - \"deploy/crds/cache.example.com_v1alpha1_memcached_cr.yaml\"\n          - \"deploy/crds/cache.example.com_v1alpha1_memcachedrs_cr.yaml\"\n        init-timeout: 60\n        csv-path: \"deploy/olm-catalog/memcached-operator/0.0.3/memcached-operator.v0.0.3.clusterserviceversion.yaml\"\n        proxy-image: \"scorecard-proxy\"\n        proxy-pull-policy: \"Never\"\n    - name: OLM Tests\n      olm:\n        cr-manifest:\n          - \"deploy/crds/cache.example.com_v1alpha1_memcached_cr.yaml\"\n          - \"deploy/crds/cache.example.com_v1alpha1_memcachedrs_cr.yaml\"\n        init-timeout: 60\n        csv-path: \"deploy/olm-catalog/memcached-operator/0.0.3/memcached-operator.v0.0.3.clusterserviceversion.yaml\"\n        proxy-image: \"scorecard-proxy\"\n        proxy-pull-policy: \"Never\"\n    - name: Custom Test\n      external:\n        command: bin/my-test.sh\n    - name: Custom Test v2\n      external:\n        command: bin/my-test.sh\n        args: [\"--version=2\"]\n    - name: Custom Test Cluster 2\n      external:\n        command: bin/my-test.sh\n        env:\n          - name: KUBECONFIG\n            value: \"~/.kube/config2`\n```\n\n## User facing usage\n\nThis change would be a pretty large breaking change for users. The only flag that would remain in the scorecard would be the\n`config` flag to allow users to specify where their config file is. We would need to make sure we have updated documentation\nfor scorecard users ready at the same time that we merge these changes to reduce confusion and help users migrate to the\nnew configuration format.\n"
  },
  {
    "path": "proposals/kubebuilder-integration.md",
    "content": "---\ntitle: Operator-SDK integrates Kubebuilder for Golang Operators\nauthors:\n  - \"@hasbro17\"\n  - \"@estroz\"\nreviewers:\n  - \"@joelanford\"\n  - \"@jmrodri\"\n  - \"@dmesser\"\napprovers:\n  - \"@joelanford\"\n  - \"@jmrodri\"\n  - \"@dmesser\"\ncreation-date: 2019-12-19\nlast-updated: 2020-03-05\nstatus: implementable\nsee-also:\n- https://github.com/kubernetes-sigs/kubebuilder/blob/master/designs/integrating-kubebuilder-and-osdk.md\n- https://github.com/kubernetes-sigs/kubebuilder/blob/master/designs/extensible-cli-and-scaffolding-plugins-phase-1.md\nreplaces: []\nsuperseded-by: []\n---\n\n# Operator-SDK integrates Kubebuilder for Golang Operators\n\n## Release Signoff Checklist\n\n- \\[x\\] Enhancement is `implementable`\n- \\[x\\] Design details are appropriately documented from clear requirements\n- \\[ \\] Test plan is defined\n- \\[ \\] Graduation criteria for dev preview, tech preview, GA\n- \\[ \\] User-facing documentation is created in [operator-sdk/doc][operator-sdk-doc]\n\n## Summary\n\nThe Operator SDK should become compatible with Kubebuilder so that it has the\nsame project layout and CLI workflow for developing Go operators.\nTo achieve this goal without duplicating upstream code, the SDK should integrate\nKubebuilder’s CLI to reuse the scaffolding for project creation and lifecycle management.\nAt the same time the SDK should still be able to provide SDK specific features that work\nwith the new project layout.\n\nIn order for the SDK to wrap and reuse Kubebuilder while still maintaining the\nSDK binary as the entrypoint, Kubebuilder should be extended with a CLI interface\nthat supports registering plugins. This lets the SDK reuse Kubebuilder’s existing\nscaffolding code for Go operators, while still being able to extend the CLI for SDK\nspecific features/sub-commands and provide custom plugins that will allow the SDK to\nscaffold different project types like Helm/Ansible in the future.\n\n\n## Motivation\n\nThe Operator SDK and Kubebuilder largely provide the same experience for developing\nGo operators since both projects defer to APIs provided by the same upstream projects.\nThe two projects differentiate in their CLI and UX of project setup, layout, and\nlifecycle management. These differences are largely incidental of how the two\nprojects developed over time and not due to any use cases that are only addressed by either UX.\n\nBy adopting the same workflow and layout as Kubebuilder, the SDK gains better\nalignment with the upstream community for writing Go operators. This allows the\nSDK to be used interchangeably with Kubebuilder projects, which unifies the\nexperience of writing Go operators and resolves confusion on why the Operator SDK\nand Kubebuilder differ in their UX to achieve the same goals. This lets the SDK\nfocus more on features that are outside the scope of Kubebuilder, such as\nOperator Lifecycle Manager (OLM) integration and Scorecard.\n\nReusing the project scaffolding from Kubebuilder also reduces duplication in\nthe SDK. This frees up Operator SDK maintainers to focus more on collaborating\nwith the Kubebuilder maintainers on the upstream controller-runtime and controller-tools projects\n\n\n## Goals\n\n- Operator developers get the project layout and scaffolding for Golang Operators from Kubebuilder\n- Operator developers can use the same command line switches as Kubebuilder to create and extend the project\n  - This ensures Operator SDK binary compatibility with existing Kubebuilder projects.\n- An Operator Developer is notified about deprecation of `new --type=go` once `init` subcommand is in place.\n- An Operator Developer should see the current UX maintained for these features: CSV generation, scorecard, and test-framework\n- Operator developers can re-use an existing Kubebuilder project for Go-based Operators\n- Operator developers uses the same Dockerfile and base image as Kubebuilder when using the upstream operator-sdk\n- An Operator Developer has documentation that tells them how to use a different base image.\n- An Operator Developer can leverage the Makefile from kubebuilder to instantiate the Operator locally\n- Operator Developers can use cert-manager to generate TLS certificates for their webhook servers\n\n### Non-Goals\n\n- An Operator Developer can use the new plugin interface to scaffold and manage helm and ansible projects\n  - While Kubebuilder’s new plugin based CLI architecture should allow the SDK to extend it for scaffolding\n  Helm/Ansible projects, the implementation of those plugins is not currently in scope for this proposal.\n- An Operator Developer can use the Makefile to run an Operator and is notified about the deprecation of `up local`\n- Webhook support for Ansible/Helm based operators\n\n## Proposal\n\n### User Stories\n\n#### Story 1 - Design a Kubebuilder plugin interface that lets the SDK reuse and extend the CLI\n\nStatus: **Done**\n\nThe complete proposal can be viewed [here][plugin-proposal].\n\nAfter upstream discussions with the Kubebuilder maintainers there is consensus\nthat Kubebuilder should support an interface to register plugins that would be\nused to provide the implementation of CLI commands. This way Kubebuilder would\nnot have to directly expose its CLI for the SDK’s consumption: the SDK would\nreuse Kubebuilder’s plugins to scaffold new projects (`init`) and modify existing\nones (`create`) while also being able to register its own plugins to extend the\nCLI for SDK specific subcommands (ex. `generate csv`, `scorecard`).\n\nThis plugin interface should also allow the SDK to provide custom plugin\nimplementations for the `init` and `create` subcommands so that it can customize\nthe scaffolding of Helm and Ansible projects.\n\nThere is a [proposal PR][plugin-proposal-pr] on Kubebuilder for the design of\nsuch a plugin interface. The aim of this story is to address all reviewer\ncomments to achieve consensus on the plugin architecture and merge the proposal.\n\n[plugin-proposal]: https://github.com/kubernetes-sigs/kubebuilder/blob/bf3667c/designs/extensible-cli-and-scaffolding-plugins-phase-1.md\n[plugin-proposal-pr]: https://github.com/kubernetes-sigs/kubebuilder/pull/1250\n\n#### Story 2 - Implement the Kubebuilder plugin interface and CLI pkg\n\nAfter the plugin interface proposal has been accepted, the implementations of\nthe plugin interface and the CLI pkg should be added to Kubebuilder.\n\nThis involves writing plugin implementations for the following scaffolding\nsubcommands in Kubebuilder so that the SDK can register them for reuse in its own CLI:\n\n- `kubebuilder init`\n- `kubebuilder create api`\n- `kubebuilder create webhook`\n\nThe goal of this story is to ensure a release of Kubebuilder that supports the\nnew plugin interface that the SDK can integrate downstream into its own CLI.\n\n\n#### Story 3 - Integrate the Kubebuilder CLI into the SDK CLI to achieve the same workflow and project layout for Go operators\n\nOnce Kubebuilder supports plugin registration, the SDK CLI should be modified\nto reuse Kubebuilder’s CLI and plugins so that the SDK workflow for developing\nGo operators is identical to Kubebuilder’s workflow.\n\nProject initialization and api/webhook scaffolding would be provided by the\nupstream Kubebuilder CLI and plugins:  \n\n- `operator-sdk new` ==> `operator-sdk init`\n- `operator-sdk add api/controller` ==> `operator-sdk create api`\n- `operator-sdk create webhook`\n\nOther SDK subcommands can be removed and replaced by their equivalent Makefile\ntargets in the Kubebuilder workflow after ensuring that they fulfill all the same use cases.\n\n- `operator-sdk generate k8s` ==> `make generate`\n- `operator-sdk generate crds` ==> `make manifests`\n- `operator-sdk build` ==> `make manager`, `make docker-build`\n\nIf any of the old subcommands above are invoked for a Go operator project, the\noutput should be a deprecation error that highlights the equivalent replacement\nfor it in the new Kubebuilder workflow.\n\nA note on `operator-sdk run --local`: `kubebuilder` has a similar command `make run`\nto run an operator locally which `operator-sdk` should . However there is enough\ncomplexity in converting all functionality from `run --local` to `make run` that\ndoing so is out of scope as of this update. To align with the goals of this proposal,\nboth `operator-sdk run --local` and `make run` will be supported.\n\n#### Story 4 - Update the SDK specific features and subcommands to work with the new project layout\n\nSince features like the scorecard, CSV generation and test-framework have no\nequivalent in the Kubebuilder workflow, those subcommands would be unchanged on the CLI.\n\n- `operator-sdk generate csv`\n- `operator-sdk scorecard`\n- `operator-sdk test`\n\nWhere necessary the above commands should be adjusted to reflect the changes to\ntheir expected input and output manifest paths that is consistent with the new project layout.\n\n\n#### Story 5 - Update the Operator SDK e2e tests to work with the new project layout\n\nThe existing e2e tests and CI scripts for testing Go operators would need to be\nupdated to use the new layout so that CI passes for the new CLI workflow in the master branch.\n\n\n#### Story 6 - Update the Go operator related documentation per the Kubebuilder workflow and project layout\n\nThe user documentation for Go operators such as the user-guide, CLI reference,\nproject layout, etc will need to be updated according to the new CLI and layout.\nThese doc updates must include a detailed explanation of Dockerfile usage in\nKubebuilder projects and how users can modify their vanilla Dockerfile to use\na parent UBI image.\n\n\n### Implementation Details/Notes/Constraints\n\nThe integration work for the Go Operator CLI workflow can be done in the master\nbranch to avoid issues with merge conflicts from rebasing a separate branch at a later time.\nThe new CLI can be worked on behind a hidden subcommand, `operator-sdk alpha`, until it is ready to\nreplace the existing workflow. This would help avoid exposing it too early while\nstill providing the ability to test it on the master branch.\n\n\n### Risks and Mitigations\n\n- This proposal involves major breaking changes in all aspects of the project\nthat will discourage users from making the upgrade to the release involving these changes.\n  - Besides having enough documentation to guide users to make the switch over\n  to the new release, there should be some migration tooling to assist users in\n  switching over their existing projects. **TODO:** These efforts will be\n  addressed in a separate enhancement proposal.\n- Once the SDK switches to using Kubebuilder for Go operators, the CLI UX for\nGo vs Ansible/Helm operators will be fragmented. While they don’t target the\nsame users it could be confusing to see the operator-sdk binary support\ndifferent commands for initializing different project types.\n  - With the proposed plugin architecture it should be possible to update the\n  workflow for Helm/Ansible operators to be the same as Kubebuilder. However\n  that is not currently in scope for this proposal.\n\n\n[operator-sdk-doc]:  https://sdk.operatorframework.io/\n"
  },
  {
    "path": "proposals/kubernetes-1.17.md",
    "content": "---\ntitle: OpenShift 4.4: Operator SDK supports Kubernetes 1.17\nauthors:\n  - \"@joelanford\"\nreviewers:\n  - TBD\napprovers:\n  - TBD\ncreation-date: 2019-12-19\nlast-updated: 2019-12-19\nstatus: implementable\nsee-also:\n  - https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.17.md\nreplaces: []\nsuperseded-by: []\n---\n\n# OpenShift 4.4: Operator SDK supports Kubernetes 1.17\n\n## Release Signoff Checklist\n\n- \\[x\\] Enhancement is `implementable`\n- \\[x\\] Design details are appropriately documented from clear requirements\n- \\[ \\] Test plan is defined\n- \\[ \\] Graduation criteria for dev preview, tech preview, GA\n- \\[ \\] User-facing documentation is created in [operator-sdk/doc][operator-sdk-doc]\n\n## Summary\n\nThe release of Kubernetes 1.17 brings new features, enhancements, and bug fixes\nto the Kubernetes API and Kubernetes libraries that support operator development.\nThe focus of this enhancement is to bring Kubernetes 1.17 support to Operator SDK.\n\nSee the [Kubernetes 1.17.0 CHANGELOG][changelog] for details.\n\n[changelog]: https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.17.md\n\n## Motivation\n\nThe motivation for this enhancement is to give operator developers access to the\nlatest Kubernetes features and so that existing operator projects have a\ncontinued upgrade path to ensure their compatibility with the latest versions of\nKubernetes.\n\n## Goals\n\nThe goal is to update the Kubernetes dependencies of the Operator SDK to use 1.17.\n\n### Non-Goals\n\nN/A\n\n## Proposal\n\n### User Stories\n\n#### Story 1\n\nAs an operator developer, I want to take advantage of the features of Kubernetes\n1.17 and ensure that my operator is compatible with any API changes and removals\nin Kubernetes 1.17.\n\n### Risks and Mitigations\n\nThe biggest risk with this proposal, as always, is that Operator SDK depends on\nother projects that depend on Kubernetes, so it is typically not possible to\nupgrade Operator SDK's Kubernetes dependencies until these other projects have\nreleases that also include the Kubernetes dependency updates.\n\nThe two projects that fall into this category are:\n1. [`kubernetes-sigs/controller-runtime`][controller-runtime]\n2. [`helm/helm`][helm]\n\nTo mitigate these risks, the Operator SDK contributors must work with these projects\nto make the necessary upstream dependency changes and to make releases containing these\nchanges.\n\n## Design Details\n\n### Test Plan\n\n**Note:** *Section not required until targeted at a release.*\n\nOperator SDK's existing e2e suite will be used to verify these changes. At a minimum,\nthe e2e suite will need to be updated to run the tests against a Kubernetes 1.17\ncluster.\n\nSince our tests make use of Kubernetes utilities and APIs, other changes may be\nnecessary depending on the specific changes in Kubernetes 1.17.\n\n### Upgrade / Downgrade Strategy\n\nTo help users upgrade their projects, Operator SDK provides a migration guide that\ndocuments the steps that operator developers must take to migrate their project\nto a new version of the SDK.\n\nThe migration guide for the version containing the Kubernetes 1.17 dependency\nupdate will document the changes necessary in the project's `go.mod` file, and\nit will call out any specific breaking changes that may impact operator projects\nalong with specific instructions for mitigating the breaking change, if applicable.\n\n### Version Skew Strategy\n\nWith Operator SDK, Version skew is typically a concern when deploying an operator to a\nKubernetes cluster where the operator's Kubernetes client libraries are at a different\nversion than the Kubernetes API server with which it is interacting.\n\nThe Kubernetes API compatibility matrix documents which clients and APIs are supported by which API server versions and vice versa.\n\nSee the [`kubernetes/client-go` documentation about versioning][version-skew], which describes the supported version skew between clients and servers.\n\n[version-skew]: https://github.com/kubernetes/client-go#versioning\n\n## Implementation History\n\nMajor milestones in the life cycle of a proposal should be tracked in `Implementation\nHistory`.\n\n## Drawbacks\n\nThe only drawback is the potential for breaking changes in client code due to breaking\nchanges introduced by the Kubernetes 1.17 version update. However, this is unavoidable\nsince Kubernetes minor versions almost always contain breaking changes that impact\ncontroller-runtime and Operator SDK.\n\n## Alternatives\n\nNone\n\n## Infrastructure Needed (optional)\n\nN/A\n\n[operator-sdk-doc]:  https://sdk.operatorframework.io/\n[controller-runtime]: https://github.com/kubernetes-sigs/controller-runtime\n[helm]: https://github.com/helm/helm\n"
  },
  {
    "path": "proposals/leader-for-life.md",
    "content": "# Leader for Life Proposal for Operator SDK\n\nImplementation Owner:\n\n> Status: **implemented**\n>\n> See [leader election documentation](https://sdk.operatorframework.io/docs/golang/advanced-topics/#leader-election).\n\n- [Background](#background)\n- [Goals](#goals)\n- [Non-Goals](#non-goals)\n- [Solution](#solution)\n  - [Usage](#usage)\n- [Future](#future)\n\n## Background\n\nOperators need leader election to ensure that if the same operator is running\nin two separate pods within the same namespace, only one of them will be\nactive. The primary goal of leader election is to avoid contention between\nmultiple active operators of the same type.\n\nHigh availability is not a goal of leader election for operators.\n\nController-runtime is adding leader election based on functionality present [in\nclient-go](https://github.com/kubernetes/client-go/blob/master/tools/leaderelection/leaderelection.go). However that\nimplementation allows for the possibility of brief periods during which\nmultiple leaders are active.\n\nRequirements have been [discussed on\nGitHub](https://github.com/operator-framework/operator-sdk/issues/136).\n\nThis proposal is to add leader election to the SDK that follows a \"leader for\nlife\" model, which does not allow for multiple concurrent leaders.\n\n## Goals\n\n* Provide leader election that is easy to use\n* Provide leader election that prohibits multiple leaders\n\n## Non-Goals\n\n* Make operators highly available\n\n## Solution\n\nThe \"leader for life\" approach uses Kubernetes features to detect when a leader\nhas disappeared and then automatically remove its lock.\n\nThe approach and a PoC is detailed in [a separate\nrepository](https://github.com/mhrivnak/leaderelection). This proposal is to move\nthat implementation into `operator-sdk` and finish/modify it as appropriate.\n\n### Usage\n\n```golang\nfunc main() {\n    // create a lock named \"myapp-lock\", retrying every 5 seconds until it succeeds\n    err := leader.Become(\"myapp-lock\", 5)\n    if err != nil {\n        log.Error(err, \"\")\n        os.Exit(1)\n    }\n    ...\n    // do whatever else your app does\n}\n```\n\n## Future\n\nOnce accepted into operator-sdk, this would be valuable to contribute back to either\ncontroller-runtime directly or client-go.\n"
  },
  {
    "path": "proposals/metering-operator-metrics.md",
    "content": "# Auto register operator specific metrics as part of operator-metering Proposal for Operator SDK\n\nImplementation Owner:\n\n> Status: **implemented**\n>\n> See [metrics documentation](https://sdk.operatorframework.io/docs/golang/legacy/monitoring/).\n\n- [Motivation and goal](#motivation-and-goal)\n- [Overview of the metrics](#overview-of-the-metrics)\n- [kube-state-metrics based solution](#kube-state-metrics-based-solution)\n- [User facing architecture](#user-facing-architecture)\n- [Related work](#related-work)\n\n### Motivation and goal\n\nWe want to be able to generate the metering reports based on the operator specific Prometheus metrics. In order to be able to do that, operators must be instrumented to expose those metrics, and the operator-sdk should make this as easy as possible. The goal is to have the metering happen based on the usage of each individual operator. Metrics will be based on objects managed by the particular operator.\n\n## Overview of the metrics\n\nTo follow both the Prometheus instrumentation [best practices](https://prometheus.io/docs/practices/naming/) as well as the official Kubernetes instrumentation [guide](https://github.com/kubernetes/community/blob/cbe9c8ac5f71a99179d7ffe4a008b9018830af72/contributors/devel/sig-instrumentation/instrumentation.md), the metrics will have the following format:\n\n```\ncrd_kind_info{namespace=\"namespace\",crdkind=\"instance-name\"} 1\n```\n\nexample metric for the memchached-operator would look like this:\n\n```\nmemcached_info{namespace=\"default\",memcached=\"example-memcached\"} 1\n```\n\n## kube-state-metrics based solution\n\nThe solution makes use of Kubernetes list/watch to populate a Prometheus metrics registry, kube-state-metrics implements its own registry for performance reasons. [kube-state-metrics](https://github.com/kubernetes/kube-state-metrics#overview) is used because it solves exactly the same problem we are facing but it does it for upstream known resources. The operator-sdk can re-use its functionality to perform the same thing but with custom resources. The kube-state-metrics library can only be used for constant (/static) metrics, metrics that are immutable and thereby entirely regenerated on change. This is perfect for our above mentioned use-case. It is not meant to do e.g. counting in performance critical code paths. Thereby an operator would need kube-state-metrics library for exposing the amount of custom resources that it manages and its details and Prometheus client_golang to expose metrics of its own internals e.g. count of reconciliation loops.\n\n\n```go\n// NewCollectors returns a collection of metrics in the namespaces provided, per the api/kind resource.\n// The metrics are registered in the custom generateStore function that needs to be defined.\nfunc NewCollectors(\n    client *Client,\n    namespaces []string,\n    api string,\n    kind string,\n    metricsGenerator func(obj interface{}) []*metrics.Metric) (collectors []*kcoll.Collector)\n```\n\n```go\n// ServeMetrics takes in the collectors that were created and port number on which the metrics will be served.\nfunc ServeMetrics(collectors []*kcoll.Collector, portNumber int) {\n\n```\n\nNote: Due to taking advantage of kube-state-metrics functions and interfaces we cannot use the prometheus/client_golang and we need to register it in the same way as kube-state-metrics does, and expose the `/metrics` and serve it on a port (port `:8389/metrics` for example). For that we will need to also create a [Service](https://kubernetes.io/docs/concepts/services-networking/service/) object or rather update the current Service object.\n\n### User facing architecture\n\nBelow is how roughly an example for kube-state-metrics implementation will look like.\n\nUser will have all the below code already generated and included as part of the `main.go` file:\n\n```go\n\tc := metrics.NewCollectors(client, []string{\"default\"}, resource, kind, MetricsGenerator)\n\tmetrics.ServeMetrics(c)\n```\n\nwith the `MetricsGenerator` function living in the users `pkg/metrics` package:\n\n```go\nvar (\n\tdescMemInfo = ksmetrics.NewMetricFamilyDef(\n\t\t\"memcached_info\",\n\t\t\"The information of the resource instance.\",\n\t\t[]string{\"namespace\", \"memcached\"},\n\t\tnil,\n\t)\n)\n\n func MetricsGenerator(obj interface{}) []*ksmetrics.Metric {\n\tms := []*ksmetrics.Metric{}\n\tcrdp := obj.(*unstructured.Unstructured)\n \tcrd := *crdp\n\n\tlv := []string{crd.GetNamespace(), crd.GetName()}\n\tm, err := ksmetrics.NewMetric(descMemInfo.Name, descMemInfo.LabelKeys, lv,  float64(1))\n\tif err != nil {\n\t\tfmt.Println(err)\n\t\treturn ms\n\t}\n\tms = append(ms, m)\n\treturn ms\n}\n```\n\n## Related work\n\nIn the future if the agreed on kube-state-metrics restructure happens (see https://github.com/kubernetes/kube-state-metrics/issues/579) we can get rid of some of the duplicated functions. But that will probably take a few months and our user facing interface should not change as a result.\n"
  },
  {
    "path": "proposals/operator-testing-tool.md",
    "content": "---\ntitle: Tooling for Testing Operators\nauthors:\n  - \"@jmccormick2001\"\n  - \"@joelanford\"\nreviewers:\n  - TBD\n  - \"@joelanford\"\napprovers:\n  - TBD\ncreation-date: 2019-09-13\nlast-updated: 2019-11-07\nstatus: provisional|implementable|implemented|deferred|rejected|withdrawn|replaced\nsee-also:\n  - \"/enhancements/this-other-neat-thing.md\"  \nreplaces:\n  - \"/enhancements/that-less-than-great-idea.md\"\nsuperseded-by:\n  - \"/enhancements/our-past-effort.md\"\n---\n\n# Tooling for Testing Operators\n\n\n## Release Signoff Checklist\n\n- \\[ \\] Enhancement is `implementable`\n- \\[ \\] Design details are appropriately documented from clear requirements\n- \\[ \\] Test plan is defined\n- \\[ \\] Graduation criteria for dev preview, tech preview, GA\n- \\[ \\] User-facing documentation is created.\n\n## Summary\n\nThis proposal is for a new Operator Testing Tool that validates Operator packaging as well as run simple functional test specific to the Operator’s APIs.\n\n## Motivation\n\nOperator Testing and Validation remains difficult today due to tooling sprawl, disparate definitions of validity, and the lack of means to provide custom tests per Operator in a way that is not tied to a particular CI pipeline.\n\nHaving high quality Operators is crucial to the success of the Operator Framework.\n\n### Goals\n\n * Operator Developers can use a tool that reports on recommended, required and optional packaging requirements of a given bundle on disk\n * Operator Developers can use the same tool that reports on recommended, required and optional common black box tests of a deployed operator on cluster\n * Operator Developers can rely on a central source of truth of a valid Operator bundles shared among all Operator Framework components\n * Operator Developers can use the same tool to run custom functional tests of a deployed operator on their local cluster\n * Operator Developers can expose labels on custom functional tests that can be filtered upon in the same way as built-in labels\n * Operator Developers can use the tool to test Operator updates with OLM from a user-defined starting version to another version using a CR throughout the process\n\n\n### Non-Goals\n\nnot in scope: Operator Developers can use the same tool to run custom, functional tests of their Operator on cluster\n\n## Proposal\n\n### User Stories \n\n#### Story 1 - Show pass/fail in Scorecard Output\nToday, the scorecard output shows a percentage of tests that were successful to the end user. This story is to change the scorecard output to show a pass or fail for each test that is run in the output instead of a success percentage. \n\nThe scorecard would by default run all tests regardless if a single test fails.  Using a CLI flag such as below would cause the test execution to stop on a failure:\n * operator-sdk scorecard -l ‘necessity=required’ --fail-fast\n\nTasks for this story include:\n * change scorecard by removing earnedPoints and maximumPoints from each test\n * change scorecard output by removing totalScorePercent, partialPass, earnedPoints, maximumPoints from scorecard output\n * change scorecard existing tests to remove partialPass, instead only returning a pass or fail\n * change scorecard CLI to return an exit code based on the pass/fail results from the set of executed tests \n * (stretch goal) add support for --fast-fail CLI flag\n\n\nRough point estimate is 8 points.\n\n\n#### Story 2 - Change Scorecard Test Selection\nToday, the scorecard lets you select which tests are run by the plugins defined in the scorecard configuration (basic, olm). This story would change how users determine which tests are executed by scorecard.\n\nThis story would introduce labels for each test and then allow the scorecard CLI to filter which tests it runs based on label selectors.\n\nTests can fall into 3 groups: required, recommended, or optional. Tests can also be categorized as static or runtime. Labels for these groups and categories would allow a test to be more precisely specified by an end user.\n\nPossible examples of specifying what tests to run are as follows: \n * operator-sdk scorecard -l ‘testgroup in (required,recommended,optional)’ \n * operator-sdk scorecard -l ‘testtype in (runtime,static)’\n * operator-sdk scorecard -l updatecrtest=true\n * operator-sdk scorecard -l someplugintest=true\n\nTasks for this story include:\n * Update the test interfaces to support arbitrary test-defined labels\n * Add the labels to the tests\n * Update the CLI and scorecard library to support label selectors to filter scorecard runs\n * A stretch goal would include the ability of the CLI to perform a dry-run of tests based on label selectors to show the user which tests would be executed for a given label selector value.\n\nRough point estimate for this story is 8 points.\n#### Story 3 - Common Validation\nThe scorecard would use a common validation codebase to verify bundle contents. This story supports a single “source of truth” and avoids duplication or variance of validation logic. The scorecard user would be able to specify a bundle on the command line, that bundle would then be validated.  For example:\n * operator-sdk scorecard --bundle ./my-operator\n\n\nTasks for this story include:\n * determine the correct validation library to use\n * add support for a bundle directory flag to the CLI\n * change the scorecard code to use that validation library when validating a CR, CSV, or given a bundle directory\n * format the validation output to present to the CLI user in text or json\n\nRough point estimate in this story is 5 points.\n\n#### Story 4 - Update scorecard Documentation\nTasks:\n * Document changes to CLI\n * Document new output formats\n * Document changes to configuration\n * Update the CHANGELOG and Migration files with breaking changes and removals\n\n\n#### Story 5 - Design Custom Tests\nTasks:\n * Design the custom test format (e.g. bash, golang, other)\n * Design the custom test interface (e.g. naming, labels, exit codes, output)\n * Design how a custom test is packaged (e.g. container image, source directory, other)\n * Design the custom test configuration (e.g. config file, command line flag, image path, other)\n * Document the custom test design for end-users\n\n\n#### Story 6 - Support Custom Tests\nTasks:\n * Document how a custom test is developed, providing an example\n * Add support for custom tests in the v1alpha2 API\n * Update tests to include execution of a custom test using v1alpha2\n\n\n#### Story 7 - Support User-Defined Labels on Custom Tests\nTasks:\n * Document rules for adding labels onto custom tests\n * Add support for handling user-defined labels on custom tests in the v1alpha2 API\n * Add test to include handling user-defined labels on custom tests using v1alpha2\n\n#### Story 8 - Support Testing Operator Upgrades with OLM\nTasks:\n * Add support for testing an operator upgrade with OLM\n * Document and provide an example of how to test an operator upgrade\n * Add test to perform an operator upgrade test\n\n### Implementation Details/Notes/Constraints\n\nA scheme for applying the labels to the tests would need to be developed as well as label names to categorize tests.\n\nThe “source of truth” for validation would need to be established such as which library the scorecard would use to perform CR/CSV/bundle validation.\n\nIf no runtime tests are specified, then the scorecard would only run the static tests and not depend on a running cluster.\n\nAllow tests to declare a set of labels that can be introspected by the scorecard at runtime.\n\nAllow users to filter the set of tests to run based on a label selector string.\n\nReuse apimachinery for parsing and matching.\n\n### Risks and Mitigations\n\nThe scorecard would implement a version flag in the CLI to allow users to migrate from current functionality to the proposed functionality (e.g. v1alpha2):\n * operator-sdk scorecard --version v1alpha2\n\n\n## Design Details\n\n### Exit Codes\n\nIf you want to know if some arbitrary set of tests fail (e.g. necessity=required), you would either use label selection to run only that set of tests, or you would run some superset with -o json, and if the pass/fail exit code indicates a failure, you could use jq fu for your own custom exit code logic.\n\nFor example, the following jq command would exit with a failure if any required tests fail or error:\n\n    jq --exit-status '[.[] | select(.labels.necessity == \"required\" and (.status == \"fail\" or .status == \"error\"))] | length == 0'\n\nTwo separate meanings for exit codes would be produced by the scorecard:\n * One, to handle the case where the scorecard subcommand itself fails for some reason (e.g. couldn't read the kubernetes config, couldn't connect to the apiserver, etc.)\n * Second, to handle the pass/fail case where a test that was expected to pass did not pass. In this case, the output would be guaranteed to be valid text or JSON.\n\nFor pipelines, the test tool can be run twice:\n\n * with the required tests and then bail if the exit code is non-zero.\n * with the recommended tests and then bail of the exit code is 1 or bail or not bail if the exit code is 2.\n\nTo drive better reports the JSON structure allows for proper querying using JSONPath.\n\n### Test Plan\n\n**Note:** *Section not required until targeted at a release.*\n\nConsider the following in developing a test plan for this enhancement:\n- Will there be e2e and integration tests, in addition to unit tests?\n- How will it be tested in isolation vs with other components?\n\nNo need to outline all of the test cases, just the general strategy. Anything\nthat would count as tricky in the implementation and anything particularly\nchallenging to test should be called out.\n\nAll code is expected to have adequate tests (eventually with coverage\nexpectations).\n\n### Graduation Criteria\n\n**Note:** *Section not required until targeted at a release.*\n\nDefine graduation milestones.\n\nThese may be defined in terms of API maturity, or as something else. Initial proposal\nshould keep this high-level with a focus on what signals will be looked at to\ndetermine graduation.\n\nConsider the following in developing the graduation criteria for this\nenhancement:\n- Maturity levels - `Dev Preview`, `Tech Preview`, `GA`\n- Deprecation\n\nClearly define what graduation means.\n\n#### Examples\n\nThese are generalized examples to consider, in addition to the aforementioned\nmaturity levels.\n\n##### Dev Preview -> Tech Preview\n\n- Ability to utilize the enhancement end to end\n- End user documentation, relative API stability\n- Sufficient test coverage\n- Gather feedback from users rather than just developers\n\n##### Tech Preview -> GA \n\n- More testing (upgrade, downgrade, scale)\n- Sufficient time for feedback\n- Available by default\n\n**For non-optional features moving to GA, the graduation criteria must include\nend to end tests.**\n\n##### Removing a deprecated feature\n\n- We are adding a new --version flag to allow users to switch between\nv1alpha1 and the proposed v1alpha2 or vice-versa for backward compatibility\n- The output spec for v1alpha2 is added and the v1alpha1 spec is\nretained to support the existing output format\n- The default spec version will be v1alpha2, users will need to modify\ntheir usage to specify --version v1alpha1 to retain the older output\n- In a subsequent release, the v1alpha1 support will be removed.\n\n\n### Upgrade / Downgrade Strategy\n\nIf applicable, how will the component be upgraded and downgraded? Make sure this\nis in the test plan.\n\nConsider the following in developing an upgrade/downgrade strategy for this\nenhancement:\n- What changes (in invocations, configurations, API use, etc.) is an existing\n  cluster required to make on upgrade in order to keep previous behavior?\n- What changes (in invocations, configurations, API use, etc.) is an existing\n  cluster required to make on upgrade in order to make use of the enhancement?\n\n### Version Skew Strategy\n\nHow will the component handle version skew with other components?\nWhat are the guarantees? Make sure this is in the test plan.\n\nConsider the following in developing a version skew strategy for this\nenhancement:\n- During an upgrade, we will always have skew among components, how will this impact your work?\n- Does this enhancement involve coordinating behavior in the control plane and\n  in the kubelet? How does an n-2 kubelet without this feature available behave\n  when this feature is used?\n- Will any other components on the node change? For example, changes to CSI, CRI\n  or CNI may require updating that component before the kubelet.\n\n## Implementation History\n\nMajor milestones in the life cycle of a proposal should be tracked in `Implementation\nHistory`.\n\n## Drawbacks\n\nThe idea is to find the best form of an argument why this enhancement should _not_ be implemented.\n\n## Alternatives\n\nSimilar to the `Drawbacks` section the `Alternatives` section is used to\nhighlight and record other possible approaches to delivering the value proposed\nby an enhancement.\n\n## Infrastructure Needed\n\nUse this section if you need things from the project. Examples include a new\nsubproject, repos requested, github details, and/or testing infrastructure.\n\nListing these here allows the community to get the process for these resources\nstarted right away.\n"
  },
  {
    "path": "proposals/qa-samples-proposal.md",
    "content": "---\ntitle: QA Samples Proposal\nauthors:\n  - \"@camilamacedo86\"\nreviewers:\n  - TBD\napprovers:\n  - TBD\ncreation-date: 2019-11-22\nlast-updated: 2019-11-22\nstatus: implementable\n---\n\n# QA Samples Proposal  \n\n## Release Signoff Checklist\n\n- \\[x\\] Enhancement is `implementable`\n- \\[x\\] Design details are appropriately documented from clear requirements\n- \\[x\\] Test plan is defined\n- \\[x\\] Graduation criteria for dev preview, tech preview, GA\n- \\[x\\] User-facing documentation is created in [operator-sdk/doc][operator-sdk-doc]\n\n## Summary\n\nThe Operator SDK has a repo with [sample projects](https://github.com/operator-framework/operator-sdk-samples\n). This proposal describes quality improvements in for the sample projects.\n\n## Motivation\n\n- Address issues raised in the repository such as ; [Provide docker images for the samples](https://github.com/operator-framework/operator-sdk-samples/issues/88), [Add coveralls](https://github.com/operator-framework/operator-sdk-samples/issues/89), [Add unit test to cover the project](https://github.com/operator-framework/operator-sdk-samples/issues/87), [Add CI tests](https://github.com/operator-framework/operator-sdk-samples/issues/85).\n- Make easier the process to review changes made for the projects\n- Help users know how they can achieve common good practices\n\n## Goals\n\n- As a maintainer, I would like to ensure that samples projects continue to work after the changes performed in the PR are applied\n- As an operator developer, I would like to know how to cover the projects with tests\n- As an operator developer, I would like to know how to use the [test-framework][e2e-docs] to do unit and integration tests\n- As an operator developer, I would like to know how to call the tests in the CI and integrate them with Travis\n- As an operator developer, I would like to know good practices to ensure the quality of my operators projects \n\n**NOTE** The above goals are valid for the 3 types/projects Go, Ansible and Helm\n\n### Non-Goals\n\n- Change the code business logic implementation of the projects\n\n## Proposal\n\n- Cover the projects with unit and integration tests. \n- Integrate projects with Travis\n- Integrate projects with Coveralls\n\n### User Stories \n\n#### Unit tests for Go Memcached Sample\n\n- I as a GO operator developer, I would like to know how to cover the projects with unit tests using the test-framework\n\n**Acceptance Criteria** \n- The GO project should have a minimum of 70% of its implementation covered by unit tests. \n- The tests should all pass.\n- The project should have a makefile target to call the tests\n- A section with a short info over how to tests and the links for its documents in the README of the project\n- The tests should be done using the default GO testing lib and the [test-framework][e2e-docs] provided by SDK\n \n**NOTES** \n- See [here](https://github.com/dev4devs-com/postgresql-operator/blob/master/pkg/controller/database/controller_test.go) an example of how to cover the controller.\n- See [here](https://github.com/dev4devs-com/postgresql-operator/blob/master/pkg/controller/database/fakeclient_test.go) an example of how to create the fake client. \n\n#### e2e tests for Go Memcached Sample\n\n- I as a Go dev operator user, I'd like to know how to cover the projects with integration tests using the test-framework\n\n**Acceptance Criteria** \n- The GO project should be covered with a few basic integration tests\n- The tests should all pass.\n- The project should have a makefile target to call the integration test\n- A section with a short info over how to tests and the links for its documents in the README of the project\n- The tests should be done using the default GO testing lib and the [test-framework][e2e-docs] provided by SDK\n\n#### Unit tests for Ansible Memcached Sample\n\n- As an Ansible operator developer, I would like to know how to cover the projects with unit tests using molecule\n\n**Acceptance Criteria** \n- The Ansible project should be covered by tests using [molecule](https://github.com/operator-framework/operator-sdk-samples/tree/master/ansible/memcached-operator/molecule) which by default is scaffold\n- The tests should all pass.\n- A section with a short info over how to tests and the links for its documents in the README of the project\n- The project should have a makefile target to call the tests\n\n#### tests for Helm Memcached Sample\n\n- As an Helm operator developer, I would like to how to cover the projects with tests\n\n**Acceptance Criteria** \n- The Helm project should have test shell scripts as seen [here](https://github.com/operator-framework/operator-sdk/blob/master/hack/tests/e2e-helm.sh).- The tests should all pass.\n- A section with a short info over how to tests and the links for its documents in the README of the project\n- The project should have a makefile target to call the tests\n\n\n#### e2e tests for Ansible Memcached Sample\n\n- As an Ansible operator developer, I'd like to how to cover the projects with integration tests using molecule\n\n**Acceptance Criteria** \n- The Ansible project should have a few integration tests using [molecule](https://github.com/operator-framework/operator-sdk-samples/tree/master/ansible/memcached-operator/molecule) which by default is scaffold\n- The tests should all pass.\n- A section with a short info over how to tests and the links for its documents in the README of the project\n- The project should have a makefile target to call the tests\n\n#### Travis Integration\n\n- As an operator-sdk maintainer, I would like ensure that samples continue to work after the changes performed in the PR are applied.\n- As an operator developer, I would like to know how to call the tests in the CI and integrate them with Travis\n\n**Acceptance Criteria** \n- The Ansible, Helm and Go project should be integrated with Travis\n- All PRs against the master branch should trigger the CI\n- The unit and integration tests should be checked in the CI\n- The CI should fail if one of the tests do not pass\n\n#### Coveralls Integration\n\n- As an operator developer, I'd like to know good practices to ensure the quality of my operators projects \n\n**Acceptance Criteria** \n- Ansible and GO Memcached samples should be integrated with [Coveralls](https://coveralls.io/)\n- All above stories should be achieved successfully\n\n### Risks and Mitigations\n\n[Coveralls](https://coveralls.io/) may not work well with [molecule](https://github.com/operator-framework/operator-sdk-samples/tree/master/ansible/memcached-operator/molecule), if this is the case we can just not integrate with it or we can find a similar tool.\n\n[operator-sdk-doc]:  https://sdk.operatorframework.io/\n[e2e-docs]: https://sdk.operatorframework.io/docs/golang/legacy/e2e-tests/\n"
  },
  {
    "path": "proposals/scorecard-custom-tests-2.md",
    "content": "---\ntitle: Scorecard Custom Test Framework\nauthors:\n  - \"@jemccorm\"\nreviewers:\n  - \"@joelandford\"\n  - \"@zeus\"\napprovers:\n  - \"@shurley\"\n  - \"@dmesser\"\ncreation-date: 2020-03-19\nlast-updated: 2020-03-19\nstatus: implementable\n---\n\n# Scorecard - Custom Tests\n\n\n## Release Signoff Checklist\n\n- \\[ \\] Enhancement is `implementable`\n- \\[ \\] Design details are appropriately documented from clear requirements\n- \\[ \\] Test plan is defined\n- \\[ \\] Graduation criteria for dev preview, tech preview, GA\n- \\[ \\] User-facing documentation is created \n\n## Summary\n\nThis enhancement proposal outlines the SDK scorecard’s design for running of custom tests, specifically tests that are outside of what Red Hat includes by default within the scorecard’s tests.   The proposed design would provide both a means to write custom tests and also convert the existing scorecard tests (basic and olm) into the custom test format.\n\n## Motivation\n\nThe scorecard needs a robust means of enabling end-users of the SDK to write and execute their own operator tests.   Ideally, the custom test framework would decouple test logic from within the SDK itself, making the SDK and scorecard logic in particular more flexible and maintainable in the long run.\n\n## Goals\n\n * Document a design for scorecard to execute end-user or custom tests.\n\n * Document stories/steps required to deliver scorecard custom test functionality.\n\n### Non-Goals\n\n * This is a design proposal and does not include a proof-of-concept.\n\n## Proposal\n\nThis design proposal is to establish a pattern for implementing custom scorecard tests and also support the goal of migrating existing scorecard tests into the same format as the custom tests.\n\nWith this proposal, the scorecard will change as follows:\n\n * scorecard will not start the operator being tested\n * scorecard will not create Custom Resources on behalf of test\n * scorecard will execute tests as Pods based on scorecard configuration\n * scorecard will require a valid bundle image or on-disk bundle to determine what information will be passed to scorecard tests\n * scorecard will determine test configurations by a YAML/DSL file that is either passed on the command line or included in the bundle contents\n * scorecard will only run OLM tests if OLM manifests are found in the bundle\n * scorecard command syntax will look as follows:\n   * operator-sdk scorecard --dsl <point-to-yaml> --bundle <bundle-path/image> -l <selector>\n\n### User Stories\n\n#### Story 1\n\nI am as an Operator developer, I'd like to be able to construct custom tests and execute them via the scorecard.\n\n#### Story 2\n\nScorecard will include an example custom test that end users could use as a reference when writing their custom tests.\n\n#### Story 3\n\nScorecard internal tests will be converted to the custom test format and therefore be externalized from the scorecard binary itself.\n\n#### Story 4\n\nScorecard would process tests based on an on-disk directory or bundle image that contains the scorecard configuration.\n\n#### Story 5 \n\n- I am as an Operator developer, would like to be able to create tests using the same Assert syntax adopted by [Kuttl](https://github.com/kudobuilder/kuttl) and check its results aggregated within scorecard results. \n\n**Implementation Notes**\n\nThe Scorecard would support the creation of a Kuttl test image and then execute tests via Kuttl, however, it would be transparent for users since its results will be integrated into scorecard results.\n\n## Design Details\n\n### Glossary\n\n * test image - this is a container image built by end-users to contain a custom test implementation\n * test configuration (DSL) - this is a file that contains the test definitions and labels which determine what tests are run and how they are configured\n * Custom Test Definition - A custom test is any sort of test logic required, written in any programming language that satisfies the scorecard test requirements for output format and execution.\n\n#### Test Image\n\nA custom test is based on a container image, that image is created by\nthe end-user using whatever tools they want to use.\n\nThe test image must produce container log output that conforms to the scorecard Test Result output.  The output is a single Test Result, so a single run of a test image should execute and output the result for exactly one test.  Here is a sample of test output in the required format:\n```\n      {\n\t      \"name\": \"Spec fields with descriptors\",\n\t      \"description\": \"All spec fields have matching descriptors in the CSV\",\n\t      \"state\": \"fail\",\n\t      \"suggestions\": [\n\t\t\"Add a spec descriptor for size\"\n\t      ],\n\t      \"crname\": \"example-memcached\"\n      } \n```\n\nThe test image will be executed as a Pod by the scorecard with a restart policy of `never`.\n\nAlso, for each test execution, scorecard would also make the\nbundle image contents available to test images by mounting\nthe bundle image contents into the following location inside the test pod:\n\n```\n/scorecard/bundle/\n```\n\nThis allows tests to have access to all the bundle contents if they \nare required for the test logic.  The scorecard does not make assumptions about what the test does with this proposed design.  The test could for example:\n\n * not use the CR's at all (e.g. doing a static bundle validation)\n * use the CRs in the CSVs alm-examples annotation (e.g. to verify they validate the associated CRD schema)\n * use some other CRs built (or maybe mounted) into the test image \n\nFor the case of executing a test, the bundle image will be passed as a scorecard command flag:\n```\noperator-sdk scorecard --bundle='quay.io/myorg/mytest' --selector=suite=basic\n```\n\n#### Test Output\n\nCustom tests are expected to produce log output that conforms to the\nscorecard v1alpha2 Test Result output.  This allows scorecard to parse\nthe custom test log output and aggregate the results like any other\nscorecard test.\n\nThe scorecard expected output would be in JSON, and would match the following definition:  https://github.com/operator-framework/operator-sdk/blob/master/pkg/apis/scorecard/v1alpha2/types.go#L36\n\nThe scorecard v1alpha2 Test Result output contains information such as\npass or fail status and suggestions/errors produced by the test that\nthe end user would want to see in the aggregated scorecard results.\n\n\n### Custom Test Development Model\n\nThe developer of a custom test would have a workflow similar to:\n \n * write a custom test binary in the language of their choice, sample custom test within the SDK repository would be available as a starting point\n * test the custom test binary locally (out-of-cluster) to make sure the output is produced that matches v1alpha2 ScorecardTestResult format\n * scorecard creates a scorecard DSL config file for their test image\n * when the test binary works as expected, the developer would build and push the test image to a container registry accessible to the scorecard test environment\n * scorecard could build a bundle image that contains the scorecard DSL config\n NOTE:  the Basic and OLM test manifests would be added automatically to the bundle image as part of the bundle image build process.  This allows users to run the Basic and OLM tests along with their custom tests.\n * the developer would run the scorecard passing in their operator bundle image they just built along with any other scorecard flags (e.g. selector).\n\nThe case of a developer implementing a kuttl test would be as follows:\n * developer places kuttl test assets into a kuttl test directory known to scorecard\n * scorecard creates the scorecard DSL config file\n * scorecard runs the tests which are based on a scorecard kuttl test image\n * if the test results meet their goals, then scorecard could build a bundle image that contains the kuttl tests in a distributable format (e.g. bundle image)\n\n### Custom Test Packaging and Configuration\n\nIn this design proposal, custom tests are container images, described in the scorecard DSL yaml file.  End users would add their scorecard DSL yaml file into their operator bundle image or pass it into scorecard using a command line flag.  Custom test images are stored in a container registry outside the control of scorecard.  The scorecard DSL command flag would take precedence over the scorecard DSL config file found in the bundle image if specified.\n\n### Scorecard Configuration\n\nThe scorecard DSL yaml file would be accessible from a local disk location to scorecard or from within a bundle image. \n\nScorecard would assume that the scorecard DSL yaml file would be located in the bundle image at the following location:\n```\n/scorecard/config.yaml\n```\n\nThe scorecard DSL format is yet to be finalized but it would need to include configuration settings for each test including labels.  Here is a sample of what the scorecard DSL configuration would look like:\n```\ntests:\n# here is an example of a pair of custom tests that an ISV might implement\n- image: quay.io/someuser/customtest1:v0.0.1\n  description: some ISV test\n  labels:\n    suite: custom\n    test: customtest1\n- image: quay.io/someuser/customtest2:v0.0.1\n  description: some ISV test\n  labels:\n    test: customtest2\n# here is an example of the scorecard basic tests\n- image: quay.io/operator-framework/scorecard-basictests:v0.0.1\n  description: redhat - check spec\n  entrypoint: checkspec\n  labels:\n    suite: basic\n    test: basic-check-spec-test\n- image: quay.io/operator-framework/scorecard-basictests:v0.0.1\n  description: redhat - check status\n  entrypoint: checkstatus\n  labels:\n    suite: basic\n    test: basic-check-status-test\n# here is an example of the scorecard olm tests\n- image: quay.io/operator-framework/scorecard-olmtests:v0.0.1\n  description: redhat - CRDs have validation\n  entrypoint: crdvalidation\n  labels:\n    suite: olm\n    test: olm-crds-have-validation-test\n- image: quay.io/operator-framework/scorecard-olmtests:v0.0.1\n  description: redhat - CRDs have resources\n  entrypoint: crdhasresources\n  labels:\n    suite: olm\n    test: olm-crds-have-resources-test\n- image: quay.io/operator-framework/scorecard-olmtests:v0.0.1\n  description: redhat - spec descriptors\n  entrypoint: crdspecdescriptors\n  labels:\n    suite: olm\n    test: olm-spec-descriptors-test\n- image: quay.io/operator-framework/scorecard-olmtests:v0.0.1\n  description: redhat - status descriptors\n  entrypoint: crdstatusdescriptors\n  labels:\n    suite: olm\n    test: olm-status-descriptors-test\n- image: quay.io/operator-framework/scorecard-olmtests:v0.0.1\n  description: redhat - bundle validation\n  entrypoint: bundlevalidation\n  labels:\n    suite: olm\n    test: olm-bundle-validation-test\n# here is an example of the scorecard kuttl tests\n- image: quay.io/operator-framework/scorecard-kuttltests:v0.0.1\n  description: redhat - kuttl tests\n  labels:\n    suite: kuttl\n```\n\nUsers could override the default test images shipped with scorecard\nby adding scorecard command flags as follows:\n```\noperator-sdk scorecard --olm-image=quay.io/operator-framework/scorecard-olmtests:dev\noperator-sdk scorecard --basic-image=quay.io/operator-framework/scorecard-basictests:dev\noperator-sdk scorecard --kuttl-image=quay.io/operator-framework/scorecard-kuttltests:dev\n```\n\n### Custom Test Execution\n\nScorecard tests would be executed from the SDK scorecard CLI as is the case today.  Scorecard would execute the tests, capture the results, and provide feedback to the end-user by means of the current scorecard API (e.g. ScorecardTestResult).  Command line flags would allow the end-user a means to specify which tests are executed and upon which test environment to run the tests.  For example:\n```\noperator-sdk scorecard -o text --selector=suite=isvcustom --bundle='some/bundle/image:v0.0.1'\n```\n\nRunning the above command would have scorecard perform the following:\n \n * fetch the scorecard DSL yaml configuration from the bundle image\n * select the tests to run based on the scorecard DSL configuration and the selector\n * iterate through each test, \n   * construct a test Pod \n   * create the test Pod\n   * when the test pod completes, fetch the test image Pod log output for aggregation of test results\n * display the test results \n\n### Custom Test Environments\n\nScorecard would allow you to run tests on a local Kube cluster as is the case today.  Provisioning the test cluster is external to the scope of the scorecard itself.  Note, that with this proposal, scorecard would not be responsible for installing OLM or depend on OLM being installed in order to run. \n\n\n#### Migrating Scorecard Internal Tests to Custom Test Images\n\nWith the above custom test capability, there is benefit to Red Hat in migrating the existing scorecard internal tests to be based on the custom test format. \n\nToday there are 2 internal scorecard tests that make use of the scorecard proxy, with these tests migrating to the custom test format, the scorecard proxy is likely not necessary which would also reduce the overall scorecard implementation complexity.\n\n### Upgrade / Downgrade Strategy\n\nThe changes to scorecard are large and would require a migration off\nof the current scorecard.\n\n## Drawbacks\n\n\n## Ansible and Helm Operator Support\n\n### Ansible Operator Complex Tests\n\nFor custom tests, it might be possible to write the custom test image using ansible's callback plugin framework to produce container image log output in the scorecard required format (e.g. v1alpha2).  The complexity of the test might dictate whether this is viable or not, the fallback would be for the custom test to be developed in python, Java, or golang as discussed in this proposal.\n\n### Helm Operator Complex Tests\n\nWriting a custom test image in a Helm chart was not evaluated or pursued in this proposal.  What is likely for a Helm operator is that the operator owner would need to write custom test images using either Python, Java, golang, or some other programming language.\n\n\n## Alternatives\n\nThe alternatives to this design proposal might include:\n * Other existing/open-source test frameworks could be evaluated for use within the SDK for implementing the desired custom test functionality.\n * Other test frameworks within Redhat being planned or within use could be evaluated.\n\n\n## Conclusion\n\nThe proposed changes to the scorecard solve the immediate need to support custom or user-provided tests, both simple and complex tests.  However, the longer term implication for scorecard is that all of its tests would evolve to use a single testing format that is far more flexible that what exists today in the current implementation.\n\nThe proposed design focuses heavily on separation of concerns, turning scorecard into a test runner essentially, moving test implementations into their own concern (eg. container images).\n\n## Reference Material\n([Original Proposal](https://github.com/operator-framework/operator-sdk/pull/2624))\n([kuttl information](https://github.com/kudobuilder/kuttl))\n"
  },
  {
    "path": "proposals/scorecard-plugin-system.md",
    "content": "# Plugin System for the `operator-sdk scorecard` feature Proposal for Operator SDK \n\nImplementation Owner: AlexNPavel\n\n> Status: **implementable**\n\n- [Background](#background)\n- [Goals](#goals)\n- [Design Overview](#design-overview)\n  - [Plugin System](#plugin-system)\n\n## Background\n\nThe operator scorecard is intended to allow users to run a generic set of tests on their operators. The scorecard currently only has\nbuilt-in tests, and it would be beneficial to allow a simple way to add or remove various tests that the scorecard can run. This proposal\noutlines a plugin system that would allow us and users to dynamically add new tests without having to compile them into the scorecard/SDK\nbinary.\n\n## Goals\n\n- Implement a configurable plugin based scorecard test system\n\n## Design Overview\n\n### Plugin System\n\nIn order to increase the flexibility of the user defined tests and allow users to implement more complex E2E style tests for scorecard,\nthe user-defined tests will be implemented via a plugin system. Users would put executable files (etiher scripts or binaries) in a directory\nin the project root, for example `<root>/scorecard/bin` (the path can be configured via a flag). The scorecard would run all executable files\nsequentially and each plugin is expected to print out the result as JSON to stdout. If a plugin has a fatal error or does not return a valid JSON\nresult, the scorecard will have a default failure JSON result that specifies that the binary/script failed to run along with what the executable printed\nto stdout.\n\nThe JSON output will be reusing the Kubernetes API for marshalling and unmarshalling. This would allow us to have a standardized `TypeMeta` that will allow\nus to update the way we define tests and results in the future with proper versioning. Below is an example of what the JSON output of a test would look like:\n\nGo structs:\n\n```go\ntype ScorecardTest struct {\n    metav1.TypeMeta `json:\",inline\"`\n    // Spec describes the attributes for the test.\n    Spec *ScorecardTestSpec `json:\"spec\"`\n\n    // Status describes the current state of the test and final results.\n    // +optional\n    Status *ScorecardTestResults `json:\"results,omitempty\"`\n}\n\ntype ScorecardTestSpec struct {\n    // TestInfo is currently used for ScorecardTestSpec.\n    TestInfo `json:\",inline\"`\n}\n\ntype ScorecardTestResults struct {\n    // Log contains the scorecard's current log.\n    Log string `json:\"log\"`\n    // Results is an array of ScorecardResult for each suite of the curent scorecard run.\n    Results []ScorecardResult `json:\"results\"`\n}\n\n// ScorecardResult contains the combined results of a suite of tests\ntype ScorecardResult struct {\n    // Error is the number of tests that ended in the Error state\n    Error       int               `json:\"error\"`\n    // Pass is the number of tests that ended in the Pass state\n    Pass        int               `json:\"pass\"`\n    // PartialPass is the number of tests that ended in the PartialPass state\n    PartialPass int               `json:\"partial_pass\"`\n    // Fail is the number of tests that ended in the Fail state\n    Fail        int               `json:\"fail\"`\n    // TotalTests is the total number of tests run in this suite\n    TotalTests  int               `json:\"total_tests\"`\n    // TotalScore is the total score of this quite as a percentage\n    TotalScore  int               `json:\"total_score_percent\"`\n    // Tests is an array containing a json-ified version of the TestResults for the suite\n    Tests       []*JSONTestResult `json:\"tests\"`\n}\n\n// JSONTestResult is a simplified version of the TestResult that only include the Name and Description of the Test field in TestResult\ntype JSONTestResult struct {\n    // State is the final state of the test\n    State         State\n    // Name is the name of the test\n    Name          string\n    // Description describes what the test does\n    Description   string\n    // EarnedPoints is how many points the test received after running\n    EarnedPoints  int\n    // MaximumPoints is the maximum number of points possible for the test\n    MaximumPoints int\n    // Suggestions is a list of suggestions for the user to improve their score (if applicable)\n    Suggestions   []string\n    // Errors is a list of the errors that occurred during the test (this can include both fatal and non-fatal errors)\n    Errors        []error\n}\n\n// State is a type used to indicate the result state of a Test.\ntype State string\n\nconst (\n    // UnsetState is the default state for a TestResult. It must be updated by UpdateState or by the Test.\n    UnsetState State = \"unset\"\n    // PassState occurs when a Test's ExpectedPoints == MaximumPoints.\n    PassState State = \"pass\"\n    // PartialPassState occurs when a Test's ExpectedPoints < MaximumPoints and ExpectedPoints > 0.\n    PartialPassState State = \"partial_pass\"\n    // FailState occurs when a Test's ExpectedPoints == 0.\n    FailState State = \"fail\"\n    // ErrorState occurs when a Test encounters a fatal error and the reported points should not be considered.\n    ErrorState State = \"error\"\n)\n```\n\nJSON output for `ScorecardResult` object (for the initial `v1alpha1` of the scorecard test objects):\n\n```json\n{\n    \"error\": 0,\n    \"pass\": 1,\n    \"partial_pass\": 1,\n    \"fail\": 0,\n    \"total_tests\": 2,\n    \"total_score_percent\": 71,\n    \"tests\": [\n        {\n            \"state\": \"partial_pass\",\n            \"name\": \"Operator Actions Reflected In Status\",\n            \"description\": \"The operator updates the Custom Resources status when the application state is updated\",\n            \"earnedPoints\": 2,\n            \"maximumPoints\": 3,\n            \"suggestions\": [\n                {\n                    \"suggestion\": \"Operator should update status when scaling cluster down\"\n                }\n            ],\n            \"errors\": []\n        },\n        {\n            \"state\": \"pass\",\n            \"name\": \"Verify health of cluster\",\n            \"description\": \"The cluster created by the operator is working properly\",\n            \"earnedPoints\": 1,\n            \"maximumPoints\": 1,\n            \"suggestions\": [],\n            \"errors\": []\n        }\n    ]\n}\n```\n\nThis JSON output would make it simple for others to create scorecard plugins while keeping it simple for the scorecard\nto parse and integrate with the other tests. Each plugin would be considered a separate suite, and the full result of the scorecard\nwould be a list of `ScorecardResult`s.\n"
  },
  {
    "path": "proposals/sdk-code-annotations.md",
    "content": "# Code Annotations Proposal for Operator SDK\n\nImplementation Owner: @estroz\n\n> Status: **implemented**\n>\n> This proposal has been implemented. See the PR [#1162](https://github.com/operator-framework/operator-sdk/pull/1162).\n\n- [Background](#background)\n- [Goals](#goals)\n- [Design Overview](#design-overview)\n\n## Background\n\nCode can be annotated with special comment lines that tell a code parser information about document code. Two prominent examples are [go build tags][go_build_tags] and Kubernetes [code generators][k8s_code_gen]. The Operator SDK generates code that, after modification by users, is parsed, transformed, and then represented in an alternate form; SDK-specific code annotations can be used to inform SDK-specific tasks, like generating [Cluster Service Versions][olm_csv] from API's.\n\n## Goals\n\n- Define an annotation system that encapsulates current parsing needs and is extensible for future needs.\n\n## Design Overview\n\nAnnotations should follow this EBNF:\n\n```\ncomment token = ? the character(s) that define a line comment in some language, ex. // in go ? ;\nglobal prefix token = \"+operator-sdk\" ;\nglobal prefix = comment token , global prefix token ;\nuse case token = \":use-case\" ;\nuse case prefix = global prefix , use case token , { use case token } ; (* a set of annotations for some use case *)\nparent path token = \"parent\" ;\nchild path token = \".child\" ;\nfull path = parent path token , { child path token } ;\nprefixed path = use case prefix , \":\" , full path ;\nvalue = ['\"'] , \"text\" , ['\"'] ;\nannotation = prefixed path , \"=\" , value ;\n```\n\nThe \"use case\" token is meant to encapsulate the usage for an annotation, ex. `:gen-csv` is used for generating CSV's.\n\nA path token should have use-case-specific structure. The following [`etcd-operator`][etcd_operator_api] API code would be successfully parsed by [`operator-sdk olm-catalog gen-csv`][sdk_cli_ref_gen_csv] in the manner described below:\n\n```Go\ntype EtcdCluster struct {\n\tmetav1.TypeMeta   `json:\",inline\"`\n\tmetav1.ObjectMeta `json:\"metadata,omitempty\"`\n\tSpec              ClusterSpec   `json:\"spec\"`\n\tStatus            ClusterStatus `json:\"status\"`\n}\n\ntype ClusterSpec struct {\n\t// Pod defines the policy to create pod for the etcd pod.\n\t//\n\t// Updating Pod does not take effect on any existing etcd pods.\n\tPod *PodPolicy `json:\"pod,omitempty\"`\n}\n\n// PodPolicy defines the policy to create pod for the etcd container.\ntype PodPolicy struct {\n\t...\n\t// +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors.displayName=\"Resource Requirements\"\n\tResources v1.ResourceRequirements `json:\"resources,omitempty\"`\n\t...\n}\n```\n\nBy defining a set of paths with a `:gen-csv` use case token, an annotation parser \"knows\" that the `EtcdCluster` spec `ClusterSpec` has a `struct` field of type `PodPolicy` that should be included in the CSV manifest `spec.customresourcedefinitions` field as a `specDescriptor` entry with a `displayName` value of `Resource Requirements`.\n\nFor an annotation set to be user-friendly, these elements must be kept as simple as possible for the given task. Their parser implementation *must* be accompanied by documentation that explains how to create annotations for all supported fields, how the parser will interpret those annotations, and any constraints or requirements on paths or values.\n\n[go_build_tags]:https://golang.org/pkg/go/build/#hdr-Build_Constraints\n[k8s_code_gen]:https://blog.openshift.com/kubernetes-deep-dive-code-generation-customresources/\n[olm_csv]:https://github.com/operator-framework/operator-lifecycle-manager/blob/master/doc/design/building-your-csv.md\n[sdk_cli_ref_gen_csv]:https://github.com/operator-framework/operator-sdk/blob/v0.13.0/doc/sdk-cli-reference.md#gen-csv\n[etcd_operator_api]:https://github.com/coreos/etcd-operator/blob/387ece1ca4e9af764c9eb569ff995a21b10ba5ee/pkg/apis/etcd/v1beta2/cluster.go\n"
  },
  {
    "path": "proposals/sdk-integration-with-olm.md",
    "content": "---\ntitle: Neat-Enhancement-Idea\nauthors:\n  - \"@estroz\"\nreviewers:\n  - TBD\n  - \"@joelanford\"\n  - \"@dmesser\"\napprovers:\n  - TBD\n  - \"@joelanford\"\n  - \"@dmesser\"\ncreation-date: 2019-09-12\nlast-updated: 2019-09-12\nstatus: implementable\nsee-also:\n  - \"./cli-ux-phase1.md\"  \n---\n\n# sdk integration with olm\n\n## Release Signoff Checklist\n\n- \\[x] Enhancement is `implementable`\n- \\[x] Design details are appropriately documented from clear requirements\n- \\[ ] Test plan is defined\n- \\[ ] Graduation criteria for dev preview, tech preview, GA\n- \\[ ] User-facing documentation is created in openshift/docs\n\n## Summary\n\nThe [Operator Lifecycle Manager (OLM)][olm] is a set of cluster resources that manage the lifecycle of an Operator. OLM can be installed onto a Kubernetes cluster to provide a robust Operator management system for any cluster users. The Operator SDK (SDK) should be able to interact with OLM to a degree that gives any user the ability to deploy their Operator and tear it down using OLM, all in a reproducible fashion. This proposal aims to describe integration of OLM into the SDK for deployment and teardown.\n\n## Motivation\n\nOLM is an incredibly useful cluster management tool. There is currently no integration between SDK and OLM that encourages running an Operator with the latter.\n\n### Goals\n\n#### General\n\n* Operator developers can use `operator-sdk` to quickly deploy OLM on a given Kubernetes cluster\n* Operator developers can use `operator-sdk` to run their Operator under OLM\n* Operator developers can use `operator-sdk` to build a catalog/bundle containing their Operator for use with OLM\n\n#### Specific\n\n* `operator-sdk` creates a [bundle][bundle] from an Operator project to deploy with OLM\n* `operator-sdk` has a CLI interface to interact with OLM\n* `operator-sdk` installs a specific version of OLM onto Kubernetes cluster\n* `operator-sdk` uninstalls a specific version of OLM onto Kubernetes cluster\n* `operator-sdk` accepts a bundle and deploys that operator onto an OLM-enabled Kubernetes cluster\n* `operator-sdk` accepts a bundle and removes that operator onto an OLM-enabled Kubernetes cluster\n\n### Non-Goals\n\n## Proposal\n\n### User Stories\n\n**TODO**\n\nDetail the things that people will be able to do if this is implemented.\nInclude as much detail as possible so that people can understand the \"how\" of\nthe system. The goal here is to make this feel real for users without getting\nbogged down.\n\n#### Story 1\n\n### Implementation Details/Notes/Constraints\n\nInitial PR: https://github.com/operator-framework/operator-sdk/pull/1912\n\n#### Use of operator-registry\n\nThe SDK's approach to deployment should be as general and reliant on existing mechanisms as possible. To that end, [`operator-registry`][registry] should be used since it defines what a bundle contains and how one is structured. `operator-registry` libraries should be used to create and serve bundles, and interact with package manifests.\n\nThe idea is to create a `Deployment` containing the latest `operator-registry` [image][registry-image] to initialize a bundle database and run a registry server serving that database using binaries contained in the image. The `Deployment` will contain volume mounts from a `ConfigMap` containing bundle files and a package manifest for an operator. Using manifest data in the `ConfigMap` volume source, the registry initializer can build a local database and serve that database through the `Service`. OLM-specific resources created by the SDK or supplied by a user, described below, will establish communication between this registry server and OLM.\n\n#### OLM resources\n\nOLM understands `operator-registry` servers and served data through several objects. A [`CatalogSource`][olm-catalogsource] specifies how to communicate with a registry server. A [`Subscription`][olm-subscription] links a particular CSV channel to a `CatalogSource`, indicating from which `CatalogSource` OLM should pull an Operator. Another OLM resource that _may_ be required is an [`OperatorGroup`][olm-operatorgroup], which provides Operator namespacing information to OLM; OLM creates two `OperatorGroup`'s by default, one of which can be used for globally scoped Operators.\n\nThese resources can be created from bundle data with minimal user input. They can also be created from manifests defined by the user; however, the SDK cannot make guarantees that user-defined manifests will work as expected.\n\n#### Use of operator-framework/api validation\n\nStatic validation is necessary for users to determine problems before deploying their Operator. As we all know, static bugs are usually more tractable than runtime bugs, especially those discovered in a live cluster. The [`operator-framework/api`][of-api] repo intends to house a validation library for static, and potentially runtime, validation. The SDK should use this library as the source of truth for the qualities of a valid OLM manifest. This repo is a work-in-progress, and should be used as soon as it is ready.\n\n### Risks and Mitigations\n\nThere are fewer risks with this approach than others because external libraries that define OLM components are used whenever possible, ensuring maximum compatibility.\n\nOne risk factor is how hidden OLM nuances are from users. Much of how an Operator is deployed using a registry and OLM resources like `Subscription`'s is complex, and understanding each component is necessary for true self sufficiency. However good documentation can help direct users towards solutions. There is also an ongoing effort to reduce the complexity of OLM metadata requirements.\n\n## Design Details\n\n### Test Plan\n\n**Note:** *Section not required until targeted at a release.*\n\nConsider the following in developing a test plan for this enhancement:\n- Will there be e2e and integration tests, in addition to unit tests?\n- How will it be tested in isolation vs with other components?\n\nNo need to outline all of the test cases, just the general strategy. Anything\nthat would count as tricky in the implementation and anything particularly\nchallenging to test should be called out.\n\nAll code is expected to have adequate tests (eventually with coverage\nexpectations).\n\n### Graduation Criteria\n\n**Note:** *Section not required until targeted at a release.*\n\nDefine graduation milestones.\n\nThese may be defined in terms of API maturity, or as something else. Initial proposal\nshould keep this high-level with a focus on what signals will be looked at to\ndetermine graduation.\n\nConsider the following in developing the graduation criteria for this\nenhancement:\n- Maturity levels - `Dev Preview`, `Tech Preview`, `GA`\n- Deprecation\n\nClearly define what graduation means.\n\n#### Examples\n\nThese are generalized examples to consider, in addition to the aforementioned\nmaturity levels.\n\n##### Dev Preview -> Tech Preview\n\n- Ability to utilize the enhancement end to end\n- End user documentation, relative API stability\n- Sufficient test coverage\n- Gather feedback from users rather than just developers\n\n##### Tech Preview -> GA\n\n- More testing (upgrade, downgrade, scale)\n- Sufficient time for feedback\n- Available by default\n\n**For non-optional features moving to GA, the graduation criteria must include\nend to end tests.**\n\n##### Removing a deprecated feature\n\n- Announce deprecation and support policy of the existing feature\n- Deprecate the feature\n\n### Upgrade / Downgrade Strategy\n\nIf applicable, how will the component be upgraded and downgraded? Make sure this\nis in the test plan.\n\nConsider the following in developing an upgrade/downgrade strategy for this\nenhancement:\n- What changes (in invocations, configurations, API use, etc.) is an existing\n  cluster required to make on upgrade in order to keep previous behavior?\n- What changes (in invocations, configurations, API use, etc.) is an existing\n  cluster required to make on upgrade in order to make use of the enhancement?\n\n### Version Skew Strategy\n\nHow will the component handle version skew with other components?\nWhat are the guarantees? Make sure this is in the test plan.\n\nConsider the following in developing a version skew strategy for this\nenhancement:\n- During an upgrade, we will always have skew among components, how will this impact your work?\n- Does this enhancement involve coordinating behavior in the control plane and\n  in the kubelet? How does an n-2 kubelet without this feature available behave\n  when this feature is used?\n- Will any other components on the node change? For example, changes to CSI, CRI\n  or CNI may require updating that component before the kubelet.\n\n## Implementation History\n\nMajor milestones in the life cycle of a proposal should be tracked in `Implementation\nHistory`.\n\n## Drawbacks\n\nThe idea is to find the best form of an argument why this enhancement should _not_ be implemented.\n\n## Alternatives\n\nSimilar to the `Drawbacks` section the `Alternatives` section is used to\nhighlight and record other possible approaches to delivering the value proposed\nby an enhancement.\n\n## Infrastructure Needed\n\nUse this section if you need things from the project. Examples include a new\nsubproject, repos requested, github details, and/or testing infrastructure.\n\nListing these here allows the community to get the process for these resources\nstarted right away.\n\n[olm]:https://github.com/operator-framework/operator-lifecycle-manager/\n[olm-operatorgroup]:https://github.com/operator-framework/operator-lifecycle-manager/blob/master/doc/design/operatorgroups.md\n[olm-subscription]:https://github.com/operator-framework/community-operators/blob/master/docs/testing-operators.md#7-create-a-subscription\n[olm-catalogsource]:https://github.com/operator-framework/operator-lifecycle-manager/blob/master/doc/design/philosophy.md#catalogsource\n[registry]:https://github.com/operator-framework/operator-registry/\n[bundle]:https://github.com/operator-framework/operator-registry/#manifest-format\n[registry-image]:https://quay.io/organization/openshift/origin-operator-registry\n[of-api]:https://github.com/operator-framework/api\n"
  },
  {
    "path": "proposals/tech-debt.md",
    "content": "---\ntitle: OpenShift 4.4: Operator SDK Tech Debt\nauthors:\n  - \"@joelanford\"\nreviewers:\n  - \"@camilamacedo86\"\n  - \"@estroz\"\napprovers:\n  - TBD\ncreation-date: 2019-12-18\nlast-updated: 2019-12-18\nstatus: implementable\nsee-also: []\nreplaces: []\nsuperseded-by: []\n---\n\n# OpenShift 4.4: Operator SDK Tech Debt\n\n## Release Signoff Checklist\n\n- \\[x\\] Enhancement is `implementable`\n- \\[x\\] Design details are appropriately documented from clear requirements\n- \\[ \\] Test plan is defined\n- \\[ \\] Graduation criteria for dev preview, tech preview, GA\n- \\[ \\] User-facing documentation is created in [operator-sdk/doc][operator-sdk-doc]\n\n## Summary\n\nDuring the OpenShift 4.4 development timeframe, there are two primary areas of\nthe Operator SDK project that we plan to improve.\n\n1. Introduction of unobtrusive code health improvements (Go linting, test coverage)\n2. UX and code improvements to the `generate` subcommand.\n\n## Motivation\n\nThe motivation for these changes is to improve the user experience of the SDK's\ncommand line interface and to improve code health to ensure a quality product,\nincrease developer productivity, and provide a more inviting project for external\ncontributors.\n\n## Goals\n\n1. Enable `golangci-lint` in the project Makefile and in CI, reduce the number of\n   linter errors, and permanently enable more linters to keep avoid introducing\n   new lint errors.\n2. Enable code coverage metrics for unit tests and push results to coveralls.io\n   during CI to help contributors and maintainers keep code quality high and\n   reduce the likelihood of regressions.\n3. Refactor the `generate` subcommand to improve user experience, reduce confusion,\n   and simplify the codebase.\n\n### Non-Goals\n\nThere are numerous other areas of the codebase that are in need of refactoring\n(e.g. scorecard and the test framework). Due to the size and scope of these\nother refactorings, they need to be broken out and handled on their own, either\nin the context of another epic or as a separate epic altogether. Therefore, this\nepic is limited in the scope to the specific refactorings and improvements\ndiscussed above.\n\nIt is also not in the scope of this epic to actually _improve_ test coverage. This\nepic's goal is to simply make test coverage metrics available and visible.\n\n## Proposal\n\nThis is where we get down to the nitty gritty of what the proposal actually is.\n\n### User Stories\n\n#### Story 1 - Integrate `golangci-lint` into the development and CI processes\n\nGo linting will use golangci-lint. It be introduced as a `make` target and as a step\nin the sanity tests that run as part of the SDK's continuous integration test suite.\nThe `make` target will run all of golangci-lint's linters, whereas the sanity test\nwill run a subset that we expect to pass. Over the course of the 4.4 development\ncycle, work will continue to fix outstanding lint issues so that more linters can\nbe enabled in CI.\n\n#### Story 2 - Instrument unit tests with code coverage\n\nTest coverage will be tracked by running unit tests with code coverage enabled and\nsubmitting results to coveralls.io during CI. This integration will highlight code\ncoverage improvements or regressions in each PR, which will incentivize contributors\nand reviewers to improve code coverage over time.\n\n#### Story 3 - Refactor CRD generation\n\nImprovements to the generate subcommand will include the deprecation and\nremoval of the `generate openapi` subcommand (to be replaced with the `generate\ncrds` subcommand) and the internal refactoring of the `generate crds` subcommand\nto use a more flexible entrypoint into the underlying `controller-tools` package\nthat actually implements the CRD generation.\n\nThe `generate openapi` command currently generates both CRD yaml files and Go code\nthat defines the OpenAPI structs for the operator's Go API types. However, very few\nuse cases require the generated OpenAPI code. By removing the Go OpenAPI code\ngeneration, we are left with just CRD generation, hence the need for an improved\nname (`generate crds`).\n\nWe will add the new `generate crds` subcommand and deprecate `generate openapi`. A\ndeprecation message will be included that directs users who need to continue\ngenerating Go OpenAPI code how to do it with the upstream `openapi-gen` tool\ndirectly.\n\n### Risks and Mitigations\n\nOnly risk is that deprecation of `generate openapi` will break a small subset of SDK\nusers. The mitigation is that the SDK will include instructions for running code\ngeneration tools directly, which will be a 1-to-1 replacement of the deprecated\nfunctionality in Operator SDK.\n\n## Design Details\n\n### Test Plan\n\nAll unit tests will gain coverage metrics, which will increase visibility on the areas\nof the codebase that do not have adequete testing.\n\nThe `generate` subcommand changes will also result in refactored unit and e2e tests,\nwhich will no longer need to check for the existence of generated Go OpenAPI code.\n\n### Graduation Criteria\n\nN/A\n\n### Upgrade / Downgrade Strategy\n\nN/A\n\n### Version Skew Strategy\n\nN/A\n\n## Implementation History\n\nMajor milestones in the life cycle of a proposal should be tracked in `Implementation\nHistory`.\n\n## Drawbacks\n\nNone\n\n## Alternatives\n\nNone\n\n## Infrastructure Needed (optional)\n\nNone\n\n[operator-sdk-doc]:  https://sdk.operatorframework.io/\n"
  },
  {
    "path": "proposals/tls-utilities.md",
    "content": "# TLS Utilities Proposal for Operator SDK\n\nImplementation Owner:\n\n> Status: **deferred**\n\n- [Background](#background)\n- [Goals](#goals)\n- [Details](#details)\n- [Implementation](#implementation)\n- [Workflow](#workflow)\n- [Q&A](#qa)\n- [Future Plans](#future-plans)\n\n## Background\n\nA typical workflow of an operator that is written using the Operator-SDK involves watching a Custom Resource (CR), which specifies the desired state of the cluster, and making changes to the current state of the cluster to achieve the desired state.\n\nEach user specified CR represents a self contained system. Based on this, we can assume that any TLS assets generated are specific to each system which then is also specific to the corresponding CR.\n\nBased on the above assumption, we want to design a TLS utility pkg that helps generate TLS assets and ties them to a specific CR.\n\n## Goals\n\nTo provide TLS utilities for operator developers to create self signed Certificate Authority (CA) and the TLS encryption keys along with the signed certs. This will enable the operator to setup TLS assets for the application so that all the communication within it is secure.\n\n## Details\n\nWe will break down the TLS workflow into the following steps:\n\n1. Generate a Certificate Authority (CA): A CA is a centralized trusted third party that signs the certificates. We need to generate a CA key and CA Certificate to get started. If the users want to provide their own CA, we can add an option to do so. The generated CA certificate can be saved in a ConfigMap as follows:\n\n\tInputs:\n\n\t* CR-kind\n\t* CR-name\n\t* namespace\n\n\tOutputs:\n\n        * A ConfigMap that contains the CA Cert:\n\n\t```\n\tkind: ConfigMap\n\tapiVersion: v1\n\tmetadata:\n\tname: <crd-kind>-<crd-name>-ca\n\tnamespace: <ns>\n\tdata:\n\tca.crt: ...\n            ```\n        * A secret that contains the CA key:\n\n           ```\n\tkind: Secret\n\tapiVersion: v1\n\tmetadata:\n\tname: <cr-kind>-<cr-name>-ca\n\tnamespace: <ns>\n\tdata:\n\tca.key: ...\n\t```\n\n2. Verify the CA certificate: The newly generated CA certificate in ConfigMap should be validated i.e. the digital signature should be checked, the expiry, activation dates and validity period should be checked, etc.\n\n3. Generate Server or Client Certificate: We assume that the components inside an application communicate through a service. Therefore, we generate a TLS private key and certificate for that service.\n\n\tInputs:\n\n\t* CR-kind\n\t* CR-name\n\t* Namespace\n\t* Previously generated CA key and Certificate\n\n\tOptions:\n\n\t* Key usage: (Server, Client or Both) If Server, needs svc obj (cluster.local can be different). If client, needs CN and possible org.\n\t* Option to specify signature configuration policy i.e Signing Profile for the certificate.\n\n        Outputs:\n\n\t* A Secret containing Private Key and Server/Client Certificate signed by the CA:\n\n\t```\n\tkind: Secret\n\tapiVersion: v1\n\tmetadata:\n\t name: <cr-kind>-<cr-name>-<CertName>\n\t namespace: <ns>\n\tdata:\n\t tls.crt: ...\n\t tls.key: …\n\ttype: kubernetes.io/tls\n\t```\n\n4. Verify Server or Client Certificate: The newly generated client/server certificate in should be validated i.e. the digital signature should be checked, the expiry, activation dates and validity period should be checked, certificate chain should be verified etc\n\n\n5. Use CA configmap and TLS secret in the necessary deployment/pod object.\n\n## Implementation\n\nHave a certificate configuration object which will contain all the input arguments required to generate a server/client certificate.\n\n```\n// CertConfig configures the Cert generation.\ntype CertConfig struct {\n\t// CertName is the name of the cert.\n\tCertName string\n\t// Optional CertType. Server, client or both; defaults to both.\n\tCertType CertType\n\t// CommonName is the common name of the cert\n\tCommonName string\n\t// Organization is Organization of the cert\n\tOrganization []string\n\t// Optional CA Key, if user wants to provide custom CA\n\tCAKey string\n\t// Optional CA Certificate, if user wants to provide custom CA\n\tCACert string\n}\n```\n\nHave a method which will generate a secret that contains a newly created TLS Private key and Certificate for the given service. A unique CA is also generated by default to sign the Certificate if a prior CA certificate is not preset for the user specified CR. If the user wants to use a custom CA, it can be specified in the `CertConfig` object. The function signature of the method is as follows:\n\n```\nfunc GenerateCert(cr runtime.Object, service *v1.Service, config *CertConfig) (*v1.Secret, *v1.ConfigMap, *v1.Secret, error)\n\n```\n\nPlease note that the `GenerateCert` method cannot be used to generate TLS assets for a service of type [`ExternalName`](https://kubernetes.io/docs/concepts/services-networking/service/#externalname). This is because in the current design the fully qualified domain name (FQDN) of the Service object is used as the SAN for the certificate by default. Currently we do not have a way to customize the SAN value, we will add a field in `CertConfig` for this purpose later on.\n\nThe `GenerateCert` method can be used in the operator handler function to set up TLS for the desired application\n\n```\n// ../pkg/stub/handler.go\nfunc (h *Handler) Handle(ctx types.Context, event types.Event) error {\n\tswitch crd := event.Object.(type) {\n\tcase *api.AppService:\n\t\tcfg := CertConfig{\n\t\t\tCertName: \"server1\",\n\t\t}\n\t\ts := v1.Service{...}\n\t\ttlsCertSecret, caCertConfigMap, caKeySecret, err := GenerateCert(crd, s, cfg)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\t// use the newly generated TLS secret in a deployment manifest to mount it as volume.\n\t\t...\n\t}\n}\n```\n## Workflow\n\nTo understand the implementation details more clearly let us run through an example operator and how it can make use of the TLS utility package:\n\nLet us take the Vault Operator as an example. The Vault operator deploys and manages Vault clusters on Kubernetes. The following workflow is a step by step guide of how the vault operator can make use of the TLS utility package described above:\n\n1. Create the Vault CR using [`kubectl create`](https://github.com/coreos/vault-operator/blob/master/example/vault_crd.yaml)\n2. Modify the operator handler to generate the necessary vault server TLS assets:\n\t1. Populate the struct `CertConfig` with required values which specify the server certificate.\n\t2. Call the `GenerateCert` method which will generate and return a secret that contains a newly created TLS Private key and Certificate for the Vault server. This Certificate will be signed by a custom CA or a newly generated CA depending on the configuration in `CertConfig`.\n3. The operator is responsible for creating a service and deployment manifests for the application the user wishes to run. The deployment manifests will contain the TLS assets generated in step 2 as Volume mounts.\n\n## Q&A\n\n1. What happens after the CA certificate expires?\n   Once the CA certificate expires, all certificates signed by the CA become invalid.\n\n## Future Plans\n\n1. Maintenance and rotation of these TLS certificates: Setting a certificate rotation policy from the start will protect you against the usual key mismanagement or leaking that is bound to happen over long periods of time. This is often overlooked and never-expiring tokens are shared between administrators for convenience reasons. To start off simple, we can provide a simple command line tool `--rotate-certificates` that will perform a rotation for a specific certificate.\n\n2. Consider having a signer server and a client agent in our TLS utilities package. The server will handle HTTP requests and responses. When it receives a CSR approval requests from the client agent it attempts to sign it. If successful, the approved CSR, which contains the signed certificate, is returned to the agent. This server-client mechanism will eliminate the need to copy around certs.\n"
  },
  {
    "path": "proposals/upstream-osdk-features-into-controller-runtime.md",
    "content": "---\ntitle: upstream-OSDK-features-to-controller-runtime\nauthors:\n  - \"@hasbro17\"\nreviewers:\n  - TBD\n  - \"@joelanford\"\n  - \"@dmesser\"\napprovers:\n  - TBD\n  - \"@joelanford\"\n  - \"@dmesser\"\ncreation-date: 2019-09-22\nlast-updated: 2019-09-22\nstatus: implementable\n---\n\n# upstream-OSDK-features-to-controller-runtime\n\n## Release Signoff Checklist\n\n- Enhancement is `implementable`\n- Design details are appropriately documented from clear requirements\n- Test plan is defined\n\n\n## Summary\n\nAn operator project scaffolded with the Operator SDK will primarily use library code that lives upstream in the controller-runtime project. There is a small set of packages in the SDK that extends the functionality of the controller-runtime APIs to cover more specific use cases. Most of these features along with their documentation should be contributed upstream to the controller-runtime.\n\nAdditionally the Operator SDK is preparing to use Kubebuilder for scaffolding Go operator projects for better alignment with the upstream community. See [kubebuilder-project-board][kubebuilder-project-board] and [upstream proposal for the integration of Operator SDK and Kubebuilder][sdk-kubebuilder-integration-proposal]. As part of this integration some features from the SDK’s scaffolding machinery need to be contributed upstream to Kubebuilder before the SDK can use Kubebuilder as its upstream.\n\n\n## Motivation\n\nContributing the extra features in the SDK to the controller-runtime would make them available to all users of the controller-runtime. This also reduces the maintenance burden in the SDK by since there are more contributors and users upstream who can improve on these features over time.\n\nContributing scaffolding enhancements to Kubebuilder that cover the SDK’s use cases removes blockers in the SDK’s proposal to use Kubebuilder as upstream, and helps align the SDK and Kubebuilder on a common project layout and workflow.\n\n\n### Goals\n\n- The packages and features that are suitable for upstream contribution should be made available in the controller-runtime such that they cover the same use cases.\n- Downstream SDK users can easily switch over to using those features in the controller-runtime. In most cases this should amount to just changing the import paths. For function signature changes there should be documentation to explain the breaking changes.  \n- The contributed features should have sufficient documentation in the upstream godocs.\n- Once available upstream, those packages and APIs should be marked as deprecated and eventually removed from the SDK.\n\n\n### Non-Goals\n\n- Not all SDK library code is suitable for upstream contributions.\n  - For instance the test-framework library is closely tied to the SDK’s testing workflow and not generally applicable outside SDK projects.\n  - The SDK's leader-for-life leader election package already has an alternative in the controller-runtime’s leader election package which uses lease based leader election.\n\n\n## Proposal\n\nThe user stories outline the individual features that are suitable for upstream contribution. Some of these features may already be merged upstream or are currently under review.\n\n\n### User Stories\n\n#### Story 1 - Dynamic RestMapper that can reload to update discovery information for new resource types\n\nThe default RestMapper used in the controller-runtime will not update to reflect new resource types registered with the API server after the RestMapper is first initialized at startup. See [operator-sdk #1328][operator-sdk-1328] and [controller-runtime #321][controller-runtime-321].\n\nThe SDK has pkg/restmapper (see [operator-sdk #1329][operator-sdk-1329]) that provides a dynamic RestMapper which will reload the cached rest mappings on lookup errors due to a stale cache. This dynamic restmapper is currently under review for upstream contribution with some improvements like thread safety and rate limiting. See [controller-runtime #554][controller-runtime-554].\n\n\n#### Story 2 - GenerationChangedPredicate that can filter watch events with no generation change\n\nThe SDK provides a predicate called GenerationChangedPredicate in [pkg/predicate][sdk-pkg-predicate] that will filter out update events for objects that have no change in their metadata.Generation. This is commonly used for ignoring update events for CustomResource objects that only have their status block updated with no change to the spec block.\n\nThis feature has already been incorporated upstream with godocs on the predicate and its caveats. See [controller-runtime-553][controller-runtime-553] and [GenerationChangedPredicate godocs][gen-change-predicate-godocs].\n\n\n#### Story 3 - Add command line flags to make the controller-runtime’s zap based logger configurable\n\nThe SDK has [pkg/log/zap][sdk-pkg-log-zap] that provides a zap based logr logger that allows a number of fine grained configurations (e.g debug level, encoder formatting) via [command line flags][sdk-zap-cmd-flags] passed to the operator.\n\nThe controller-runtime’s zap based logger has recently been made configurable via functional options that should allow all the configurations in the SDK’s own zap logger (see [controller-runtime #560][controller-runtime-560]). This needs to be followed up by adding predefined options for each configuration of the logger to the controller-runtime so that users don’t have to write it themselves.\n\nIdeally the flagset for setting all the logger configurations could also live upstream but given that the controller-runtime’s [pkg/log/zap][cr-pkg-log-zap] allows instantiating multiple zap loggers with different configs, it may not be suitable to have a global flagset that provides a singular configuration for all instantiated loggers.\nThis point needs more discussion and it’s possible that the configuration flags may have to live downstream in the SDK.\n\n\n#### Story 4 - Operator Developers can use SDK’s method of building images that run as non-root users in Kubebuilder projects\n\nKubebuilder scaffolded projects would previously run the operator base images with the user as root. See Kubebuilder’s [pkg/scaffold/v2/dockerfile.go][kb-scaffold-dockerfile].\n\nOperator SDK scaffolds a project Dockerfile such that it runs as non-root by default and allows the operator image to run with arbitrary UIDs on openshift. For details, see the [openshift container guidelines][openshift-container-guidelines] for non-root images, and how the SDK includes the user setup in the image build and uses a custom entrypoint:\n\n- [internal/pkg/scaffold/build_dockerfile.go][sdk-scaffold-dockerfile]\n- [internal/pkg/scaffold/entrypoint.go][sdk-scaffold-entrypoint]\n- [internal/pkg/scaffold/usersetup.go][sdk-scaffold-user-setup]\n\nKubebuilder should support scaffolding projects that will allow the base image to run as non-root and support arbitrary user ids. \nCurrently with [kubebuilder #983][kubebuilder-983], a non-root base image should be supported by Kubebuilder.\n\n\n#### Story 5 - Operator Developers can use the prometheus-operator’s ServiceMonitor API to configure prometheus to scrape their operator metrics in Kubebuilder projects\n\nThe Operator SDK’s [pkg/metrics][sdk-pkg-metrics] has helpers that let’s operators configure and create [ServiceMonitors][service-monitor-doc] that lets a prometheus instance on a cluster target the operator’s Service object that exposes operator metrics.\n\nInstead of having this functionality live in controller-runtime as helpers that can be called to setup ServiceMonitors, this can added as manifests that are scaffolded by Kubebuilder for an operator project. This would be similar to other resources that need to be created alongside the operator and can be customized in the manifest. Upstream issue at [kubebuilder #887][kubebuilder-887].\n\n\n#### Story 6 - Operator Developers have documentation that demonstrates how to create and expose custom operator metrics\n\nOnce Kubebuilder supports scaffolding ServiceMonitor manifests, the [Kubebuilder book][kubebuilder-book] documentation on [recording custom metrics][recording-custom-metrics] should be extended to show how to expose these metrics via the ServiceMonitor.\n\n\n\n### Risks and Mitigations\n\nAlmost all of the upstream work entails breaking changes for SDK users.\nBefore the features are removed from the SDK they should first be deprecated in prior release with sufficient documentation that explains how to use the equivalent features upstream in the controller-runtime.\n\nThe features that have replacements in kubebuilder will need to wait until the SDK is ready to upstream kubebuilder for Go operators before being removed.\n\n\n### Test Plan\n\nAll library features being upstreamed into the controller-runtime would need to have unit tests to run as part of its CI.\n\nSimilarly any scaffolding and manifest changes to Kubebuilder would need e2e tests that verify the effects of those manifest changes as part of Kubebuilder’s CI.\n\n\n[kubebuilder-project-board]: https://github.com/kubernetes-sigs/kubebuilder/projects/7\n[sdk-kubebuilder-integration-proposal]: https://github.com/kubernetes-sigs/kubebuilder/blob/992ecdfd3f47e4cca79937a4fd46a0ee10f477d7/designs/integrating-kubebuilder-and-osdk.md\n[operator-sdk-1328]: https://github.com/operator-framework/operator-sdk/issues/1328\n[operator-sdk-1329]: https://github.com/operator-framework/operator-sdk/pull/1329\n[controller-runtime-321]: https://github.com/kubernetes-sigs/controller-runtime/issues/321\n[controller-runtime-554]: https://github.com/kubernetes-sigs/controller-runtime/pull/554\n[sdk-pkg-predicate]: https://github.com/operator-framework/operator-sdk/blob/947a464dbe968b8af147049e76e40f787ccb0847/pkg/predicate/predicate.go\n[controller-runtime-553]: https://github.com/kubernetes-sigs/controller-runtime/pull/553\n[gen-change-predicate-godocs]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/predicate#GenerationChangedPredicate\n[sdk-pkg-log-zap]: https://github.com/operator-framework/operator-sdk/tree/947a464dbe968b8af147049e76e40f787ccb0847/pkg/log/zap\n[sdk-zap-cmd-flags]: https://github.com/operator-framework/operator-sdk/blob/947a464dbe968b8af147049e76e40f787ccb0847/pkg/log/zap/flags.go#L41-L45\n[controller-runtime-560]: https://github.com/kubernetes-sigs/controller-runtime/pull/560\n[cr-pkg-log-zap]: https://github.com/kubernetes-sigs/controller-runtime/blob/e825f3aafdb522bbdac626387f3c9e7d489e35a7/pkg/log/zap/zap.go#L35-L37\n[kb-scaffold-dockerfile]: https://github.com/kubernetes-sigs/kubebuilder/blob/1f4fc57416ddc74ea52feb13494eb4d003d7db08/pkg/scaffold/v2/dockerfile.go#L58-L60\n[openshift-container-guidelines]: https://access.redhat.com/documentation/en-us/openshift_container_platform/4.1/html/images/creating_images#images-create-guide-openshift_create-images\n[sdk-scaffold-dockerfile]: https://github.com/operator-framework/operator-sdk/blob/c084b570a6af7674fd102f4ebfd3303c705e1d94/internal/pkg/scaffold/build_dockerfile.go\n[sdk-scaffold-entrypoint]: https://github.com/operator-framework/operator-sdk/blob/c084b570a6af7674fd102f4ebfd3303c705e1d94/internal/pkg/scaffold/entrypoint.go\n[sdk-scaffold-user-setup]: https://github.com/operator-framework/operator-sdk/blob/c084b570a6af7674fd102f4ebfd3303c705e1d94/internal/pkg/scaffold/usersetup.go\n[kubebuilder-983]: https://github.com/kubernetes-sigs/kubebuilder/pull/983\n[sdk-pkg-metrics]: https://github.com/operator-framework/operator-sdk/blob/f5d20c4819b98a60ec782a9a5cac784b55ea2951/pkg/metrics/service-monitor.go\n[service-monitor-doc]: https://github.com/coreos/prometheus-operator/blob/master/Documentation/user-guides/getting-started.md#related-resources\n[kubebuilder-887]: https://github.com/kubernetes-sigs/kubebuilder/issues/887\n[kubebuilder-book]: https://book.kubebuilder.io/quick-start.html\n[recording-custom-metrics]: https://book.kubebuilder.io/reference/metrics.html#publishing-additional-metrics\n"
  },
  {
    "path": "release/Makefile",
    "content": "## This Makefile should only be called from the project root Makefile ##\n\n# Needed for glob expansion.\nSHELL = /bin/bash\n.SHELLFLAGS = -O extglob -c\n\n# Dry run flags.\nifneq ($(DRY_RUN),)\nSNAPSHOT_FLAGS = --snapshot --skip-publish --skip-sign --rm-dist\nCHANGELOG = changelog/generated/tmp.md\n$(shell touch $(CHANGELOG))\nendif\n\n# Ensure that this Makefile is run from the project root (always contains the 'cmd/' directory).\nifeq (,$(wildcard cmd))\n\t$(error \"This Makefile must be invoked from the operator-sdk project root\")\nendif\n\n##@ Release\n\n.PHONY: release\nCHANGELOG ?= changelog/generated/$(GIT_VERSION).md\nrelease: ## Publish an operator-sdk release, with option for a dry run with DRY_RUN.\nifeq (,$(GIT_VERSION))\n\t$(error \"GIT_VERSION must be set to a git tag\")\nendif\n\t$(SCRIPTS_DIR)/fetch goreleaser 0.177.0\n\tGORELEASER_CURRENT_TAG=$(GIT_VERSION) $(TOOLS_DIR)/goreleaser $(SNAPSHOT_FLAGS) --release-notes=$(CHANGELOG) --parallelism 5\nifneq ($(DRY_RUN),)\n\trm $(CHANGELOG)\nendif\n\n##@ Pre-Release\n\n.PHONY: check_release_version\ncheck_release_version:\nifeq (,$(RELEASE_VERSION))\n\t$(error \"RELEASE_VERSION must be set to a release tag\")\nendif\n\n.PHONY: prerelease\nprerelease: check_release_version changelog ## Create release commit changes to commit.\n\t./website/scripts/update_branch_mappings.sh $(RELEASE_VERSION)\n\t./website/scripts/update_download_url.sh $(RELEASE_VERSION)\n\t./website/scripts/update_latest_release_compat.sh\n\n.PHONY: changelog\nchangelog: check_release_version ## Generate the changelog.\n\t@mkdir -p changelog/generated && rm -f changelog/generated/$(RELEASE_VERSION).md\n\tgo run ./release/changelog/gen-changelog.go -tag=$(RELEASE_VERSION) -changelog=changelog/generated/$(RELEASE_VERSION).md\n\trm -f ./changelog/fragments/!(00-template.yaml)\n\n.PHONY: tag\nVERSION_REGEXP := ^(scorecard-kuttl/)?v[0-9]+\\.[0-9]+\\.[0-9]+(\\-(alpha|beta|rc)\\.[0-9]+)?$\ntag: ## Create a release tag.\nifeq (,$(RELEASE_VERSION))\n\t$(error \"RELEASE_VERSION must be set to tag HEAD\")\nendif\nifeq (,$(shell [[ \"$(RELEASE_VERSION)\" =~ $(VERSION_REGEXP) ]] && echo 1))\n\t$(error \"Version $(RELEASE_VERSION) must match regexp $(VERSION_REGEXP)\")\nendif\n\tgit tag --sign --message \"Operator SDK $(RELEASE_VERSION)\" $(RELEASE_VERSION)\n\tgit verify-tag --verbose $(RELEASE_VERSION)\n\n.DEFAULT_GOAL := help\n.PHONY: help\nhelp: ## Show this help screen.\n\t@echo 'Usage: make <OPTIONS> ... <TARGETS>'\n\t@echo ''\n\t@echo 'Available targets are:'\n\t@echo ''\n\t@awk 'BEGIN {FS = \":.*##\"; printf \"\\nUsage:\\n  make \\033[36m<target>\\033[0m\\n\"} /^[a-zA-Z0-9_-]+:.*?##/ { printf \"  \\033[36m%-25s\\033[0m %s\\n\", $$1, $$2 } /^##@/ { printf \"\\n\\033[1m%s\\033[0m\\n\", substr($$0, 5) } ' $(MAKEFILE_LIST)\n"
  },
  {
    "path": "release/changelog/gen-changelog.go",
    "content": "package main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/blang/semver/v4\"\n\tlog \"github.com/sirupsen/logrus\"\n\n\tutil \"github.com/operator-framework/operator-sdk/release/changelog/internal\"\n)\n\nconst repo = \"github.com/operator-framework/operator-sdk\"\n\nfunc main() {\n\tvar (\n\t\ttag           string\n\t\tfragmentsDir  string\n\t\tchangelogFile string\n\t\tmigrationDir  string\n\t\tvalidateOnly  bool\n\t)\n\n\tflag.StringVar(&tag, \"tag\", \"\",\n\t\t\"Title for generated CHANGELOG and migration guide sections\")\n\tflag.StringVar(&fragmentsDir, \"fragments-dir\", filepath.Join(\"changelog\", \"fragments\"),\n\t\t\"Path to changelog fragments directory\")\n\tflag.StringVar(&changelogFile, \"changelog\", \"CHANGELOG.md\",\n\t\t\"Path to CHANGELOG\")\n\tflag.StringVar(&migrationDir, \"migration-guide-dir\",\n\t\tfilepath.Join(\"website\", \"content\", \"en\", \"docs\", \"upgrading-sdk-version\"),\n\t\t\"Path to migration guide directory\")\n\tflag.BoolVar(&validateOnly, \"validate-only\", false,\n\t\t\"Only validate fragments\")\n\tflag.Parse()\n\n\tif tag == \"\" && !validateOnly {\n\t\tlog.Fatalf(\"flag '-tag' is required without '-validate-only'\")\n\t}\n\n\tentries, err := util.LoadEntries(fragmentsDir, repo)\n\tif err != nil {\n\t\tlog.Fatalf(\"failed to load fragments: %v\", err)\n\t}\n\tif len(entries) == 0 {\n\t\tlog.Warnf(\"no entries found\")\n\t}\n\n\tif validateOnly {\n\t\treturn\n\t}\n\n\tversion, err := semver.Parse(strings.TrimPrefix(tag, \"v\"))\n\tif err != nil {\n\t\tlog.Fatalf(\"flag '-tag' is not a valid semantic version: %v\", err)\n\t}\n\tif len(version.Build) > 0 {\n\t\tlog.Fatalf(\"flag '-tag' must not include a build number\")\n\t}\n\n\tcl := util.ChangelogFromEntries(version, entries)\n\tif err := cl.WriteFile(changelogFile); err != nil {\n\t\tlog.Fatalf(\"failed to update CHANGELOG: %v\", err)\n\t}\n\n\tmg := util.MigrationGuideFromEntries(version, entries)\n\tmgFile := filepath.Join(migrationDir, fmt.Sprintf(\"v%s.md\", version))\n\tif err := mg.WriteFile(mgFile); err != nil {\n\t\tlog.Fatalf(\"failed to create migration guide: %v\", err)\n\t}\n}\n"
  },
  {
    "path": "release/changelog/internal/changelog.go",
    "content": "package util\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n\t\"text/template\"\n\n\t\"github.com/blang/semver/v4\"\n)\n\ntype Changelog struct {\n\tVersion      string\n\tAdditions    []ChangelogEntry\n\tChanges      []ChangelogEntry\n\tRemovals     []ChangelogEntry\n\tDeprecations []ChangelogEntry\n\tBugfixes     []ChangelogEntry\n\n\tRepo string\n}\n\ntype ChangelogEntry struct {\n\tDescription string\n\tLink        string\n}\n\nconst changelogTemplate = `## {{ .Version }}\n{{- if or .Additions .Changes .Removals .Deprecations .Bugfixes -}}\n{{- with .Additions }}\n\n### Additions\n{{ range . }}\n- {{ .Description }}{{ if .Link }} ({{ .Link }}){{ end }}\n{{- end }}{{- end }}\n{{- with .Changes }}\n\n### Changes\n{{ range . }}\n- {{ .Description }}{{ if .Link }} ({{ .Link }}){{ end }}\n{{- end }}{{- end }}\n{{- with .Removals }}\n\n### Removals\n{{ range . }}\n- {{ .Description }}{{ if .Link }} ({{ .Link }}){{ end }}\n{{- end }}{{- end }}\n{{- with .Deprecations }}\n\n### Deprecations\n{{ range . }}\n- {{ .Description }}{{ if .Link }} ({{ .Link }}){{ end }}\n{{- end }}{{- end }}\n{{- with .Bugfixes }}\n\n### Bug Fixes\n{{ range . }}\n- {{ .Description }}{{ if .Link }} ({{ .Link }}){{ end }}\n{{- end }}{{- end }}{{- else }}\n\nNo changes for this release!{{ end }}\n`\n\nvar changelogTmpl = template.Must(template.New(\"changelog\").Parse(changelogTemplate))\n\nfunc (c *Changelog) Template() ([]byte, error) {\n\tw := &bytes.Buffer{}\n\tif err := changelogTmpl.Execute(w, c); err != nil {\n\t\treturn nil, err\n\t}\n\treturn w.Bytes(), nil\n}\n\nfunc (c *Changelog) WriteFile(path string) error {\n\tdata, err := c.Template()\n\tif err != nil {\n\t\treturn err\n\t}\n\texistingFile, err := os.ReadFile(path)\n\tif err != nil && !errors.Is(err, os.ErrNotExist) {\n\t\treturn err\n\t}\n\tif errors.Is(err, os.ErrNotExist) || len(existingFile) == 0 {\n\t\treturn os.WriteFile(path, data, 0644)\n\t}\n\n\tdata = append(data, '\\n')\n\tdata = append(data, existingFile...)\n\treturn os.WriteFile(path, data, 0644)\n}\n\nfunc ChangelogFromEntries(version semver.Version, entries []FragmentEntry) Changelog {\n\tcl := Changelog{\n\t\tVersion: fmt.Sprintf(\"v%s\", version),\n\t}\n\tfor _, e := range entries {\n\t\tcle := e.toChangelogEntry()\n\t\tswitch e.Kind {\n\t\tcase Addition:\n\t\t\tcl.Additions = append(cl.Additions, cle)\n\t\tcase Change:\n\t\t\tcl.Changes = append(cl.Changes, cle)\n\t\tcase Removal:\n\t\t\tcl.Removals = append(cl.Removals, cle)\n\t\tcase Deprecation:\n\t\t\tcl.Deprecations = append(cl.Deprecations, cle)\n\t\tcase Bugfix:\n\t\t\tcl.Bugfixes = append(cl.Bugfixes, cle)\n\t\t}\n\t}\n\treturn cl\n}\n\nfunc (e *FragmentEntry) toChangelogEntry() ChangelogEntry {\n\tcle := ChangelogEntry{}\n\tdesc := strings.TrimSpace(e.Description)\n\tif e.Breaking {\n\t\tdesc = fmt.Sprintf(\"**Breaking change**: %s\", desc)\n\t}\n\tif !strings.HasSuffix(desc, \".\") && !strings.HasSuffix(desc, \"!\") {\n\t\tdesc = fmt.Sprintf(\"%s.\", desc)\n\t}\n\tcle.Description = desc\n\tcle.Link = e.PullRequestLink\n\treturn cle\n}\n"
  },
  {
    "path": "release/changelog/internal/changelog_test.go",
    "content": "package util\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"testing\"\n\n\t\"github.com/blang/semver/v4\"\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc getChangelogEntries(n int) []ChangelogEntry {\n\tentries := make([]ChangelogEntry, n)\n\tfor i := 0; i < n; i++ {\n\t\tentries[i] = ChangelogEntry{\n\t\t\tDescription: fmt.Sprintf(\"Changelog entry description %d.\", i),\n\t\t\tLink:        \"[#999999](https://example.com/test/changelog/pulls/999999)\",\n\t\t}\n\t}\n\treturn entries\n}\n\nfunc TestChangelog_Template(t *testing.T) {\n\ttestCases := []struct {\n\t\tname      string\n\t\tchangelog Changelog\n\t\toutput    string\n\t}{\n\t\t{\n\t\t\tname: \"all with 1 entry\",\n\t\t\tchangelog: Changelog{\n\t\t\t\tVersion:      \"v999.999.999\",\n\t\t\t\tAdditions:    getChangelogEntries(1),\n\t\t\t\tChanges:      getChangelogEntries(1),\n\t\t\t\tRemovals:     getChangelogEntries(1),\n\t\t\t\tDeprecations: getChangelogEntries(1),\n\t\t\t\tBugfixes:     getChangelogEntries(1),\n\t\t\t},\n\t\t\toutput: `## v999.999.999\n\n### Additions\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Changes\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Removals\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Deprecations\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Bug Fixes\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"all with 2 entries\",\n\t\t\tchangelog: Changelog{\n\t\t\t\tVersion:      \"v999.999.999\",\n\t\t\t\tAdditions:    getChangelogEntries(2),\n\t\t\t\tChanges:      getChangelogEntries(2),\n\t\t\t\tRemovals:     getChangelogEntries(2),\n\t\t\t\tDeprecations: getChangelogEntries(2),\n\t\t\t\tBugfixes:     getChangelogEntries(2),\n\t\t\t},\n\t\t\toutput: `## v999.999.999\n\n### Additions\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n- Changelog entry description 1. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Changes\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n- Changelog entry description 1. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Removals\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n- Changelog entry description 1. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Deprecations\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n- Changelog entry description 1. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Bug Fixes\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n- Changelog entry description 1. ([#999999](https://example.com/test/changelog/pulls/999999))\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"no additions\",\n\t\t\tchangelog: Changelog{\n\t\t\t\tVersion:      \"v999.999.999\",\n\t\t\t\tAdditions:    nil,\n\t\t\t\tChanges:      getChangelogEntries(1),\n\t\t\t\tRemovals:     getChangelogEntries(1),\n\t\t\t\tDeprecations: getChangelogEntries(1),\n\t\t\t\tBugfixes:     getChangelogEntries(1),\n\t\t\t},\n\t\t\toutput: `## v999.999.999\n\n### Changes\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Removals\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Deprecations\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Bug Fixes\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"no changes\",\n\t\t\tchangelog: Changelog{\n\t\t\t\tVersion:      \"v999.999.999\",\n\t\t\t\tAdditions:    getChangelogEntries(1),\n\t\t\t\tChanges:      nil,\n\t\t\t\tRemovals:     getChangelogEntries(1),\n\t\t\t\tDeprecations: getChangelogEntries(1),\n\t\t\t\tBugfixes:     getChangelogEntries(1),\n\t\t\t},\n\t\t\toutput: `## v999.999.999\n\n### Additions\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Removals\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Deprecations\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Bug Fixes\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"no removals\",\n\t\t\tchangelog: Changelog{\n\t\t\t\tVersion:      \"v999.999.999\",\n\t\t\t\tAdditions:    getChangelogEntries(1),\n\t\t\t\tChanges:      getChangelogEntries(1),\n\t\t\t\tRemovals:     nil,\n\t\t\t\tDeprecations: getChangelogEntries(1),\n\t\t\t\tBugfixes:     getChangelogEntries(1),\n\t\t\t},\n\t\t\toutput: `## v999.999.999\n\n### Additions\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Changes\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Deprecations\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Bug Fixes\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"no deprecations\",\n\t\t\tchangelog: Changelog{\n\t\t\t\tVersion:      \"v999.999.999\",\n\t\t\t\tAdditions:    getChangelogEntries(1),\n\t\t\t\tChanges:      getChangelogEntries(1),\n\t\t\t\tRemovals:     getChangelogEntries(1),\n\t\t\t\tDeprecations: nil,\n\t\t\t\tBugfixes:     getChangelogEntries(1),\n\t\t\t},\n\t\t\toutput: `## v999.999.999\n\n### Additions\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Changes\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Removals\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Bug Fixes\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"no bug fixes\",\n\t\t\tchangelog: Changelog{\n\t\t\t\tVersion:      \"v999.999.999\",\n\t\t\t\tAdditions:    getChangelogEntries(1),\n\t\t\t\tChanges:      getChangelogEntries(1),\n\t\t\t\tRemovals:     getChangelogEntries(1),\n\t\t\t\tDeprecations: getChangelogEntries(1),\n\t\t\t\tBugfixes:     nil,\n\t\t\t},\n\t\t\toutput: `## v999.999.999\n\n### Additions\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Changes\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Removals\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Deprecations\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"entry with no link\",\n\t\t\tchangelog: Changelog{\n\t\t\t\tVersion: \"v999.999.999\",\n\t\t\t\tAdditions: []ChangelogEntry{\n\t\t\t\t\t{\n\t\t\t\t\t\tDescription: \"Changelog entry description 0.\",\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tDescription: \"Changelog entry description 1.\",\n\t\t\t\t\t\tLink:        \"[#999999](https://example.com/test/changelog/pulls/999999)\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\toutput: `## v999.999.999\n\n### Additions\n\n- Changelog entry description 0.\n- Changelog entry description 1. ([#999999](https://example.com/test/changelog/pulls/999999))\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"no entries\",\n\t\t\tchangelog: Changelog{\n\t\t\t\tVersion:      \"v999.999.999\",\n\t\t\t\tAdditions:    nil,\n\t\t\t\tChanges:      nil,\n\t\t\t\tRemovals:     nil,\n\t\t\t\tDeprecations: nil,\n\t\t\t\tBugfixes:     nil,\n\t\t\t},\n\t\t\toutput: `## v999.999.999\n\nNo changes for this release!\n`,\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\td, err := tc.changelog.Template()\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"Got unexpected error: %v\", err)\n\t\t\t}\n\t\t\tassert.Equal(t, tc.output, string(d))\n\t\t})\n\t}\n}\n\nfunc TestChangelog_WriteFile(t *testing.T) {\n\n\ttestCases := []struct {\n\t\tname                 string\n\t\tchangelog            Changelog\n\t\texistingFile         bool\n\t\texistingFileContents string\n\t\toutput               string\n\t}{\n\t\t{\n\t\t\tname: \"non-existent file\",\n\t\t\tchangelog: Changelog{\n\t\t\t\tVersion:      \"v999.999.999\",\n\t\t\t\tAdditions:    getChangelogEntries(2),\n\t\t\t\tChanges:      getChangelogEntries(2),\n\t\t\t\tRemovals:     getChangelogEntries(2),\n\t\t\t\tDeprecations: getChangelogEntries(2),\n\t\t\t\tBugfixes:     getChangelogEntries(2),\n\t\t\t},\n\t\t\toutput: `## v999.999.999\n\n### Additions\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n- Changelog entry description 1. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Changes\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n- Changelog entry description 1. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Removals\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n- Changelog entry description 1. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Deprecations\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n- Changelog entry description 1. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Bug Fixes\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n- Changelog entry description 1. ([#999999](https://example.com/test/changelog/pulls/999999))\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"empty file\",\n\t\t\tchangelog: Changelog{\n\t\t\t\tVersion:      \"v999.999.999\",\n\t\t\t\tAdditions:    getChangelogEntries(2),\n\t\t\t\tChanges:      getChangelogEntries(2),\n\t\t\t\tRemovals:     getChangelogEntries(2),\n\t\t\t\tDeprecations: getChangelogEntries(2),\n\t\t\t\tBugfixes:     getChangelogEntries(2),\n\t\t\t},\n\t\t\texistingFile: true,\n\t\t\toutput: `## v999.999.999\n\n### Additions\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n- Changelog entry description 1. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Changes\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n- Changelog entry description 1. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Removals\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n- Changelog entry description 1. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Deprecations\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n- Changelog entry description 1. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Bug Fixes\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n- Changelog entry description 1. ([#999999](https://example.com/test/changelog/pulls/999999))\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"existing file\",\n\t\t\tchangelog: Changelog{\n\t\t\t\tVersion:      \"v999.999.999\",\n\t\t\t\tAdditions:    getChangelogEntries(2),\n\t\t\t\tChanges:      getChangelogEntries(2),\n\t\t\t\tRemovals:     getChangelogEntries(2),\n\t\t\t\tDeprecations: getChangelogEntries(2),\n\t\t\t\tBugfixes:     getChangelogEntries(2),\n\t\t\t},\n\t\t\texistingFileContents: `## v999.999.998\n\n### Bug Fixes\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n- Changelog entry description 1. ([#999999](https://example.com/test/changelog/pulls/999999))\n`,\n\t\t\toutput: `## v999.999.999\n\n### Additions\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n- Changelog entry description 1. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Changes\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n- Changelog entry description 1. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Removals\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n- Changelog entry description 1. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Deprecations\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n- Changelog entry description 1. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n### Bug Fixes\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n- Changelog entry description 1. ([#999999](https://example.com/test/changelog/pulls/999999))\n\n## v999.999.998\n\n### Bug Fixes\n\n- Changelog entry description 0. ([#999999](https://example.com/test/changelog/pulls/999999))\n- Changelog entry description 1. ([#999999](https://example.com/test/changelog/pulls/999999))\n`,\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\ttmpFile, err := os.CreateTemp(\"\", \"go-test-changelog\")\n\t\t\tassert.NoError(t, err)\n\t\t\tassert.NoError(t, tmpFile.Close())\n\t\t\tdefer assert.NoError(t, os.Remove(tmpFile.Name()))\n\n\t\t\tif tc.existingFile || len(tc.existingFileContents) > 0 {\n\t\t\t\tassert.NoError(t, os.WriteFile(tmpFile.Name(), []byte(tc.existingFileContents), 0644))\n\t\t\t}\n\n\t\t\tassert.NoError(t, tc.changelog.WriteFile(tmpFile.Name()))\n\n\t\t\td, err := os.ReadFile(tmpFile.Name())\n\t\t\tassert.NoError(t, err)\n\t\t\tassert.Equal(t, tc.output, string(d))\n\t\t})\n\t}\n}\n\nfunc TestChangelog_ChangelogFromEntries(t *testing.T) {\n\ttestCases := []struct {\n\t\tname      string\n\t\tversion   semver.Version\n\t\tentries   []FragmentEntry\n\t\tchangelog Changelog\n\t}{\n\t\t{\n\t\t\tname:      \"no entries\",\n\t\t\tversion:   semver.MustParse(\"999.999.999\"),\n\t\t\tchangelog: Changelog{Version: \"v999.999.999\"},\n\t\t},\n\t\t{\n\t\t\tname:    \"add periods to descriptions and breaking change prefix\",\n\t\t\tversion: semver.MustParse(\"999.999.999\"),\n\t\t\tentries: []FragmentEntry{\n\t\t\t\t{\n\t\t\t\t\tDescription:     \"Changelog entry description 0\",\n\t\t\t\t\tKind:            Addition,\n\t\t\t\t\tBreaking:        false,\n\t\t\t\t\tPullRequestLink: \"[#999999](https://example.com/test/changelog/pulls/999999)\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tDescription: \"Changelog entry description 0\",\n\t\t\t\t\tKind:        Change,\n\t\t\t\t\tBreaking:    true,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tDescription: \"Changelog entry description 0\",\n\t\t\t\t\tKind:        Removal,\n\t\t\t\t\tBreaking:    true,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tDescription: \"Changelog entry description 0\",\n\t\t\t\t\tKind:        Deprecation,\n\t\t\t\t\tBreaking:    false,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tDescription: \"Changelog entry description 0\",\n\t\t\t\t\tKind:        Bugfix,\n\t\t\t\t\tBreaking:    false,\n\t\t\t\t},\n\t\t\t},\n\t\t\tchangelog: Changelog{\n\t\t\t\tVersion: \"v999.999.999\",\n\t\t\t\tAdditions: []ChangelogEntry{\n\t\t\t\t\t{\n\t\t\t\t\t\tDescription: \"Changelog entry description 0.\",\n\t\t\t\t\t\tLink:        \"[#999999](https://example.com/test/changelog/pulls/999999)\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tChanges: []ChangelogEntry{\n\t\t\t\t\t{\n\t\t\t\t\t\tDescription: \"**Breaking change**: Changelog entry description 0.\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tRemovals: []ChangelogEntry{\n\t\t\t\t\t{\n\t\t\t\t\t\tDescription: \"**Breaking change**: Changelog entry description 0.\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tDeprecations: []ChangelogEntry{\n\t\t\t\t\t{\n\t\t\t\t\t\tDescription: \"Changelog entry description 0.\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tBugfixes: []ChangelogEntry{\n\t\t\t\t\t{\n\t\t\t\t\t\tDescription: \"Changelog entry description 0.\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tcl := ChangelogFromEntries(tc.version, tc.entries)\n\t\t\tassert.Equal(t, tc.changelog, cl)\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "release/changelog/internal/fragment.go",
    "content": "package util\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\tlog \"github.com/sirupsen/logrus\"\n\t\"sigs.k8s.io/yaml\"\n)\n\ntype Fragment struct {\n\tEntries []FragmentEntry `yaml:\"entries\"`\n}\n\nfunc (f *Fragment) Validate() error {\n\tfor i, e := range f.Entries {\n\t\tif err := e.Validate(); err != nil {\n\t\t\treturn fmt.Errorf(\"entry[%d] invalid: %v\", i, err)\n\t\t}\n\t}\n\treturn nil\n}\n\ntype FragmentEntry struct {\n\tDescription string          `json:\"description\"`\n\tKind        EntryKind       `json:\"kind\"`\n\tBreaking    bool            `json:\"breaking\"`\n\tMigration   *EntryMigration `json:\"migration,omitempty\"`\n\tPullRequest *uint           `json:\"pull_request_override,omitempty\"`\n\n\tPullRequestLink string `json:\"-\"`\n}\n\nfunc (e *FragmentEntry) Validate() error {\n\tif err := e.Kind.Validate(); err != nil {\n\t\treturn fmt.Errorf(\"invalid kind: %v\", err)\n\t}\n\n\tif len(e.Description) == 0 {\n\t\treturn errors.New(\"missing description\")\n\t}\n\n\tif e.Breaking && e.Kind != Change && e.Kind != Removal {\n\t\treturn fmt.Errorf(\"breaking changes can only be kind %q or %q, got %q\", Change, Removal, e.Kind)\n\t}\n\n\tif e.Breaking && e.Migration == nil {\n\t\treturn fmt.Errorf(\"breaking changes require migration sections\")\n\t}\n\n\tif e.Migration != nil {\n\t\tif err := e.Migration.Validate(); err != nil {\n\t\t\treturn fmt.Errorf(\"invalid migration: %v\", err)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (e FragmentEntry) pullRequestLink(repo string) string {\n\tif e.PullRequest == nil {\n\t\treturn \"\"\n\t}\n\treturn fmt.Sprintf(\"[#%d](https://%s/pull/%d)\", *e.PullRequest, repo, *e.PullRequest)\n}\n\ntype EntryKind string\n\nconst (\n\tAddition    EntryKind = \"addition\"\n\tChange      EntryKind = \"change\"\n\tRemoval     EntryKind = \"removal\"\n\tDeprecation EntryKind = \"deprecation\"\n\tBugfix      EntryKind = \"bugfix\"\n)\n\nfunc (k EntryKind) Validate() error {\n\tfor _, t := range []EntryKind{Addition, Change, Removal, Deprecation, Bugfix} {\n\t\tif k == t {\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn fmt.Errorf(\"%q is not a supported kind\", k)\n}\n\ntype EntryMigration struct {\n\tHeader string `yaml:\"header\"`\n\tBody   string `yaml:\"body\"`\n}\n\nfunc (m EntryMigration) Validate() error {\n\tif len(m.Header) == 0 {\n\t\treturn errors.New(\"header not specified\")\n\t}\n\tif len(m.Body) == 0 {\n\t\treturn errors.New(\"body not specified\")\n\t}\n\treturn nil\n}\n\nfunc LoadEntries(fragmentsDir, repo string) ([]FragmentEntry, error) {\n\tfiles, err := os.ReadDir(fragmentsDir)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to read fragments directory: %w\", err)\n\t}\n\n\tvar entries []FragmentEntry\n\tfor _, fragFile := range files {\n\t\tif fragFile.Name() == \"00-template.yaml\" {\n\t\t\tcontinue\n\t\t}\n\t\tif fragFile.IsDir() {\n\t\t\tlog.Warnf(\"Skipping directory %q\", fragFile.Name())\n\t\t\tcontinue\n\t\t}\n\t\tif filepath.Ext(fragFile.Name()) != \".yaml\" && filepath.Ext(fragFile.Name()) != \".yml\" {\n\t\t\tlog.Warnf(\"Skipping non-YAML file %q\", fragFile.Name())\n\t\t\tcontinue\n\t\t}\n\t\tpath := filepath.Join(fragmentsDir, fragFile.Name())\n\t\tfragmentData, err := os.ReadFile(path)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to read fragment file %q: %w\", fragFile.Name(), err)\n\t\t}\n\n\t\tfragment := Fragment{}\n\t\tif err := yaml.Unmarshal(fragmentData, &fragment); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to parse fragment file %q: %w\", fragFile.Name(), err)\n\t\t}\n\n\t\tif err := fragment.Validate(); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to validate fragment file %q: %w\", fragFile.Name(), err)\n\t\t}\n\n\t\tprNum, err := prGetter.GetPullRequestNumberFor(path)\n\t\tif err != nil {\n\t\t\tlog.Warn(err)\n\t\t}\n\n\t\tif prNum != 0 {\n\t\t\tfor i, e := range fragment.Entries {\n\t\t\t\tif e.PullRequest == nil {\n\t\t\t\t\tfragment.Entries[i].PullRequest = &prNum\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor i, e := range fragment.Entries {\n\t\t\tfragment.Entries[i].PullRequestLink = e.pullRequestLink(repo)\n\t\t}\n\n\t\tentries = append(entries, fragment.Entries...)\n\t}\n\treturn entries, nil\n}\n\nvar prGetter PullRequestNumberGetter = &gitPullRequestNumberGetter{}\n\ntype PullRequestNumberGetter interface {\n\tGetPullRequestNumberFor(file string) (uint, error)\n}\n\ntype gitPullRequestNumberGetter struct{}\n\nfunc (g *gitPullRequestNumberGetter) GetPullRequestNumberFor(filename string) (uint, error) {\n\tmsg, err := g.getCommitMessage(filename)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn g.parsePRNumber(msg)\n}\n\nfunc (g *gitPullRequestNumberGetter) getCommitMessage(filename string) (string, error) {\n\targs := fmt.Sprintf(\"log --follow --pretty=format:%%s --diff-filter=A --find-renames=90%% %s\", filename)\n\tline, err := exec.Command(\"git\", strings.Split(args, \" \")...).CombinedOutput()\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to locate git commit for PR discovery: %v\", err)\n\t}\n\treturn string(line), nil\n}\n\nvar numRegex = regexp.MustCompile(`\\(#(\\d+)\\)$`)\n\nfunc (g *gitPullRequestNumberGetter) parsePRNumber(msg string) (uint, error) {\n\tmatches := numRegex.FindAllStringSubmatch(msg, 1)\n\tif len(matches) == 0 || len(matches[0]) < 2 {\n\t\treturn 0, fmt.Errorf(\"could not find PR number in commit message\")\n\t}\n\tu64, err := strconv.ParseUint(matches[0][1], 10, 64)\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"failed to parse PR number %q from commit message: %v\", matches[0][1], err)\n\t}\n\treturn uint(u64), nil\n}\n"
  },
  {
    "path": "release/changelog/internal/fragment_test.go",
    "content": "package util\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\ntype mockValidPRGetter struct{}\n\nvar _ PullRequestNumberGetter = &mockValidPRGetter{}\n\nfunc (m *mockValidPRGetter) GetPullRequestNumberFor(_ string) (uint, error) {\n\treturn 999998, nil\n}\n\nfunc TestFragment_LoadEntries(t *testing.T) {\n\tdiscoveredPRNum := uint(999998)\n\toverriddenPRNum := uint(999999)\n\trepoLink := \"example.com/test/changelog\"\n\n\ttestCases := []struct {\n\t\tname            string\n\t\tfragmentsDir    string\n\t\tprGetter        PullRequestNumberGetter\n\t\texpectedEntries []FragmentEntry\n\t\texpectedErr     string\n\t}{\n\t\t{\n\t\t\tname:            \"ignore non-fragments\",\n\t\t\tfragmentsDir:    \"testdata/ignore\",\n\t\t\texpectedEntries: nil,\n\t\t},\n\t\t{\n\t\t\tname:            \"invalid yaml\",\n\t\t\tfragmentsDir:    \"testdata/invalid_yaml\",\n\t\t\texpectedEntries: nil,\n\t\t\texpectedErr:     \"error unmarshaling\",\n\t\t},\n\t\t{\n\t\t\tname:            \"invalid entry\",\n\t\t\tfragmentsDir:    \"testdata/invalid_entry\",\n\t\t\texpectedEntries: nil,\n\t\t\texpectedErr:     `failed to validate fragment file`,\n\t\t},\n\t\t{\n\t\t\tname:         \"valid fragments\",\n\t\t\tfragmentsDir: \"testdata/valid\",\n\t\t\tprGetter:     &mockValidPRGetter{},\n\t\t\texpectedEntries: []FragmentEntry{\n\t\t\t\t{\n\t\t\t\t\tDescription:     \"Addition description 0\",\n\t\t\t\t\tKind:            Addition,\n\t\t\t\t\tPullRequest:     &discoveredPRNum,\n\t\t\t\t\tPullRequestLink: fmt.Sprintf(\"[#%d](https://%s/pull/%d)\", discoveredPRNum, repoLink, discoveredPRNum),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tDescription:     \"Change description 0\",\n\t\t\t\t\tKind:            Change,\n\t\t\t\t\tPullRequest:     &discoveredPRNum,\n\t\t\t\t\tPullRequestLink: fmt.Sprintf(\"[#%d](https://%s/pull/%d)\", discoveredPRNum, repoLink, discoveredPRNum),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tDescription: \"Removal description 0\",\n\t\t\t\t\tKind:        Removal,\n\t\t\t\t\tBreaking:    true,\n\t\t\t\t\tMigration: &EntryMigration{\n\t\t\t\t\t\tHeader: \"Header for removal migration 0\",\n\t\t\t\t\t\tBody:   \"Body for removal migration 0\",\n\t\t\t\t\t},\n\t\t\t\t\tPullRequest:     &discoveredPRNum,\n\t\t\t\t\tPullRequestLink: fmt.Sprintf(\"[#%d](https://%s/pull/%d)\", discoveredPRNum, repoLink, discoveredPRNum),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tDescription:     \"Deprecation description 0\",\n\t\t\t\t\tKind:            Deprecation,\n\t\t\t\t\tPullRequest:     &discoveredPRNum,\n\t\t\t\t\tPullRequestLink: fmt.Sprintf(\"[#%d](https://%s/pull/%d)\", discoveredPRNum, repoLink, discoveredPRNum),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tDescription:     \"Bugfix description 0\",\n\t\t\t\t\tKind:            Bugfix,\n\t\t\t\t\tPullRequest:     &discoveredPRNum,\n\t\t\t\t\tPullRequestLink: fmt.Sprintf(\"[#%d](https://%s/pull/%d)\", discoveredPRNum, repoLink, discoveredPRNum),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tDescription:     \"Addition description 1\",\n\t\t\t\t\tKind:            Addition,\n\t\t\t\t\tPullRequest:     &overriddenPRNum,\n\t\t\t\t\tPullRequestLink: fmt.Sprintf(\"[#%d](https://%s/pull/%d)\", overriddenPRNum, repoLink, overriddenPRNum),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tDescription:     \"Change description 1\",\n\t\t\t\t\tKind:            Change,\n\t\t\t\t\tPullRequest:     &overriddenPRNum,\n\t\t\t\t\tPullRequestLink: fmt.Sprintf(\"[#%d](https://%s/pull/%d)\", overriddenPRNum, repoLink, overriddenPRNum),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tDescription: \"Removal description 1\",\n\t\t\t\t\tKind:        Removal,\n\t\t\t\t\tBreaking:    true,\n\t\t\t\t\tMigration: &EntryMigration{\n\t\t\t\t\t\tHeader: \"Header for removal migration 1\",\n\t\t\t\t\t\tBody:   \"Body for removal migration 1\",\n\t\t\t\t\t},\n\t\t\t\t\tPullRequest:     &overriddenPRNum,\n\t\t\t\t\tPullRequestLink: fmt.Sprintf(\"[#%d](https://%s/pull/%d)\", overriddenPRNum, repoLink, overriddenPRNum),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tDescription:     \"Deprecation description 1\",\n\t\t\t\t\tKind:            Deprecation,\n\t\t\t\t\tPullRequest:     &overriddenPRNum,\n\t\t\t\t\tPullRequestLink: fmt.Sprintf(\"[#%d](https://%s/pull/%d)\", overriddenPRNum, repoLink, overriddenPRNum),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tDescription:     \"Bugfix description 1\",\n\t\t\t\t\tKind:            Bugfix,\n\t\t\t\t\tPullRequest:     &overriddenPRNum,\n\t\t\t\t\tPullRequestLink: fmt.Sprintf(\"[#%d](https://%s/pull/%d)\", overriddenPRNum, repoLink, overriddenPRNum),\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tprGetter = tc.prGetter\n\t\t\tentries, err := LoadEntries(tc.fragmentsDir, repoLink)\n\t\t\tassert.Equal(t, tc.expectedEntries, entries)\n\t\t\tif len(tc.expectedErr) > 0 {\n\t\t\t\tif !strings.Contains(err.Error(), tc.expectedErr) {\n\t\t\t\t\tt.Errorf(\"expected error to contain: %q, got %q\", tc.expectedErr, err)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tassert.NoError(t, err)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestFragmentEntry_Validate(t *testing.T) {\n\ttestCases := []struct {\n\t\tname          string\n\t\tfragmentEntry FragmentEntry\n\t\texpectedErr   string\n\t}{\n\t\t{\n\t\t\tname: \"invalid kind\",\n\t\t\tfragmentEntry: FragmentEntry{\n\t\t\t\tDescription: \"description\",\n\t\t\t\tKind:        \"invalid\",\n\t\t\t\tBreaking:    false,\n\t\t\t},\n\t\t\texpectedErr: \"invalid kind\",\n\t\t},\n\t\t{\n\t\t\tname: \"missing description\",\n\t\t\tfragmentEntry: FragmentEntry{\n\t\t\t\tDescription: \"\",\n\t\t\t\tKind:        Addition,\n\t\t\t\tBreaking:    false,\n\t\t\t},\n\t\t\texpectedErr: \"missing description\",\n\t\t},\n\t\t{\n\t\t\tname: \"breaking addition not allowed\",\n\t\t\tfragmentEntry: FragmentEntry{\n\t\t\t\tDescription: \"description\",\n\t\t\t\tKind:        Addition,\n\t\t\t\tBreaking:    true,\n\t\t\t},\n\t\t\texpectedErr: `breaking changes can only be kind \"change\" or \"removal\", got \"addition\"`,\n\t\t},\n\t\t{\n\t\t\tname: \"breaking deprecation not allowed\",\n\t\t\tfragmentEntry: FragmentEntry{\n\t\t\t\tDescription: \"description\",\n\t\t\t\tKind:        Deprecation,\n\t\t\t\tBreaking:    true,\n\t\t\t},\n\t\t\texpectedErr: `breaking changes can only be kind \"change\" or \"removal\", got \"deprecation\"`,\n\t\t},\n\t\t{\n\t\t\tname: \"breaking bugfix not allowed\",\n\t\t\tfragmentEntry: FragmentEntry{\n\t\t\t\tDescription: \"description\",\n\t\t\t\tKind:        Bugfix,\n\t\t\t\tBreaking:    true,\n\t\t\t},\n\t\t\texpectedErr: `breaking changes can only be kind \"change\" or \"removal\", got \"bugfix\"`,\n\t\t},\n\t\t{\n\t\t\tname: \"migration missing\",\n\t\t\tfragmentEntry: FragmentEntry{\n\t\t\t\tDescription: \"description\",\n\t\t\t\tKind:        Change,\n\t\t\t\tBreaking:    true,\n\t\t\t},\n\t\t\texpectedErr: `breaking changes require migration sections`,\n\t\t},\n\t\t{\n\t\t\tname: \"migration header missing\",\n\t\t\tfragmentEntry: FragmentEntry{\n\t\t\t\tDescription: \"description\",\n\t\t\t\tKind:        Change,\n\t\t\t\tBreaking:    true,\n\t\t\t\tMigration: &EntryMigration{\n\t\t\t\t\tHeader: \"\",\n\t\t\t\t\tBody:   \"migration body\",\n\t\t\t\t},\n\t\t\t},\n\t\t\texpectedErr: `invalid migration: header not specified`,\n\t\t},\n\t\t{\n\t\t\tname: \"migration body missing\",\n\t\t\tfragmentEntry: FragmentEntry{\n\t\t\t\tDescription: \"description\",\n\t\t\t\tKind:        Change,\n\t\t\t\tBreaking:    true,\n\t\t\t\tMigration: &EntryMigration{\n\t\t\t\t\tHeader: \"migration header\",\n\t\t\t\t\tBody:   \"\",\n\t\t\t\t},\n\t\t\t},\n\t\t\texpectedErr: `invalid migration: body not specified`,\n\t\t},\n\t\t{\n\t\t\tname: \"breaking change allowed\",\n\t\t\tfragmentEntry: FragmentEntry{\n\t\t\t\tDescription: \"description\",\n\t\t\t\tKind:        Change,\n\t\t\t\tBreaking:    true,\n\t\t\t\tMigration: &EntryMigration{\n\t\t\t\t\tHeader: \"migration header\",\n\t\t\t\t\tBody:   \"migration body\",\n\t\t\t\t},\n\t\t\t},\n\t\t\texpectedErr: ``,\n\t\t},\n\t\t{\n\t\t\tname: \"breaking removal allowed\",\n\t\t\tfragmentEntry: FragmentEntry{\n\t\t\t\tDescription: \"description\",\n\t\t\t\tKind:        Removal,\n\t\t\t\tBreaking:    true,\n\t\t\t\tMigration: &EntryMigration{\n\t\t\t\t\tHeader: \"migration header\",\n\t\t\t\t\tBody:   \"migration body\",\n\t\t\t\t},\n\t\t\t},\n\t\t\texpectedErr: ``,\n\t\t},\n\t\t{\n\t\t\tname: \"non-breaking migration allowed\",\n\t\t\tfragmentEntry: FragmentEntry{\n\t\t\t\tDescription: \"description\",\n\t\t\t\tKind:        Addition,\n\t\t\t\tBreaking:    false,\n\t\t\t\tMigration: &EntryMigration{\n\t\t\t\t\tHeader: \"migration header\",\n\t\t\t\t\tBody:   \"migration body\",\n\t\t\t\t},\n\t\t\t},\n\t\t\texpectedErr: ``,\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\terr := tc.fragmentEntry.Validate()\n\n\t\t\tif len(tc.expectedErr) == 0 {\n\t\t\t\tassert.NoError(t, err)\n\t\t\t} else if err == nil {\n\t\t\t\tt.Errorf(\"expected error to contain %q, got no error\", tc.expectedErr)\n\t\t\t} else {\n\t\t\t\tif !strings.Contains(err.Error(), tc.expectedErr) {\n\t\t\t\t\tt.Errorf(\"expected error to contain: %q, got %q\", tc.expectedErr, err)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestFragmentEntry_PullRequestLink(t *testing.T) {\n\tprNum := uint(999999)\n\ttestCases := []struct {\n\t\tname          string\n\t\tfragmentEntry FragmentEntry\n\t\trepo          string\n\t\tlink          string\n\t}{\n\t\t{\n\t\t\tname:          \"no link\",\n\t\t\tfragmentEntry: FragmentEntry{},\n\t\t\tlink:          \"\",\n\t\t},\n\t\t{\n\t\t\tname:          \"link with repo 1\",\n\t\t\trepo:          \"example.com/test/repo1\",\n\t\t\tfragmentEntry: FragmentEntry{PullRequest: &prNum},\n\t\t\tlink:          \"[#999999](https://example.com/test/repo1/pull/999999)\",\n\t\t},\n\t\t{\n\t\t\tname:          \"link with repo 2\",\n\t\t\trepo:          \"example.com/test/repo2\",\n\t\t\tfragmentEntry: FragmentEntry{PullRequest: &prNum},\n\t\t\tlink:          \"[#999999](https://example.com/test/repo2/pull/999999)\",\n\t\t},\n\t}\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tlink := tc.fragmentEntry.pullRequestLink(tc.repo)\n\t\t\tassert.Equal(t, tc.link, link)\n\t\t})\n\t}\n}\n\nfunc TestGitPullRequestNumberGetter_parsePRNumber(t *testing.T) {\n\tprg := &gitPullRequestNumberGetter{}\n\ttestCases := []struct {\n\t\tname        string\n\t\tmsg         string\n\t\tprNum       uint\n\t\texpectedErr string\n\t}{\n\t\t{\n\t\t\tname:  \"valid message\",\n\t\t\tmsg:   \"this is a message with a PR number at the end (#999999)\",\n\t\t\tprNum: uint(999999),\n\t\t},\n\t\t{\n\t\t\tname:        \"missing parentheses\",\n\t\t\tmsg:         \"this is a message with a PR number at the end #999999\",\n\t\t\texpectedErr: `could not find PR number in commit message`,\n\t\t},\n\t\t{\n\t\t\tname:        \"not at the end\",\n\t\t\tmsg:         \"this is a message with a PR number (#999999) in the middle\",\n\t\t\texpectedErr: `could not find PR number in commit message`,\n\t\t},\n\t\t{\n\t\t\tname:        \"no PR number\",\n\t\t\tmsg:         \"this is a message without a PR number\",\n\t\t\texpectedErr: `could not find PR number in commit message`,\n\t\t},\n\t\t{\n\t\t\tname:        \"invalid PR number\",\n\t\t\tmsg:         \"this is a message with a really big PR number (#99999999999999999999999999999999999999)\",\n\t\t\texpectedErr: `value out of range`,\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tprNum, err := prg.parsePRNumber(tc.msg)\n\n\t\t\tif len(tc.expectedErr) == 0 {\n\t\t\t\tassert.NoError(t, err)\n\t\t\t} else if err == nil {\n\t\t\t\tt.Errorf(\"expected error to contain %q, got no error\", tc.expectedErr)\n\t\t\t} else {\n\t\t\t\tif !strings.Contains(err.Error(), tc.expectedErr) {\n\t\t\t\t\tt.Errorf(\"expected error to contain: %q, got %q\", tc.expectedErr, err)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tassert.Equal(t, tc.prNum, prNum)\n\t\t})\n\t}\n}\n\nfunc Test_gitPullRequestNumberGetter_getCommitMessage(t *testing.T) {\n\ttests := []struct {\n\t\tname     string\n\t\tfilename string\n\t\twantErr  bool\n\t}{\n\t\t{\n\t\t\tname:     \"should fail when the fragment file cannot be found in any commit\",\n\t\t\tfilename: \"/does/not/exist\",\n\t\t\twantErr:  true,\n\t\t},\n\t\t{\n\t\t\tname:     \"should work successfully when there is a commit with the fragment file\",\n\t\t\tfilename: \"testdata/valid/fragment1.yaml\",\n\t\t\twantErr:  false,\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\n\t\t\tg := &gitPullRequestNumberGetter{}\n\t\t\t_, err := g.getCommitMessage(tt.filename)\n\t\t\tif (err != nil) != tt.wantErr {\n\t\t\t\tt.Errorf(\"getCommitMessage() error = %v, wantErr %v\", err, tt.wantErr)\n\t\t\t\treturn\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "release/changelog/internal/migration_guide.go",
    "content": "package util\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n\t\"text/template\"\n\n\t\"github.com/blang/semver/v4\"\n)\n\ntype MigrationGuide struct {\n\tVersion    string\n\tWeight     uint64\n\tMigrations []Migration\n}\n\ntype Migration struct {\n\tHeader          string\n\tBody            string\n\tPullRequestLink string\n}\n\nconst migrationGuideTemplate = `---\ntitle: {{ .Version }}\nweight: {{ .Weight }}\n---\n{{ range .Migrations }}\n## {{ .Header }}\n\n{{ .Body }}\n{{ if .PullRequestLink }}\n_See {{ .PullRequestLink }} for more details._\n{{ end }}{{ else }}\nThere are no migrations for this release! 🎉\n{{ end }}`\n\nvar migrationGuideTmpl = template.Must(template.New(\"migrationGuide\").Parse(migrationGuideTemplate))\n\nfunc (mg *MigrationGuide) Template() ([]byte, error) {\n\tw := &bytes.Buffer{}\n\tif err := migrationGuideTmpl.Execute(w, mg); err != nil {\n\t\treturn nil, err\n\t}\n\treturn w.Bytes(), nil\n}\n\nfunc (mg *MigrationGuide) WriteFile(path string) error {\n\tdata, err := mg.Template()\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn os.WriteFile(path, data, 0644)\n}\n\nfunc MigrationGuideFromEntries(version semver.Version, entries []FragmentEntry) MigrationGuide {\n\tmg := MigrationGuide{\n\t\tVersion: fmt.Sprintf(\"v%s\", version.String()),\n\t\tWeight:  versionToWeight(version),\n\t}\n\tfor _, e := range entries {\n\t\tif e.Migration == nil {\n\t\t\tcontinue\n\t\t}\n\t\tmg.Migrations = append(mg.Migrations, Migration{\n\t\t\tHeader:          e.Migration.Header,\n\t\t\tBody:            strings.TrimSpace(e.Migration.Body),\n\t\t\tPullRequestLink: e.PullRequestLink,\n\t\t})\n\t}\n\treturn mg\n}\n\nfunc versionToWeight(v semver.Version) uint64 {\n\treturn 1_000_000_000 - (v.Major * 1_000_000) - (v.Minor * 1_000) - v.Patch\n}\n"
  },
  {
    "path": "release/changelog/internal/migration_guide_test.go",
    "content": "package util\n\nimport (\n\t\"os\"\n\t\"testing\"\n\n\t\"github.com/blang/semver/v4\"\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestMigrationGuide_Template(t *testing.T) {\n\ttestCases := []struct {\n\t\tname   string\n\t\tmg     MigrationGuide\n\t\toutput string\n\t}{\n\t\t{\n\t\t\tname: \"link_then_no_link\",\n\t\t\tmg: MigrationGuide{\n\t\t\t\tVersion: \"v999.999.999\",\n\t\t\t\tWeight:  1,\n\t\t\t\tMigrations: []Migration{\n\t\t\t\t\t{\n\t\t\t\t\t\tHeader:          \"Migration header 0\",\n\t\t\t\t\t\tBody:            \"Migration body 0\",\n\t\t\t\t\t\tPullRequestLink: \"[#999999](https://example.com/test/changelog/pull/999999)\",\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tHeader: \"Migration header 1\",\n\t\t\t\t\t\tBody:   \"Migration body 1\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\toutput: `---\ntitle: v999.999.999\nweight: 1\n---\n\n## Migration header 0\n\nMigration body 0\n\n_See [#999999](https://example.com/test/changelog/pull/999999) for more details._\n\n## Migration header 1\n\nMigration body 1\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"no_link_then_link\",\n\t\t\tmg: MigrationGuide{\n\t\t\t\tVersion: \"v999.999.999\",\n\t\t\t\tWeight:  2,\n\t\t\t\tMigrations: []Migration{\n\t\t\t\t\t{\n\t\t\t\t\t\tHeader: \"Migration header 0\",\n\t\t\t\t\t\tBody:   \"Migration body 0\",\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tHeader:          \"Migration header 1\",\n\t\t\t\t\t\tBody:            \"Migration body 1\",\n\t\t\t\t\t\tPullRequestLink: \"[#999999](https://example.com/test/changelog/pull/999999)\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\toutput: `---\ntitle: v999.999.999\nweight: 2\n---\n\n## Migration header 0\n\nMigration body 0\n\n## Migration header 1\n\nMigration body 1\n\n_See [#999999](https://example.com/test/changelog/pull/999999) for more details._\n`,\n\t\t},\n\t\t{\n\t\t\tname: \"no migrations\",\n\t\t\tmg: MigrationGuide{\n\t\t\t\tVersion: \"v999.999.999\",\n\t\t\t\tWeight:  3,\n\t\t\t},\n\t\t\toutput: `---\ntitle: v999.999.999\nweight: 3\n---\n\nThere are no migrations for this release! 🎉\n`,\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\td, err := tc.mg.Template()\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"Got unexpected error: %v\", err)\n\t\t\t}\n\t\t\tassert.Equal(t, tc.output, string(d))\n\t\t})\n\t}\n}\n\nfunc TestMigrationGuide_WriteFile(t *testing.T) {\n\n\ttestCases := []struct {\n\t\tname   string\n\t\tmg     MigrationGuide\n\t\toutput string\n\t}{\n\t\t{\n\t\t\tname: \"valid\",\n\t\t\tmg: MigrationGuide{\n\t\t\t\tVersion: \"v999.999.999\",\n\t\t\t\tMigrations: []Migration{\n\t\t\t\t\t{\n\t\t\t\t\t\tHeader:          \"Migration header 0\",\n\t\t\t\t\t\tBody:            \"Migration body 0\",\n\t\t\t\t\t\tPullRequestLink: \"[#999999](https://example.com/test/changelog/pull/999999)\",\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tHeader: \"Migration header 1\",\n\t\t\t\t\t\tBody:   \"Migration body 1\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\toutput: `---\ntitle: v999.999.999\nweight: 0\n---\n\n## Migration header 0\n\nMigration body 0\n\n_See [#999999](https://example.com/test/changelog/pull/999999) for more details._\n\n## Migration header 1\n\nMigration body 1\n`,\n\t\t},\n\t}\n\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\ttmpFile, err := os.CreateTemp(\"\", \"go-test-changelog\")\n\t\t\tassert.NoError(t, err)\n\t\t\tassert.NoError(t, tmpFile.Close())\n\t\t\tdefer assert.NoError(t, os.Remove(tmpFile.Name()))\n\n\t\t\tassert.NoError(t, tc.mg.WriteFile(tmpFile.Name()))\n\n\t\t\td, err := os.ReadFile(tmpFile.Name())\n\t\t\tassert.NoError(t, err)\n\t\t\tassert.Equal(t, tc.output, string(d))\n\t\t})\n\t}\n}\n\nfunc TestMigrationGuide_MigrationGuideFromEntries(t *testing.T) {\n\ttestCases := []struct {\n\t\tname    string\n\t\tversion semver.Version\n\t\tentries []FragmentEntry\n\t\tmg      MigrationGuide\n\t}{\n\t\t{\n\t\t\tname:    \"no entries, weight 1\",\n\t\t\tversion: semver.MustParse(\"999.999.999\"),\n\t\t\tmg: MigrationGuide{\n\t\t\t\tVersion: \"v999.999.999\",\n\t\t\t\tWeight:  1,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:    \"no entries, weight 2\",\n\t\t\tversion: semver.MustParse(\"999.999.998\"),\n\t\t\tmg: MigrationGuide{\n\t\t\t\tVersion: \"v999.999.998\",\n\t\t\t\tWeight:  2,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:    \"no entries, weight 998_997_997\",\n\t\t\tversion: semver.MustParse(\"1.2.3\"),\n\t\t\tmg: MigrationGuide{\n\t\t\t\tVersion: \"v1.2.3\",\n\t\t\t\tWeight:  998_997_997,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:    \"no entries, weight 2\",\n\t\t\tversion: semver.MustParse(\"3.2.1\"),\n\t\t\tmg: MigrationGuide{\n\t\t\t\tVersion: \"v3.2.1\",\n\t\t\t\tWeight:  996_997_999,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname:    \"some migrations\",\n\t\t\tversion: semver.MustParse(\"999.999.999\"),\n\t\t\tentries: []FragmentEntry{\n\t\t\t\t{\n\t\t\t\t\tDescription:     \"Changelog entry description 0\",\n\t\t\t\t\tKind:            Addition,\n\t\t\t\t\tBreaking:        false,\n\t\t\t\t\tPullRequestLink: \"[#999999](https://example.com/test/changelog/pulls/999999)\",\n\t\t\t\t\tMigration: &EntryMigration{\n\t\t\t\t\t\tHeader: \"Migration header 0\",\n\t\t\t\t\t\tBody:   \"Migration body 0\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tDescription: \"Changelog entry description 1\",\n\t\t\t\t\tKind:        Change,\n\t\t\t\t\tBreaking:    true,\n\t\t\t\t\tMigration: &EntryMigration{\n\t\t\t\t\t\tHeader: \"Migration header 1\",\n\t\t\t\t\t\tBody:   \"Migration body 1\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tDescription: \"Changelog entry description 2\",\n\t\t\t\t\tKind:        Removal,\n\t\t\t\t\tBreaking:    true,\n\t\t\t\t\tMigration: &EntryMigration{\n\t\t\t\t\t\tHeader: \"Migration header 2\",\n\t\t\t\t\t\tBody:   \"Migration body 2\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tDescription: \"Changelog entry description 0\",\n\t\t\t\t\tKind:        Deprecation,\n\t\t\t\t\tBreaking:    false,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tDescription: \"Changelog entry description 0\",\n\t\t\t\t\tKind:        Bugfix,\n\t\t\t\t\tBreaking:    false,\n\t\t\t\t},\n\t\t\t},\n\t\t\tmg: MigrationGuide{\n\t\t\t\tVersion: \"v999.999.999\",\n\t\t\t\tWeight:  1,\n\t\t\t\tMigrations: []Migration{\n\t\t\t\t\t{\n\t\t\t\t\t\tHeader:          \"Migration header 0\",\n\t\t\t\t\t\tBody:            \"Migration body 0\",\n\t\t\t\t\t\tPullRequestLink: \"[#999999](https://example.com/test/changelog/pulls/999999)\",\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tHeader: \"Migration header 1\",\n\t\t\t\t\t\tBody:   \"Migration body 1\",\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tHeader: \"Migration header 2\",\n\t\t\t\t\t\tBody:   \"Migration body 2\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\tfor _, tc := range testCases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tmg := MigrationGuideFromEntries(tc.version, tc.entries)\n\t\t\tassert.Equal(t, tc.mg, mg)\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "release/changelog/internal/testdata/ignore/00-template.yaml",
    "content": "# entries is a list of entries to include in\n# release notes and/or the migration guide\nentries:\n  - description: >\n      Description is the line that shows up in the CHANGELOG. This\n      should be formatted as markdown and be on a single line. Using\n      the YAML string '>' operator means you can write your entry\n      multiple lines and it will still be parsed as a single line.\n\n    # kind is one of:\n    # - addition\n    # - change\n    # - deprecation\n    # - removal\n    # - bugfix\n    kind: \"\"\n\n    # Is this a breaking change?\n    breaking: false\n\n    # NOTE: ONLY USE `pull_request_override` WHEN ADDING THIS\n    # FILE FOR A PREVIOUSLY MERGED PULL_REQUEST!\n    #\n    # The generator auto-detects the PR number from the commit\n    # message in which this file was originally added.\n    #\n    # What is the pull request number (without the \"#\")?\n    # pull_request_override: 0\n\n\n    # Migration can be defined to automatically add a section to\n    # the migration guide. This is required for breaking changes.\n    migration:\n      header: Header text for the migration section\n      body: >\n        Body of the migration section.\n"
  },
  {
    "path": "release/changelog/internal/testdata/ignore/more-fragments/ignored.yaml",
    "content": "entries:\n  - addition: Addition description\n    kind: addition\n    breaking: false\n  - description: Change description\n    kind: change\n    breaking: false\n  - description: Removal description\n    kind: removal\n    breaking: true\n    migration:\n      header: Header for removal migration\n      body: Body for removal migration\n  - description: Deprecation description\n    kind: deprecation\n    breaking: false\n  - description: Bugfix description\n    kind: bugfix\n    breaking: false"
  },
  {
    "path": "release/changelog/internal/testdata/ignore/non-yaml.txt",
    "content": ""
  },
  {
    "path": "release/changelog/internal/testdata/invalid_entry/fragment1.yaml",
    "content": "entries:\n  - description: Addition description 0\n    kind: addition\n    breaking: true"
  },
  {
    "path": "release/changelog/internal/testdata/invalid_yaml/fragment1.yaml",
    "content": "- description: Addition description 0\n  kind: addition\n  breaking: false\n- description: Change description 0\n  kind: change\n  breaking: false\n- description: Removal description 0\n  kind: removal\n  breaking: true\n  migration:\n    header: Header for removal migration 0\n    body: Body for removal migration 0\n- description: Deprecation description 0\n  kind: deprecation\n  breaking: false\n- description: Bugfix description 0\n  kind: bugfix\n  breaking: false"
  },
  {
    "path": "release/changelog/internal/testdata/valid/fragment1.yaml",
    "content": "entries:\n  - description: Addition description 0\n    kind: addition\n    breaking: false\n  - description: Change description 0\n    kind: change\n    breaking: false\n  - description: Removal description 0\n    kind: removal\n    breaking: true\n    migration:\n      header: Header for removal migration 0\n      body: Body for removal migration 0\n  - description: Deprecation description 0\n    kind: deprecation\n    breaking: false\n  - description: Bugfix description 0\n    kind: bugfix\n    breaking: false"
  },
  {
    "path": "release/changelog/internal/testdata/valid/fragment2.yml",
    "content": "entries:\n  - description: Addition description 1\n    kind: addition\n    breaking: false\n    pull_request_override: 999999\n  - description: Change description 1\n    kind: change\n    breaking: false\n    pull_request_override: 999999\n  - description: Removal description 1\n    kind: removal\n    breaking: true\n    pull_request_override: 999999\n    migration:\n      header: Header for removal migration 1\n      body: Body for removal migration 1\n  - description: Deprecation description 1\n    kind: deprecation\n    breaking: false\n    pull_request_override: 999999\n  - description: Bugfix description 1\n    kind: bugfix\n    breaking: false\n    pull_request_override: 999999\n"
  },
  {
    "path": "test/common/sa_secret.go",
    "content": "// Copyright 2022 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage common\n\nimport (\n\t\"fmt\"\n\t\"os\"\n)\n\nvar saSecretTemplate = `---\napiVersion: v1\nkind: Secret\ntype: kubernetes.io/service-account-token\nmetadata:\n  name: %s\n  annotations:\n    kubernetes.io/service-account.name: \"%s\"\n`\n\n// GetSASecret writes a service account token secret to a file. It returns a string to the file or an error if it fails to write the file\nfunc GetSASecret(name string, dir string) (string, error) {\n\tsecretName := name + \"-secret\"\n\tfileName := dir + \"/\" + secretName + \".yaml\"\n\terr := os.WriteFile(fileName, []byte(fmt.Sprintf(saSecretTemplate, secretName, name)), 0777)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\treturn fileName, nil\n}\n"
  },
  {
    "path": "test/common/scorecard.go",
    "content": "// Copyright 2021 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage common\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os/exec\"\n\t\"strings\"\n\n\t. \"github.com/onsi/ginkgo/v2\" //nolint:staticcheck\n\t. \"github.com/onsi/gomega\"    //nolint:staticcheck\n\n\t\"github.com/operator-framework/api/pkg/apis/scorecard/v1alpha3\"\n\t\"github.com/operator-framework/operator-sdk/internal/testutils\"\n)\n\n// ScorecardSpec runs a set of scorecard tests common to all operator types.\nfunc ScorecardSpec(tc *testutils.TestContext, operatorType string) func() {\n\treturn func() {\n\t\tvar (\n\t\t\terr         error\n\t\t\tcmd         *exec.Cmd\n\t\t\toutputBytes []byte\n\t\t\toutput      v1alpha3.TestList\n\t\t)\n\n\t\tIt(\"should run a single scorecard test successfully\", func() {\n\t\t\tcmd = exec.Command(tc.BinaryName, \"scorecard\", \"bundle\",\n\t\t\t\t\"--selector\", \"suite=basic\",\n\t\t\t\t\"--output\", \"json\",\n\t\t\t\t\"--wait-time\", \"2m\")\n\t\t\toutputBytes, err = tc.Run(cmd)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\tExpect(json.Unmarshal(outputBytes, &output)).To(Succeed())\n\n\t\t\tExpect(output.Items).To(HaveLen(1))\n\t\t\tresults := output.Items[0].Status.Results\n\t\t\tExpect(results).To(HaveLen(1))\n\t\t\tExpect(results[0].Name).To(Equal(\"basic-check-spec\"))\n\t\t\tExpect(results[0].State).To(Equal(v1alpha3.PassState))\n\t\t})\n\n\t\tIt(\"should run all enabled scorecard tests successfully\", func() {\n\t\t\tcmd = exec.Command(tc.BinaryName, \"scorecard\", \"bundle\",\n\t\t\t\t\"--output\", \"json\",\n\t\t\t\t\"--wait-time\", \"4m\")\n\t\t\toutputBytes, err = tc.Run(cmd)\n\t\t\t// Some tests are expected to fail, which results in scorecard exiting 1.\n\t\t\t// Go tests no longer expect to fail\n\t\t\tif strings.ToLower(operatorType) != \"go\" {\n\t\t\t\tExpect(err).To(HaveOccurred())\n\t\t\t}\n\t\t\tExpect(json.Unmarshal(outputBytes, &output)).To(Succeed())\n\n\t\t\texpected := map[string]v1alpha3.State{\n\t\t\t\t// Basic suite.\n\t\t\t\t\"basic-check-spec\": v1alpha3.PassState,\n\t\t\t\t// OLM suite.\n\t\t\t\t\"olm-bundle-validation\":    v1alpha3.PassState,\n\t\t\t\t\"olm-crds-have-validation\": v1alpha3.FailState,\n\t\t\t\t\"olm-crds-have-resources\":  v1alpha3.FailState,\n\t\t\t\t\"olm-spec-descriptors\":     v1alpha3.FailState,\n\t\t\t\t// For Ansible/Helm should PASS with a Suggestion\n\t\t\t\t// For Golang should pass because we have status spec and descriptions\n\t\t\t\t\"olm-status-descriptors\": v1alpha3.PassState,\n\t\t\t}\n\t\t\tif strings.ToLower(operatorType) == \"go\" {\n\t\t\t\t// Go projects have generated CRD validation.\n\t\t\t\texpected[\"olm-crds-have-validation\"] = v1alpha3.PassState\n\t\t\t\t// Go generated test operator now has CSV markers\n\t\t\t\t// that allows these validations to pass\n\t\t\t\texpected[\"olm-crds-have-resources\"] = v1alpha3.PassState\n\t\t\t\texpected[\"olm-spec-descriptors\"] = v1alpha3.PassState\n\t\t\t\texpected[\"olm-status-descriptors\"] = v1alpha3.PassState\n\t\t\t\t// The Go sample project tests a custom suite.\n\t\t\t\texpected[\"customtest1\"] = v1alpha3.PassState\n\t\t\t\texpected[\"customtest2\"] = v1alpha3.PassState\n\t\t\t}\n\n\t\t\tExpect(output.Items).To(HaveLen(len(expected)))\n\t\t\tfor i := 0; i < len(output.Items); i++ {\n\t\t\t\tresults := output.Items[i].Status.Results\n\t\t\t\tExpect(results).To(HaveLen(1))\n\t\t\t\tExpect(results[0].Name).NotTo(BeEmpty())\n\t\t\t\tfmt.Fprintln(GinkgoWriter, \"    - Name: \", results[0].Name)\n\t\t\t\tfmt.Fprintln(GinkgoWriter, \"      Expected: \", expected[results[0].Name])\n\t\t\t\tfmt.Fprintln(GinkgoWriter, \"      Output: \", results[0].State)\n\t\t\t\tExpect(results[0].State).To(Equal(expected[results[0].Name]))\n\t\t\t}\n\t\t})\n\n\t\tIt(\"should configure scorecard storage successfully\", func() {\n\t\t\tcmd = exec.Command(tc.BinaryName, \"scorecard\", \"bundle\",\n\t\t\t\t\"--selector\", \"suite=basic\",\n\t\t\t\t\"--output\", \"json\",\n\t\t\t\t\"--test-output\", \"/testdata\",\n\t\t\t\t\"--wait-time\", \"4m\")\n\t\t\toutputBytes, err = tc.Run(cmd)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\tExpect(json.Unmarshal(outputBytes, &output)).To(Succeed())\n\n\t\t\tExpect(output.Items).To(HaveLen(1))\n\t\t\tresults := output.Items[0].Status.Results\n\t\t\tExpect(results).To(HaveLen(1))\n\t\t\tExpect(results[0].Name).To(Equal(\"basic-check-spec\"))\n\t\t\tExpect(results[0].State).To(Equal(v1alpha3.PassState))\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "test/e2e/go/cluster_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Modified from https://github.com/kubernetes-sigs/kubebuilder/tree/39224f0/test/e2e/v3\n\npackage e2e_go_test\n\nimport (\n\t\"encoding/base64\"\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"time\"\n\n\tkbutil \"sigs.k8s.io/kubebuilder/v4/pkg/plugin/util\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\t\"github.com/operator-framework/operator-sdk/internal/testutils\"\n\t\"github.com/operator-framework/operator-sdk/test/common\"\n)\n\nvar _ = Describe(\"operator-sdk\", func() {\n\tvar controllerPodName, metricsClusterRoleBindingName string\n\n\tContext(\"built with operator-sdk\", func() {\n\n\t\tBeforeEach(func() {\n\t\t\tmetricsClusterRoleBindingName = fmt.Sprintf(\"%s-metrics-reader\", tc.ProjectName)\n\n\t\t\tBy(\"deploying project on the cluster\")\n\t\t\tExpect(tc.Make(\"deploy\", \"IMG=\"+tc.ImageName)).To(Succeed())\n\t\t})\n\n\t\tAfterEach(func() {\n\t\t\tBy(\"deleting curl pod\")\n\t\t\ttestutils.WrapWarnOutput(tc.Kubectl.Delete(true, \"pod\", \"curl\"))\n\n\t\t\tBy(\"cleaning up permissions\")\n\t\t\ttestutils.WrapWarnOutput(tc.Kubectl.Command(\"delete\", \"clusterrolebinding\", metricsClusterRoleBindingName))\n\n\t\t\tBy(\"ensuring that the namespace was deleted\")\n\t\t\ttestutils.WrapWarnOutput(tc.Kubectl.Wait(false, \"namespace\", \"foo\", \"--for\", \"delete\", \"--timeout\", \"2m\"))\n\t\t})\n\n\t\tIt(\"should run correctly in a cluster\", func() {\n\t\t\tBy(\"checking if the Operator project Pod is running\")\n\t\t\tverifyControllerUp := func() error {\n\t\t\t\t// Get the controller-manager pod name\n\t\t\t\tpodOutput, err := tc.Kubectl.Get(\n\t\t\t\t\ttrue,\n\t\t\t\t\t\"pods\", \"-l\", \"control-plane=controller-manager\",\n\t\t\t\t\t\"-o\", \"go-template={{ range .items }}{{ if not .metadata.deletionTimestamp }}{{ .metadata.name }}\"+\n\t\t\t\t\t\t\"{{ \\\"\\\\n\\\" }}{{ end }}{{ end }}\")\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"could not get pods: %v\", err)\n\t\t\t\t}\n\t\t\t\tpodNames := kbutil.GetNonEmptyLines(podOutput)\n\t\t\t\tif len(podNames) != 1 {\n\t\t\t\t\treturn fmt.Errorf(\"expecting 1 pod, have %d\", len(podNames))\n\t\t\t\t}\n\t\t\t\tcontrollerPodName = podNames[0]\n\t\t\t\tif !strings.Contains(controllerPodName, \"controller-manager\") {\n\t\t\t\t\treturn fmt.Errorf(\"expecting pod name %q to contain %q\", controllerPodName, \"controller-manager\")\n\t\t\t\t}\n\n\t\t\t\t// Ensure the controller-manager Pod is running.\n\t\t\t\tstatus, err := tc.Kubectl.Get(\n\t\t\t\t\ttrue,\n\t\t\t\t\t\"pods\", controllerPodName, \"-o\", \"jsonpath={.status.phase}\")\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"failed to get pod status for %q: %v\", controllerPodName, err)\n\t\t\t\t}\n\t\t\t\tif status != \"Running\" {\n\t\t\t\t\treturn fmt.Errorf(\"controller pod in %s status\", status)\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tEventually(verifyControllerUp, 2*time.Minute, time.Second).Should(Succeed())\n\n\t\t\tBy(\"ensuring the created ServiceMonitor for the manager\")\n\t\t\t_, err := tc.Kubectl.Get(\n\t\t\t\ttrue,\n\t\t\t\t\"ServiceMonitor\",\n\t\t\t\tfmt.Sprintf(\"%s-controller-manager-metrics-monitor\", tc.ProjectName))\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"ensuring the created metrics Service for the manager\")\n\t\t\t_, err = tc.Kubectl.Get(\n\t\t\t\ttrue,\n\t\t\t\t\"Service\",\n\t\t\t\tfmt.Sprintf(\"%s-controller-manager-metrics-service\", tc.ProjectName))\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"creating an instance of CR\")\n\t\t\t// currently controller-runtime doesn't provide a readiness probe, we retry a few times\n\t\t\t// we can change it to probe the readiness endpoint after CR supports it.\n\t\t\tsampleFile := filepath.Join(\"config\", \"samples\",\n\t\t\t\tfmt.Sprintf(\"%s_%s_%s.yaml\", tc.Group, tc.Version, strings.ToLower(tc.Kind)))\n\t\t\tEventually(func() error {\n\t\t\t\t_, err = tc.Kubectl.Apply(true, \"-f\", sampleFile)\n\t\t\t\treturn err\n\t\t\t}, time.Minute, time.Second).Should(Succeed())\n\n\t\t\tBy(\"granting permissions to access the metrics and read the token\")\n\t\t\t_, err = tc.Kubectl.Command(\"create\", \"clusterrolebinding\", metricsClusterRoleBindingName,\n\t\t\t\tfmt.Sprintf(\"--clusterrole=%s-metrics-reader\", tc.ProjectName),\n\t\t\t\tfmt.Sprintf(\"--serviceaccount=%s:%s\", tc.Kubectl.Namespace, tc.Kubectl.ServiceAccount))\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\t// As of Kubernetes 1.24 a ServiceAccount no longer has a ServiceAccount token secret autogenerated. We have to create it manually here\n\t\t\tBy(\"Creating the ServiceAccount token\")\n\t\t\tsecretFile, err := common.GetSASecret(tc.Kubectl.ServiceAccount, tc.Dir)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\tEventually(func() error {\n\t\t\t\t_, err = tc.Kubectl.Apply(true, \"-f\", secretFile)\n\t\t\t\treturn err\n\t\t\t}, time.Minute, time.Second).Should(Succeed())\n\n\t\t\tBy(\"reading the metrics token\")\n\t\t\t// Filter token query by service account in case more than one exists in a namespace.\n\t\t\tquery := fmt.Sprintf(`{.items[?(@.metadata.annotations.kubernetes\\.io/service-account\\.name==\"%s\")].data.token}`,\n\t\t\t\ttc.Kubectl.ServiceAccount,\n\t\t\t)\n\t\t\tb64Token, err := tc.Kubectl.Get(true, \"secrets\", \"-o=jsonpath=\"+query)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\ttoken, err := base64.StdEncoding.DecodeString(strings.TrimSpace(b64Token))\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\tExpect(token).ToNot(BeEmpty())\n\n\t\t\tBy(\"creating a curl pod\")\n\t\t\tcmdOpts := []string{\n\t\t\t\t\"run\", \"curl\", \"--image=curlimages/curl:7.68.0\", \"--restart=OnFailure\", \"--\",\n\t\t\t\t\"curl\", \"-v\", \"-k\", \"-H\", fmt.Sprintf(`Authorization: Bearer %s`, token),\n\t\t\t\tfmt.Sprintf(\"https://%s-controller-manager-metrics-service.%s.svc:8443/metrics\", tc.ProjectName, tc.Kubectl.Namespace),\n\t\t\t}\n\t\t\t_, err = tc.Kubectl.CommandInNamespace(cmdOpts...)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"validating that the curl pod is running as expected\")\n\t\t\tverifyCurlUp := func() error {\n\t\t\t\t// Validate pod status\n\t\t\t\tstatus, err := tc.Kubectl.Get(\n\t\t\t\t\ttrue,\n\t\t\t\t\t\"pods\", \"curl\", \"-o\", \"jsonpath={.status.phase}\")\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tif status != \"Completed\" && status != \"Succeeded\" {\n\t\t\t\t\treturn fmt.Errorf(\"curl pod in %s status\", status)\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tEventually(verifyCurlUp, 2*time.Minute, time.Second).Should(Succeed())\n\n\t\t\tBy(\"validating that the metrics endpoint is serving as expected\")\n\t\t\tvar metricsOutput string\n\t\t\tgetCurlLogs := func() string {\n\t\t\t\tmetricsOutput, err = tc.Kubectl.Logs(\"curl\")\n\t\t\t\tExpectWithOffset(1, err).NotTo(HaveOccurred())\n\t\t\t\treturn metricsOutput\n\t\t\t}\n\t\t\tEventually(getCurlLogs, 3*time.Minute, time.Second).Should(ContainSubstring(\"< HTTP/1.1 200 OK\"))\n\n\t\t\tBy(\"validating that pod(s) status.phase=Running\")\n\t\t\tgetMemcachedPodStatus := func() error {\n\t\t\t\tstatus, err := tc.Kubectl.Get(true, \"pods\", \"-l\",\n\t\t\t\t\t\"app.kubernetes.io/name=Memcached\",\n\t\t\t\t\t\"-o\", \"jsonpath={.items[*].status}\",\n\t\t\t\t)\n\t\t\t\tExpectWithOffset(2, err).NotTo(HaveOccurred())\n\t\t\t\tif !strings.Contains(status, \"\\\"phase\\\":\\\"Running\\\"\") {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tEventuallyWithOffset(1, getMemcachedPodStatus, 3*time.Minute, time.Second).Should(Succeed())\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "test/e2e/go/local_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n// To run locally you need to export the env var with the image\n// $ export MEMCACHED_IMAGE=memcached:1.4.36-alpine\n\npackage e2e_go_test\n\nimport (\n\t\"os/exec\"\n\n\t. \"github.com/onsi/ginkgo/v2\" //nolint:golint,staticcheck\n\t. \"github.com/onsi/gomega\"    //nolint:golint,staticcheck\n)\n\nvar _ = Describe(\"Running Go projects\", func() {\n\tContext(\"built with operator-sdk\", func() {\n\n\t\tBeforeEach(func() {\n\t\t\tBy(\"installing CRD's\")\n\t\t\terr := tc.Make(\"install\")\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t})\n\n\t\tAfterEach(func() {\n\t\t\tBy(\"uninstalling CRD's\")\n\t\t\terr := tc.Make(\"uninstall\")\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t})\n\n\t\tIt(\"should run correctly locally\", func() {\n\t\t\tBy(\"running the project\")\n\t\t\tcmd := exec.Command(\"make\", \"run\")\n\t\t\terr := cmd.Start()\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"killing the project\")\n\t\t\terr = cmd.Process.Kill()\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "test/e2e/go/scorecard_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage e2e_go_test\n\nimport (\n\t. \"github.com/onsi/ginkgo/v2\"\n\n\t\"github.com/operator-framework/operator-sdk/test/common\"\n)\n\nvar _ = Describe(\"scorecard\", common.ScorecardSpec(&tc, \"go\"))\n"
  },
  {
    "path": "test/e2e/go/suite_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage e2e_go_test\n\nimport (\n\t\"fmt\"\n\t\"os/exec\"\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/testutils\"\n)\n\n// TestE2EGo ensures the Go projects built with the SDK tool by using its binary.\nfunc TestE2EGo(t *testing.T) {\n\tif testing.Short() {\n\t\tt.Skip(\"skipping Operator SDK E2E Go Suite testing in short mode\")\n\t}\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"E2EGo Suite\")\n}\n\nvar (\n\ttc testutils.TestContext\n)\n\n// BeforeSuite run before any specs are run to perform the required actions for all e2e Go tests.\nvar _ = BeforeSuite(func() {\n\tvar err error\n\n\tBy(\"creating a new test context\")\n\ttc, err = testutils.NewTestContext(testutils.BinaryName, \"GO111MODULE=on\")\n\tExpect(err).NotTo(HaveOccurred())\n\n\ttc.Domain = \"example.com\"\n\ttc.Group = \"cache\"\n\ttc.Version = \"v1alpha1\"\n\ttc.Kind = \"Memcached\"\n\ttc.Resources = \"memcacheds\"\n\ttc.ProjectName = \"memcached-operator\"\n\ttc.Kubectl.Namespace = fmt.Sprintf(\"%s-system\", tc.ProjectName)\n\ttc.Kubectl.ServiceAccount = fmt.Sprintf(\"%s-controller-manager\", tc.ProjectName)\n\n\tBy(\"copying sample to a temporary e2e directory\")\n\tExpect(exec.Command(\"cp\", \"-r\", \"../../../testdata/go/v4/memcached-operator\", tc.Dir).Run()).To(Succeed())\n\n\tBy(\"preparing the prerequisites on cluster\")\n\ttc.InstallPrerequisites()\n\n\tBy(\"by adding scorecard custom patch file\")\n\terr = tc.AddScorecardCustomPatchFile()\n\tExpect(err).NotTo(HaveOccurred())\n\n\tBy(\"using dev image for scorecard-test\")\n\terr = tc.ReplaceScorecardImagesForDev()\n\tExpect(err).NotTo(HaveOccurred())\n\n\tBy(\"building the project image\")\n\terr = tc.Make(\"docker-build\", \"IMG=\"+tc.ImageName)\n\tExpect(err).NotTo(HaveOccurred())\n\n\tonKind, err := tc.IsRunningOnKind()\n\tExpect(err).NotTo(HaveOccurred())\n\tif onKind {\n\t\tBy(\"loading the required images into Kind cluster\")\n\t\tExpect(tc.LoadImageToKindCluster()).To(Succeed())\n\t\tExpect(tc.LoadImageToKindClusterWithName(\"quay.io/operator-framework/scorecard-test:dev\")).To(Succeed())\n\t\tExpect(tc.LoadImageToKindClusterWithName(\"quay.io/operator-framework/custom-scorecard-tests:dev\")).To(Succeed())\n\t}\n\n\tBy(\"generating bundle\")\n\tExpect(tc.GenerateBundle()).To(Succeed())\n\n\tBy(\"installing cert manager bundle\")\n\tExpect(tc.InstallCertManager()).To(Succeed())\n})\n\n// AfterSuite run after all the specs have run, regardless of whether any tests have failed to ensures that\n// all be cleaned up\nvar _ = AfterSuite(func() {\n\tBy(\"uninstall cert manager bundle\")\n\ttc.UninstallCertManager()\n\n\tBy(\"uninstalling prerequisites\")\n\ttc.UninstallPrerequisites()\n\n\tBy(\"destroying container image and work dir\")\n\ttc.Destroy()\n})\n"
  },
  {
    "path": "test/e2e/helm/cluster_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage e2e_helm_test\n\nimport (\n\t\"encoding/base64\"\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"time\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\tkbutil \"sigs.k8s.io/kubebuilder/v4/pkg/plugin/util\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/testutils\"\n\t\"github.com/operator-framework/operator-sdk/test/common\"\n)\n\nvar _ = Describe(\"Running Helm projects\", func() {\n\tvar (\n\t\tcontrollerPodName, metricsClusterRoleBindingName string\n\t\tmemcachedSampleFile                              string\n\t)\n\n\tContext(\"built with operator-sdk\", func() {\n\t\tBeforeEach(func() {\n\t\t\tmetricsClusterRoleBindingName = fmt.Sprintf(\"%s-metrics-reader\", tc.ProjectName)\n\t\t\tmemcachedSampleFile = filepath.Join(tc.Dir, \"config\", \"samples\",\n\t\t\t\tfmt.Sprintf(\"%s_%s_%s.yaml\", tc.Group, tc.Version, strings.ToLower(tc.Kind)))\n\n\t\t\tBy(\"deploying project on the cluster\")\n\t\t\tExpect(tc.Make(\"deploy\", \"IMG=\"+tc.ImageName)).To(Succeed())\n\t\t})\n\n\t\tAfterEach(func() {\n\t\t\tBy(\"deleting curl pod\")\n\t\t\ttestutils.WrapWarnOutput(tc.Kubectl.Delete(true, \"pod\", \"curl\"))\n\n\t\t\tBy(\"deleting test CR instances\")\n\t\t\ttestutils.WrapWarnOutput(tc.Kubectl.Delete(false, \"-f\", memcachedSampleFile))\n\n\t\t\tBy(\"cleaning up permissions\")\n\t\t\ttestutils.WrapWarnOutput(tc.Kubectl.Command(\"delete\", \"clusterrolebinding\", metricsClusterRoleBindingName))\n\n\t\t\tBy(\"undeploy project\")\n\t\t\ttestutils.WrapWarn(tc.Make(\"undeploy\"))\n\n\t\t\tBy(\"ensuring that the namespace was deleted\")\n\t\t\ttestutils.WrapWarnOutput(tc.Kubectl.Wait(false, \"namespace\", \"foo\", \"--for\", \"delete\", \"--timeout\", \"2m\"))\n\t\t})\n\n\t\tIt(\"should run correctly in a cluster\", func() {\n\t\t\tBy(\"checking if the Operator project Pod is running\")\n\t\t\tverifyControllerUp := func() error {\n\t\t\t\t// Get the controller-manager pod name\n\t\t\t\tpodOutput, err := tc.Kubectl.Get(\n\t\t\t\t\ttrue,\n\t\t\t\t\t\"pods\", \"-l\", \"control-plane=controller-manager\",\n\t\t\t\t\t\"-o\", \"go-template={{ range .items }}{{ if not .metadata.deletionTimestamp }}{{ .metadata.name }}\"+\n\t\t\t\t\t\t\"{{ \\\"\\\\n\\\" }}{{ end }}{{ end }}\")\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"could not get pods: %v\", err)\n\t\t\t\t}\n\t\t\t\tpodNames := kbutil.GetNonEmptyLines(podOutput)\n\t\t\t\tif len(podNames) != 1 {\n\t\t\t\t\treturn fmt.Errorf(\"expecting 1 pod, have %d\", len(podNames))\n\t\t\t\t}\n\t\t\t\tcontrollerPodName = podNames[0]\n\t\t\t\tif !strings.Contains(controllerPodName, \"controller-manager\") {\n\t\t\t\t\treturn fmt.Errorf(\"expecting pod name %q to contain %q\", controllerPodName, \"controller-manager\")\n\t\t\t\t}\n\n\t\t\t\t// Ensure the controller-manager Pod is running.\n\t\t\t\tstatus, err := tc.Kubectl.Get(\n\t\t\t\t\ttrue,\n\t\t\t\t\t\"pods\", controllerPodName, \"-o\", \"jsonpath={.status.phase}\")\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"failed to get pod status for %q: %v\", controllerPodName, err)\n\t\t\t\t}\n\t\t\t\tif status != \"Running\" {\n\t\t\t\t\treturn fmt.Errorf(\"controller pod in %s status\", status)\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tEventually(verifyControllerUp, 2*time.Minute, time.Second).Should(Succeed())\n\n\t\t\tBy(\"ensuring the created ServiceMonitor for the manager\")\n\t\t\t_, err := tc.Kubectl.Get(\n\t\t\t\ttrue,\n\t\t\t\t\"ServiceMonitor\",\n\t\t\t\tfmt.Sprintf(\"%s-controller-manager-metrics-monitor\", tc.ProjectName))\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"ensuring the created metrics Service for the manager\")\n\t\t\t_, err = tc.Kubectl.Get(\n\t\t\t\ttrue,\n\t\t\t\t\"Service\",\n\t\t\t\tfmt.Sprintf(\"%s-controller-manager-metrics-service\", tc.ProjectName))\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tsampleFile := filepath.Join(\"config\", \"samples\",\n\t\t\t\tfmt.Sprintf(\"%s_%s_%s.yaml\", tc.Group, tc.Version, strings.ToLower(tc.Kind)))\n\n\t\t\tBy(\"updating replicaCount to 1 in the CR manifest\")\n\t\t\terr = kbutil.ReplaceInFile(filepath.Join(tc.Dir, sampleFile), \"replicaCount: 3\", \"replicaCount: 1\")\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"creating an instance of release(CR)\")\n\t\t\t_, err = tc.Kubectl.Apply(false, \"-f\", sampleFile)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"ensuring the CR gets reconciled and the release was Installed\")\n\t\t\tmanagerContainerLogs := func() string {\n\t\t\t\tlogOutput, err := tc.Kubectl.Logs(controllerPodName, \"-c\", \"manager\")\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t\treturn logOutput\n\t\t\t}\n\t\t\tEventually(managerContainerLogs, time.Minute, time.Second).Should(ContainSubstring(\"Installed release\"))\n\n\t\t\tBy(\"getting the release name\")\n\t\t\treleaseName, err := tc.Kubectl.Get(\n\t\t\t\tfalse,\n\t\t\t\ttc.Kind, \"-o\", \"jsonpath={..status.deployedRelease.name}\")\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\tExpect(len(releaseName)).NotTo(BeIdenticalTo(0))\n\n\t\t\tBy(\"checking the release(CR) statefulset status\")\n\t\t\tverifyReleaseUp := func() string {\n\t\t\t\toutput, err := tc.Kubectl.Command(\n\t\t\t\t\t\"rollout\", \"status\", \"statefulset\", releaseName)\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t\treturn output\n\t\t\t}\n\t\t\tEventually(verifyReleaseUp, time.Minute, time.Second).Should(ContainSubstring(\"statefulset rolling update complete\"))\n\n\t\t\tBy(\"ensuring the created Service for the release(CR)\")\n\t\t\tcrServiceName, err := tc.Kubectl.Get(\n\t\t\t\tfalse,\n\t\t\t\t\"Service\", \"-l\", fmt.Sprintf(\"app.kubernetes.io/instance=%s\", releaseName),\n\t\t\t\t\"-o\", \"jsonpath={..metadata.name}\")\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\tExpect(len(crServiceName)).NotTo(BeIdenticalTo(0))\n\n\t\t\tBy(\"scaling statefulset replicas to 2\")\n\t\t\t_, err = tc.Kubectl.Command(\n\t\t\t\t\"scale\", \"statefulset\", releaseName, \"--replicas\", \"2\")\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"verifying the statefulset automatically scales back down to 1\")\n\t\t\tverifyRelease := func() error {\n\t\t\t\treplicas, err := tc.Kubectl.Get(\n\t\t\t\t\tfalse,\n\t\t\t\t\t\"statefulset\", releaseName, \"-o\", \"jsonpath={..spec.replicas}\")\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t\tif replicas != \"1\" {\n\t\t\t\t\treturn fmt.Errorf(\"release(CR) statefulset with %s replicas\", replicas)\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tEventually(verifyRelease, time.Minute, time.Second).Should(Succeed())\n\n\t\t\tBy(\"updating replicaCount to 2 in the CR manifest\")\n\t\t\terr = kbutil.ReplaceInFile(filepath.Join(tc.Dir, sampleFile), \"replicaCount: 1\", \"replicaCount: 2\")\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"applying CR manifest with replicaCount: 2\")\n\t\t\t_, err = tc.Kubectl.Apply(false, \"-f\", sampleFile)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"ensuring the CR gets reconciled and the release was Upgraded\")\n\t\t\tmanagerContainerLogsAfterUpdateCR := func() string {\n\t\t\t\tlogOutput, err := tc.Kubectl.Logs(controllerPodName, \"-c\", \"manager\")\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t\treturn logOutput\n\t\t\t}\n\t\t\tEventually(managerContainerLogsAfterUpdateCR, time.Minute, time.Second).Should(\n\t\t\t\tContainSubstring(\"Upgraded release\"))\n\n\t\t\tBy(\"checking StatefulSet replicas spec is equals 2\")\n\t\t\tverifyReleaseUpgrade := func() error {\n\t\t\t\treplicas, err := tc.Kubectl.Get(\n\t\t\t\t\tfalse,\n\t\t\t\t\t\"statefulset\", releaseName, \"-o\", \"jsonpath={..spec.replicas}\")\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t\tif replicas != \"2\" {\n\t\t\t\t\treturn fmt.Errorf(\"release(CR) statefulset with %s replicas\", replicas)\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tEventually(verifyReleaseUpgrade, time.Minute, time.Second).Should(Succeed())\n\n\t\t\t// As of Kubernetes 1.24 a ServiceAccount no longer has a ServiceAccount token secret autogenerated. We have to create it manually here\n\t\t\tBy(\"Creating the ServiceAccount token\")\n\t\t\tsecretFile, err := common.GetSASecret(tc.Kubectl.ServiceAccount, tc.Dir)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\tEventually(func() error {\n\t\t\t\t_, err = tc.Kubectl.Apply(true, \"-f\", secretFile)\n\t\t\t\treturn err\n\t\t\t}, time.Minute, time.Second).Should(Succeed())\n\n\t\t\tBy(\"granting permissions to access the metrics and read the token\")\n\t\t\t_, err = tc.Kubectl.Command(\"create\", \"clusterrolebinding\", metricsClusterRoleBindingName,\n\t\t\t\tfmt.Sprintf(\"--clusterrole=%s-metrics-reader\", tc.ProjectName),\n\t\t\t\tfmt.Sprintf(\"--serviceaccount=%s:%s\", tc.Kubectl.Namespace, tc.Kubectl.ServiceAccount))\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"reading the metrics token\")\n\t\t\t// Filter token query by service account in case more than one exists in a namespace.\n\t\t\tquery := fmt.Sprintf(`{.items[?(@.metadata.annotations.kubernetes\\.io/service-account\\.name==\"%s\")].data.token}`,\n\t\t\t\ttc.Kubectl.ServiceAccount,\n\t\t\t)\n\t\t\tb64Token, err := tc.Kubectl.Get(true, \"secrets\", \"-o=jsonpath=\"+query)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\ttoken, err := base64.StdEncoding.DecodeString(strings.TrimSpace(b64Token))\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\tExpect(token).ToNot(BeEmpty())\n\n\t\t\tBy(\"creating a curl pod\")\n\t\t\tcmdOpts := []string{\n\t\t\t\t\"run\", \"curl\", \"--image=curlimages/curl:7.68.0\", \"--restart=OnFailure\", \"--\",\n\t\t\t\t\"curl\", \"-v\", \"-k\", \"-H\", fmt.Sprintf(`Authorization: Bearer %s`, token),\n\t\t\t\tfmt.Sprintf(\"https://%s-controller-manager-metrics-service.%s.svc:8443/metrics\", tc.ProjectName, tc.Kubectl.Namespace),\n\t\t\t}\n\t\t\t_, err = tc.Kubectl.CommandInNamespace(cmdOpts...)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"validating that the curl pod is running as expected\")\n\t\t\tverifyCurlUp := func() error {\n\t\t\t\t// Validate pod status\n\t\t\t\tstatus, err := tc.Kubectl.Get(\n\t\t\t\t\ttrue,\n\t\t\t\t\t\"pods\", \"curl\", \"-o\", \"jsonpath={.status.phase}\")\n\t\t\t\tExpectWithOffset(1, err).NotTo(HaveOccurred())\n\t\t\t\tif status != \"Completed\" && status != \"Succeeded\" {\n\t\t\t\t\treturn fmt.Errorf(\"curl pod in %s status\", status)\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tEventually(verifyCurlUp, 2*time.Minute, time.Second).Should(Succeed())\n\n\t\t\tBy(\"checking metrics endpoint serving as expected\")\n\t\t\tgetCurlLogs := func() string {\n\t\t\t\tlogOutput, err := tc.Kubectl.Logs(\"curl\")\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t\treturn logOutput\n\t\t\t}\n\t\t\tEventually(getCurlLogs, time.Minute, time.Second).Should(ContainSubstring(\"< HTTP/1.1 200 OK\"))\n\n\t\t\tBy(\"getting the CR namespace token\")\n\t\t\tcrNamespace, err := tc.Kubectl.Get(\n\t\t\t\tfalse,\n\t\t\t\ttc.Kind,\n\t\t\t\tfmt.Sprintf(\"%s-sample\", strings.ToLower(tc.Kind)),\n\t\t\t\t\"-o=jsonpath={..metadata.namespace}\")\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\tExpect(crNamespace).NotTo(BeEmpty())\n\n\t\t\tBy(\"ensuring the operator metrics contains a `resource_created_at` metric for the CR\")\n\t\t\tmetricExportedCR := fmt.Sprintf(\"resource_created_at_seconds{group=\\\"%s\\\",\"+\n\t\t\t\t\"kind=\\\"%s\\\",\"+\n\t\t\t\t\"name=\\\"%s-sample\\\",\"+\n\t\t\t\t\"namespace=\\\"%s\\\",\"+\n\t\t\t\t\"version=\\\"%s\\\"}\",\n\t\t\t\tfmt.Sprintf(\"%s.%s\", tc.Group, tc.Domain),\n\t\t\t\ttc.Kind,\n\t\t\t\tstrings.ToLower(tc.Kind),\n\t\t\t\tcrNamespace,\n\t\t\t\ttc.Version)\n\t\t\tEventually(getCurlLogs, time.Minute, time.Second).Should(ContainSubstring(metricExportedCR))\n\n\t\t\tBy(\"annotate CR with uninstall-wait\")\n\t\t\tcmdOpts = []string{\n\t\t\t\t\"annotate\", tc.Kind, fmt.Sprintf(\"%s-sample\", strings.ToLower(tc.Kind)),\n\t\t\t\t\"helm.sdk.operatorframework.io/uninstall-wait=true\",\n\t\t\t}\n\t\t\t_, err = tc.Kubectl.Command(cmdOpts...)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"adding a finalizer to statefulset\")\n\t\t\tcmdOpts = []string{\n\t\t\t\t\"patch\", \"statefulset\", releaseName, \"-p\",\n\t\t\t\t\"{\\\"metadata\\\":{\\\"finalizers\\\":[\\\"helm.sdk.operatorframework.io/fake-finalizer\\\"]}}\",\n\t\t\t\t\"--type=merge\",\n\t\t\t}\n\t\t\t_, err = tc.Kubectl.Command(cmdOpts...)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"deleting CR manifest\")\n\t\t\t_, err = tc.Kubectl.Delete(false, \"-f\", sampleFile, \"--wait=false\")\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"ensuring the CR gets reconciled and uninstall-wait is enabled\")\n\t\t\tmanagerContainerLogsAfterDeleteCR := func() string {\n\t\t\t\tlogOutput, err := tc.Kubectl.Logs(controllerPodName, \"-c\", \"manager\")\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t\treturn logOutput\n\t\t\t}\n\t\t\tEventually(managerContainerLogsAfterDeleteCR, time.Minute, time.Second).Should(ContainSubstring(\"Uninstall wait\"))\n\t\t\tEventually(managerContainerLogsAfterDeleteCR, time.Minute, time.Second).Should(ContainSubstring(\"Waiting until all resources are deleted\"))\n\n\t\t\tBy(\"removing the finalizer from statefulset\")\n\t\t\tcmdOpts = []string{\n\t\t\t\t\"patch\", \"statefulset\", releaseName, \"-p\",\n\t\t\t\t\"{\\\"metadata\\\":{\\\"finalizers\\\":[]}}\",\n\t\t\t\t\"--type=merge\",\n\t\t\t}\n\t\t\t_, err = tc.Kubectl.Command(cmdOpts...)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"ensuring the CR gets reconciled and CR finalizer is removed\")\n\t\t\tEventually(managerContainerLogsAfterDeleteCR, 2*time.Minute, time.Second).Should(ContainSubstring(\"Removing finalizer\"))\n\n\t\t\tBy(\"ensuring the CR is deleted\")\n\t\t\tverifyDeletedCR := func() error {\n\t\t\t\t_, err := tc.Kubectl.Get(\n\t\t\t\t\ttrue,\n\t\t\t\t\ttc.Kind, fmt.Sprintf(\"%s-sample\", strings.ToLower(tc.Kind)))\n\t\t\t\tif err == nil {\n\t\t\t\t\treturn fmt.Errorf(\"the %s CR is not deleted\", tc.Kind)\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tEventually(verifyDeletedCR, time.Minute, time.Second).Should(Succeed())\n\n\t\t\tBy(\"creating an instance of release(CR) again after a delete with uninstall-wait\")\n\t\t\t_, err = tc.Kubectl.Apply(false, \"-f\", sampleFile)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"ensuring the CR gets reconciled and the release was Installed again\")\n\t\t\tmanagerContainerLogs = func() string {\n\t\t\t\tlogOutput, err := tc.Kubectl.Logs(controllerPodName, \"-c\", \"manager\")\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t\treturn logOutput\n\t\t\t}\n\t\t\tEventually(managerContainerLogs, time.Minute, time.Second).Should(ContainSubstring(\"Installed release\"))\n\n\t\t\tBy(\"deleting CR manifest again without uninstall-wait\")\n\t\t\t_, err = tc.Kubectl.Delete(false, \"-f\", sampleFile)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"ensuring the CR gets reconciled and the release was Uninstalled\")\n\t\t\tmanagerContainerLogsAfterDeleteCR = func() string {\n\t\t\t\tlogOutput, err := tc.Kubectl.Logs(controllerPodName, \"-c\", \"manager\")\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t\treturn logOutput\n\t\t\t}\n\t\t\tEventually(managerContainerLogsAfterDeleteCR, time.Minute, time.Second).Should(ContainSubstring(\"Uninstalled release\"))\n\t\t\tEventually(managerContainerLogsAfterDeleteCR, time.Minute, time.Second).Should(ContainSubstring(\"Removing finalizer\"))\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "test/e2e/helm/local_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage e2e_helm_test\n\nimport (\n\t\"os/exec\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nvar _ = Describe(\"Running Helm projects\", func() {\n\tContext(\"built with operator-sdk\", func() {\n\n\t\tBeforeEach(func() {\n\t\t\tBy(\"installing CRD's\")\n\t\t\terr := tc.Make(\"install\")\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t})\n\n\t\tAfterEach(func() {\n\t\t\tBy(\"uninstalling CRD's\")\n\t\t\terr := tc.Make(\"uninstall\")\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t})\n\n\t\tIt(\"should run correctly locally\", func() {\n\t\t\tBy(\"running the project\")\n\t\t\tcmd := exec.Command(\"make\", \"run\")\n\t\t\terr := cmd.Start()\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"killing the project\")\n\t\t\terr = cmd.Process.Kill()\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "test/e2e/helm/olm_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage e2e_helm_test\n\nimport (\n\t\"os/exec\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/util/projutil\"\n)\n\nvar _ = Describe(\"Integrating Helm Projects with OLM\", func() {\n\tContext(\"with operator-sdk\", func() {\n\t\tconst operatorVersion = \"0.0.1\"\n\n\t\tIt(\"should generate and run a valid OLM bundle and packagemanifests\", func() {\n\t\t\tBy(\"building the operator bundle image\")\n\t\t\terr := tc.Make(\"bundle-build\", \"BUNDLE_IMG=\"+tc.BundleImageName)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"adding the 'packagemanifests' rule to the Makefile\")\n\t\t\terr = tc.AddPackagemanifestsTarget(projutil.OperatorTypeHelm)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"generating the operator package manifests\")\n\t\t\terr = tc.Make(\"packagemanifests\", \"IMG=\"+tc.ImageName)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"running the package\")\n\t\t\trunPkgManCmd := exec.Command(tc.BinaryName, \"run\", \"packagemanifests\",\n\t\t\t\t\"--install-mode\", \"AllNamespaces\",\n\t\t\t\t\"--version\", operatorVersion,\n\t\t\t\t\"--timeout\", \"4m\")\n\t\t\t_, err = tc.Run(runPkgManCmd)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"destroying the deployed package manifests-formatted operator\")\n\t\t\tcleanupPkgManCmd := exec.Command(tc.BinaryName, \"cleanup\", tc.ProjectName,\n\t\t\t\t\"--timeout\", \"4m\")\n\t\t\t_, err = tc.Run(cleanupPkgManCmd)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "test/e2e/helm/scorecard_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage e2e_helm_test\n\nimport (\n\t. \"github.com/onsi/ginkgo/v2\"\n\n\t\"github.com/operator-framework/operator-sdk/test/common\"\n)\n\nvar _ = Describe(\"scorecard\", common.ScorecardSpec(&tc, \"helm\"))\n"
  },
  {
    "path": "test/e2e/helm/suite_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage e2e_helm_test\n\nimport (\n\t\"fmt\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\tkbutil \"sigs.k8s.io/kubebuilder/v4/pkg/plugin/util\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/testutils\"\n)\n\n// TestE2EHelm ensures the Helm projects built with the SDK tool by using its binary.\nfunc TestE2EHelm(t *testing.T) {\n\tif testing.Short() {\n\t\tt.Skip(\"skipping Operator SDK E2E Helm Suite testing in short mode\")\n\t}\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"E2EHelm Suite\")\n}\n\nvar (\n\ttc testutils.TestContext\n)\n\n// BeforeSuite run before any specs are run to perform the required actions for all e2e Helm tests.\nvar _ = BeforeSuite(func() {\n\tvar err error\n\n\tBy(\"creating a new test context\")\n\ttc, err = testutils.NewTestContext(testutils.BinaryName, \"GO111MODULE=on\")\n\tExpect(err).NotTo(HaveOccurred())\n\n\ttc.Domain = \"example.com\"\n\ttc.Group = \"cache\"\n\ttc.Version = \"v1alpha1\"\n\ttc.Kind = \"Memcached\"\n\ttc.Resources = \"memcacheds\"\n\ttc.ProjectName = \"memcached-operator\"\n\ttc.Kubectl.Namespace = fmt.Sprintf(\"%s-system\", tc.ProjectName)\n\ttc.Kubectl.ServiceAccount = fmt.Sprintf(\"%s-controller-manager\", tc.ProjectName)\n\n\tBy(\"copying sample to a temporary e2e directory\")\n\tExpect(exec.Command(\"cp\", \"-r\", \"../../../testdata/helm/memcached-operator\", tc.Dir).Run()).To(Succeed())\n\n\tBy(\"preparing the prerequisites on cluster\")\n\ttc.InstallPrerequisites()\n\n\tBy(\"using dev image for scorecard-test\")\n\terr = tc.ReplaceScorecardImagesForDev()\n\tExpect(err).NotTo(HaveOccurred())\n\n\tBy(\"replacing project Dockerfile to use Helm base image with the dev tag\")\n\terr = kbutil.ReplaceRegexInFile(filepath.Join(tc.Dir, \"Dockerfile\"), \"quay.io/operator-framework/helm-operator:.*\", \"quay.io/operator-framework/helm-operator:dev\")\n\tExpect(err).Should(Succeed())\n\n\tBy(\"checking the kustomize setup\")\n\terr = tc.Make(\"kustomize\")\n\tExpect(err).NotTo(HaveOccurred())\n\n\tBy(\"building the project image\")\n\terr = tc.Make(\"docker-build\", \"IMG=\"+tc.ImageName)\n\tExpect(err).NotTo(HaveOccurred())\n\n\tonKind, err := tc.IsRunningOnKind()\n\tExpect(err).NotTo(HaveOccurred())\n\tif onKind {\n\t\tBy(\"loading the required images into Kind cluster\")\n\t\tExpect(tc.LoadImageToKindCluster()).To(Succeed())\n\t\tExpect(tc.LoadImageToKindClusterWithName(\"quay.io/operator-framework/scorecard-test:dev\")).To(Succeed())\n\t}\n\n\tBy(\"generating bundle\")\n\tExpect(tc.GenerateBundle()).To(Succeed())\n})\n\n// AfterSuite run after all the specs have run, regardless of whether any tests have failed to ensures that\n// all be cleaned up\nvar _ = AfterSuite(func() {\n\tBy(\"uninstalling prerequisites\")\n\ttc.UninstallPrerequisites()\n\n\tBy(\"destroying container image and work dir\")\n\ttc.Destroy()\n})\n"
  },
  {
    "path": "test/integration/packagemanifests_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage integration\n\nimport (\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\nvar _ = Describe(\"run packagemanifests\", func() {\n\n\tvar (\n\t\terr    error\n\t\toutput string\n\t)\n\n\tAfterEach(func() {\n\t\tBy(\"cleaning up\")\n\t\t_, err = cleanup(&tc)\n\t\tExpect(err).NotTo(HaveOccurred())\n\t})\n\n\tIt(\"should handle existing operator deployments correctly\", func() {\n\t\toutput, err = cleanup(&tc)\n\t\tExpect(err).NotTo(HaveOccurred())\n\t\tExpect(output).To(ContainSubstring(`package \\\"memcached-operator\\\" not found`))\n\t\tExpect(runPackageManifests(&tc, \"--version\", \"0.0.1\")).To(Succeed())\n\t\tExpect(runPackageManifests(&tc, \"--version\", \"0.0.1\")).NotTo(Succeed())\n\t\t_, err = cleanup(&tc)\n\t\tExpect(err).NotTo(HaveOccurred())\n\t\toutput, err = cleanup(&tc)\n\t\tExpect(err).NotTo(HaveOccurred())\n\t\tExpect(output).To(ContainSubstring(`package \\\"memcached-operator\\\" not found`))\n\t})\n\n\tIt(\"should succeed with a single operator version in AllNamespaces mode\", func() {\n\t\tExpect(runPackageManifests(&tc, \"--install-mode\", \"AllNamespaces\", \"--version\", \"0.0.1\")).To(Succeed())\n\t})\n})\n"
  },
  {
    "path": "test/integration/suite_test.go",
    "content": "// Copyright 2020 The Operator-SDK Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage integration\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\t\"github.com/operator-framework/api/pkg/operators/v1alpha1\"\n\t\"github.com/operator-framework/operator-registry/pkg/lib/bundle\"\n\t\"sigs.k8s.io/yaml\"\n\n\t\"github.com/operator-framework/operator-sdk/internal/testutils\"\n\t\"github.com/operator-framework/operator-sdk/internal/util/projutil\"\n\tkbutil \"sigs.k8s.io/kubebuilder/v4/pkg/plugin/util\"\n)\n\n// TestIntegration tests operator-sdk projects with OLM.\nfunc TestIntegration(t *testing.T) {\n\tif testing.Short() {\n\t\tt.Skip(\"skipping Integration Suite in short mode\")\n\t}\n\tRegisterFailHandler(Fail)\n\tRunSpecs(t, \"Integration\")\n}\n\nvar (\n\ttc     testutils.TestContext\n\tonKind bool\n)\n\nvar _ = BeforeSuite(func() {\n\tvar err error\n\n\tBy(\"creating a new test context\")\n\ttc, err = testutils.NewTestContext(testutils.BinaryName, \"GO111MODULE=on\")\n\tExpect(err).NotTo(HaveOccurred())\n\n\ttc.Domain = \"example.com\"\n\ttc.Group = \"cache\"\n\ttc.Version = \"v1alpha1\"\n\ttc.Kind = \"Memcached\"\n\ttc.Resources = \"memcacheds\"\n\ttc.ProjectName = \"memcached-operator\"\n\ttc.ImageName = fmt.Sprintf(\"quay.io/integration/%s:0.0.1\", tc.ProjectName)\n\ttc.BundleImageName = fmt.Sprintf(\"quay.io/integration/%s-bundle:0.0.1\", tc.ProjectName)\n\n\tBy(\"copying sample to a temporary e2e directory\")\n\tExpect(exec.Command(\"cp\", \"-r\", \"../../testdata/go/v4/memcached-operator\", tc.Dir).Run()).To(Succeed())\n\n\tBy(\"updating the project configuration\")\n\tExpect(tc.AddPackagemanifestsTarget(projutil.OperatorTypeGo)).To(Succeed())\n\n\tBy(\"installing OLM\")\n\tExpect(tc.InstallOLMVersion(testutils.OlmVersionForTestSuite)).To(Succeed())\n\n\tBy(\"installing prometheus-operator\")\n\tExpect(tc.InstallPrometheusOperManager()).To(Succeed())\n\n\t// Previously, we used kube-rbac-proxy, which generated TLS certificates on the fly —\n\t// a practice not recommended and also deprecated on it due this reason.\n\t//\n\t// Newer versions of the scaffolding support passing real certificates to the metrics server\n\t// using cert-manager. However, the `packagemanifests` command does not support this capability.\n\t// Since `packagemanifests` is deprecated and will be removed in the future, we are choosing\n\t// not to implement support for cert-manager in this context.\n\t//\n\t// Therefore, for testing purposes — specifically when using `packagemanifests` — we are\n\t// disabling the metrics server with cert-manager.\n\tBy(\"Disabling metrics with certs - no supported by packagemanifests\")\n\t// nolint: errcheck\n\tkbutil.CommentCode(filepath.Join(tc.Dir, \"config\", \"default\", \"kustomization.yaml\"), targetMetricsCertFragment, \"#\")\n\n\tBy(\"building the manager image\")\n\tExpect(tc.Make(\"docker-build\", \"IMG=\"+tc.ImageName)).To(Succeed())\n\n\tonKind, err = tc.IsRunningOnKind()\n\tExpect(err).NotTo(HaveOccurred())\n\tif onKind {\n\t\tBy(\"loading the required images into Kind cluster\")\n\t\tExpect(tc.LoadImageToKindCluster()).To(Succeed())\n\t}\n\n\tBy(\"generating the operator package manifests and enabling AllNamespaces InstallMode\")\n\tExpect(tc.Make(\"packagemanifests\", \"IMG=\"+tc.ImageName)).To(Succeed())\n\tcsv, err := readCSV(&tc, \"0.0.1\", false)\n\tExpect(err).NotTo(HaveOccurred())\n\tfor i := range csv.Spec.InstallModes {\n\t\tif csv.Spec.InstallModes[i].Type == \"AllNamespaces\" {\n\t\t\tcsv.Spec.InstallModes[i].Supported = true\n\t\t}\n\t}\n\tExpect(writeCSV(&tc, \"0.0.1\", csv, false)).To(Succeed())\n\n\t// TODO(estroz): enable when bundles can be tested locally.\n\t//\n\t// By(\"generating the operator bundle\")\n\t// err = tc.Make(\"bundle\", \"IMG=\"+tc.ImageName)\n\t// Expect(err).NotTo(HaveOccurred())\n\t//\n\t// By(\"building the operator bundle image\")\n\t// err = tc.Make(\"bundle-build\", \"BUNDLE_IMG=\"+tc.BundleImageName)\n\t// Expect(err).NotTo(HaveOccurred())\n\n\tBy(\"creating the test namespace\")\n\t_, err = tc.Kubectl.Command(\"create\", \"namespace\", tc.Kubectl.Namespace)\n\tExpect(err).NotTo(HaveOccurred())\n})\n\nconst targetMetricsCertFragment = `- path: cert_metrics_manager_patch.yaml\n  target:\n    kind: Deployment`\n\nvar _ = AfterSuite(func() {\n\tBy(\"uninstalling OLM\")\n\ttc.UninstallOLM()\n\n\tBy(\"uninstalling prometheus-operator\")\n\ttc.UninstallPrometheusOperManager()\n\n\tBy(\"deleting the test namespace\")\n\twarn(tc.Kubectl.Delete(false, \"namespace\", tc.Kubectl.Namespace))\n\n\tBy(\"cleaning up the project\")\n\ttc.Destroy()\n})\n\nfunc warn(output string, err error) {\n\tif err != nil {\n\t\tfmt.Fprintf(GinkgoWriter, \"warning: %s\\n%s\", err, output)\n\t}\n}\n\nfunc runPackageManifests(tc *testutils.TestContext, args ...string) error {\n\tallArgs := []string{\"run\", \"packagemanifests\", \"--timeout\", \"6m\", \"--namespace\", tc.Kubectl.Namespace}\n\toutput, err := tc.Run(exec.Command(tc.BinaryName, append(allArgs, args...)...))\n\tif err == nil {\n\t\tfmt.Fprintln(GinkgoWriter, string(output))\n\t}\n\treturn err\n}\n\nfunc cleanup(tc *testutils.TestContext) (string, error) {\n\tallArgs := []string{\"cleanup\", tc.ProjectName, \"--timeout\", \"4m\", \"--namespace\", tc.Kubectl.Namespace}\n\toutput, err := tc.Run(exec.Command(tc.BinaryName, allArgs...))\n\tif err == nil {\n\t\tfmt.Fprintln(GinkgoWriter, string(output))\n\t}\n\treturn string(output), err\n}\n\nfunc readCSV(tc *testutils.TestContext, version string, isBundle bool) (*v1alpha1.ClusterServiceVersion, error) {\n\tb, err := os.ReadFile(csvPath(tc, version, isBundle))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tcsv := &v1alpha1.ClusterServiceVersion{}\n\tif err := yaml.Unmarshal(b, csv); err != nil {\n\t\treturn nil, err\n\t}\n\treturn csv, nil\n}\n\nfunc writeCSV(tc *testutils.TestContext, version string, csv *v1alpha1.ClusterServiceVersion, isBundle bool) error {\n\tb, err := yaml.Marshal(csv)\n\tif err != nil {\n\t\treturn err\n\t}\n\tf, err := os.OpenFile(csvPath(tc, version, isBundle), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif _, err := f.Write(b); err != nil {\n\t\treturn err\n\t}\n\tif err := f.Sync(); err != nil {\n\t\treturn err\n\t}\n\treturn f.Close()\n}\n\nfunc csvPath(tc *testutils.TestContext, version string, isBundle bool) string {\n\tfileName := fmt.Sprintf(\"%s.clusterserviceversion.yaml\", tc.ProjectName)\n\tif isBundle {\n\t\treturn filepath.Join(tc.Dir, \"bundle\", bundle.ManifestsDir, fileName)\n\t}\n\treturn filepath.Join(tc.Dir, \"packagemanifests\", version, fileName)\n}\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/.devcontainer/devcontainer.json",
    "content": "{\n  \"name\": \"Kubebuilder DevContainer\",\n  \"image\": \"golang:1.24\",\n  \"features\": {\n    \"ghcr.io/devcontainers/features/docker-in-docker:2\": {},\n    \"ghcr.io/devcontainers/features/git:1\": {}\n  },\n\n  \"runArgs\": [\"--network=host\"],\n\n  \"customizations\": {\n    \"vscode\": {\n      \"settings\": {\n        \"terminal.integrated.shell.linux\": \"/bin/bash\"\n      },\n      \"extensions\": [\n        \"ms-kubernetes-tools.vscode-kubernetes-tools\",\n        \"ms-azuretools.vscode-docker\"\n      ]\n    }\n  },\n\n  \"onCreateCommand\": \"bash .devcontainer/post-install.sh\"\n}\n\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/.devcontainer/post-install.sh",
    "content": "#!/bin/bash\nset -x\n\ncurl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64\nchmod +x ./kind\nmv ./kind /usr/local/bin/kind\n\ncurl -L -o kubebuilder https://go.kubebuilder.io/dl/latest/linux/amd64\nchmod +x kubebuilder\nmv kubebuilder /usr/local/bin/\n\nKUBECTL_VERSION=$(curl -L -s https://dl.k8s.io/release/stable.txt)\ncurl -LO \"https://dl.k8s.io/release/$KUBECTL_VERSION/bin/linux/amd64/kubectl\"\nchmod +x kubectl\nmv kubectl /usr/local/bin/kubectl\n\ndocker network create -d=bridge --subnet=172.19.0.0/24 kind\n\nkind version\nkubebuilder version\ndocker --version\ngo version\nkubectl version --client\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/.dockerignore",
    "content": "# More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file\n# Ignore build and test binaries.\nbin/\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/.github/workflows/lint.yml",
    "content": "name: Lint\n\non:\n  push:\n  pull_request:\n\njobs:\n  lint:\n    name: Run on Ubuntu\n    runs-on: ubuntu-latest\n    steps:\n      - name: Clone the code\n        uses: actions/checkout@v4\n\n      - name: Setup Go\n        uses: actions/setup-go@v5\n        with:\n          go-version-file: go.mod\n\n      - name: Run linter\n        uses: golangci/golangci-lint-action@v8\n        with:\n          version: v2.1.0\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/.github/workflows/test-e2e.yml",
    "content": "name: E2E Tests\n\non:\n  push:\n  pull_request:\n\njobs:\n  test-e2e:\n    name: Run on Ubuntu\n    runs-on: ubuntu-latest\n    steps:\n      - name: Clone the code\n        uses: actions/checkout@v4\n\n      - name: Setup Go\n        uses: actions/setup-go@v5\n        with:\n          go-version-file: go.mod\n\n      - name: Install the latest version of kind\n        run: |\n          curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64\n          chmod +x ./kind\n          sudo mv ./kind /usr/local/bin/kind\n\n      - name: Verify kind installation\n        run: kind version\n\n      - name: Running Test e2e\n        run: |\n          go mod tidy\n          make test-e2e\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/.github/workflows/test.yml",
    "content": "name: Tests\n\non:\n  push:\n  pull_request:\n\njobs:\n  test:\n    name: Run on Ubuntu\n    runs-on: ubuntu-latest\n    steps:\n      - name: Clone the code\n        uses: actions/checkout@v4\n\n      - name: Setup Go\n        uses: actions/setup-go@v5\n        with:\n          go-version-file: go.mod\n\n      - name: Running Tests\n        run: |\n          go mod tidy\n          make test\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/.gitignore",
    "content": "# Binaries for programs and plugins\n*.exe\n*.exe~\n*.dll\n*.so\n*.dylib\nbin/*\nDockerfile.cross\n\n# Test binary, built with `go test -c`\n*.test\n\n# Output of the go coverage tool, specifically when used with LiteIDE\n*.out\n\n# Go workspace file\ngo.work\n\n# Kubernetes Generated files - skip generated files, except for vendored files\n!vendor/**/zz_generated.*\n\n# editor and IDE paraphernalia\n.idea\n.vscode\n*.swp\n*.swo\n*~\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/.golangci.yml",
    "content": "version: \"2\"\nrun:\n  allow-parallel-runners: true\nlinters:\n  default: none\n  enable:\n    - copyloopvar\n    - dupl\n    - errcheck\n    - ginkgolinter\n    - goconst\n    - gocyclo\n    - govet\n    - ineffassign\n    - lll\n    - misspell\n    - nakedret\n    - prealloc\n    - revive\n    - staticcheck\n    - unconvert\n    - unparam\n    - unused\n  settings:\n    revive:\n      rules:\n        - name: comment-spacings\n        - name: import-shadowing\n  exclusions:\n    generated: lax\n    rules:\n      - linters:\n          - lll\n        path: api/*\n      - linters:\n          - dupl\n          - lll\n        path: internal/*\n    paths:\n      - third_party$\n      - builtin$\n      - examples$\nformatters:\n  enable:\n    - gofmt\n    - goimports\n  exclusions:\n    generated: lax\n    paths:\n      - third_party$\n      - builtin$\n      - examples$\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/Dockerfile",
    "content": "# Build the manager binary\nFROM golang:1.24 AS builder\nARG TARGETOS\nARG TARGETARCH\n\nWORKDIR /workspace\n# Copy the Go Modules manifests\nCOPY go.mod go.mod\nCOPY go.sum go.sum\n# cache deps before building and copying source so that we don't need to re-download as much\n# and so that source changes don't invalidate our downloaded layer\nRUN go mod download\n\n# Copy the go source\nCOPY cmd/main.go cmd/main.go\nCOPY api/ api/\nCOPY internal/ internal/\n\n# Build\n# the GOARCH has not a default value to allow the binary be built according to the host where the command\n# was called. For example, if we call make docker-build in a local env which has the Apple Silicon M1 SO\n# the docker BUILDPLATFORM arg will be linux/arm64 when for Apple x86 it will be linux/amd64. Therefore,\n# by leaving it empty we can ensure that the container and binary shipped on it will have the same platform.\nRUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o manager cmd/main.go\n\n# Use distroless as minimal base image to package the manager binary\n# Refer to https://github.com/GoogleContainerTools/distroless for more details\nFROM gcr.io/distroless/static:nonroot\nWORKDIR /\nCOPY --from=builder /workspace/manager .\nUSER 65532:65532\n\nENTRYPOINT [\"/manager\"]\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/Makefile",
    "content": "# VERSION defines the project version for the bundle.\n# Update this value when you upgrade the version of your project.\n# To re-generate a bundle for another specific version without changing the standard setup, you can:\n# - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2)\n# - use environment variables to overwrite this value (e.g export VERSION=0.0.2)\nVERSION ?= 0.0.1\n\n# CHANNELS define the bundle channels used in the bundle.\n# Add a new line here if you would like to change its default config. (E.g CHANNELS = \"candidate,fast,stable\")\n# To re-generate a bundle for other specific channels without changing the standard setup, you can:\n# - use the CHANNELS as arg of the bundle target (e.g make bundle CHANNELS=candidate,fast,stable)\n# - use environment variables to overwrite this value (e.g export CHANNELS=\"candidate,fast,stable\")\nifneq ($(origin CHANNELS), undefined)\nBUNDLE_CHANNELS := --channels=$(CHANNELS)\nendif\n\n# DEFAULT_CHANNEL defines the default channel used in the bundle.\n# Add a new line here if you would like to change its default config. (E.g DEFAULT_CHANNEL = \"stable\")\n# To re-generate a bundle for any other default channel without changing the default setup, you can:\n# - use the DEFAULT_CHANNEL as arg of the bundle target (e.g make bundle DEFAULT_CHANNEL=stable)\n# - use environment variables to overwrite this value (e.g export DEFAULT_CHANNEL=\"stable\")\nifneq ($(origin DEFAULT_CHANNEL), undefined)\nBUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL)\nendif\nBUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL)\n\n# IMAGE_TAG_BASE defines the docker.io namespace and part of the image name for remote images.\n# This variable is used to construct full image tags for bundle and catalog images.\n#\n# For example, running 'make bundle-build bundle-push catalog-build catalog-push' will build and push both\n# example.com/memcached-operator-bundle:$VERSION and example.com/memcached-operator-catalog:$VERSION.\nIMAGE_TAG_BASE ?= example.com/memcached-operator\n\n# BUNDLE_IMG defines the image:tag used for the bundle.\n# You can use it as an arg. (E.g make bundle-build BUNDLE_IMG=<some-registry>/<project-name-bundle>:<tag>)\nBUNDLE_IMG ?= $(IMAGE_TAG_BASE)-bundle:v$(VERSION)\n\n# BUNDLE_GEN_FLAGS are the flags passed to the operator-sdk generate bundle command\nBUNDLE_GEN_FLAGS ?= -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS)\n\n# USE_IMAGE_DIGESTS defines if images are resolved via tags or digests\n# You can enable this value if you would like to use SHA Based Digests\n# To enable set flag to true\nUSE_IMAGE_DIGESTS ?= false\nifeq ($(USE_IMAGE_DIGESTS), true)\n\tBUNDLE_GEN_FLAGS += --use-image-digests\nendif\n\n# Set the Operator SDK version to use. By default, what is installed on the system is used.\n# This is useful for CI or a project to utilize a specific version of the operator-sdk toolkit.\nOPERATOR_SDK_VERSION ?= v1.42.2\n# Image URL to use all building/pushing image targets\nIMG ?= controller:latest\n\n# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)\nifeq (,$(shell go env GOBIN))\nGOBIN=$(shell go env GOPATH)/bin\nelse\nGOBIN=$(shell go env GOBIN)\nendif\n\n# CONTAINER_TOOL defines the container tool to be used for building images.\n# Be aware that the target commands are only tested with Docker which is\n# scaffolded by default. However, you might want to replace it to use other\n# tools. (i.e. podman)\nCONTAINER_TOOL ?= docker\n\n# Setting SHELL to bash allows bash commands to be executed by recipes.\n# Options are set to exit when a recipe line exits non-zero or a piped command fails.\nSHELL = /usr/bin/env bash -o pipefail\n.SHELLFLAGS = -ec\n\n.PHONY: all\nall: build\n\n##@ General\n\n# The help target prints out all targets with their descriptions organized\n# beneath their categories. The categories are represented by '##@' and the\n# target descriptions by '##'. The awk command is responsible for reading the\n# entire set of makefiles included in this invocation, looking for lines of the\n# file as xyz: ## something, and then pretty-format the target and help. Then,\n# if there's a line with ##@ something, that gets pretty-printed as a category.\n# More info on the usage of ANSI control characters for terminal formatting:\n# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters\n# More info on the awk command:\n# http://linuxcommand.org/lc3_adv_awk.php\n\n.PHONY: help\nhelp: ## Display this help.\n\t@awk 'BEGIN {FS = \":.*##\"; printf \"\\nUsage:\\n  make \\033[36m<target>\\033[0m\\n\"} /^[a-zA-Z_0-9-]+:.*?##/ { printf \"  \\033[36m%-15s\\033[0m %s\\n\", $$1, $$2 } /^##@/ { printf \"\\n\\033[1m%s\\033[0m\\n\", substr($$0, 5) } ' $(MAKEFILE_LIST)\n\n##@ Development\n\n.PHONY: manifests\nmanifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.\n\t$(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths=\"./...\" output:crd:artifacts:config=config/crd/bases\n\n.PHONY: generate\ngenerate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.\n\t$(CONTROLLER_GEN) object:headerFile=\"hack/boilerplate.go.txt\" paths=\"./...\"\n\n.PHONY: fmt\nfmt: ## Run go fmt against code.\n\tgo fmt ./...\n\n.PHONY: vet\nvet: ## Run go vet against code.\n\tgo vet ./...\n\n.PHONY: test\ntest: manifests generate fmt vet setup-envtest ## Run tests.\n\tKUBEBUILDER_ASSETS=\"$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)\"  go test $(shell go list ./... | grep -v /test/) -coverprofile cover.out\n\n# TODO(user): To use a different vendor for e2e tests, modify the setup under 'tests/e2e'.\n# The default setup assumes Kind is pre-installed and builds/loads the Manager Docker image locally.\n# CertManager is installed by default; skip with:\n# - CERT_MANAGER_INSTALL_SKIP=true\nKIND_CLUSTER ?= memcached-operator-test-e2e\n\n.PHONY: setup-test-e2e\nsetup-test-e2e: ## Set up a Kind cluster for e2e tests if it does not exist\n\t@command -v $(KIND) >/dev/null 2>&1 || { \\\n\t\techo \"Kind is not installed. Please install Kind manually.\"; \\\n\t\texit 1; \\\n\t}\n\t@case \"$$($(KIND) get clusters)\" in \\\n\t\t*\"$(KIND_CLUSTER)\"*) \\\n\t\t\techo \"Kind cluster '$(KIND_CLUSTER)' already exists. Skipping creation.\" ;; \\\n\t\t*) \\\n\t\t\techo \"Creating Kind cluster '$(KIND_CLUSTER)'...\"; \\\n\t\t\t$(KIND) create cluster --name $(KIND_CLUSTER) ;; \\\n\tesac\n\n.PHONY: test-e2e\ntest-e2e: setup-test-e2e manifests generate fmt vet ## Run the e2e tests. Expected an isolated environment using Kind.\n\tKIND_CLUSTER=$(KIND_CLUSTER) go test ./test/e2e/ -v -ginkgo.v\n\t$(MAKE) cleanup-test-e2e\n\n.PHONY: cleanup-test-e2e\ncleanup-test-e2e: ## Tear down the Kind cluster used for e2e tests\n\t@$(KIND) delete cluster --name $(KIND_CLUSTER)\n\n.PHONY: lint\nlint: golangci-lint ## Run golangci-lint linter\n\t$(GOLANGCI_LINT) run\n\n.PHONY: lint-fix\nlint-fix: golangci-lint ## Run golangci-lint linter and perform fixes\n\t$(GOLANGCI_LINT) run --fix\n\n.PHONY: lint-config\nlint-config: golangci-lint ## Verify golangci-lint linter configuration\n\t$(GOLANGCI_LINT) config verify\n\n##@ Build\n\n.PHONY: build\nbuild: manifests generate fmt vet ## Build manager binary.\n\tgo build -o bin/manager cmd/main.go\n\n.PHONY: run\nrun: manifests generate fmt vet ## Run a controller from your host.\n\tgo run ./cmd/main.go\n\n# If you wish to build the manager image targeting other platforms you can use the --platform flag.\n# (i.e. docker build --platform linux/arm64). However, you must enable docker buildKit for it.\n# More info: https://docs.docker.com/develop/develop-images/build_enhancements/\n.PHONY: docker-build\ndocker-build: ## Build docker image with the manager.\n\t$(CONTAINER_TOOL) build -t ${IMG} .\n\n.PHONY: docker-push\ndocker-push: ## Push docker image with the manager.\n\t$(CONTAINER_TOOL) push ${IMG}\n\n# PLATFORMS defines the target platforms for the manager image be built to provide support to multiple\n# architectures. (i.e. make docker-buildx IMG=myregistry/mypoperator:0.0.1). To use this option you need to:\n# - be able to use docker buildx. More info: https://docs.docker.com/build/buildx/\n# - have enabled BuildKit. More info: https://docs.docker.com/develop/develop-images/build_enhancements/\n# - be able to push the image to your registry (i.e. if you do not set a valid value via IMG=<myregistry/image:<tag>> then the export will fail)\n# To adequately provide solutions that are compatible with multiple platforms, you should consider using this option.\nPLATFORMS ?= linux/arm64,linux/amd64,linux/s390x,linux/ppc64le\n.PHONY: docker-buildx\ndocker-buildx: ## Build and push docker image for the manager for cross-platform support\n\t# copy existing Dockerfile and insert --platform=${BUILDPLATFORM} into Dockerfile.cross, and preserve the original Dockerfile\n\tsed -e '1 s/\\(^FROM\\)/FROM --platform=\\$$\\{BUILDPLATFORM\\}/; t' -e ' 1,// s//FROM --platform=\\$$\\{BUILDPLATFORM\\}/' Dockerfile > Dockerfile.cross\n\t- $(CONTAINER_TOOL) buildx create --name memcached-operator-builder\n\t$(CONTAINER_TOOL) buildx use memcached-operator-builder\n\t- $(CONTAINER_TOOL) buildx build --push --platform=$(PLATFORMS) --tag ${IMG} -f Dockerfile.cross .\n\t- $(CONTAINER_TOOL) buildx rm memcached-operator-builder\n\trm Dockerfile.cross\n\n.PHONY: build-installer\nbuild-installer: manifests generate kustomize ## Generate a consolidated YAML with CRDs and deployment.\n\tmkdir -p dist\n\tcd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}\n\t$(KUSTOMIZE) build config/default > dist/install.yaml\n\n##@ Deployment\n\nifndef ignore-not-found\n  ignore-not-found = false\nendif\n\n.PHONY: install\ninstall: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config.\n\t$(KUSTOMIZE) build config/crd | $(KUBECTL) apply -f -\n\n.PHONY: uninstall\nuninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.\n\t$(KUSTOMIZE) build config/crd | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f -\n\n.PHONY: deploy\ndeploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.\n\tcd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}\n\t$(KUSTOMIZE) build config/default | $(KUBECTL) apply -f -\n\n.PHONY: undeploy\nundeploy: kustomize ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.\n\t$(KUSTOMIZE) build config/default | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f -\n\n##@ Dependencies\n\n## Location to install dependencies to\nLOCALBIN ?= $(shell pwd)/bin\n$(LOCALBIN):\n\tmkdir -p $(LOCALBIN)\n\n## Tool Binaries\nKUBECTL ?= kubectl\nKIND ?= kind\nKUSTOMIZE ?= $(LOCALBIN)/kustomize\nCONTROLLER_GEN ?= $(LOCALBIN)/controller-gen\nENVTEST ?= $(LOCALBIN)/setup-envtest\nGOLANGCI_LINT = $(LOCALBIN)/golangci-lint\n\n## Tool Versions\nKUSTOMIZE_VERSION ?= v5.6.0\nCONTROLLER_TOOLS_VERSION ?= v0.18.0\n#ENVTEST_VERSION is the version of controller-runtime release branch to fetch the envtest setup script (i.e. release-0.20)\nENVTEST_VERSION ?= $(shell go list -m -f \"{{ .Version }}\" sigs.k8s.io/controller-runtime | awk -F'[v.]' '{printf \"release-%d.%d\", $$2, $$3}')\n#ENVTEST_K8S_VERSION is the version of Kubernetes to use for setting up ENVTEST binaries (i.e. 1.31)\nENVTEST_K8S_VERSION ?= $(shell go list -m -f \"{{ .Version }}\" k8s.io/api | awk -F'[v.]' '{printf \"1.%d\", $$3}')\nGOLANGCI_LINT_VERSION ?= v2.1.0\n\n.PHONY: kustomize\nkustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary.\n$(KUSTOMIZE): $(LOCALBIN)\n\t$(call go-install-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v5,$(KUSTOMIZE_VERSION))\n\n.PHONY: controller-gen\ncontroller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary.\n$(CONTROLLER_GEN): $(LOCALBIN)\n\t$(call go-install-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen,$(CONTROLLER_TOOLS_VERSION))\n\n.PHONY: setup-envtest\nsetup-envtest: envtest ## Download the binaries required for ENVTEST in the local bin directory.\n\t@echo \"Setting up envtest binaries for Kubernetes version $(ENVTEST_K8S_VERSION)...\"\n\t@$(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path || { \\\n\t\techo \"Error: Failed to set up envtest binaries for version $(ENVTEST_K8S_VERSION).\"; \\\n\t\texit 1; \\\n\t}\n\n.PHONY: envtest\nenvtest: $(ENVTEST) ## Download setup-envtest locally if necessary.\n$(ENVTEST): $(LOCALBIN)\n\t$(call go-install-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest,$(ENVTEST_VERSION))\n\n.PHONY: golangci-lint\ngolangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary.\n$(GOLANGCI_LINT): $(LOCALBIN)\n\t$(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/v2/cmd/golangci-lint,$(GOLANGCI_LINT_VERSION))\n\n# go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist\n# $1 - target path with name of binary\n# $2 - package url which can be installed\n# $3 - specific version of package\ndefine go-install-tool\n@[ -f \"$(1)-$(3)\" ] || { \\\nset -e; \\\npackage=$(2)@$(3) ;\\\necho \"Downloading $${package}\" ;\\\nrm -f $(1) || true ;\\\nGOBIN=$(LOCALBIN) go install $${package} ;\\\nmv $(1) $(1)-$(3) ;\\\n} ;\\\nln -sf $(1)-$(3) $(1)\nendef\n\n.PHONY: operator-sdk\nOPERATOR_SDK ?= $(LOCALBIN)/operator-sdk\noperator-sdk: ## Download operator-sdk locally if necessary.\nifeq (,$(wildcard $(OPERATOR_SDK)))\nifeq (, $(shell which operator-sdk 2>/dev/null))\n\t@{ \\\n\tset -e ;\\\n\tmkdir -p $(dir $(OPERATOR_SDK)) ;\\\n\tOS=$(shell go env GOOS) && ARCH=$(shell go env GOARCH) && \\\n\tcurl -sSLo $(OPERATOR_SDK) https://github.com/operator-framework/operator-sdk/releases/download/$(OPERATOR_SDK_VERSION)/operator-sdk_$${OS}_$${ARCH} ;\\\n\tchmod +x $(OPERATOR_SDK) ;\\\n\t}\nelse\nOPERATOR_SDK = $(shell which operator-sdk)\nendif\nendif\n\n.PHONY: bundle\nbundle: manifests kustomize operator-sdk ## Generate bundle manifests and metadata, then validate generated files.\n\t$(OPERATOR_SDK) generate kustomize manifests --interactive=false -q\n\tcd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG)\n\t$(KUSTOMIZE) build config/manifests | $(OPERATOR_SDK) generate bundle $(BUNDLE_GEN_FLAGS)\n\t$(OPERATOR_SDK) bundle validate ./bundle\n\n.PHONY: bundle-build\nbundle-build: ## Build the bundle image.\n\t$(CONTAINER_TOOL) build -f bundle.Dockerfile -t $(BUNDLE_IMG) .\n\n.PHONY: bundle-push\nbundle-push: ## Push the bundle image.\n\t$(MAKE) docker-push IMG=$(BUNDLE_IMG)\n\n.PHONY: opm\nOPM = $(LOCALBIN)/opm\nopm: ## Download opm locally if necessary.\nifeq (,$(wildcard $(OPM)))\nifeq (,$(shell which opm 2>/dev/null))\n\t@{ \\\n\tset -e ;\\\n\tmkdir -p $(dir $(OPM)) ;\\\n\tOS=$(shell go env GOOS) && ARCH=$(shell go env GOARCH) && \\\n\tcurl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/v1.55.0/$${OS}-$${ARCH}-opm ;\\\n\tchmod +x $(OPM) ;\\\n\t}\nelse\nOPM = $(shell which opm)\nendif\nendif\n\n# A comma-separated list of bundle images (e.g. make catalog-build BUNDLE_IMGS=example.com/operator-bundle:v0.1.0,example.com/operator-bundle:v0.2.0).\n# These images MUST exist in a registry and be pull-able.\nBUNDLE_IMGS ?= $(BUNDLE_IMG)\n\n# The image tag given to the resulting catalog image (e.g. make catalog-build CATALOG_IMG=example.com/operator-catalog:v0.2.0).\nCATALOG_IMG ?= $(IMAGE_TAG_BASE)-catalog:v$(VERSION)\n\n# Set CATALOG_BASE_IMG to an existing catalog image tag to add $BUNDLE_IMGS to that image.\nifneq ($(origin CATALOG_BASE_IMG), undefined)\nFROM_INDEX_OPT := --from-index $(CATALOG_BASE_IMG)\nendif\n\n# Build a catalog image by adding bundle images to an empty catalog using the operator package manager tool, 'opm'.\n# This recipe invokes 'opm' in 'semver' bundle add mode. For more information on add modes, see:\n# https://github.com/operator-framework/community-operators/blob/7f1438c/docs/packaging-operator.md#updating-your-existing-operator\n.PHONY: catalog-build\ncatalog-build: opm ## Build a catalog image.\n\t$(OPM) index add --container-tool $(CONTAINER_TOOL) --mode semver --tag $(CATALOG_IMG) --bundles $(BUNDLE_IMGS) $(FROM_INDEX_OPT)\n\n# Push the catalog image.\n.PHONY: catalog-push\ncatalog-push: ## Push a catalog image.\n\t$(MAKE) docker-push IMG=$(CATALOG_IMG)\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/PROJECT",
    "content": "# Code generated by tool. DO NOT EDIT.\n# This file is used to track the info used to scaffold your project\n# and allow the plugins properly work.\n# More info: https://book.kubebuilder.io/reference/project-config.html\ndomain: example.com\nlayout:\n- go.kubebuilder.io/v4\nplugins:\n  deploy-image.go.kubebuilder.io/v1-alpha:\n    resources:\n    - domain: example.com\n      group: cache\n      kind: Memcached\n      options:\n        containerCommand: memcached,-m=64,-o,modern,-v\n        containerPort: \"11211\"\n        image: memcached:1.4.36-alpine\n        runAsUser: \"1001\"\n      version: v1alpha1\n  manifests.sdk.operatorframework.io/v2: {}\n  scorecard.sdk.operatorframework.io/v2: {}\nprojectName: memcached-operator\nrepo: github.com/example/memcached-operator\nresources:\n- api:\n    crdVersion: v1\n    namespaced: true\n  controller: true\n  domain: example.com\n  group: cache\n  kind: Memcached\n  path: github.com/example/memcached-operator/api/v1alpha1\n  version: v1alpha1\n  webhooks:\n    defaulting: true\n    webhookVersion: v1\nversion: \"3\"\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/README.md",
    "content": "# memcached-operator\n// TODO(user): Add simple overview of use/purpose\n\n## Description\n// TODO(user): An in-depth paragraph about your project and overview of use\n\n## Getting Started\n\n### Prerequisites\n- go version v1.24.0+\n- docker version 17.03+.\n- kubectl version v1.11.3+.\n- Access to a Kubernetes v1.11.3+ cluster.\n\n### To Deploy on the cluster\n**Build and push your image to the location specified by `IMG`:**\n\n```sh\nmake docker-build docker-push IMG=<some-registry>/memcached-operator:tag\n```\n\n**NOTE:** This image ought to be published in the personal registry you specified.\nAnd it is required to have access to pull the image from the working environment.\nMake sure you have the proper permission to the registry if the above commands don’t work.\n\n**Install the CRDs into the cluster:**\n\n```sh\nmake install\n```\n\n**Deploy the Manager to the cluster with the image specified by `IMG`:**\n\n```sh\nmake deploy IMG=<some-registry>/memcached-operator:tag\n```\n\n> **NOTE**: If you encounter RBAC errors, you may need to grant yourself cluster-admin\nprivileges or be logged in as admin.\n\n**Create instances of your solution**\nYou can apply the samples (examples) from the config/sample:\n\n```sh\nkubectl apply -k config/samples/\n```\n\n>**NOTE**: Ensure that the samples has default values to test it out.\n\n### To Uninstall\n**Delete the instances (CRs) from the cluster:**\n\n```sh\nkubectl delete -k config/samples/\n```\n\n**Delete the APIs(CRDs) from the cluster:**\n\n```sh\nmake uninstall\n```\n\n**UnDeploy the controller from the cluster:**\n\n```sh\nmake undeploy\n```\n\n## Project Distribution\n\nFollowing the options to release and provide this solution to the users.\n\n### By providing a bundle with all YAML files\n\n1. Build the installer for the image built and published in the registry:\n\n```sh\nmake build-installer IMG=<some-registry>/memcached-operator:tag\n```\n\n**NOTE:** The makefile target mentioned above generates an 'install.yaml'\nfile in the dist directory. This file contains all the resources built\nwith Kustomize, which are necessary to install this project without its\ndependencies.\n\n2. Using the installer\n\nUsers can just run 'kubectl apply -f <URL for YAML BUNDLE>' to install\nthe project, i.e.:\n\n```sh\nkubectl apply -f https://raw.githubusercontent.com/<org>/memcached-operator/<tag or branch>/dist/install.yaml\n```\n\n### By providing a Helm Chart\n\n1. Build the chart using the optional helm plugin\n\n```sh\noperator-sdk edit --plugins=helm/v1-alpha\n```\n\n2. See that a chart was generated under 'dist/chart', and users\ncan obtain this solution from there.\n\n**NOTE:** If you change the project, you need to update the Helm Chart\nusing the same command above to sync the latest changes. Furthermore,\nif you create webhooks, you need to use the above command with\nthe '--force' flag and manually ensure that any custom configuration\npreviously added to 'dist/chart/values.yaml' or 'dist/chart/manager/manager.yaml'\nis manually re-applied afterwards.\n\n## Contributing\n// TODO(user): Add detailed information on how you would like others to contribute to this project\n\n**NOTE:** Run `make help` for more information on all potential `make` targets\n\nMore information can be found via the [Kubebuilder Documentation](https://book.kubebuilder.io/introduction.html)\n\n## License\n\nCopyright 2026.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/api/v1alpha1/groupversion_info.go",
    "content": "/*\nCopyright 2026.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\n// Package v1alpha1 contains API Schema definitions for the cache v1alpha1 API group.\n// +kubebuilder:object:generate=true\n// +groupName=cache.example.com\npackage v1alpha1\n\nimport (\n\t\"k8s.io/apimachinery/pkg/runtime/schema\"\n\t\"sigs.k8s.io/controller-runtime/pkg/scheme\"\n)\n\nvar (\n\t// GroupVersion is group version used to register these objects.\n\tGroupVersion = schema.GroupVersion{Group: \"cache.example.com\", Version: \"v1alpha1\"}\n\n\t// SchemeBuilder is used to add go types to the GroupVersionKind scheme.\n\tSchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}\n\n\t// AddToScheme adds the types in this group-version to the given scheme.\n\tAddToScheme = SchemeBuilder.AddToScheme\n)\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/api/v1alpha1/memcached_types.go",
    "content": "/*\nCopyright 2026.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage v1alpha1\n\nimport (\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n)\n\n// EDIT THIS FILE!  THIS IS SCAFFOLDING FOR YOU TO OWN!\n// NOTE: json tags are required.  Any new fields you add must have json tags for the fields to be serialized.\n\n// MemcachedSpec defines the desired state of Memcached\ntype MemcachedSpec struct {\n\t// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster\n\t// Important: Run \"make\" to regenerate code after modifying this file\n\n\t// The following markers will use OpenAPI v3 schema to validate the value\n\t// More info: https://book.kubebuilder.io/reference/markers/crd-validation.html\n\t// +kubebuilder:validation:Minimum=1\n\t// +kubebuilder:validation:Maximum=3\n\t// +kubebuilder:validation:ExclusiveMaximum=false\n\n\t// Size defines the number of Memcached instances\n\t// +operator-sdk:csv:customresourcedefinitions:type=spec\n\tSize int32 `json:\"size,omitempty\"`\n\n\t// Port defines the port that will be used to init the container with the image\n\t// +operator-sdk:csv:customresourcedefinitions:type=spec\n\tContainerPort int32 `json:\"containerPort,omitempty\"`\n}\n\n// MemcachedStatus defines the observed state of Memcached\ntype MemcachedStatus struct {\n\t// Represents the observations of a Memcached's current state.\n\t// Memcached.status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\"\n\t// Memcached.status.conditions.status are one of True, False, Unknown.\n\t// Memcached.status.conditions.reason the value should be a CamelCase string and producers of specific\n\t// condition types may define expected values and meanings for this field, and whether the values\n\t// are considered a guaranteed API.\n\t// Memcached.status.conditions.Message is a human readable message indicating details about the transition.\n\t// For further information see: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties\n\n\t// Conditions store the status conditions of the Memcached instances\n\t// +operator-sdk:csv:customresourcedefinitions:type=status\n\tConditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n}\n\n// +kubebuilder:object:root=true\n// +kubebuilder:subresource:status\n// +operator-sdk:csv:customresourcedefinitions:resources={{Deployment,v1,memcached-deployment}}\n\n// Memcached is the Schema for the memcacheds API\ntype Memcached struct {\n\tmetav1.TypeMeta   `json:\",inline\"`\n\tmetav1.ObjectMeta `json:\"metadata,omitempty\"`\n\n\tSpec   MemcachedSpec   `json:\"spec,omitempty\"`\n\tStatus MemcachedStatus `json:\"status,omitempty\"`\n}\n\n// +kubebuilder:object:root=true\n\n// MemcachedList contains a list of Memcached\ntype MemcachedList struct {\n\tmetav1.TypeMeta `json:\",inline\"`\n\tmetav1.ListMeta `json:\"metadata,omitempty\"`\n\tItems           []Memcached `json:\"items\"`\n}\n\nfunc init() {\n\tSchemeBuilder.Register(&Memcached{}, &MemcachedList{})\n}\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go",
    "content": "//go:build !ignore_autogenerated\n\n/*\nCopyright 2026.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\n// Code generated by controller-gen. DO NOT EDIT.\n\npackage v1alpha1\n\nimport (\n\t\"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\truntime \"k8s.io/apimachinery/pkg/runtime\"\n)\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *Memcached) DeepCopyInto(out *Memcached) {\n\t*out = *in\n\tout.TypeMeta = in.TypeMeta\n\tin.ObjectMeta.DeepCopyInto(&out.ObjectMeta)\n\tout.Spec = in.Spec\n\tin.Status.DeepCopyInto(&out.Status)\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Memcached.\nfunc (in *Memcached) DeepCopy() *Memcached {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(Memcached)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.\nfunc (in *Memcached) DeepCopyObject() runtime.Object {\n\tif c := in.DeepCopy(); c != nil {\n\t\treturn c\n\t}\n\treturn nil\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *MemcachedList) DeepCopyInto(out *MemcachedList) {\n\t*out = *in\n\tout.TypeMeta = in.TypeMeta\n\tin.ListMeta.DeepCopyInto(&out.ListMeta)\n\tif in.Items != nil {\n\t\tin, out := &in.Items, &out.Items\n\t\t*out = make([]Memcached, len(*in))\n\t\tfor i := range *in {\n\t\t\t(*in)[i].DeepCopyInto(&(*out)[i])\n\t\t}\n\t}\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MemcachedList.\nfunc (in *MemcachedList) DeepCopy() *MemcachedList {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(MemcachedList)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.\nfunc (in *MemcachedList) DeepCopyObject() runtime.Object {\n\tif c := in.DeepCopy(); c != nil {\n\t\treturn c\n\t}\n\treturn nil\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *MemcachedSpec) DeepCopyInto(out *MemcachedSpec) {\n\t*out = *in\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MemcachedSpec.\nfunc (in *MemcachedSpec) DeepCopy() *MemcachedSpec {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(MemcachedSpec)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *MemcachedStatus) DeepCopyInto(out *MemcachedStatus) {\n\t*out = *in\n\tif in.Conditions != nil {\n\t\tin, out := &in.Conditions, &out.Conditions\n\t\t*out = make([]v1.Condition, len(*in))\n\t\tfor i := range *in {\n\t\t\t(*in)[i].DeepCopyInto(&(*out)[i])\n\t\t}\n\t}\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MemcachedStatus.\nfunc (in *MemcachedStatus) DeepCopy() *MemcachedStatus {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(MemcachedStatus)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/bundle/manifests/cache.example.com_memcacheds.yaml",
    "content": "apiVersion: apiextensions.k8s.io/v1\nkind: CustomResourceDefinition\nmetadata:\n  annotations:\n    controller-gen.kubebuilder.io/version: v0.18.0\n  creationTimestamp: null\n  name: memcacheds.cache.example.com\nspec:\n  group: cache.example.com\n  names:\n    kind: Memcached\n    listKind: MemcachedList\n    plural: memcacheds\n    singular: memcached\n  scope: Namespaced\n  versions:\n  - name: v1alpha1\n    schema:\n      openAPIV3Schema:\n        description: Memcached is the Schema for the memcacheds API\n        properties:\n          apiVersion:\n            description: |-\n              APIVersion defines the versioned schema of this representation of an object.\n              Servers should convert recognized schemas to the latest internal value, and\n              may reject unrecognized values.\n              More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources\n            type: string\n          kind:\n            description: |-\n              Kind is a string value representing the REST resource this object represents.\n              Servers may infer this from the endpoint the client submits requests to.\n              Cannot be updated.\n              In CamelCase.\n              More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds\n            type: string\n          metadata:\n            type: object\n          spec:\n            description: MemcachedSpec defines the desired state of Memcached\n            properties:\n              containerPort:\n                description: Port defines the port that will be used to init the container\n                  with the image\n                format: int32\n                type: integer\n              size:\n                description: Size defines the number of Memcached instances\n                format: int32\n                maximum: 3\n                minimum: 1\n                type: integer\n            type: object\n          status:\n            description: MemcachedStatus defines the observed state of Memcached\n            properties:\n              conditions:\n                description: Conditions store the status conditions of the Memcached\n                  instances\n                items:\n                  description: Condition contains details for one aspect of the current\n                    state of this API Resource.\n                  properties:\n                    lastTransitionTime:\n                      description: |-\n                        lastTransitionTime is the last time the condition transitioned from one status to another.\n                        This should be when the underlying condition changed.  If that is not known, then using the time when the API field changed is acceptable.\n                      format: date-time\n                      type: string\n                    message:\n                      description: |-\n                        message is a human readable message indicating details about the transition.\n                        This may be an empty string.\n                      maxLength: 32768\n                      type: string\n                    observedGeneration:\n                      description: |-\n                        observedGeneration represents the .metadata.generation that the condition was set based upon.\n                        For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date\n                        with respect to the current state of the instance.\n                      format: int64\n                      minimum: 0\n                      type: integer\n                    reason:\n                      description: |-\n                        reason contains a programmatic identifier indicating the reason for the condition's last transition.\n                        Producers of specific condition types may define expected values and meanings for this field,\n                        and whether the values are considered a guaranteed API.\n                        The value should be a CamelCase string.\n                        This field may not be empty.\n                      maxLength: 1024\n                      minLength: 1\n                      pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$\n                      type: string\n                    status:\n                      description: status of the condition, one of True, False, Unknown.\n                      enum:\n                      - \"True\"\n                      - \"False\"\n                      - Unknown\n                      type: string\n                    type:\n                      description: type of condition in CamelCase or in foo.example.com/CamelCase.\n                      maxLength: 316\n                      pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$\n                      type: string\n                  required:\n                  - lastTransitionTime\n                  - message\n                  - reason\n                  - status\n                  - type\n                  type: object\n                type: array\n            type: object\n        type: object\n    served: true\n    storage: true\n    subresources:\n      status: {}\nstatus:\n  acceptedNames:\n    kind: \"\"\n    plural: \"\"\n  conditions: null\n  storedVersions: null\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-monitor_monitoring.coreos.com_v1_servicemonitor.yaml",
    "content": "apiVersion: monitoring.coreos.com/v1\nkind: ServiceMonitor\nmetadata:\n  labels:\n    app.kubernetes.io/managed-by: kustomize\n    app.kubernetes.io/name: memcached-operator\n    control-plane: controller-manager\n  name: memcached-operator-controller-manager-metrics-monitor\nspec:\n  endpoints:\n  - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token\n    path: /metrics\n    port: https\n    scheme: https\n    tlsConfig:\n      insecureSkipVerify: true\n      serverName: memcached-operator-controller-manager-metrics-service.memcached-operator-system\n  selector:\n    matchLabels:\n      app.kubernetes.io/name: memcached-operator\n      control-plane: controller-manager\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-service_v1_service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  creationTimestamp: null\n  labels:\n    app.kubernetes.io/managed-by: kustomize\n    app.kubernetes.io/name: memcached-operator\n    control-plane: controller-manager\n  name: memcached-operator-controller-manager-metrics-service\nspec:\n  ports:\n  - name: https\n    port: 8443\n    protocol: TCP\n    targetPort: 8443\n  selector:\n    app.kubernetes.io/name: memcached-operator\n    control-plane: controller-manager\nstatus:\n  loadBalancer: {}\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/bundle/manifests/memcached-operator-memcached-admin-role_rbac.authorization.k8s.io_v1_clusterrole.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  creationTimestamp: null\n  labels:\n    app.kubernetes.io/managed-by: kustomize\n    app.kubernetes.io/name: memcached-operator\n  name: memcached-operator-memcached-admin-role\nrules:\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds\n  verbs:\n  - '*'\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds/status\n  verbs:\n  - get\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/bundle/manifests/memcached-operator-memcached-editor-role_rbac.authorization.k8s.io_v1_clusterrole.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  creationTimestamp: null\n  labels:\n    app.kubernetes.io/managed-by: kustomize\n    app.kubernetes.io/name: memcached-operator\n  name: memcached-operator-memcached-editor-role\nrules:\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds/status\n  verbs:\n  - get\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/bundle/manifests/memcached-operator-memcached-viewer-role_rbac.authorization.k8s.io_v1_clusterrole.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  creationTimestamp: null\n  labels:\n    app.kubernetes.io/managed-by: kustomize\n    app.kubernetes.io/name: memcached-operator\n  name: memcached-operator-memcached-viewer-role\nrules:\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds\n  verbs:\n  - get\n  - list\n  - watch\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds/status\n  verbs:\n  - get\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/bundle/manifests/memcached-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  creationTimestamp: null\n  name: memcached-operator-metrics-reader\nrules:\n- nonResourceURLs:\n  - /metrics\n  verbs:\n  - get\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/bundle/manifests/memcached-operator-webhook-service_v1_service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  creationTimestamp: null\n  labels:\n    app.kubernetes.io/managed-by: kustomize\n    app.kubernetes.io/name: memcached-operator\n  name: memcached-operator-webhook-service\nspec:\n  ports:\n  - port: 443\n    protocol: TCP\n    targetPort: 9443\n  selector:\n    app.kubernetes.io/name: memcached-operator\n    control-plane: controller-manager\nstatus:\n  loadBalancer: {}\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml",
    "content": "apiVersion: operators.coreos.com/v1alpha1\nkind: ClusterServiceVersion\nmetadata:\n  annotations:\n    alm-examples: |-\n      [\n        {\n          \"apiVersion\": \"cache.example.com/v1alpha1\",\n          \"kind\": \"Memcached\",\n          \"metadata\": {\n            \"labels\": {\n              \"app.kubernetes.io/managed-by\": \"kustomize\",\n              \"app.kubernetes.io/name\": \"memcached-operator\"\n            },\n            \"name\": \"memcached-sample\"\n          },\n          \"spec\": {\n            \"containerPort\": 11211,\n            \"size\": 1\n          }\n        }\n      ]\n    capabilities: Basic Install\n    createdAt: \"2022-11-08T17:26:37Z\"\n  name: memcached-operator.v0.0.1\n  namespace: placeholder\nspec:\n  apiservicedefinitions: {}\n  customresourcedefinitions:\n    owned:\n    - description: Memcached is the Schema for the memcacheds API\n      displayName: Memcached\n      kind: Memcached\n      name: memcacheds.cache.example.com\n      resources:\n      - kind: Deployment\n        name: memcached-deployment\n        version: v1\n      specDescriptors:\n      - description: Port defines the port that will be used to init the container\n          with the image\n        displayName: Container Port\n        path: containerPort\n      - description: Size defines the number of Memcached instances\n        displayName: Size\n        path: size\n      statusDescriptors:\n      - description: Conditions store the status conditions of the Memcached instances\n        displayName: Conditions\n        path: conditions\n      version: v1alpha1\n  description: Memcached Operator description. TODO.\n  displayName: Memcached Operator\n  icon:\n  - base64data: \"\"\n    mediatype: \"\"\n  install:\n    spec:\n      clusterPermissions:\n      - rules:\n        - apiGroups:\n          - \"\"\n          resources:\n          - events\n          verbs:\n          - create\n          - patch\n        - apiGroups:\n          - \"\"\n          resources:\n          - pods\n          verbs:\n          - get\n          - list\n          - watch\n        - apiGroups:\n          - apps\n          resources:\n          - deployments\n          verbs:\n          - create\n          - delete\n          - get\n          - list\n          - patch\n          - update\n          - watch\n        - apiGroups:\n          - cache.example.com\n          resources:\n          - memcacheds\n          verbs:\n          - create\n          - delete\n          - get\n          - list\n          - patch\n          - update\n          - watch\n        - apiGroups:\n          - cache.example.com\n          resources:\n          - memcacheds/finalizers\n          verbs:\n          - update\n        - apiGroups:\n          - cache.example.com\n          resources:\n          - memcacheds/status\n          verbs:\n          - get\n          - patch\n          - update\n        - apiGroups:\n          - authentication.k8s.io\n          resources:\n          - tokenreviews\n          verbs:\n          - create\n        - apiGroups:\n          - authorization.k8s.io\n          resources:\n          - subjectaccessreviews\n          verbs:\n          - create\n        serviceAccountName: memcached-operator-controller-manager\n      deployments:\n      - label:\n          app.kubernetes.io/managed-by: kustomize\n          app.kubernetes.io/name: memcached-operator\n          control-plane: controller-manager\n        name: memcached-operator-controller-manager\n        spec:\n          replicas: 1\n          selector:\n            matchLabels:\n              app.kubernetes.io/name: memcached-operator\n              control-plane: controller-manager\n          strategy: {}\n          template:\n            metadata:\n              annotations:\n                kubectl.kubernetes.io/default-container: manager\n              labels:\n                app.kubernetes.io/name: memcached-operator\n                control-plane: controller-manager\n            spec:\n              containers:\n              - args:\n                - --metrics-bind-address=:8443\n                - --leader-elect\n                - --health-probe-bind-address=:8081\n                - --metrics-cert-path=/tmp/k8s-metrics-server/metrics-certs\n                - --webhook-cert-path=/tmp/k8s-webhook-server/serving-certs\n                command:\n                - /manager\n                env:\n                - name: MEMCACHED_IMAGE\n                  value: memcached:1.4.36-alpine\n                image: quay.io/example/memcached-operator:v0.0.1\n                livenessProbe:\n                  httpGet:\n                    path: /healthz\n                    port: 8081\n                  initialDelaySeconds: 15\n                  periodSeconds: 20\n                name: manager\n                ports:\n                - containerPort: 9443\n                  name: webhook-server\n                  protocol: TCP\n                readinessProbe:\n                  httpGet:\n                    path: /readyz\n                    port: 8081\n                  initialDelaySeconds: 5\n                  periodSeconds: 10\n                resources:\n                  limits:\n                    cpu: 500m\n                    memory: 128Mi\n                  requests:\n                    cpu: 10m\n                    memory: 64Mi\n                securityContext:\n                  allowPrivilegeEscalation: false\n                  capabilities:\n                    drop:\n                    - ALL\n                volumeMounts:\n                - mountPath: /tmp/k8s-webhook-server/serving-certs\n                  name: webhook-certs\n                  readOnly: true\n              securityContext:\n                runAsNonRoot: true\n                seccompProfile:\n                  type: RuntimeDefault\n              serviceAccountName: memcached-operator-controller-manager\n              terminationGracePeriodSeconds: 10\n              volumes:\n              - name: webhook-certs\n                secret:\n                  secretName: webhook-server-cert\n      permissions:\n      - rules:\n        - apiGroups:\n          - \"\"\n          resources:\n          - configmaps\n          verbs:\n          - get\n          - list\n          - watch\n          - create\n          - update\n          - patch\n          - delete\n        - apiGroups:\n          - coordination.k8s.io\n          resources:\n          - leases\n          verbs:\n          - get\n          - list\n          - watch\n          - create\n          - update\n          - patch\n          - delete\n        - apiGroups:\n          - \"\"\n          resources:\n          - events\n          verbs:\n          - create\n          - patch\n        serviceAccountName: memcached-operator-controller-manager\n    strategy: deployment\n  installModes:\n  - supported: false\n    type: OwnNamespace\n  - supported: false\n    type: SingleNamespace\n  - supported: false\n    type: MultiNamespace\n  - supported: true\n    type: AllNamespaces\n  keywords:\n  - memcached-operator\n  links:\n  - name: Memcached Operator\n    url: https://memcached-operator.domain\n  maintainers:\n  - email: your@email.com\n    name: Maintainer Name\n  maturity: alpha\n  provider:\n    name: Provider Name\n    url: https://your.domain\n  version: 0.0.1\n  webhookdefinitions:\n  - admissionReviewVersions:\n    - v1\n    containerPort: 443\n    deploymentName: memcached-operator-controller-manager\n    failurePolicy: Fail\n    generateName: mmemcached-v1alpha1.kb.io\n    rules:\n    - apiGroups:\n      - cache.example.com\n      apiVersions:\n      - v1alpha1\n      operations:\n      - CREATE\n      - UPDATE\n      resources:\n      - memcacheds\n    sideEffects: None\n    targetPort: 9443\n    type: MutatingAdmissionWebhook\n    webhookPath: /mutate-cache-example-com-v1alpha1-memcached\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/bundle/metadata/annotations.yaml",
    "content": "annotations:\n  # Core bundle annotations.\n  operators.operatorframework.io.bundle.mediatype.v1: registry+v1\n  operators.operatorframework.io.bundle.manifests.v1: manifests/\n  operators.operatorframework.io.bundle.metadata.v1: metadata/\n  operators.operatorframework.io.bundle.package.v1: memcached-operator\n  operators.operatorframework.io.bundle.channels.v1: alpha\n\n  # Annotations for testing.\n  operators.operatorframework.io.test.mediatype.v1: scorecard+v1\n  operators.operatorframework.io.test.config.v1: tests/scorecard/\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/bundle/tests/scorecard/config.yaml",
    "content": "apiVersion: scorecard.operatorframework.io/v1alpha3\nkind: Configuration\nmetadata:\n  name: config\nstages:\n- parallel: true\n  tests:\n  - entrypoint:\n    - scorecard-test\n    - basic-check-spec\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: basic\n      test: basic-check-spec-test\n    storage:\n      spec:\n        mountPath: {}\n  - entrypoint:\n    - scorecard-test\n    - olm-bundle-validation\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: olm\n      test: olm-bundle-validation-test\n    storage:\n      spec:\n        mountPath: {}\n  - entrypoint:\n    - scorecard-test\n    - olm-crds-have-validation\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: olm\n      test: olm-crds-have-validation-test\n    storage:\n      spec:\n        mountPath: {}\n  - entrypoint:\n    - scorecard-test\n    - olm-crds-have-resources\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: olm\n      test: olm-crds-have-resources-test\n    storage:\n      spec:\n        mountPath: {}\n  - entrypoint:\n    - scorecard-test\n    - olm-spec-descriptors\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: olm\n      test: olm-spec-descriptors-test\n    storage:\n      spec:\n        mountPath: {}\n  - entrypoint:\n    - scorecard-test\n    - olm-status-descriptors\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: olm\n      test: olm-status-descriptors-test\n    storage:\n      spec:\n        mountPath: {}\nstorage:\n  spec:\n    mountPath: {}\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/bundle.Dockerfile",
    "content": "FROM scratch\n\n# Core bundle labels.\nLABEL operators.operatorframework.io.bundle.mediatype.v1=registry+v1\nLABEL operators.operatorframework.io.bundle.manifests.v1=manifests/\nLABEL operators.operatorframework.io.bundle.metadata.v1=metadata/\nLABEL operators.operatorframework.io.bundle.package.v1=memcached-operator\nLABEL operators.operatorframework.io.bundle.channels.v1=alpha\n\n# Labels for testing.\nLABEL operators.operatorframework.io.test.mediatype.v1=scorecard+v1\nLABEL operators.operatorframework.io.test.config.v1=tests/scorecard/\n\n# Copy files to locations specified by labels.\nCOPY bundle/manifests /manifests/\nCOPY bundle/metadata /metadata/\nCOPY bundle/tests/scorecard /tests/scorecard/\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/cmd/main.go",
    "content": "/*\nCopyright 2026.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage main\n\nimport (\n\t\"crypto/tls\"\n\t\"flag\"\n\t\"os\"\n\t\"path/filepath\"\n\n\t// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)\n\t// to ensure that exec-entrypoint and run can make use of them.\n\t_ \"k8s.io/client-go/plugin/pkg/client/auth\"\n\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\tutilruntime \"k8s.io/apimachinery/pkg/util/runtime\"\n\tclientgoscheme \"k8s.io/client-go/kubernetes/scheme\"\n\tctrl \"sigs.k8s.io/controller-runtime\"\n\t\"sigs.k8s.io/controller-runtime/pkg/certwatcher\"\n\t\"sigs.k8s.io/controller-runtime/pkg/healthz\"\n\t\"sigs.k8s.io/controller-runtime/pkg/log/zap\"\n\t\"sigs.k8s.io/controller-runtime/pkg/metrics/filters\"\n\tmetricsserver \"sigs.k8s.io/controller-runtime/pkg/metrics/server\"\n\t\"sigs.k8s.io/controller-runtime/pkg/webhook\"\n\n\tcachev1alpha1 \"github.com/example/memcached-operator/api/v1alpha1\"\n\t\"github.com/example/memcached-operator/internal/controller\"\n\twebhookv1alpha1 \"github.com/example/memcached-operator/internal/webhook/v1alpha1\"\n\t// +kubebuilder:scaffold:imports\n)\n\nvar (\n\tscheme   = runtime.NewScheme()\n\tsetupLog = ctrl.Log.WithName(\"setup\")\n)\n\nfunc init() {\n\tutilruntime.Must(clientgoscheme.AddToScheme(scheme))\n\n\tutilruntime.Must(cachev1alpha1.AddToScheme(scheme))\n\t// +kubebuilder:scaffold:scheme\n}\n\n// nolint:gocyclo\nfunc main() {\n\tvar metricsAddr string\n\tvar metricsCertPath, metricsCertName, metricsCertKey string\n\tvar webhookCertPath, webhookCertName, webhookCertKey string\n\tvar enableLeaderElection bool\n\tvar probeAddr string\n\tvar secureMetrics bool\n\tvar enableHTTP2 bool\n\tvar tlsOpts []func(*tls.Config)\n\tflag.StringVar(&metricsAddr, \"metrics-bind-address\", \"0\", \"The address the metrics endpoint binds to. \"+\n\t\t\"Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.\")\n\tflag.StringVar(&probeAddr, \"health-probe-bind-address\", \":8081\", \"The address the probe endpoint binds to.\")\n\tflag.BoolVar(&enableLeaderElection, \"leader-elect\", false,\n\t\t\"Enable leader election for controller manager. \"+\n\t\t\t\"Enabling this will ensure there is only one active controller manager.\")\n\tflag.BoolVar(&secureMetrics, \"metrics-secure\", true,\n\t\t\"If set, the metrics endpoint is served securely via HTTPS. Use --metrics-secure=false to use HTTP instead.\")\n\tflag.StringVar(&webhookCertPath, \"webhook-cert-path\", \"\", \"The directory that contains the webhook certificate.\")\n\tflag.StringVar(&webhookCertName, \"webhook-cert-name\", \"tls.crt\", \"The name of the webhook certificate file.\")\n\tflag.StringVar(&webhookCertKey, \"webhook-cert-key\", \"tls.key\", \"The name of the webhook key file.\")\n\tflag.StringVar(&metricsCertPath, \"metrics-cert-path\", \"\",\n\t\t\"The directory that contains the metrics server certificate.\")\n\tflag.StringVar(&metricsCertName, \"metrics-cert-name\", \"tls.crt\", \"The name of the metrics server certificate file.\")\n\tflag.StringVar(&metricsCertKey, \"metrics-cert-key\", \"tls.key\", \"The name of the metrics server key file.\")\n\tflag.BoolVar(&enableHTTP2, \"enable-http2\", false,\n\t\t\"If set, HTTP/2 will be enabled for the metrics and webhook servers\")\n\topts := zap.Options{\n\t\tDevelopment: true,\n\t}\n\topts.BindFlags(flag.CommandLine)\n\tflag.Parse()\n\n\tctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))\n\n\t// if the enable-http2 flag is false (the default), http/2 should be disabled\n\t// due to its vulnerabilities. More specifically, disabling http/2 will\n\t// prevent from being vulnerable to the HTTP/2 Stream Cancellation and\n\t// Rapid Reset CVEs. For more information see:\n\t// - https://github.com/advisories/GHSA-qppj-fm5r-hxr3\n\t// - https://github.com/advisories/GHSA-4374-p667-p6c8\n\tdisableHTTP2 := func(c *tls.Config) {\n\t\tsetupLog.Info(\"disabling http/2\")\n\t\tc.NextProtos = []string{\"http/1.1\"}\n\t}\n\n\tif !enableHTTP2 {\n\t\ttlsOpts = append(tlsOpts, disableHTTP2)\n\t}\n\n\t// Create watchers for metrics and webhooks certificates\n\tvar metricsCertWatcher, webhookCertWatcher *certwatcher.CertWatcher\n\n\t// Initial webhook TLS options\n\twebhookTLSOpts := tlsOpts\n\n\tif len(webhookCertPath) > 0 {\n\t\tsetupLog.Info(\"Initializing webhook certificate watcher using provided certificates\",\n\t\t\t\"webhook-cert-path\", webhookCertPath, \"webhook-cert-name\", webhookCertName, \"webhook-cert-key\", webhookCertKey)\n\n\t\tvar err error\n\t\twebhookCertWatcher, err = certwatcher.New(\n\t\t\tfilepath.Join(webhookCertPath, webhookCertName),\n\t\t\tfilepath.Join(webhookCertPath, webhookCertKey),\n\t\t)\n\t\tif err != nil {\n\t\t\tsetupLog.Error(err, \"Failed to initialize webhook certificate watcher\")\n\t\t\tos.Exit(1)\n\t\t}\n\n\t\twebhookTLSOpts = append(webhookTLSOpts, func(config *tls.Config) {\n\t\t\tconfig.GetCertificate = webhookCertWatcher.GetCertificate\n\t\t})\n\t}\n\n\twebhookServer := webhook.NewServer(webhook.Options{\n\t\tTLSOpts: webhookTLSOpts,\n\t})\n\n\t// Metrics endpoint is enabled in 'config/default/kustomization.yaml'. The Metrics options configure the server.\n\t// More info:\n\t// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.21.0/pkg/metrics/server\n\t// - https://book.kubebuilder.io/reference/metrics.html\n\tmetricsServerOptions := metricsserver.Options{\n\t\tBindAddress:   metricsAddr,\n\t\tSecureServing: secureMetrics,\n\t\tTLSOpts:       tlsOpts,\n\t}\n\n\tif secureMetrics {\n\t\t// FilterProvider is used to protect the metrics endpoint with authn/authz.\n\t\t// These configurations ensure that only authorized users and service accounts\n\t\t// can access the metrics endpoint. The RBAC are configured in 'config/rbac/kustomization.yaml'. More info:\n\t\t// https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.21.0/pkg/metrics/filters#WithAuthenticationAndAuthorization\n\t\tmetricsServerOptions.FilterProvider = filters.WithAuthenticationAndAuthorization\n\t}\n\n\t// If the certificate is not specified, controller-runtime will automatically\n\t// generate self-signed certificates for the metrics server. While convenient for development and testing,\n\t// this setup is not recommended for production.\n\t//\n\t// TODO(user): If you enable certManager, uncomment the following lines:\n\t// - [METRICS-WITH-CERTS] at config/default/kustomization.yaml to generate and use certificates\n\t// managed by cert-manager for the metrics server.\n\t// - [PROMETHEUS-WITH-CERTS] at config/prometheus/kustomization.yaml for TLS certification.\n\tif len(metricsCertPath) > 0 {\n\t\tsetupLog.Info(\"Initializing metrics certificate watcher using provided certificates\",\n\t\t\t\"metrics-cert-path\", metricsCertPath, \"metrics-cert-name\", metricsCertName, \"metrics-cert-key\", metricsCertKey)\n\n\t\tvar err error\n\t\tmetricsCertWatcher, err = certwatcher.New(\n\t\t\tfilepath.Join(metricsCertPath, metricsCertName),\n\t\t\tfilepath.Join(metricsCertPath, metricsCertKey),\n\t\t)\n\t\tif err != nil {\n\t\t\tsetupLog.Error(err, \"to initialize metrics certificate watcher\", \"error\", err)\n\t\t\tos.Exit(1)\n\t\t}\n\n\t\tmetricsServerOptions.TLSOpts = append(metricsServerOptions.TLSOpts, func(config *tls.Config) {\n\t\t\tconfig.GetCertificate = metricsCertWatcher.GetCertificate\n\t\t})\n\t}\n\n\tmgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{\n\t\tScheme:                 scheme,\n\t\tMetrics:                metricsServerOptions,\n\t\tWebhookServer:          webhookServer,\n\t\tHealthProbeBindAddress: probeAddr,\n\t\tLeaderElection:         enableLeaderElection,\n\t\tLeaderElectionID:       \"86f835c3.example.com\",\n\t\t// LeaderElectionReleaseOnCancel defines if the leader should step down voluntarily\n\t\t// when the Manager ends. This requires the binary to immediately end when the\n\t\t// Manager is stopped, otherwise, this setting is unsafe. Setting this significantly\n\t\t// speeds up voluntary leader transitions as the new leader don't have to wait\n\t\t// LeaseDuration time first.\n\t\t//\n\t\t// In the default scaffold provided, the program ends immediately after\n\t\t// the manager stops, so would be fine to enable this option. However,\n\t\t// if you are doing or is intended to do any operation such as perform cleanups\n\t\t// after the manager stops then its usage might be unsafe.\n\t\t// LeaderElectionReleaseOnCancel: true,\n\t})\n\tif err != nil {\n\t\tsetupLog.Error(err, \"unable to start manager\")\n\t\tos.Exit(1)\n\t}\n\n\tif err := (&controller.MemcachedReconciler{\n\t\tClient: mgr.GetClient(),\n\t\tScheme: mgr.GetScheme(),\n\t\t// Add a Recorder to the reconciler.\n\t\t// This allows the operator author to emit events during reconcilliation.\n\t\tRecorder: mgr.GetEventRecorderFor(\"memcached-controller\"),\n\t}).SetupWithManager(mgr); err != nil {\n\t\tsetupLog.Error(err, \"unable to create controller\", \"controller\", \"Memcached\")\n\t\tos.Exit(1)\n\t}\n\t// nolint:goconst\n\tif os.Getenv(\"ENABLE_WEBHOOKS\") != \"false\" {\n\t\tif err := webhookv1alpha1.SetupMemcachedWebhookWithManager(mgr); err != nil {\n\t\t\tsetupLog.Error(err, \"unable to create webhook\", \"webhook\", \"Memcached\")\n\t\t\tos.Exit(1)\n\t\t}\n\t}\n\t// +kubebuilder:scaffold:builder\n\n\tif metricsCertWatcher != nil {\n\t\tsetupLog.Info(\"Adding metrics certificate watcher to manager\")\n\t\tif err := mgr.Add(metricsCertWatcher); err != nil {\n\t\t\tsetupLog.Error(err, \"unable to add metrics certificate watcher to manager\")\n\t\t\tos.Exit(1)\n\t\t}\n\t}\n\n\tif webhookCertWatcher != nil {\n\t\tsetupLog.Info(\"Adding webhook certificate watcher to manager\")\n\t\tif err := mgr.Add(webhookCertWatcher); err != nil {\n\t\t\tsetupLog.Error(err, \"unable to add webhook certificate watcher to manager\")\n\t\t\tos.Exit(1)\n\t\t}\n\t}\n\n\tif err := mgr.AddHealthzCheck(\"healthz\", healthz.Ping); err != nil {\n\t\tsetupLog.Error(err, \"unable to set up health check\")\n\t\tos.Exit(1)\n\t}\n\tif err := mgr.AddReadyzCheck(\"readyz\", healthz.Ping); err != nil {\n\t\tsetupLog.Error(err, \"unable to set up ready check\")\n\t\tos.Exit(1)\n\t}\n\n\tsetupLog.Info(\"starting manager\")\n\tif err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {\n\t\tsetupLog.Error(err, \"problem running manager\")\n\t\tos.Exit(1)\n\t}\n}\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/certmanager/certificate-metrics.yaml",
    "content": "# The following manifests contain a self-signed issuer CR and a metrics certificate CR.\n# More document can be found at https://docs.cert-manager.io\napiVersion: cert-manager.io/v1\nkind: Certificate\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: metrics-certs  # this name should match the one appeared in kustomizeconfig.yaml\n  namespace: system\nspec:\n  dnsNames:\n  # SERVICE_NAME and SERVICE_NAMESPACE will be substituted by kustomize\n  # replacements in the config/default/kustomization.yaml file.\n  - SERVICE_NAME.SERVICE_NAMESPACE.svc\n  - SERVICE_NAME.SERVICE_NAMESPACE.svc.cluster.local\n  issuerRef:\n    kind: Issuer\n    name: selfsigned-issuer\n  secretName: metrics-server-cert\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/certmanager/certificate-webhook.yaml",
    "content": "# The following manifests contain a self-signed issuer CR and a certificate CR.\n# More document can be found at https://docs.cert-manager.io\napiVersion: cert-manager.io/v1\nkind: Certificate\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: serving-cert  # this name should match the one appeared in kustomizeconfig.yaml\n  namespace: system\nspec:\n  # SERVICE_NAME and SERVICE_NAMESPACE will be substituted by kustomize\n  # replacements in the config/default/kustomization.yaml file.\n  dnsNames:\n  - SERVICE_NAME.SERVICE_NAMESPACE.svc\n  - SERVICE_NAME.SERVICE_NAMESPACE.svc.cluster.local\n  issuerRef:\n    kind: Issuer\n    name: selfsigned-issuer\n  secretName: webhook-server-cert\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/certmanager/issuer.yaml",
    "content": "# The following manifest contains a self-signed issuer CR.\n# More information can be found at https://docs.cert-manager.io\n# WARNING: Targets CertManager v1.0. Check https://cert-manager.io/docs/installation/upgrading/ for breaking changes.\napiVersion: cert-manager.io/v1\nkind: Issuer\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: selfsigned-issuer\n  namespace: system\nspec:\n  selfSigned: {}\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/certmanager/kustomization.yaml",
    "content": "resources:\n- issuer.yaml\n- certificate-webhook.yaml\n- certificate-metrics.yaml\n\nconfigurations:\n- kustomizeconfig.yaml\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/certmanager/kustomizeconfig.yaml",
    "content": "# This configuration is for teaching kustomize how to update name ref substitution\nnameReference:\n- kind: Issuer\n  group: cert-manager.io\n  fieldSpecs:\n  - kind: Certificate\n    group: cert-manager.io\n    path: spec/issuerRef/name\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/crd/bases/cache.example.com_memcacheds.yaml",
    "content": "---\napiVersion: apiextensions.k8s.io/v1\nkind: CustomResourceDefinition\nmetadata:\n  annotations:\n    controller-gen.kubebuilder.io/version: v0.18.0\n  name: memcacheds.cache.example.com\nspec:\n  group: cache.example.com\n  names:\n    kind: Memcached\n    listKind: MemcachedList\n    plural: memcacheds\n    singular: memcached\n  scope: Namespaced\n  versions:\n  - name: v1alpha1\n    schema:\n      openAPIV3Schema:\n        description: Memcached is the Schema for the memcacheds API\n        properties:\n          apiVersion:\n            description: |-\n              APIVersion defines the versioned schema of this representation of an object.\n              Servers should convert recognized schemas to the latest internal value, and\n              may reject unrecognized values.\n              More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources\n            type: string\n          kind:\n            description: |-\n              Kind is a string value representing the REST resource this object represents.\n              Servers may infer this from the endpoint the client submits requests to.\n              Cannot be updated.\n              In CamelCase.\n              More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds\n            type: string\n          metadata:\n            type: object\n          spec:\n            description: MemcachedSpec defines the desired state of Memcached\n            properties:\n              containerPort:\n                description: Port defines the port that will be used to init the container\n                  with the image\n                format: int32\n                type: integer\n              size:\n                description: Size defines the number of Memcached instances\n                format: int32\n                maximum: 3\n                minimum: 1\n                type: integer\n            type: object\n          status:\n            description: MemcachedStatus defines the observed state of Memcached\n            properties:\n              conditions:\n                description: Conditions store the status conditions of the Memcached\n                  instances\n                items:\n                  description: Condition contains details for one aspect of the current\n                    state of this API Resource.\n                  properties:\n                    lastTransitionTime:\n                      description: |-\n                        lastTransitionTime is the last time the condition transitioned from one status to another.\n                        This should be when the underlying condition changed.  If that is not known, then using the time when the API field changed is acceptable.\n                      format: date-time\n                      type: string\n                    message:\n                      description: |-\n                        message is a human readable message indicating details about the transition.\n                        This may be an empty string.\n                      maxLength: 32768\n                      type: string\n                    observedGeneration:\n                      description: |-\n                        observedGeneration represents the .metadata.generation that the condition was set based upon.\n                        For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date\n                        with respect to the current state of the instance.\n                      format: int64\n                      minimum: 0\n                      type: integer\n                    reason:\n                      description: |-\n                        reason contains a programmatic identifier indicating the reason for the condition's last transition.\n                        Producers of specific condition types may define expected values and meanings for this field,\n                        and whether the values are considered a guaranteed API.\n                        The value should be a CamelCase string.\n                        This field may not be empty.\n                      maxLength: 1024\n                      minLength: 1\n                      pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$\n                      type: string\n                    status:\n                      description: status of the condition, one of True, False, Unknown.\n                      enum:\n                      - \"True\"\n                      - \"False\"\n                      - Unknown\n                      type: string\n                    type:\n                      description: type of condition in CamelCase or in foo.example.com/CamelCase.\n                      maxLength: 316\n                      pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$\n                      type: string\n                  required:\n                  - lastTransitionTime\n                  - message\n                  - reason\n                  - status\n                  - type\n                  type: object\n                type: array\n            type: object\n        type: object\n    served: true\n    storage: true\n    subresources:\n      status: {}\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/crd/kustomization.yaml",
    "content": "# This kustomization.yaml is not intended to be run by itself,\n# since it depends on service name and namespace that are out of this kustomize package.\n# It should be run by config/default\nresources:\n- bases/cache.example.com_memcacheds.yaml\n# +kubebuilder:scaffold:crdkustomizeresource\n\npatches:\n# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix.\n# patches here are for enabling the conversion webhook for each CRD\n# +kubebuilder:scaffold:crdkustomizewebhookpatch\n\n# [WEBHOOK] To enable webhook, uncomment the following section\n# the following config is for teaching kustomize how to do kustomization for CRDs.\n#configurations:\n#- kustomizeconfig.yaml\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/crd/kustomizeconfig.yaml",
    "content": "# This file is for teaching kustomize how to substitute name and namespace reference in CRD\nnameReference:\n- kind: Service\n  version: v1\n  fieldSpecs:\n  - kind: CustomResourceDefinition\n    version: v1\n    group: apiextensions.k8s.io\n    path: spec/conversion/webhook/clientConfig/service/name\n\nnamespace:\n- kind: CustomResourceDefinition\n  version: v1\n  group: apiextensions.k8s.io\n  path: spec/conversion/webhook/clientConfig/service/namespace\n  create: false\n\nvarReference:\n- path: metadata/annotations\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/default/cert_metrics_manager_patch.yaml",
    "content": "# This patch adds the args, volumes, and ports to allow the manager to use the metrics-server certs.\n\n# Add the volumeMount for the metrics-server certs\n- op: add\n  path: /spec/template/spec/containers/0/volumeMounts/-\n  value:\n    mountPath: /tmp/k8s-metrics-server/metrics-certs\n    name: metrics-certs\n    readOnly: true\n\n# Add the --metrics-cert-path argument for the metrics server\n- op: add\n  path: /spec/template/spec/containers/0/args/-\n  value: --metrics-cert-path=/tmp/k8s-metrics-server/metrics-certs\n\n# Add the metrics-server certs volume configuration\n- op: add\n  path: /spec/template/spec/volumes/-\n  value:\n    name: metrics-certs\n    secret:\n      secretName: metrics-server-cert\n      optional: false\n      items:\n        - key: ca.crt\n          path: ca.crt\n        - key: tls.crt\n          path: tls.crt\n        - key: tls.key\n          path: tls.key\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/default/kustomization.yaml",
    "content": "# Adds namespace to all resources.\nnamespace: memcached-operator-system\n\n# Value of this field is prepended to the\n# names of all resources, e.g. a deployment named\n# \"wordpress\" becomes \"alices-wordpress\".\n# Note that it should also match with the prefix (text before '-') of the namespace\n# field above.\nnamePrefix: memcached-operator-\n\n# Labels to add to all resources and selectors.\n#labels:\n#- includeSelectors: true\n#  pairs:\n#    someName: someValue\n\nresources:\n- ../crd\n- ../rbac\n- ../manager\n# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in\n# crd/kustomization.yaml\n- ../webhook\n# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required.\n- ../certmanager\n# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'.\n- ../prometheus\n# [METRICS] Expose the controller manager metrics service.\n- metrics_service.yaml\n# [NETWORK POLICY] Protect the /metrics endpoint and Webhook Server with NetworkPolicy.\n# Only Pod(s) running a namespace labeled with 'metrics: enabled' will be able to gather the metrics.\n# Only CR(s) which requires webhooks and are applied on namespaces labeled with 'webhooks: enabled' will\n# be able to communicate with the Webhook Server.\n#- ../network-policy\n\n# Uncomment the patches line if you enable Metrics\npatches:\n# [METRICS] The following patch will enable the metrics endpoint using HTTPS and the port :8443.\n# More info: https://book.kubebuilder.io/reference/metrics\n- path: manager_metrics_patch.yaml\n  target:\n    kind: Deployment\n\n# Uncomment the patches line if you enable Metrics and CertManager\n# [METRICS-WITH-CERTS] To enable metrics protected with certManager, uncomment the following line.\n# This patch will protect the metrics with certManager self-signed certs.\n- path: cert_metrics_manager_patch.yaml\n  target:\n    kind: Deployment\n\n# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in\n# crd/kustomization.yaml\n- path: manager_webhook_patch.yaml\n  target:\n    kind: Deployment\n\n# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix.\n# Uncomment the following replacements to add the cert-manager CA injection annotations\nreplacements:\n - source: # Uncomment the following block to enable certificates for metrics\n     kind: Service\n     version: v1\n     name: controller-manager-metrics-service\n     fieldPath: metadata.name\n   targets:\n     - select:\n         kind: Certificate\n         group: cert-manager.io\n         version: v1\n         name: metrics-certs\n       fieldPaths:\n         - spec.dnsNames.0\n         - spec.dnsNames.1\n       options:\n         delimiter: '.'\n         index: 0\n         create: true\n     - select: # Uncomment the following to set the Service name for TLS config in Prometheus ServiceMonitor\n         kind: ServiceMonitor\n         group: monitoring.coreos.com\n         version: v1\n         name: controller-manager-metrics-monitor\n       fieldPaths:\n         - spec.endpoints.0.tlsConfig.serverName\n       options:\n         delimiter: '.'\n         index: 0\n         create: true\n\n - source:\n     kind: Service\n     version: v1\n     name: controller-manager-metrics-service\n     fieldPath: metadata.namespace\n   targets:\n     - select:\n         kind: Certificate\n         group: cert-manager.io\n         version: v1\n         name: metrics-certs\n       fieldPaths:\n         - spec.dnsNames.0\n         - spec.dnsNames.1\n       options:\n         delimiter: '.'\n         index: 1\n         create: true\n     - select: # Uncomment the following to set the Service namespace for TLS in Prometheus ServiceMonitor\n         kind: ServiceMonitor\n         group: monitoring.coreos.com\n         version: v1\n         name: controller-manager-metrics-monitor\n       fieldPaths:\n         - spec.endpoints.0.tlsConfig.serverName\n       options:\n         delimiter: '.'\n         index: 1\n         create: true\n\n - source: # Uncomment the following block if you have any webhook\n     kind: Service\n     version: v1\n     name: webhook-service\n     fieldPath: .metadata.name # Name of the service\n   targets:\n     - select:\n         kind: Certificate\n         group: cert-manager.io\n         version: v1\n         name: serving-cert\n       fieldPaths:\n         - .spec.dnsNames.0\n         - .spec.dnsNames.1\n       options:\n         delimiter: '.'\n         index: 0\n         create: true\n - source:\n     kind: Service\n     version: v1\n     name: webhook-service\n     fieldPath: .metadata.namespace # Namespace of the service\n   targets:\n     - select:\n         kind: Certificate\n         group: cert-manager.io\n         version: v1\n         name: serving-cert\n       fieldPaths:\n         - .spec.dnsNames.0\n         - .spec.dnsNames.1\n       options:\n         delimiter: '.'\n         index: 1\n         create: true\n\n# - source: # Uncomment the following block if you have a ValidatingWebhook (--programmatic-validation)\n#     kind: Certificate\n#     group: cert-manager.io\n#     version: v1\n#     name: serving-cert # This name should match the one in certificate.yaml\n#     fieldPath: .metadata.namespace # Namespace of the certificate CR\n#   targets:\n#     - select:\n#         kind: ValidatingWebhookConfiguration\n#       fieldPaths:\n#         - .metadata.annotations.[cert-manager.io/inject-ca-from]\n#       options:\n#         delimiter: '/'\n#         index: 0\n#         create: true\n# - source:\n#     kind: Certificate\n#     group: cert-manager.io\n#     version: v1\n#     name: serving-cert\n#     fieldPath: .metadata.name\n#   targets:\n#     - select:\n#         kind: ValidatingWebhookConfiguration\n#       fieldPaths:\n#         - .metadata.annotations.[cert-manager.io/inject-ca-from]\n#       options:\n#         delimiter: '/'\n#         index: 1\n#         create: true\n#\n - source: # Uncomment the following block if you have a DefaultingWebhook (--defaulting )\n     kind: Certificate\n     group: cert-manager.io\n     version: v1\n     name: serving-cert\n     fieldPath: .metadata.namespace # Namespace of the certificate CR\n   targets:\n     - select:\n         kind: MutatingWebhookConfiguration\n       fieldPaths:\n         - .metadata.annotations.[cert-manager.io/inject-ca-from]\n       options:\n         delimiter: '/'\n         index: 0\n         create: true\n - source:\n     kind: Certificate\n     group: cert-manager.io\n     version: v1\n     name: serving-cert\n     fieldPath: .metadata.name\n   targets:\n     - select:\n         kind: MutatingWebhookConfiguration\n       fieldPaths:\n         - .metadata.annotations.[cert-manager.io/inject-ca-from]\n       options:\n         delimiter: '/'\n         index: 1\n         create: true\n\n# - source: # Uncomment the following block if you have a ConversionWebhook (--conversion)\n#     kind: Certificate\n#     group: cert-manager.io\n#     version: v1\n#     name: serving-cert\n#     fieldPath: .metadata.namespace # Namespace of the certificate CR\n#   targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD.\n# +kubebuilder:scaffold:crdkustomizecainjectionns\n# - source:\n#     kind: Certificate\n#     group: cert-manager.io\n#     version: v1\n#     name: serving-cert\n#     fieldPath: .metadata.name\n#   targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD.\n# +kubebuilder:scaffold:crdkustomizecainjectionname\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/default/manager_metrics_patch.yaml",
    "content": "# This patch adds the args to allow exposing the metrics endpoint using HTTPS\n- op: add\n  path: /spec/template/spec/containers/0/args/0\n  value: --metrics-bind-address=:8443\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/default/manager_webhook_patch.yaml",
    "content": "# This patch ensures the webhook certificates are properly mounted in the manager container.\n# It configures the necessary arguments, volumes, volume mounts, and container ports.\n\n# Add the --webhook-cert-path argument for configuring the webhook certificate path\n- op: add\n  path: /spec/template/spec/containers/0/args/-\n  value: --webhook-cert-path=/tmp/k8s-webhook-server/serving-certs\n\n# Add the volumeMount for the webhook certificates\n- op: add\n  path: /spec/template/spec/containers/0/volumeMounts/-\n  value:\n    mountPath: /tmp/k8s-webhook-server/serving-certs\n    name: webhook-certs\n    readOnly: true\n\n# Add the port configuration for the webhook server\n- op: add\n  path: /spec/template/spec/containers/0/ports/-\n  value:\n    containerPort: 9443\n    name: webhook-server\n    protocol: TCP\n\n# Add the volume configuration for the webhook certificates\n- op: add\n  path: /spec/template/spec/volumes/-\n  value:\n    name: webhook-certs\n    secret:\n      secretName: webhook-server-cert\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/default/metrics_service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    control-plane: controller-manager\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: controller-manager-metrics-service\n  namespace: system\nspec:\n  ports:\n  - name: https\n    port: 8443\n    protocol: TCP\n    targetPort: 8443\n  selector:\n    control-plane: controller-manager\n    app.kubernetes.io/name: memcached-operator\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/manager/kustomization.yaml",
    "content": "resources:\n- manager.yaml\napiVersion: kustomize.config.k8s.io/v1beta1\nkind: Kustomization\nimages:\n- name: controller\n  newName: quay.io/example/memcached-operator\n  newTag: v0.0.1\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/manager/manager.yaml",
    "content": "apiVersion: v1\nkind: Namespace\nmetadata:\n  labels:\n    control-plane: controller-manager\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: system\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: controller-manager\n  namespace: system\n  labels:\n    control-plane: controller-manager\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\nspec:\n  selector:\n    matchLabels:\n      control-plane: controller-manager\n      app.kubernetes.io/name: memcached-operator\n  replicas: 1\n  template:\n    metadata:\n      annotations:\n        kubectl.kubernetes.io/default-container: manager\n      labels:\n        control-plane: controller-manager\n        app.kubernetes.io/name: memcached-operator\n    spec:\n      # TODO(user): Uncomment the following code to configure the nodeAffinity expression\n      # according to the platforms which are supported by your solution.\n      # It is considered best practice to support multiple architectures. You can\n      # build your manager image using the makefile target docker-buildx.\n      # affinity:\n      #   nodeAffinity:\n      #     requiredDuringSchedulingIgnoredDuringExecution:\n      #       nodeSelectorTerms:\n      #         - matchExpressions:\n      #           - key: kubernetes.io/arch\n      #             operator: In\n      #             values:\n      #               - amd64\n      #               - arm64\n      #               - ppc64le\n      #               - s390x\n      #           - key: kubernetes.io/os\n      #             operator: In\n      #             values:\n      #               - linux\n      securityContext:\n        # Projects are configured by default to adhere to the \"restricted\" Pod Security Standards.\n        # This ensures that deployments meet the highest security requirements for Kubernetes.\n        # For more details, see: https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted\n        runAsNonRoot: true\n        seccompProfile:\n          type: RuntimeDefault\n      containers:\n      - command:\n        - /manager\n        args:\n          - --leader-elect\n          - --health-probe-bind-address=:8081\n        image: controller:latest\n        name: manager\n        env:\n        - name: MEMCACHED_IMAGE\n          value: memcached:1.4.36-alpine\n        ports: []\n        securityContext:\n          allowPrivilegeEscalation: false\n          capabilities:\n            drop:\n            - \"ALL\"\n        livenessProbe:\n          httpGet:\n            path: /healthz\n            port: 8081\n          initialDelaySeconds: 15\n          periodSeconds: 20\n        readinessProbe:\n          httpGet:\n            path: /readyz\n            port: 8081\n          initialDelaySeconds: 5\n          periodSeconds: 10\n        # TODO(user): Configure the resources accordingly based on the project requirements.\n        # More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/\n        resources:\n          limits:\n            cpu: 500m\n            memory: 128Mi\n          requests:\n            cpu: 10m\n            memory: 64Mi\n        volumeMounts: []\n      volumes: []\n      serviceAccountName: controller-manager\n      terminationGracePeriodSeconds: 10\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml",
    "content": "apiVersion: operators.coreos.com/v1alpha1\nkind: ClusterServiceVersion\nmetadata:\n  annotations:\n    alm-examples: '[]'\n    capabilities: Basic Install\n  name: memcached-operator.v0.0.0\n  namespace: placeholder\nspec:\n  apiservicedefinitions: {}\n  customresourcedefinitions:\n    owned:\n    - description: Memcached is the Schema for the memcacheds API\n      displayName: Memcached\n      kind: Memcached\n      name: memcacheds.cache.example.com\n      resources:\n      - kind: Deployment\n        name: memcached-deployment\n        version: v1\n      specDescriptors:\n      - description: Port defines the port that will be used to init the container\n          with the image\n        displayName: Container Port\n        path: containerPort\n      - description: Size defines the number of Memcached instances\n        displayName: Size\n        path: size\n      statusDescriptors:\n      - description: Conditions store the status conditions of the Memcached instances\n        displayName: Conditions\n        path: conditions\n      version: v1alpha1\n  description: Memcached Operator description. TODO.\n  displayName: Memcached Operator\n  icon:\n  - base64data: \"\"\n    mediatype: \"\"\n  install:\n    spec:\n      deployments: null\n    strategy: \"\"\n  installModes:\n  - supported: false\n    type: OwnNamespace\n  - supported: false\n    type: SingleNamespace\n  - supported: false\n    type: MultiNamespace\n  - supported: true\n    type: AllNamespaces\n  keywords:\n  - memcached-operator\n  links:\n  - name: Memcached Operator\n    url: https://memcached-operator.domain\n  maintainers:\n  - email: your@email.com\n    name: Maintainer Name\n  maturity: alpha\n  provider:\n    name: Provider Name\n    url: https://your.domain\n  version: 0.0.0\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/manifests/kustomization.yaml",
    "content": "# These resources constitute the fully configured set of manifests\n# used to generate the 'manifests/' directory in a bundle.\nresources:\n- bases/memcached-operator.clusterserviceversion.yaml\n- ../default\n- ../samples\n- ../scorecard\n\n# [WEBHOOK] To enable webhooks, uncomment all the sections with [WEBHOOK] prefix.\n# Do NOT uncomment sections with prefix [CERTMANAGER], as OLM does not support cert-manager.\n# These patches remove the unnecessary \"cert\" volume and its manager container volumeMount.\npatches:\n- target:\n    group: apps\n    version: v1\n    kind: Deployment\n    name: controller-manager\n    namespace: system\n  patch: |-\n    # Remove the manager container's \"cert\" volumeMount, since OLM will create and mount a set of certs.\n    # Update the indices in this path if adding or removing containers/volumeMounts in the manager's Deployment.\n    - op: remove\n\n      path: /spec/template/spec/containers/0/volumeMounts/0\n    # Remove the \"cert\" volume, since OLM will create and mount a set of certs.\n    # Update the indices in this path if adding or removing volumes in the manager's Deployment.\n    - op: remove\n      path: /spec/template/spec/volumes/0\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/network-policy/allow-metrics-traffic.yaml",
    "content": "# This NetworkPolicy allows ingress traffic\n# with Pods running on namespaces labeled with 'metrics: enabled'. Only Pods on those\n# namespaces are able to gather data from the metrics endpoint.\napiVersion: networking.k8s.io/v1\nkind: NetworkPolicy\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: allow-metrics-traffic\n  namespace: system\nspec:\n  podSelector:\n    matchLabels:\n      control-plane: controller-manager\n      app.kubernetes.io/name: memcached-operator\n  policyTypes:\n    - Ingress\n  ingress:\n    # This allows ingress traffic from any namespace with the label metrics: enabled\n    - from:\n      - namespaceSelector:\n          matchLabels:\n            metrics: enabled  # Only from namespaces with this label\n      ports:\n        - port: 8443\n          protocol: TCP\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/network-policy/allow-webhook-traffic.yaml",
    "content": "# This NetworkPolicy allows ingress traffic to your webhook server running\n# as part of the controller-manager from specific namespaces and pods. CR(s) which uses webhooks\n# will only work when applied in namespaces labeled with 'webhook: enabled'\napiVersion: networking.k8s.io/v1\nkind: NetworkPolicy\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: allow-webhook-traffic\n  namespace: system\nspec:\n  podSelector:\n    matchLabels:\n      control-plane: controller-manager\n      app.kubernetes.io/name: memcached-operator\n  policyTypes:\n    - Ingress\n  ingress:\n    # This allows ingress traffic from any namespace with the label webhook: enabled\n    - from:\n      - namespaceSelector:\n          matchLabels:\n            webhook: enabled # Only from namespaces with this label\n      ports:\n        - port: 443\n          protocol: TCP\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/network-policy/kustomization.yaml",
    "content": "resources:\n- allow-webhook-traffic.yaml\n- allow-metrics-traffic.yaml\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/prometheus/kustomization.yaml",
    "content": "resources:\n- monitor.yaml\n\n# [PROMETHEUS-WITH-CERTS] The following patch configures the ServiceMonitor in ../prometheus\n# to securely reference certificates created and managed by cert-manager.\n# Additionally, ensure that you uncomment the [METRICS WITH CERTMANAGER] patch under config/default/kustomization.yaml\n# to mount the \"metrics-server-cert\" secret in the Manager Deployment.\n#patches:\n#  - path: monitor_tls_patch.yaml\n#    target:\n#      kind: ServiceMonitor\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/prometheus/monitor.yaml",
    "content": "# Prometheus Monitor Service (Metrics)\napiVersion: monitoring.coreos.com/v1\nkind: ServiceMonitor\nmetadata:\n  labels:\n    control-plane: controller-manager\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: controller-manager-metrics-monitor\n  namespace: system\nspec:\n  endpoints:\n    - path: /metrics\n      port: https # Ensure this is the name of the port that exposes HTTPS metrics\n      scheme: https\n      bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token\n      tlsConfig:\n        # TODO(user): The option insecureSkipVerify: true is not recommended for production since it disables\n        # certificate verification, exposing the system to potential man-in-the-middle attacks.\n        # For production environments, it is recommended to use cert-manager for automatic TLS certificate management.\n        # To apply this configuration, enable cert-manager and use the patch located at config/prometheus/servicemonitor_tls_patch.yaml,\n        # which securely references the certificate from the 'metrics-server-cert' secret.\n        insecureSkipVerify: true\n  selector:\n    matchLabels:\n      control-plane: controller-manager\n      app.kubernetes.io/name: memcached-operator\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/prometheus/monitor_tls_patch.yaml",
    "content": "# Patch for Prometheus ServiceMonitor to enable secure TLS configuration\n# using certificates managed by cert-manager\n- op: replace\n  path: /spec/endpoints/0/tlsConfig\n  value:\n    # SERVICE_NAME and SERVICE_NAMESPACE will be substituted by kustomize\n    serverName: SERVICE_NAME.SERVICE_NAMESPACE.svc\n    insecureSkipVerify: false\n    ca:\n      secret:\n        name: metrics-server-cert\n        key: ca.crt\n    cert:\n      secret:\n        name: metrics-server-cert\n        key: tls.crt\n    keySecret:\n      name: metrics-server-cert\n      key: tls.key\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/rbac/kustomization.yaml",
    "content": "resources:\n# All RBAC will be applied under this service account in\n# the deployment namespace. You may comment out this resource\n# if your manager will use a service account that exists at\n# runtime. Be sure to update RoleBinding and ClusterRoleBinding\n# subjects if changing service account names.\n- service_account.yaml\n- role.yaml\n- role_binding.yaml\n- leader_election_role.yaml\n- leader_election_role_binding.yaml\n# The following RBAC configurations are used to protect\n# the metrics endpoint with authn/authz. These configurations\n# ensure that only authorized users and service accounts\n# can access the metrics endpoint. Comment the following\n# permissions if you want to disable this protection.\n# More info: https://book.kubebuilder.io/reference/metrics.html\n- metrics_auth_role.yaml\n- metrics_auth_role_binding.yaml\n- metrics_reader_role.yaml\n# For each CRD, \"Admin\", \"Editor\" and \"Viewer\" roles are scaffolded by\n# default, aiding admins in cluster management. Those roles are\n# not used by the memcached-operator itself. You can comment the following lines\n# if you do not want those helpers be installed with your Project.\n- memcached_admin_role.yaml\n- memcached_editor_role.yaml\n- memcached_viewer_role.yaml\n\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/rbac/leader_election_role.yaml",
    "content": "# permissions to do leader election.\napiVersion: rbac.authorization.k8s.io/v1\nkind: Role\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: leader-election-role\nrules:\n- apiGroups:\n  - \"\"\n  resources:\n  - configmaps\n  verbs:\n  - get\n  - list\n  - watch\n  - create\n  - update\n  - patch\n  - delete\n- apiGroups:\n  - coordination.k8s.io\n  resources:\n  - leases\n  verbs:\n  - get\n  - list\n  - watch\n  - create\n  - update\n  - patch\n  - delete\n- apiGroups:\n  - \"\"\n  resources:\n  - events\n  verbs:\n  - create\n  - patch\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/rbac/leader_election_role_binding.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: RoleBinding\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: leader-election-rolebinding\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: Role\n  name: leader-election-role\nsubjects:\n- kind: ServiceAccount\n  name: controller-manager\n  namespace: system\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/rbac/memcached_admin_role.yaml",
    "content": "# This rule is not used by the project memcached-operator itself.\n# It is provided to allow the cluster admin to help manage permissions for users.\n#\n# Grants full permissions ('*') over cache.example.com.\n# This role is intended for users authorized to modify roles and bindings within the cluster,\n# enabling them to delegate specific permissions to other users or groups as needed.\n\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: memcached-admin-role\nrules:\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds\n  verbs:\n  - '*'\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds/status\n  verbs:\n  - get\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/rbac/memcached_editor_role.yaml",
    "content": "# This rule is not used by the project memcached-operator itself.\n# It is provided to allow the cluster admin to help manage permissions for users.\n#\n# Grants permissions to create, update, and delete resources within the cache.example.com.\n# This role is intended for users who need to manage these resources\n# but should not control RBAC or manage permissions for others.\n\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: memcached-editor-role\nrules:\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds/status\n  verbs:\n  - get\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/rbac/memcached_viewer_role.yaml",
    "content": "# This rule is not used by the project memcached-operator itself.\n# It is provided to allow the cluster admin to help manage permissions for users.\n#\n# Grants read-only access to cache.example.com resources.\n# This role is intended for users who need visibility into these resources\n# without permissions to modify them. It is ideal for monitoring purposes and limited-access viewing.\n\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: memcached-viewer-role\nrules:\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds\n  verbs:\n  - get\n  - list\n  - watch\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds/status\n  verbs:\n  - get\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/rbac/metrics_auth_role.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  name: metrics-auth-role\nrules:\n- apiGroups:\n  - authentication.k8s.io\n  resources:\n  - tokenreviews\n  verbs:\n  - create\n- apiGroups:\n  - authorization.k8s.io\n  resources:\n  - subjectaccessreviews\n  verbs:\n  - create\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/rbac/metrics_auth_role_binding.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n  name: metrics-auth-rolebinding\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: metrics-auth-role\nsubjects:\n- kind: ServiceAccount\n  name: controller-manager\n  namespace: system\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/rbac/metrics_reader_role.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  name: metrics-reader\nrules:\n- nonResourceURLs:\n  - \"/metrics\"\n  verbs:\n  - get\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/rbac/role.yaml",
    "content": "---\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  name: manager-role\nrules:\n- apiGroups:\n  - \"\"\n  resources:\n  - events\n  verbs:\n  - create\n  - patch\n- apiGroups:\n  - \"\"\n  resources:\n  - pods\n  verbs:\n  - get\n  - list\n  - watch\n- apiGroups:\n  - apps\n  resources:\n  - deployments\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds/finalizers\n  verbs:\n  - update\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds/status\n  verbs:\n  - get\n  - patch\n  - update\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/rbac/role_binding.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: manager-rolebinding\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: manager-role\nsubjects:\n- kind: ServiceAccount\n  name: controller-manager\n  namespace: system\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/rbac/service_account.yaml",
    "content": "apiVersion: v1\nkind: ServiceAccount\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: controller-manager\n  namespace: system\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml",
    "content": "apiVersion: cache.example.com/v1alpha1\nkind: Memcached\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: memcached-sample\nspec:\n  # TODO(user): edit the following value to ensure the number\n  # of Pods/Instances your Operand must have on cluster\n  size: 1\n\n  # TODO(user): edit the following value to ensure the container has the right port to be initialized\n  containerPort: 11211\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/samples/kustomization.yaml",
    "content": "## Append samples of your project ##\nresources:\n- cache_v1alpha1_memcached.yaml\n# +kubebuilder:scaffold:manifestskustomizesamples\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/scorecard/bases/config.yaml",
    "content": "apiVersion: scorecard.operatorframework.io/v1alpha3\nkind: Configuration\nmetadata:\n  name: config\nstages:\n- parallel: true\n  tests: []\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/scorecard/kustomization.yaml",
    "content": "resources:\n- bases/config.yaml\napiVersion: kustomize.config.k8s.io/v1beta1\nkind: Kustomization\npatches:\n- path: patches/basic.config.yaml\n  target:\n    group: scorecard.operatorframework.io\n    kind: Configuration\n    name: config\n    version: v1alpha3\n- path: patches/olm.config.yaml\n  target:\n    group: scorecard.operatorframework.io\n    kind: Configuration\n    name: config\n    version: v1alpha3\n# +kubebuilder:scaffold:patches\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/scorecard/patches/basic.config.yaml",
    "content": "- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - scorecard-test\n    - basic-check-spec\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: basic\n      test: basic-check-spec-test\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/scorecard/patches/olm.config.yaml",
    "content": "- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - scorecard-test\n    - olm-bundle-validation\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: olm\n      test: olm-bundle-validation-test\n- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - scorecard-test\n    - olm-crds-have-validation\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: olm\n      test: olm-crds-have-validation-test\n- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - scorecard-test\n    - olm-crds-have-resources\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: olm\n      test: olm-crds-have-resources-test\n- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - scorecard-test\n    - olm-spec-descriptors\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: olm\n      test: olm-spec-descriptors-test\n- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - scorecard-test\n    - olm-status-descriptors\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: olm\n      test: olm-status-descriptors-test\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/webhook/kustomization.yaml",
    "content": "resources:\n- manifests.yaml\n- service.yaml\n\nconfigurations:\n- kustomizeconfig.yaml\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/webhook/kustomizeconfig.yaml",
    "content": "# the following config is for teaching kustomize where to look at when substituting nameReference.\n# It requires kustomize v2.1.0 or newer to work properly.\nnameReference:\n- kind: Service\n  version: v1\n  fieldSpecs:\n  - kind: MutatingWebhookConfiguration\n    group: admissionregistration.k8s.io\n    path: webhooks/clientConfig/service/name\n  - kind: ValidatingWebhookConfiguration\n    group: admissionregistration.k8s.io\n    path: webhooks/clientConfig/service/name\n\nnamespace:\n- kind: MutatingWebhookConfiguration\n  group: admissionregistration.k8s.io\n  path: webhooks/clientConfig/service/namespace\n  create: true\n- kind: ValidatingWebhookConfiguration\n  group: admissionregistration.k8s.io\n  path: webhooks/clientConfig/service/namespace\n  create: true\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/webhook/manifests.yaml",
    "content": "---\napiVersion: admissionregistration.k8s.io/v1\nkind: MutatingWebhookConfiguration\nmetadata:\n  name: mutating-webhook-configuration\nwebhooks:\n- admissionReviewVersions:\n  - v1\n  clientConfig:\n    service:\n      name: webhook-service\n      namespace: system\n      path: /mutate-cache-example-com-v1alpha1-memcached\n  failurePolicy: Fail\n  name: mmemcached-v1alpha1.kb.io\n  rules:\n  - apiGroups:\n    - cache.example.com\n    apiVersions:\n    - v1alpha1\n    operations:\n    - CREATE\n    - UPDATE\n    resources:\n    - memcacheds\n  sideEffects: None\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/config/webhook/service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: webhook-service\n  namespace: system\nspec:\n  ports:\n    - port: 443\n      protocol: TCP\n      targetPort: 9443\n  selector:\n    control-plane: controller-manager\n    app.kubernetes.io/name: memcached-operator\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/go.mod",
    "content": "module github.com/example/memcached-operator\n\ngo 1.24.0\n\nrequire (\n\tgithub.com/onsi/ginkgo/v2 v2.22.0\n\tgithub.com/onsi/gomega v1.36.1\n\tk8s.io/api v0.33.0\n\tk8s.io/apimachinery v0.33.0\n\tk8s.io/client-go v0.33.0\n\tk8s.io/utils v0.0.0-20241104100929-3ea5e8cea738\n\tsigs.k8s.io/controller-runtime v0.21.0\n)\n\nrequire (\n\tcel.dev/expr v0.19.1 // indirect\n\tgithub.com/antlr4-go/antlr/v4 v4.13.0 // indirect\n\tgithub.com/beorn7/perks v1.0.1 // indirect\n\tgithub.com/blang/semver/v4 v4.0.0 // indirect\n\tgithub.com/cenkalti/backoff/v4 v4.3.0 // indirect\n\tgithub.com/cespare/xxhash/v2 v2.3.0 // indirect\n\tgithub.com/davecgh/go-spew v1.1.1 // indirect\n\tgithub.com/emicklei/go-restful/v3 v3.11.0 // indirect\n\tgithub.com/evanphx/json-patch/v5 v5.9.11 // indirect\n\tgithub.com/felixge/httpsnoop v1.0.4 // indirect\n\tgithub.com/fsnotify/fsnotify v1.7.0 // indirect\n\tgithub.com/fxamacker/cbor/v2 v2.7.0 // indirect\n\tgithub.com/go-logr/logr v1.4.2 // indirect\n\tgithub.com/go-logr/stdr v1.2.2 // indirect\n\tgithub.com/go-logr/zapr v1.3.0 // indirect\n\tgithub.com/go-openapi/jsonpointer v0.21.0 // indirect\n\tgithub.com/go-openapi/jsonreference v0.20.2 // indirect\n\tgithub.com/go-openapi/swag v0.23.0 // indirect\n\tgithub.com/go-task/slim-sprig/v3 v3.0.0 // indirect\n\tgithub.com/gogo/protobuf v1.3.2 // indirect\n\tgithub.com/google/btree v1.1.3 // indirect\n\tgithub.com/google/cel-go v0.23.2 // indirect\n\tgithub.com/google/gnostic-models v0.6.9 // indirect\n\tgithub.com/google/go-cmp v0.7.0 // indirect\n\tgithub.com/google/pprof v0.0.0-20241029153458-d1b30febd7db // indirect\n\tgithub.com/google/uuid v1.6.0 // indirect\n\tgithub.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 // indirect\n\tgithub.com/inconshreveable/mousetrap v1.1.0 // indirect\n\tgithub.com/josharian/intern v1.0.0 // indirect\n\tgithub.com/json-iterator/go v1.1.12 // indirect\n\tgithub.com/mailru/easyjson v0.7.7 // indirect\n\tgithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect\n\tgithub.com/modern-go/reflect2 v1.0.2 // indirect\n\tgithub.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect\n\tgithub.com/pkg/errors v0.9.1 // indirect\n\tgithub.com/prometheus/client_golang v1.22.0 // indirect\n\tgithub.com/prometheus/client_model v0.6.1 // indirect\n\tgithub.com/prometheus/common v0.62.0 // indirect\n\tgithub.com/prometheus/procfs v0.15.1 // indirect\n\tgithub.com/spf13/cobra v1.8.1 // indirect\n\tgithub.com/spf13/pflag v1.0.5 // indirect\n\tgithub.com/stoewer/go-strcase v1.3.0 // indirect\n\tgithub.com/x448/float16 v0.8.4 // indirect\n\tgo.opentelemetry.io/auto/sdk v1.1.0 // indirect\n\tgo.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 // indirect\n\tgo.opentelemetry.io/otel v1.33.0 // indirect\n\tgo.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 // indirect\n\tgo.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0 // indirect\n\tgo.opentelemetry.io/otel/metric v1.33.0 // indirect\n\tgo.opentelemetry.io/otel/sdk v1.33.0 // indirect\n\tgo.opentelemetry.io/otel/trace v1.33.0 // indirect\n\tgo.opentelemetry.io/proto/otlp v1.4.0 // indirect\n\tgo.uber.org/multierr v1.11.0 // indirect\n\tgo.uber.org/zap v1.27.0 // indirect\n\tgolang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect\n\tgolang.org/x/net v0.38.0 // indirect\n\tgolang.org/x/oauth2 v0.27.0 // indirect\n\tgolang.org/x/sync v0.12.0 // indirect\n\tgolang.org/x/sys v0.31.0 // indirect\n\tgolang.org/x/term v0.30.0 // indirect\n\tgolang.org/x/text v0.23.0 // indirect\n\tgolang.org/x/time v0.9.0 // indirect\n\tgolang.org/x/tools v0.26.0 // indirect\n\tgomodules.xyz/jsonpatch/v2 v2.4.0 // indirect\n\tgoogle.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 // indirect\n\tgoogle.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 // indirect\n\tgoogle.golang.org/grpc v1.68.1 // indirect\n\tgoogle.golang.org/protobuf v1.36.5 // indirect\n\tgopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect\n\tgopkg.in/inf.v0 v0.9.1 // indirect\n\tgopkg.in/yaml.v3 v3.0.1 // indirect\n\tk8s.io/apiextensions-apiserver v0.33.0 // indirect\n\tk8s.io/apiserver v0.33.0 // indirect\n\tk8s.io/component-base v0.33.0 // indirect\n\tk8s.io/klog/v2 v2.130.1 // indirect\n\tk8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect\n\tsigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 // indirect\n\tsigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect\n\tsigs.k8s.io/randfill v1.0.0 // indirect\n\tsigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect\n\tsigs.k8s.io/yaml v1.4.0 // indirect\n)\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/go.sum",
    "content": "cel.dev/expr v0.19.1 h1:NciYrtDRIR0lNCnH1LFJegdjspNx9fI59O7TWcua/W4=\ncel.dev/expr v0.19.1/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw=\ngithub.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=\ngithub.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g=\ngithub.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=\ngithub.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=\ngithub.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=\ngithub.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=\ngithub.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=\ngithub.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=\ngithub.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=\ngithub.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=\ngithub.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=\ngithub.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=\ngithub.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=\ngithub.com/evanphx/json-patch v0.5.2 h1:xVCHIVMUu1wtM/VkR9jVZ45N3FhZfYMMYGorLCR8P3k=\ngithub.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ=\ngithub.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU=\ngithub.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM=\ngithub.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=\ngithub.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=\ngithub.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=\ngithub.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=\ngithub.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=\ngithub.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=\ngithub.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=\ngithub.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=\ngithub.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=\ngithub.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=\ngithub.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=\ngithub.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=\ngithub.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg=\ngithub.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=\ngithub.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=\ngithub.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=\ngithub.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=\ngithub.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=\ngithub.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=\ngithub.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=\ngithub.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=\ngithub.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=\ngithub.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=\ngithub.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=\ngithub.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=\ngithub.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=\ngithub.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=\ngithub.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=\ngithub.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=\ngithub.com/google/cel-go v0.23.2 h1:UdEe3CvQh3Nv+E/j9r1Y//WO0K0cSyD7/y0bzyLIMI4=\ngithub.com/google/cel-go v0.23.2/go.mod h1:52Pb6QsDbC5kvgxvZhiL9QX1oZEkcUF/ZqaPx1J5Wwo=\ngithub.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=\ngithub.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw=\ngithub.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=\ngithub.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=\ngithub.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=\ngithub.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=\ngithub.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=\ngithub.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=\ngithub.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo=\ngithub.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=\ngithub.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=\ngithub.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 h1:TmHmbvxPmaegwhDubVz0lICL0J5Ka2vwTzhoePEXsGE=\ngithub.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0/go.mod h1:qztMSjm835F2bXf+5HKAPIS5qsmQDqZna/PgVt4rWtI=\ngithub.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=\ngithub.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=\ngithub.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=\ngithub.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=\ngithub.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=\ngithub.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=\ngithub.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=\ngithub.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=\ngithub.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=\ngithub.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=\ngithub.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=\ngithub.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=\ngithub.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=\ngithub.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=\ngithub.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=\ngithub.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=\ngithub.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=\ngithub.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=\ngithub.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=\ngithub.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=\ngithub.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=\ngithub.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=\ngithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=\ngithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=\ngithub.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=\ngithub.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=\ngithub.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=\ngithub.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=\ngithub.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg=\ngithub.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=\ngithub.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw=\ngithub.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=\ngithub.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=\ngithub.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=\ngithub.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=\ngithub.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=\ngithub.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=\ngithub.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=\ngithub.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=\ngithub.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=\ngithub.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=\ngithub.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=\ngithub.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=\ngithub.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=\ngithub.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=\ngithub.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=\ngithub.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=\ngithub.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=\ngithub.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs=\ngithub.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=\ngithub.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=\ngithub.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=\ngithub.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=\ngithub.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=\ngithub.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=\ngithub.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=\ngithub.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=\ngithub.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=\ngithub.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=\ngithub.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=\ngithub.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=\ngithub.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=\ngo.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=\ngo.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=\ngo.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 h1:yd02MEjBdJkG3uabWP9apV+OuWRIXGDuJEUJbOHmCFU=\ngo.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q=\ngo.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw=\ngo.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I=\ngo.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 h1:Vh5HayB/0HHfOQA7Ctx69E/Y/DcQSMPpKANYVMQ7fBA=\ngo.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0/go.mod h1:cpgtDBaqD/6ok/UG0jT15/uKjAY8mRA53diogHBg3UI=\ngo.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0 h1:5pojmb1U1AogINhN3SurB+zm/nIcusopeBNp42f45QM=\ngo.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0/go.mod h1:57gTHJSE5S1tqg+EKsLPlTWhpHMsWlVmer+LA926XiA=\ngo.opentelemetry.io/otel/metric v1.33.0 h1:r+JOocAyeRVXD8lZpjdQjzMadVZp2M4WmQ+5WtEnklQ=\ngo.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M=\ngo.opentelemetry.io/otel/sdk v1.33.0 h1:iax7M131HuAm9QkZotNHEfstof92xM+N8sr3uHXc2IM=\ngo.opentelemetry.io/otel/sdk v1.33.0/go.mod h1:A1Q5oi7/9XaMlIWzPSxLRWOI8nG3FnzHJNbiENQuihM=\ngo.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s=\ngo.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck=\ngo.opentelemetry.io/proto/otlp v1.4.0 h1:TA9WRvW6zMwP+Ssb6fLoUIuirti1gGbP28GcKG1jgeg=\ngo.opentelemetry.io/proto/otlp v1.4.0/go.mod h1:PPBWZIP98o2ElSqI35IHfu7hIhSwvc5N38Jw8pXuGFY=\ngo.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=\ngo.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=\ngo.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=\ngo.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=\ngo.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=\ngo.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=\ngolang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=\ngolang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=\ngolang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=\ngolang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=\ngolang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=\ngolang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=\ngolang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=\ngolang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=\ngolang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=\ngolang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=\ngolang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=\ngolang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=\ngolang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=\ngolang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=\ngolang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=\ngolang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=\ngolang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=\ngolang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=\ngolang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=\ngolang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=\ngolang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=\ngolang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=\ngolang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=\ngolang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=\ngolang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=\ngolang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw=\ngomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=\ngoogle.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 h1:CkkIfIt50+lT6NHAVoRYEyAvQGFM7xEwXUUywFvEb3Q=\ngoogle.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576/go.mod h1:1R3kvZ1dtP3+4p4d3G8uJ8rFk/fWlScl38vanWACI08=\ngoogle.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 h1:8ZmaLZE4XWrtU3MyClkYqqtl6Oegr3235h7jxsDyqCY=\ngoogle.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU=\ngoogle.golang.org/grpc v1.68.1 h1:oI5oTa11+ng8r8XMMN7jAOmWfPZWbYpCFaMUTACxkM0=\ngoogle.golang.org/grpc v1.68.1/go.mod h1:+q1XYFJjShcqn0QZHvCyeR4CXPA+llXIeUIfIe00waw=\ngoogle.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=\ngoogle.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=\ngopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=\ngopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=\ngopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=\ngopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=\ngopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=\ngopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=\ngopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\nk8s.io/api v0.33.0 h1:yTgZVn1XEe6opVpP1FylmNrIFWuDqe2H0V8CT5gxfIU=\nk8s.io/api v0.33.0/go.mod h1:CTO61ECK/KU7haa3qq8sarQ0biLq2ju405IZAd9zsiM=\nk8s.io/apiextensions-apiserver v0.33.0 h1:d2qpYL7Mngbsc1taA4IjJPRJ9ilnsXIrndH+r9IimOs=\nk8s.io/apiextensions-apiserver v0.33.0/go.mod h1:VeJ8u9dEEN+tbETo+lFkwaaZPg6uFKLGj5vyNEwwSzc=\nk8s.io/apimachinery v0.33.0 h1:1a6kHrJxb2hs4t8EE5wuR/WxKDwGN1FKH3JvDtA0CIQ=\nk8s.io/apimachinery v0.33.0/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=\nk8s.io/apiserver v0.33.0 h1:QqcM6c+qEEjkOODHppFXRiw/cE2zP85704YrQ9YaBbc=\nk8s.io/apiserver v0.33.0/go.mod h1:EixYOit0YTxt8zrO2kBU7ixAtxFce9gKGq367nFmqI8=\nk8s.io/client-go v0.33.0 h1:UASR0sAYVUzs2kYuKn/ZakZlcs2bEHaizrrHUZg0G98=\nk8s.io/client-go v0.33.0/go.mod h1:kGkd+l/gNGg8GYWAPr0xF1rRKvVWvzh9vmZAMXtaKOg=\nk8s.io/component-base v0.33.0 h1:Ot4PyJI+0JAD9covDhwLp9UNkUja209OzsJ4FzScBNk=\nk8s.io/component-base v0.33.0/go.mod h1:aXYZLbw3kihdkOPMDhWbjGCO6sg+luw554KP51t8qCU=\nk8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=\nk8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=\nk8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=\nk8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8=\nk8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro=\nk8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=\nsigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM=\nsigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=\nsigs.k8s.io/controller-runtime v0.21.0 h1:CYfjpEuicjUecRk+KAeyYh+ouUBn4llGyDYytIGcJS8=\nsigs.k8s.io/controller-runtime v0.21.0/go.mod h1:OSg14+F65eWqIu4DceX7k/+QRAbTTvxeQSNSOQpukWM=\nsigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8=\nsigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo=\nsigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=\nsigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=\nsigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=\nsigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW1TdblaLVAc=\nsigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=\nsigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=\nsigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/hack/boilerplate.go.txt",
    "content": "/*\nCopyright 2026.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/"
  },
  {
    "path": "testdata/go/v4/memcached-operator/internal/controller/memcached_controller.go",
    "content": "/*\nCopyright 2026.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage controller\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n\t\"time\"\n\n\tappsv1 \"k8s.io/api/apps/v1\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\tapierrors \"k8s.io/apimachinery/pkg/api/errors\"\n\t\"k8s.io/apimachinery/pkg/api/meta\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\t\"k8s.io/apimachinery/pkg/types\"\n\t\"k8s.io/client-go/tools/record\"\n\t\"k8s.io/utils/ptr\"\n\tctrl \"sigs.k8s.io/controller-runtime\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client\"\n\t\"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil\"\n\tlogf \"sigs.k8s.io/controller-runtime/pkg/log\"\n\n\tcachev1alpha1 \"github.com/example/memcached-operator/api/v1alpha1\"\n)\n\nconst memcachedFinalizer = \"cache.example.com/finalizer\"\n\n// Definitions to manage status conditions\nconst (\n\t// typeAvailableMemcached represents the status of the Deployment reconciliation\n\ttypeAvailableMemcached = \"Available\"\n\t// typeDegradedMemcached represents the status used when the custom resource is deleted and the finalizer operations are yet to occur.\n\ttypeDegradedMemcached = \"Degraded\"\n)\n\n// MemcachedReconciler reconciles a Memcached object\ntype MemcachedReconciler struct {\n\tclient.Client\n\tScheme   *runtime.Scheme\n\tRecorder record.EventRecorder\n}\n\n// The following markers are used to generate the rules permissions (RBAC) on config/rbac using controller-gen\n// when the command <make manifests> is executed.\n// To know more about markers see: https://book.kubebuilder.io/reference/markers.html\n\n// +kubebuilder:rbac:groups=cache.example.com,resources=memcacheds,verbs=get;list;watch;create;update;patch;delete\n// +kubebuilder:rbac:groups=cache.example.com,resources=memcacheds/status,verbs=get;update;patch\n// +kubebuilder:rbac:groups=cache.example.com,resources=memcacheds/finalizers,verbs=update\n// +kubebuilder:rbac:groups=core,resources=events,verbs=create;patch\n// +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete\n// +kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;watch\n\n// Reconcile is part of the main kubernetes reconciliation loop which aims to\n// move the current state of the cluster closer to the desired state.\n// It is essential for the controller's reconciliation loop to be idempotent. By following the Operator\n// pattern you will create Controllers which provide a reconcile function\n// responsible for synchronizing resources until the desired state is reached on the cluster.\n// Breaking this recommendation goes against the design principles of controller-runtime.\n// and may lead to unforeseen consequences such as resources becoming stuck and requiring manual intervention.\n// For further info:\n// - About Operator Pattern: https://kubernetes.io/docs/concepts/extend-kubernetes/operator/\n// - About Controllers: https://kubernetes.io/docs/concepts/architecture/controller/\n// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.21.0/pkg/reconcile\nfunc (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {\n\tlog := logf.FromContext(ctx)\n\n\t// Fetch the Memcached instance\n\t// The purpose is check if the Custom Resource for the Kind Memcached\n\t// is applied on the cluster if not we return nil to stop the reconciliation\n\tmemcached := &cachev1alpha1.Memcached{}\n\terr := r.Get(ctx, req.NamespacedName, memcached)\n\tif err != nil {\n\t\tif apierrors.IsNotFound(err) {\n\t\t\t// If the custom resource is not found then it usually means that it was deleted or not created\n\t\t\t// In this way, we will stop the reconciliation\n\t\t\tlog.Info(\"memcached resource not found. Ignoring since object must be deleted\")\n\t\t\treturn ctrl.Result{}, nil\n\t\t}\n\t\t// Error reading the object - requeue the request.\n\t\tlog.Error(err, \"Failed to get memcached\")\n\t\treturn ctrl.Result{}, err\n\t}\n\n\t// Let's just set the status as Unknown when no status is available\n\tif len(memcached.Status.Conditions) == 0 {\n\t\tmeta.SetStatusCondition(&memcached.Status.Conditions, metav1.Condition{Type: typeAvailableMemcached, Status: metav1.ConditionUnknown, Reason: \"Reconciling\", Message: \"Starting reconciliation\"})\n\t\tif err = r.Status().Update(ctx, memcached); err != nil {\n\t\t\tlog.Error(err, \"Failed to update Memcached status\")\n\t\t\treturn ctrl.Result{}, err\n\t\t}\n\n\t\t// Let's re-fetch the memcached Custom Resource after updating the status\n\t\t// so that we have the latest state of the resource on the cluster and we will avoid\n\t\t// raising the error \"the object has been modified, please apply\n\t\t// your changes to the latest version and try again\" which would re-trigger the reconciliation\n\t\t// if we try to update it again in the following operations\n\t\tif err := r.Get(ctx, req.NamespacedName, memcached); err != nil {\n\t\t\tlog.Error(err, \"Failed to re-fetch memcached\")\n\t\t\treturn ctrl.Result{}, err\n\t\t}\n\t}\n\n\t// Let's add a finalizer. Then, we can define some operations which should\n\t// occur before the custom resource is deleted.\n\t// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/finalizers\n\tif !controllerutil.ContainsFinalizer(memcached, memcachedFinalizer) {\n\t\tlog.Info(\"Adding Finalizer for Memcached\")\n\t\tif ok := controllerutil.AddFinalizer(memcached, memcachedFinalizer); !ok {\n\t\t\terr = fmt.Errorf(\"finalizer for Memcached was not added\")\n\t\t\tlog.Error(err, \"Failed to add finalizer for Memcached\")\n\t\t\treturn ctrl.Result{}, err\n\t\t}\n\n\t\tif err = r.Update(ctx, memcached); err != nil {\n\t\t\tlog.Error(err, \"Failed to update custom resource to add finalizer\")\n\t\t\treturn ctrl.Result{}, err\n\t\t}\n\t}\n\n\t// Check if the Memcached instance is marked to be deleted, which is\n\t// indicated by the deletion timestamp being set.\n\tisMemcachedMarkedToBeDeleted := memcached.GetDeletionTimestamp() != nil\n\tif isMemcachedMarkedToBeDeleted {\n\t\tif controllerutil.ContainsFinalizer(memcached, memcachedFinalizer) {\n\t\t\tlog.Info(\"Performing Finalizer Operations for Memcached before delete CR\")\n\n\t\t\t// Let's add here a status \"Downgrade\" to reflect that this resource began its process to be terminated.\n\t\t\tmeta.SetStatusCondition(&memcached.Status.Conditions, metav1.Condition{Type: typeDegradedMemcached,\n\t\t\t\tStatus: metav1.ConditionUnknown, Reason: \"Finalizing\",\n\t\t\t\tMessage: fmt.Sprintf(\"Performing finalizer operations for the custom resource: %s \", memcached.Name)})\n\n\t\t\tif err := r.Status().Update(ctx, memcached); err != nil {\n\t\t\t\tlog.Error(err, \"Failed to update Memcached status\")\n\t\t\t\treturn ctrl.Result{}, err\n\t\t\t}\n\n\t\t\t// Perform all operations required before removing the finalizer and allow\n\t\t\t// the Kubernetes API to remove the custom resource.\n\t\t\tr.doFinalizerOperationsForMemcached(memcached)\n\n\t\t\t// TODO(user): If you add operations to the doFinalizerOperationsForMemcached method\n\t\t\t// then you need to ensure that all worked fine before deleting and updating the Downgrade status\n\t\t\t// otherwise, you should requeue here.\n\n\t\t\t// Re-fetch the memcached Custom Resource before updating the status\n\t\t\t// so that we have the latest state of the resource on the cluster and we will avoid\n\t\t\t// raising the error \"the object has been modified, please apply\n\t\t\t// your changes to the latest version and try again\" which would re-trigger the reconciliation\n\t\t\tif err := r.Get(ctx, req.NamespacedName, memcached); err != nil {\n\t\t\t\tlog.Error(err, \"Failed to re-fetch memcached\")\n\t\t\t\treturn ctrl.Result{}, err\n\t\t\t}\n\n\t\t\tmeta.SetStatusCondition(&memcached.Status.Conditions, metav1.Condition{Type: typeDegradedMemcached,\n\t\t\t\tStatus: metav1.ConditionTrue, Reason: \"Finalizing\",\n\t\t\t\tMessage: fmt.Sprintf(\"Finalizer operations for custom resource %s name were successfully accomplished\", memcached.Name)})\n\n\t\t\tif err := r.Status().Update(ctx, memcached); err != nil {\n\t\t\t\tlog.Error(err, \"Failed to update Memcached status\")\n\t\t\t\treturn ctrl.Result{}, err\n\t\t\t}\n\n\t\t\tlog.Info(\"Removing Finalizer for Memcached after successfully perform the operations\")\n\t\t\tif ok := controllerutil.RemoveFinalizer(memcached, memcachedFinalizer); !ok {\n\t\t\t\terr = fmt.Errorf(\"finalizer for Memcached was not removed\")\n\t\t\t\tlog.Error(err, \"Failed to remove finalizer for Memcached\")\n\t\t\t\treturn ctrl.Result{}, err\n\t\t\t}\n\n\t\t\tif err := r.Update(ctx, memcached); err != nil {\n\t\t\t\tlog.Error(err, \"Failed to remove finalizer for Memcached\")\n\t\t\t\treturn ctrl.Result{}, err\n\t\t\t}\n\t\t}\n\t\treturn ctrl.Result{}, nil\n\t}\n\n\t// Check if the deployment already exists, if not create a new one\n\tfound := &appsv1.Deployment{}\n\terr = r.Get(ctx, types.NamespacedName{Name: memcached.Name, Namespace: memcached.Namespace}, found)\n\tif err != nil && apierrors.IsNotFound(err) {\n\t\t// Define a new deployment\n\t\tdep, err := r.deploymentForMemcached(memcached)\n\t\tif err != nil {\n\t\t\tlog.Error(err, \"Failed to define new Deployment resource for Memcached\")\n\n\t\t\t// The following implementation will update the status\n\t\t\tmeta.SetStatusCondition(&memcached.Status.Conditions, metav1.Condition{Type: typeAvailableMemcached,\n\t\t\t\tStatus: metav1.ConditionFalse, Reason: \"Reconciling\",\n\t\t\t\tMessage: fmt.Sprintf(\"Failed to create Deployment for the custom resource (%s): (%s)\", memcached.Name, err)})\n\n\t\t\tif err := r.Status().Update(ctx, memcached); err != nil {\n\t\t\t\tlog.Error(err, \"Failed to update Memcached status\")\n\t\t\t\treturn ctrl.Result{}, err\n\t\t\t}\n\n\t\t\treturn ctrl.Result{}, err\n\t\t}\n\n\t\tlog.Info(\"Creating a new Deployment\",\n\t\t\t\"Deployment.Namespace\", dep.Namespace, \"Deployment.Name\", dep.Name)\n\t\tif err = r.Create(ctx, dep); err != nil {\n\t\t\tlog.Error(err, \"Failed to create new Deployment\",\n\t\t\t\t\"Deployment.Namespace\", dep.Namespace, \"Deployment.Name\", dep.Name)\n\t\t\treturn ctrl.Result{}, err\n\t\t}\n\n\t\t// Deployment created successfully\n\t\t// We will requeue the reconciliation so that we can ensure the state\n\t\t// and move forward for the next operations\n\t\treturn ctrl.Result{RequeueAfter: time.Minute}, nil\n\t} else if err != nil {\n\t\tlog.Error(err, \"Failed to get Deployment\")\n\t\t// Let's return the error for the reconciliation be re-triggered again\n\t\treturn ctrl.Result{}, err\n\t}\n\n\t// The CRD API defines that the Memcached type have a MemcachedSpec.Size field\n\t// to set the quantity of Deployment instances to the desired state on the cluster.\n\t// Therefore, the following code will ensure the Deployment size is the same as defined\n\t// via the Size spec of the Custom Resource which we are reconciling.\n\tsize := memcached.Spec.Size\n\tif *found.Spec.Replicas != size {\n\t\tfound.Spec.Replicas = &size\n\t\tif err = r.Update(ctx, found); err != nil {\n\t\t\tlog.Error(err, \"Failed to update Deployment\",\n\t\t\t\t\"Deployment.Namespace\", found.Namespace, \"Deployment.Name\", found.Name)\n\n\t\t\t// Re-fetch the memcached Custom Resource before updating the status\n\t\t\t// so that we have the latest state of the resource on the cluster and we will avoid\n\t\t\t// raising the error \"the object has been modified, please apply\n\t\t\t// your changes to the latest version and try again\" which would re-trigger the reconciliation\n\t\t\tif err := r.Get(ctx, req.NamespacedName, memcached); err != nil {\n\t\t\t\tlog.Error(err, \"Failed to re-fetch memcached\")\n\t\t\t\treturn ctrl.Result{}, err\n\t\t\t}\n\n\t\t\t// The following implementation will update the status\n\t\t\tmeta.SetStatusCondition(&memcached.Status.Conditions, metav1.Condition{Type: typeAvailableMemcached,\n\t\t\t\tStatus: metav1.ConditionFalse, Reason: \"Resizing\",\n\t\t\t\tMessage: fmt.Sprintf(\"Failed to update the size for the custom resource (%s): (%s)\", memcached.Name, err)})\n\n\t\t\tif err := r.Status().Update(ctx, memcached); err != nil {\n\t\t\t\tlog.Error(err, \"Failed to update Memcached status\")\n\t\t\t\treturn ctrl.Result{}, err\n\t\t\t}\n\n\t\t\treturn ctrl.Result{}, err\n\t\t}\n\n\t\t// Now, that we update the size we want to requeue the reconciliation\n\t\t// so that we can ensure that we have the latest state of the resource before\n\t\t// update. Also, it will help ensure the desired state on the cluster\n\t\treturn ctrl.Result{Requeue: true}, nil\n\t}\n\n\t// The following implementation will update the status\n\tmeta.SetStatusCondition(&memcached.Status.Conditions, metav1.Condition{Type: typeAvailableMemcached,\n\t\tStatus: metav1.ConditionTrue, Reason: \"Reconciling\",\n\t\tMessage: fmt.Sprintf(\"Deployment for custom resource (%s) with %d replicas created successfully\", memcached.Name, size)})\n\n\tif err := r.Status().Update(ctx, memcached); err != nil {\n\t\tlog.Error(err, \"Failed to update Memcached status\")\n\t\treturn ctrl.Result{}, err\n\t}\n\n\treturn ctrl.Result{}, nil\n}\n\n// finalizeMemcached will perform the required operations before delete the CR.\nfunc (r *MemcachedReconciler) doFinalizerOperationsForMemcached(cr *cachev1alpha1.Memcached) {\n\t// TODO(user): Add the cleanup steps that the operator\n\t// needs to do before the CR can be deleted. Examples\n\t// of finalizers include performing backups and deleting\n\t// resources that are not owned by this CR, like a PVC.\n\n\t// Note: It is not recommended to use finalizers with the purpose of deleting resources which are\n\t// created and managed in the reconciliation. These ones, such as the Deployment created on this reconcile,\n\t// are defined as dependent of the custom resource. See that we use the method ctrl.SetControllerReference.\n\t// to set the ownerRef which means that the Deployment will be deleted by the Kubernetes API.\n\t// More info: https://kubernetes.io/docs/tasks/administer-cluster/use-cascading-deletion/\n\n\t// The following implementation will raise an event\n\tr.Recorder.Event(cr, \"Warning\", \"Deleting\",\n\t\tfmt.Sprintf(\"Custom Resource %s is being deleted from the namespace %s\",\n\t\t\tcr.Name,\n\t\t\tcr.Namespace))\n}\n\n// deploymentForMemcached returns a Memcached Deployment object\nfunc (r *MemcachedReconciler) deploymentForMemcached(\n\tmemcached *cachev1alpha1.Memcached) (*appsv1.Deployment, error) {\n\tls := labelsForMemcached()\n\treplicas := memcached.Spec.Size\n\n\t// Get the Operand image\n\timage, err := imageForMemcached()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tdep := &appsv1.Deployment{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      memcached.Name,\n\t\t\tNamespace: memcached.Namespace,\n\t\t},\n\t\tSpec: appsv1.DeploymentSpec{\n\t\t\tReplicas: &replicas,\n\t\t\tSelector: &metav1.LabelSelector{\n\t\t\t\tMatchLabels: ls,\n\t\t\t},\n\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\tLabels: ls,\n\t\t\t\t},\n\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t// TODO(user): Uncomment the following code to configure the nodeAffinity expression\n\t\t\t\t\t// according to the platforms which are supported by your solution. It is considered\n\t\t\t\t\t// best practice to support multiple architectures. build your manager image using the\n\t\t\t\t\t// makefile target docker-buildx. Also, you can use docker manifest inspect <image>\n\t\t\t\t\t// to check what are the platforms supported.\n\t\t\t\t\t// More info: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity\n\t\t\t\t\t// Affinity: &corev1.Affinity{\n\t\t\t\t\t//\t NodeAffinity: &corev1.NodeAffinity{\n\t\t\t\t\t//\t\t RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{\n\t\t\t\t\t//\t\t\t NodeSelectorTerms: []corev1.NodeSelectorTerm{\n\t\t\t\t\t//\t\t\t\t {\n\t\t\t\t\t//\t\t\t\t\t MatchExpressions: []corev1.NodeSelectorRequirement{\n\t\t\t\t\t//\t\t\t\t\t\t {\n\t\t\t\t\t//\t\t\t\t\t\t\t Key:      \"kubernetes.io/arch\",\n\t\t\t\t\t//\t\t\t\t\t\t\t Operator: \"In\",\n\t\t\t\t\t//\t\t\t\t\t\t\t Values:   []string{\"amd64\", \"arm64\", \"ppc64le\", \"s390x\"},\n\t\t\t\t\t//\t\t\t\t\t\t },\n\t\t\t\t\t//\t\t\t\t\t\t {\n\t\t\t\t\t//\t\t\t\t\t\t\t Key:      \"kubernetes.io/os\",\n\t\t\t\t\t//\t\t\t\t\t\t\t Operator: \"In\",\n\t\t\t\t\t//\t\t\t\t\t\t\t Values:   []string{\"linux\"},\n\t\t\t\t\t//\t\t\t\t\t\t },\n\t\t\t\t\t//\t\t\t\t\t },\n\t\t\t\t\t//\t\t\t\t },\n\t\t\t\t\t//\t\t \t },\n\t\t\t\t\t//\t\t },\n\t\t\t\t\t//\t },\n\t\t\t\t\t// },\n\t\t\t\t\tSecurityContext: &corev1.PodSecurityContext{\n\t\t\t\t\t\tRunAsNonRoot: ptr.To(true),\n\t\t\t\t\t\t// The memcached image does not use a non-zero numeric user as the default user.\n\t\t\t\t\t\t// Due to RunAsNonRoot field being set to true, we need to force the user in the\n\t\t\t\t\t\t// container to a non-zero numeric user. We do this using the RunAsUser field.\n\t\t\t\t\t\t// However, if you are looking to provide solution for K8s vendors like OpenShift\n\t\t\t\t\t\t// be aware that you cannot run under its restricted-v2 SCC if you set this value.\n\t\t\t\t\t\t// IMPORTANT: seccomProfile was introduced with Kubernetes 1.19\n\t\t\t\t\t\t// If you are looking for to produce solutions to be supported\n\t\t\t\t\t\t// on lower versions you must remove this option.\n\t\t\t\t\t\tSeccompProfile: &corev1.SeccompProfile{\n\t\t\t\t\t\t\tType: corev1.SeccompProfileTypeRuntimeDefault,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tContainers: []corev1.Container{{\n\t\t\t\t\t\tImage:           image,\n\t\t\t\t\t\tName:            \"memcached\",\n\t\t\t\t\t\tImagePullPolicy: corev1.PullIfNotPresent,\n\t\t\t\t\t\t// Ensure restrictive context for the container\n\t\t\t\t\t\t// More info: https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted\n\t\t\t\t\t\tSecurityContext: &corev1.SecurityContext{\n\t\t\t\t\t\t\t// WARNING: Ensure that the image used defines an UserID in the Dockerfile\n\t\t\t\t\t\t\t// otherwise the Pod will not run and will fail with \"container has runAsNonRoot and image has non-numeric user\"\".\n\t\t\t\t\t\t\t// If you want your workloads admitted in namespaces enforced with the restricted mode in OpenShift/OKD vendors\n\t\t\t\t\t\t\t// then, you MUST ensure that the Dockerfile defines a User ID OR you MUST leave the \"RunAsNonRoot\" and\n\t\t\t\t\t\t\t// \"RunAsUser\" fields empty.\n\t\t\t\t\t\t\tRunAsNonRoot:             ptr.To(true),\n\t\t\t\t\t\t\tRunAsUser:                ptr.To(int64(1001)),\n\t\t\t\t\t\t\tAllowPrivilegeEscalation: ptr.To(false),\n\t\t\t\t\t\t\tCapabilities: &corev1.Capabilities{\n\t\t\t\t\t\t\t\tDrop: []corev1.Capability{\n\t\t\t\t\t\t\t\t\t\"ALL\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tPorts: []corev1.ContainerPort{{\n\t\t\t\t\t\t\tContainerPort: memcached.Spec.ContainerPort,\n\t\t\t\t\t\t\tName:          \"memcached\",\n\t\t\t\t\t\t}},\n\t\t\t\t\t\tCommand: []string{\"memcached\", \"-m=64\", \"-o\", \"modern\", \"-v\"},\n\t\t\t\t\t}},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\t// Set the ownerRef for the Deployment\n\t// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/owners-dependents/\n\tif err := ctrl.SetControllerReference(memcached, dep, r.Scheme); err != nil {\n\t\treturn nil, err\n\t}\n\treturn dep, nil\n}\n\n// labelsForMemcached returns the labels for selecting the resources\n// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/\nfunc labelsForMemcached() map[string]string {\n\tvar imageTag string\n\timage, err := imageForMemcached()\n\tif err == nil {\n\t\timageTag = strings.Split(image, \":\")[1]\n\t}\n\treturn map[string]string{\n\t\t\"app.kubernetes.io/name\":       \"memcached-operator\",\n\t\t\"app.kubernetes.io/version\":    imageTag,\n\t\t\"app.kubernetes.io/managed-by\": \"MemcachedController\",\n\t}\n}\n\n// imageForMemcached gets the Operand image which is managed by this controller\n// from the MEMCACHED_IMAGE environment variable defined in the config/manager/manager.yaml\nfunc imageForMemcached() (string, error) {\n\tvar imageEnvVar = \"MEMCACHED_IMAGE\"\n\timage, found := os.LookupEnv(imageEnvVar)\n\tif !found {\n\t\treturn \"\", fmt.Errorf(\"unable to find %s environment variable with the image\", imageEnvVar)\n\t}\n\treturn image, nil\n}\n\n// SetupWithManager sets up the controller with the Manager.\n// The whole idea is to be watching the resources that matter for the controller.\n// When a resource that the controller is interested in changes, the Watch triggers\n// the controller’s reconciliation loop, ensuring that the actual state of the resource\n// matches the desired state as defined in the controller’s logic.\n//\n// Notice how we configured the Manager to monitor events such as the creation, update,\n// or deletion of a Custom Resource (CR) of the Memcached kind, as well as any changes\n// to the Deployment that the controller manages and owns.\nfunc (r *MemcachedReconciler) SetupWithManager(mgr ctrl.Manager) error {\n\treturn ctrl.NewControllerManagedBy(mgr).\n\t\t// Watch the Memcached CR(s) and trigger reconciliation whenever it\n\t\t// is created, updated, or deleted\n\t\tFor(&cachev1alpha1.Memcached{}).\n\t\tNamed(\"memcached\").\n\t\t// Watch the Deployment managed by the MemcachedReconciler. If any changes occur to the Deployment\n\t\t// owned and managed by this controller, it will trigger reconciliation, ensuring that the cluster\n\t\t// state aligns with the desired state. See that the ownerRef was set when the Deployment was created.\n\t\tOwns(&appsv1.Deployment{}).\n\t\tComplete(r)\n}\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/internal/controller/memcached_controller_test.go",
    "content": "/*\nCopyright 2026.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage controller\n\nimport (\n\t\"context\"\n\t\"os\"\n\t\"time\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\n\tappsv1 \"k8s.io/api/apps/v1\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\t\"k8s.io/apimachinery/pkg/api/errors\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/types\"\n\t\"sigs.k8s.io/controller-runtime/pkg/reconcile\"\n\n\tcachev1alpha1 \"github.com/example/memcached-operator/api/v1alpha1\"\n)\n\nvar _ = Describe(\"Memcached controller\", func() {\n\tContext(\"Memcached controller test\", func() {\n\n\t\tconst MemcachedName = \"test-memcached\"\n\n\t\tctx := context.Background()\n\n\t\tnamespace := &corev1.Namespace{\n\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\tName:      MemcachedName,\n\t\t\t\tNamespace: MemcachedName,\n\t\t\t},\n\t\t}\n\n\t\ttypeNamespacedName := types.NamespacedName{\n\t\t\tName:      MemcachedName,\n\t\t\tNamespace: MemcachedName,\n\t\t}\n\t\tmemcached := &cachev1alpha1.Memcached{}\n\n\t\tSetDefaultEventuallyTimeout(2 * time.Minute)\n\t\tSetDefaultEventuallyPollingInterval(time.Second)\n\n\t\tBeforeEach(func() {\n\t\t\tBy(\"Creating the Namespace to perform the tests\")\n\t\t\terr := k8sClient.Create(ctx, namespace)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"Setting the Image ENV VAR which stores the Operand image\")\n\t\t\terr = os.Setenv(\"MEMCACHED_IMAGE\", \"example.com/image:test\")\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"creating the custom resource for the Kind Memcached\")\n\t\t\terr = k8sClient.Get(ctx, typeNamespacedName, memcached)\n\t\t\tif err != nil && errors.IsNotFound(err) {\n\t\t\t\t// Let's mock our custom resource at the same way that we would\n\t\t\t\t// apply on the cluster the manifest under config/samples\n\t\t\t\tmemcached := &cachev1alpha1.Memcached{\n\t\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\t\tName:      MemcachedName,\n\t\t\t\t\t\tNamespace: namespace.Name,\n\t\t\t\t\t},\n\t\t\t\t\tSpec: cachev1alpha1.MemcachedSpec{\n\t\t\t\t\t\tSize:          1,\n\t\t\t\t\t\tContainerPort: 11211,\n\t\t\t\t\t},\n\t\t\t\t}\n\n\t\t\t\terr = k8sClient.Create(ctx, memcached)\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t}\n\t\t})\n\n\t\tAfterEach(func() {\n\t\t\tBy(\"removing the custom resource for the Kind Memcached\")\n\t\t\tfound := &cachev1alpha1.Memcached{}\n\t\t\terr := k8sClient.Get(ctx, typeNamespacedName, found)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tEventually(func(g Gomega) {\n\t\t\t\tg.Expect(k8sClient.Delete(context.TODO(), found)).To(Succeed())\n\t\t\t}).Should(Succeed())\n\n\t\t\t// TODO(user): Attention if you improve this code by adding other context test you MUST\n\t\t\t// be aware of the current delete namespace limitations.\n\t\t\t// More info: https://book.kubebuilder.io/reference/envtest.html#testing-considerations\n\t\t\tBy(\"Deleting the Namespace to perform the tests\")\n\t\t\t_ = k8sClient.Delete(ctx, namespace)\n\n\t\t\tBy(\"Removing the Image ENV VAR which stores the Operand image\")\n\t\t\t_ = os.Unsetenv(\"MEMCACHED_IMAGE\")\n\t\t})\n\n\t\tIt(\"should successfully reconcile a custom resource for Memcached\", func() {\n\t\t\tBy(\"Checking if the custom resource was successfully created\")\n\t\t\tEventually(func(g Gomega) {\n\t\t\t\tfound := &cachev1alpha1.Memcached{}\n\t\t\t\tExpect(k8sClient.Get(ctx, typeNamespacedName, found)).To(Succeed())\n\t\t\t}).Should(Succeed())\n\n\t\t\tBy(\"Reconciling the custom resource created\")\n\t\t\tmemcachedReconciler := &MemcachedReconciler{\n\t\t\t\tClient: k8sClient,\n\t\t\t\tScheme: k8sClient.Scheme(),\n\t\t\t}\n\n\t\t\t_, err := memcachedReconciler.Reconcile(ctx, reconcile.Request{\n\t\t\t\tNamespacedName: typeNamespacedName,\n\t\t\t})\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"Checking if Deployment was successfully created in the reconciliation\")\n\t\t\tEventually(func(g Gomega) {\n\t\t\t\tfound := &appsv1.Deployment{}\n\t\t\t\tg.Expect(k8sClient.Get(ctx, typeNamespacedName, found)).To(Succeed())\n\t\t\t}).Should(Succeed())\n\n\t\t\tBy(\"Reconciling the custom resource again\")\n\t\t\t_, err = memcachedReconciler.Reconcile(ctx, reconcile.Request{\n\t\t\t\tNamespacedName: typeNamespacedName,\n\t\t\t})\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"Checking the latest Status Condition added to the Memcached instance\")\n\t\t\tExpect(k8sClient.Get(ctx, typeNamespacedName, memcached)).To(Succeed())\n\t\t\tvar conditions []metav1.Condition\n\t\t\tExpect(memcached.Status.Conditions).To(ContainElement(\n\t\t\t\tHaveField(\"Type\", Equal(typeAvailableMemcached)), &conditions))\n\t\t\tExpect(conditions).To(HaveLen(1), \"Multiple conditions of type %s\", typeAvailableMemcached)\n\t\t\tExpect(conditions[0].Status).To(Equal(metav1.ConditionTrue), \"condition %s\", typeAvailableMemcached)\n\t\t\tExpect(conditions[0].Reason).To(Equal(\"Reconciling\"), \"condition %s\", typeAvailableMemcached)\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/internal/controller/suite_test.go",
    "content": "/*\nCopyright 2026.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage controller\n\nimport (\n\t\"context\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\n\t\"k8s.io/client-go/kubernetes/scheme\"\n\t\"k8s.io/client-go/rest\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client\"\n\t\"sigs.k8s.io/controller-runtime/pkg/envtest\"\n\tlogf \"sigs.k8s.io/controller-runtime/pkg/log\"\n\t\"sigs.k8s.io/controller-runtime/pkg/log/zap\"\n\n\tcachev1alpha1 \"github.com/example/memcached-operator/api/v1alpha1\"\n\t// +kubebuilder:scaffold:imports\n)\n\n// These tests use Ginkgo (BDD-style Go testing framework). Refer to\n// http://onsi.github.io/ginkgo/ to learn more about Ginkgo.\n\nvar (\n\tctx       context.Context\n\tcancel    context.CancelFunc\n\ttestEnv   *envtest.Environment\n\tcfg       *rest.Config\n\tk8sClient client.Client\n)\n\nfunc TestControllers(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\n\tRunSpecs(t, \"Controller Suite\")\n}\n\nvar _ = BeforeSuite(func() {\n\tlogf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true)))\n\n\tctx, cancel = context.WithCancel(context.TODO())\n\n\tvar err error\n\terr = cachev1alpha1.AddToScheme(scheme.Scheme)\n\tExpect(err).NotTo(HaveOccurred())\n\n\t// +kubebuilder:scaffold:scheme\n\n\tBy(\"bootstrapping test environment\")\n\ttestEnv = &envtest.Environment{\n\t\tCRDDirectoryPaths:     []string{filepath.Join(\"..\", \"..\", \"config\", \"crd\", \"bases\")},\n\t\tErrorIfCRDPathMissing: true,\n\t}\n\n\t// Retrieve the first found binary directory to allow running tests from IDEs\n\tif getFirstFoundEnvTestBinaryDir() != \"\" {\n\t\ttestEnv.BinaryAssetsDirectory = getFirstFoundEnvTestBinaryDir()\n\t}\n\n\t// cfg is defined in this file globally.\n\tcfg, err = testEnv.Start()\n\tExpect(err).NotTo(HaveOccurred())\n\tExpect(cfg).NotTo(BeNil())\n\n\tk8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme})\n\tExpect(err).NotTo(HaveOccurred())\n\tExpect(k8sClient).NotTo(BeNil())\n})\n\nvar _ = AfterSuite(func() {\n\tBy(\"tearing down the test environment\")\n\tcancel()\n\terr := testEnv.Stop()\n\tExpect(err).NotTo(HaveOccurred())\n})\n\n// getFirstFoundEnvTestBinaryDir locates the first binary in the specified path.\n// ENVTEST-based tests depend on specific binaries, usually located in paths set by\n// controller-runtime. When running tests directly (e.g., via an IDE) without using\n// Makefile targets, the 'BinaryAssetsDirectory' must be explicitly configured.\n//\n// This function streamlines the process by finding the required binaries, similar to\n// setting the 'KUBEBUILDER_ASSETS' environment variable. To ensure the binaries are\n// properly set up, run 'make setup-envtest' beforehand.\nfunc getFirstFoundEnvTestBinaryDir() string {\n\tbasePath := filepath.Join(\"..\", \"..\", \"bin\", \"k8s\")\n\tentries, err := os.ReadDir(basePath)\n\tif err != nil {\n\t\tlogf.Log.Error(err, \"Failed to read directory\", \"path\", basePath)\n\t\treturn \"\"\n\t}\n\tfor _, entry := range entries {\n\t\tif entry.IsDir() {\n\t\t\treturn filepath.Join(basePath, entry.Name())\n\t\t}\n\t}\n\treturn \"\"\n}\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/internal/webhook/v1alpha1/memcached_webhook.go",
    "content": "/*\nCopyright 2026.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage v1alpha1\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\tctrl \"sigs.k8s.io/controller-runtime\"\n\tlogf \"sigs.k8s.io/controller-runtime/pkg/log\"\n\t\"sigs.k8s.io/controller-runtime/pkg/webhook\"\n\n\tcachev1alpha1 \"github.com/example/memcached-operator/api/v1alpha1\"\n)\n\n// nolint:unused\n// log is for logging in this package.\nvar memcachedlog = logf.Log.WithName(\"memcached-resource\")\n\n// SetupMemcachedWebhookWithManager registers the webhook for Memcached in the manager.\nfunc SetupMemcachedWebhookWithManager(mgr ctrl.Manager) error {\n\treturn ctrl.NewWebhookManagedBy(mgr).For(&cachev1alpha1.Memcached{}).\n\t\tWithDefaulter(&MemcachedCustomDefaulter{}).\n\t\tComplete()\n}\n\n// TODO(user): EDIT THIS FILE!  THIS IS SCAFFOLDING FOR YOU TO OWN!\n\n// +kubebuilder:webhook:path=/mutate-cache-example-com-v1alpha1-memcached,mutating=true,failurePolicy=fail,sideEffects=None,groups=cache.example.com,resources=memcacheds,verbs=create;update,versions=v1alpha1,name=mmemcached-v1alpha1.kb.io,admissionReviewVersions=v1\n\n// MemcachedCustomDefaulter struct is responsible for setting default values on the custom resource of the\n// Kind Memcached when those are created or updated.\n//\n// NOTE: The +kubebuilder:object:generate=false marker prevents controller-gen from generating DeepCopy methods,\n// as it is used only for temporary operations and does not need to be deeply copied.\ntype MemcachedCustomDefaulter struct {\n\t// TODO(user): Add more fields as needed for defaulting\n}\n\nvar _ webhook.CustomDefaulter = &MemcachedCustomDefaulter{}\n\n// Default implements webhook.CustomDefaulter so a webhook will be registered for the Kind Memcached.\nfunc (d *MemcachedCustomDefaulter) Default(_ context.Context, obj runtime.Object) error {\n\tmemcached, ok := obj.(*cachev1alpha1.Memcached)\n\n\tif !ok {\n\t\treturn fmt.Errorf(\"expected an Memcached object but got %T\", obj)\n\t}\n\tmemcachedlog.Info(\"Defaulting for Memcached\", \"name\", memcached.GetName())\n\n\tif memcached.Spec.Size == 0 {\n\t\tmemcached.Spec.Size = 3\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/internal/webhook/v1alpha1/memcached_webhook_test.go",
    "content": "/*\nCopyright 2026.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage v1alpha1\n\nimport (\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\n\tcachev1alpha1 \"github.com/example/memcached-operator/api/v1alpha1\"\n\t// TODO (user): Add any additional imports if needed\n)\n\nvar _ = Describe(\"Memcached Webhook\", func() {\n\tvar (\n\t\tobj       *cachev1alpha1.Memcached\n\t\toldObj    *cachev1alpha1.Memcached\n\t\tdefaulter MemcachedCustomDefaulter\n\t)\n\n\tBeforeEach(func() {\n\t\tobj = &cachev1alpha1.Memcached{}\n\t\toldObj = &cachev1alpha1.Memcached{}\n\t\tdefaulter = MemcachedCustomDefaulter{}\n\t\tExpect(defaulter).NotTo(BeNil(), \"Expected defaulter to be initialized\")\n\t\tExpect(oldObj).NotTo(BeNil(), \"Expected oldObj to be initialized\")\n\t\tExpect(obj).NotTo(BeNil(), \"Expected obj to be initialized\")\n\t\t// TODO (user): Add any setup logic common to all tests\n\t})\n\n\tAfterEach(func() {\n\t\t// TODO (user): Add any teardown logic common to all tests\n\t})\n\n\tContext(\"When creating Memcached under Defaulting Webhook\", func() {\n\t\t// TODO (user): Add logic for defaulting webhooks\n\t\t// Example:\n\t\t// It(\"Should apply defaults when a required field is empty\", func() {\n\t\t//     By(\"simulating a scenario where defaults should be applied\")\n\t\t//     obj.SomeFieldWithDefault = \"\"\n\t\t//     By(\"calling the Default method to apply defaults\")\n\t\t//     defaulter.Default(ctx, obj)\n\t\t//     By(\"checking that the default values are set\")\n\t\t//     Expect(obj.SomeFieldWithDefault).To(Equal(\"default_value\"))\n\t\t// })\n\t})\n\n})\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/internal/webhook/v1alpha1/webhook_suite_test.go",
    "content": "/*\nCopyright 2026.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage v1alpha1\n\nimport (\n\t\"context\"\n\t\"crypto/tls\"\n\t\"fmt\"\n\t\"net\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\t\"time\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\n\t\"k8s.io/client-go/kubernetes/scheme\"\n\t\"k8s.io/client-go/rest\"\n\tctrl \"sigs.k8s.io/controller-runtime\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client\"\n\t\"sigs.k8s.io/controller-runtime/pkg/envtest\"\n\tlogf \"sigs.k8s.io/controller-runtime/pkg/log\"\n\t\"sigs.k8s.io/controller-runtime/pkg/log/zap\"\n\tmetricsserver \"sigs.k8s.io/controller-runtime/pkg/metrics/server\"\n\t\"sigs.k8s.io/controller-runtime/pkg/webhook\"\n\n\tcachev1alpha1 \"github.com/example/memcached-operator/api/v1alpha1\"\n\t// +kubebuilder:scaffold:imports\n)\n\n// These tests use Ginkgo (BDD-style Go testing framework). Refer to\n// http://onsi.github.io/ginkgo/ to learn more about Ginkgo.\n\nvar (\n\tctx       context.Context\n\tcancel    context.CancelFunc\n\tk8sClient client.Client\n\tcfg       *rest.Config\n\ttestEnv   *envtest.Environment\n)\n\nfunc TestAPIs(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\n\tRunSpecs(t, \"Webhook Suite\")\n}\n\nvar _ = BeforeSuite(func() {\n\tlogf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true)))\n\n\tctx, cancel = context.WithCancel(context.TODO())\n\n\tvar err error\n\terr = cachev1alpha1.AddToScheme(scheme.Scheme)\n\tExpect(err).NotTo(HaveOccurred())\n\n\t// +kubebuilder:scaffold:scheme\n\n\tBy(\"bootstrapping test environment\")\n\ttestEnv = &envtest.Environment{\n\t\tCRDDirectoryPaths:     []string{filepath.Join(\"..\", \"..\", \"..\", \"config\", \"crd\", \"bases\")},\n\t\tErrorIfCRDPathMissing: false,\n\n\t\tWebhookInstallOptions: envtest.WebhookInstallOptions{\n\t\t\tPaths: []string{filepath.Join(\"..\", \"..\", \"..\", \"config\", \"webhook\")},\n\t\t},\n\t}\n\n\t// Retrieve the first found binary directory to allow running tests from IDEs\n\tif getFirstFoundEnvTestBinaryDir() != \"\" {\n\t\ttestEnv.BinaryAssetsDirectory = getFirstFoundEnvTestBinaryDir()\n\t}\n\n\t// cfg is defined in this file globally.\n\tcfg, err = testEnv.Start()\n\tExpect(err).NotTo(HaveOccurred())\n\tExpect(cfg).NotTo(BeNil())\n\n\tk8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme})\n\tExpect(err).NotTo(HaveOccurred())\n\tExpect(k8sClient).NotTo(BeNil())\n\n\t// start webhook server using Manager.\n\twebhookInstallOptions := &testEnv.WebhookInstallOptions\n\tmgr, err := ctrl.NewManager(cfg, ctrl.Options{\n\t\tScheme: scheme.Scheme,\n\t\tWebhookServer: webhook.NewServer(webhook.Options{\n\t\t\tHost:    webhookInstallOptions.LocalServingHost,\n\t\t\tPort:    webhookInstallOptions.LocalServingPort,\n\t\t\tCertDir: webhookInstallOptions.LocalServingCertDir,\n\t\t}),\n\t\tLeaderElection: false,\n\t\tMetrics:        metricsserver.Options{BindAddress: \"0\"},\n\t})\n\tExpect(err).NotTo(HaveOccurred())\n\n\terr = SetupMemcachedWebhookWithManager(mgr)\n\tExpect(err).NotTo(HaveOccurred())\n\n\t// +kubebuilder:scaffold:webhook\n\n\tgo func() {\n\t\tdefer GinkgoRecover()\n\t\terr = mgr.Start(ctx)\n\t\tExpect(err).NotTo(HaveOccurred())\n\t}()\n\n\t// wait for the webhook server to get ready.\n\tdialer := &net.Dialer{Timeout: time.Second}\n\taddrPort := fmt.Sprintf(\"%s:%d\", webhookInstallOptions.LocalServingHost, webhookInstallOptions.LocalServingPort)\n\tEventually(func() error {\n\t\tconn, err := tls.DialWithDialer(dialer, \"tcp\", addrPort, &tls.Config{InsecureSkipVerify: true})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\treturn conn.Close()\n\t}).Should(Succeed())\n})\n\nvar _ = AfterSuite(func() {\n\tBy(\"tearing down the test environment\")\n\tcancel()\n\terr := testEnv.Stop()\n\tExpect(err).NotTo(HaveOccurred())\n})\n\n// getFirstFoundEnvTestBinaryDir locates the first binary in the specified path.\n// ENVTEST-based tests depend on specific binaries, usually located in paths set by\n// controller-runtime. When running tests directly (e.g., via an IDE) without using\n// Makefile targets, the 'BinaryAssetsDirectory' must be explicitly configured.\n//\n// This function streamlines the process by finding the required binaries, similar to\n// setting the 'KUBEBUILDER_ASSETS' environment variable. To ensure the binaries are\n// properly set up, run 'make setup-envtest' beforehand.\nfunc getFirstFoundEnvTestBinaryDir() string {\n\tbasePath := filepath.Join(\"..\", \"..\", \"..\", \"bin\", \"k8s\")\n\tentries, err := os.ReadDir(basePath)\n\tif err != nil {\n\t\tlogf.Log.Error(err, \"Failed to read directory\", \"path\", basePath)\n\t\treturn \"\"\n\t}\n\tfor _, entry := range entries {\n\t\tif entry.IsDir() {\n\t\t\treturn filepath.Join(basePath, entry.Name())\n\t\t}\n\t}\n\treturn \"\"\n}\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/test/e2e/e2e_suite_test.go",
    "content": "/*\nCopyright 2022.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage e2e\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\n// Run e2e tests using the Ginkgo runner.\nfunc TestE2E(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tfmt.Fprintf(GinkgoWriter, \"Starting Memcached Operator suite\\n\")\n\tRunSpecs(t, \"Memcached e2e suite\")\n}\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/test/e2e/e2e_test.go",
    "content": "/*\nCopyright 2022.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage e2e\n\nimport (\n\t\"fmt\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"time\"\n\n\t//nolint:golint\n\t//nolint:revive\n\t. \"github.com/onsi/ginkgo/v2\"\n\n\t//nolint:golint\n\t//nolint:revive\n\t. \"github.com/onsi/gomega\"\n\n\t\"github.com/example/memcached-operator/test/utils\"\n)\n\n// constant parts of the file\nconst namespace = \"memcached-operator-system\"\n\nvar _ = Describe(\"memcached\", Ordered, func() {\n\tBeforeAll(func() {\n\t\t// The prometheus and the certmanager are installed in this test\n\t\t// because the Memcached sample has this option enable and\n\t\t// when we try to apply the manifests both will be required to be installed\n\t\tBy(\"installing prometheus operator\")\n\t\tExpect(utils.InstallPrometheusOperator()).To(Succeed())\n\n\t\tBy(\"installing the cert-manager\")\n\t\tExpect(utils.InstallCertManager()).To(Succeed())\n\n\t\t// The namespace can be created when we run make install\n\t\t// However, in this test we want ensure that the solution\n\t\t// can run in a ns labeled as restricted. Therefore, we are\n\t\t// creating the namespace an lebeling it.\n\t\tBy(\"creating manager namespace\")\n\t\tcmd := exec.Command(\"kubectl\", \"create\", \"ns\", namespace)\n\t\t_, _ = utils.Run(cmd)\n\n\t\t// Now, let's ensure that all namespaces can raise an Warn when we apply the manifests\n\t\t// and that the namespace where the Operator and Operand will run are enforced as\n\t\t// restricted so that we can ensure that both can be admitted and run with the enforcement\n\t\tBy(\"labeling all namespaces to warn when we apply the manifest if would violate the PodStandards\")\n\t\tcmd = exec.Command(\"kubectl\", \"label\", \"--overwrite\", \"ns\", \"--all\",\n\t\t\t\"pod-security.kubernetes.io/audit=restricted\",\n\t\t\t\"pod-security.kubernetes.io/enforce-version=v1.24\",\n\t\t\t\"pod-security.kubernetes.io/warn=restricted\")\n\t\t_, err := utils.Run(cmd)\n\t\tExpectWithOffset(1, err).NotTo(HaveOccurred())\n\n\t\tBy(\"labeling enforce the namespace where the Operator and Operand(s) will run\")\n\t\tcmd = exec.Command(\"kubectl\", \"label\", \"--overwrite\", \"ns\", namespace,\n\t\t\t\"pod-security.kubernetes.io/audit=restricted\",\n\t\t\t\"pod-security.kubernetes.io/enforce-version=v1.24\",\n\t\t\t\"pod-security.kubernetes.io/enforce=restricted\")\n\t\t_, err = utils.Run(cmd)\n\t\tExpect(err).To(Not(HaveOccurred()))\n\t})\n\n\tAfterAll(func() {\n\t\tBy(\"uninstalling the Prometheus manager bundle\")\n\t\tutils.UninstallPrometheusOperator()\n\n\t\tBy(\"uninstalling the cert-manager bundle\")\n\t\tutils.UninstallCertManager()\n\n\t\tBy(\"removing manager namespace\")\n\t\tcmd := exec.Command(\"kubectl\", \"create\", \"ns\", namespace)\n\t\t_, _ = utils.Run(cmd)\n\t})\n\n\tContext(\"Memcached Operator\", func() {\n\t\tIt(\"should run successfully\", func() {\n\t\t\tvar controllerPodName string\n\t\t\tvar err error\n\t\t\tprojectDir, _ := utils.GetProjectDir()\n\n\t\t\t// operatorImage stores the name of the image used in the example\n\t\t\tvar operatorImage = \"example.com/memcached-operator:v0.0.1\"\n\n\t\t\tBy(\"building the manager(Operator) image\")\n\t\t\tcmd := exec.Command(\"make\", \"docker-build\", fmt.Sprintf(\"IMG=%s\", operatorImage))\n\t\t\t_, err = utils.Run(cmd)\n\t\t\tExpectWithOffset(1, err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"loading the manager(Operator) image on Kind\")\n\t\t\terr = utils.LoadImageToKindClusterWithName(operatorImage)\n\t\t\tExpectWithOffset(1, err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"installing CRDs\")\n\t\t\tcmd = exec.Command(\"make\", \"install\")\n\t\t\t_, err = utils.Run(cmd)\n\t\t\tExpectWithOffset(1, err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"deploying the controller-manager\")\n\t\t\tcmd = exec.Command(\"make\", \"deploy\", fmt.Sprintf(\"IMG=%s\", operatorImage))\n\t\t\toutputMake, err := utils.Run(cmd)\n\t\t\tExpectWithOffset(1, err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"validating that manager Pod/container(s) are restricted\")\n\t\t\tExpectWithOffset(1, outputMake).NotTo(ContainSubstring(\"Warning: would violate PodSecurity\"))\n\n\t\t\tBy(\"validating that the controller-manager pod is running as expected\")\n\t\t\tverifyControllerUp := func() error {\n\t\t\t\t// Get pod name\n\t\t\t\tcmd = exec.Command(\"kubectl\", \"get\",\n\t\t\t\t\t\"pods\", \"-l\", \"control-plane=controller-manager\",\n\t\t\t\t\t\"-o\", \"go-template={{ range .items }}{{ if not .metadata.deletionTimestamp }}{{ .metadata.name }}\"+\n\t\t\t\t\t\t\"{{ \\\"\\\\n\\\" }}{{ end }}{{ end }}\",\n\t\t\t\t\t\"-n\", namespace,\n\t\t\t\t)\n\t\t\t\tpodOutput, err := utils.Run(cmd)\n\t\t\t\tExpectWithOffset(2, err).NotTo(HaveOccurred())\n\t\t\t\tpodNames := utils.GetNonEmptyLines(string(podOutput))\n\t\t\t\tif len(podNames) != 1 {\n\t\t\t\t\treturn fmt.Errorf(\"expect 1 controller pods running, but got %d\", len(podNames))\n\t\t\t\t}\n\t\t\t\tcontrollerPodName = podNames[0]\n\t\t\t\tExpectWithOffset(2, controllerPodName).Should(ContainSubstring(\"controller-manager\"))\n\n\t\t\t\t// Validate pod status\n\t\t\t\tcmd = exec.Command(\"kubectl\", \"get\",\n\t\t\t\t\t\"pods\", controllerPodName, \"-o\", \"jsonpath={.status.phase}\",\n\t\t\t\t\t\"-n\", namespace,\n\t\t\t\t)\n\t\t\t\tstatus, err := utils.Run(cmd)\n\t\t\t\tExpectWithOffset(2, err).NotTo(HaveOccurred())\n\t\t\t\tif string(status) != \"Running\" {\n\t\t\t\t\treturn fmt.Errorf(\"controller pod in %s status\", status)\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tEventuallyWithOffset(1, verifyControllerUp, time.Minute, time.Second).Should(Succeed())\n\n\t\t\tBy(\"creating an instance of the Memcached Operand(CR)\")\n\t\t\tEventuallyWithOffset(1, func() error {\n\t\t\t\tcmd = exec.Command(\"kubectl\", \"apply\", \"-f\", filepath.Join(projectDir,\n\t\t\t\t\t\"config/samples/cache_v1alpha1_memcached.yaml\"), \"-n\", namespace)\n\t\t\t\t_, err = utils.Run(cmd)\n\t\t\t\treturn err\n\t\t\t}, time.Minute, time.Second).Should(Succeed())\n\n\t\t\tBy(\"validating that pod(s) status.phase=Running\")\n\t\t\tgetMemcachedPodStatus := func() error {\n\t\t\t\tcmd = exec.Command(\"kubectl\", \"get\",\n\t\t\t\t\t\"pods\", \"-l\", \"app.kubernetes.io/name=memcached-operator\",\n\t\t\t\t\t\"-o\", \"jsonpath={.items[*].status}\", \"-n\", namespace,\n\t\t\t\t)\n\t\t\t\tstatus, err := utils.Run(cmd)\n\t\t\t\tfmt.Println(string(status))\n\t\t\t\tExpectWithOffset(2, err).NotTo(HaveOccurred())\n\t\t\t\tif !strings.Contains(string(status), \"\\\"phase\\\":\\\"Running\\\"\") {\n\t\t\t\t\treturn fmt.Errorf(\"memcached pod in %s status\", status)\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tEventuallyWithOffset(1, getMemcachedPodStatus, time.Minute, time.Second).Should(Succeed())\n\n\t\t\tBy(\"validating that the status of the custom resource created is updated or not\")\n\t\t\tgetStatus := func() error {\n\t\t\t\tcmd = exec.Command(\"kubectl\", \"get\", \"memcached\",\n\t\t\t\t\t\"memcached-sample\", \"-o\", \"jsonpath={.status.conditions}\",\n\t\t\t\t\t\"-n\", namespace,\n\t\t\t\t)\n\t\t\t\tstatus, err := utils.Run(cmd)\n\t\t\t\tfmt.Println(string(status))\n\t\t\t\tExpectWithOffset(2, err).NotTo(HaveOccurred())\n\t\t\t\tif !strings.Contains(string(status), \"Available\") {\n\t\t\t\t\treturn fmt.Errorf(\"status condition with type Available should be set\")\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tEventually(getStatus, time.Minute, time.Second).Should(Succeed())\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "testdata/go/v4/memcached-operator/test/utils/utils.go",
    "content": "/*\nCopyright 2022.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage utils\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strings\"\n\n\t. \"github.com/onsi/ginkgo/v2\" //nolint:golint,revive\n)\n\nconst (\n\tprometheusOperatorVersion = \"0.51\"\n\tprometheusOperatorURL     = \"https://raw.githubusercontent.com/prometheus-operator/\" +\n\t\t\"prometheus-operator/release-%s/bundle.yaml\"\n\n\tcertmanagerVersion = \"v1.5.3\"\n\tcertmanagerURLTmpl = \"https://github.com/jetstack/cert-manager/releases/download/%s/cert-manager.yaml\"\n)\n\nfunc warnError(err error) {\n\tfmt.Fprintf(GinkgoWriter, \"warning: %v\\n\", err)\n}\n\n// InstallPrometheusOperator installs the prometheus Operator to be used to export the enabled metrics.\nfunc InstallPrometheusOperator() error {\n\turl := fmt.Sprintf(prometheusOperatorURL, prometheusOperatorVersion)\n\tcmd := exec.Command(\"kubectl\", \"apply\", \"-f\", url)\n\t_, err := Run(cmd)\n\treturn err\n}\n\n// Run executes the provided command within this context\nfunc Run(cmd *exec.Cmd) ([]byte, error) {\n\tdir, _ := GetProjectDir()\n\tcmd.Dir = dir\n\tfmt.Fprintf(GinkgoWriter, \"running dir: %s\\n\", cmd.Dir)\n\n\t// To allow make commands be executed from the project directory which is subdir on SDK repo\n\t// TODO:(user) You might not need the following code\n\tif err := os.Chdir(cmd.Dir); err != nil {\n\t\tfmt.Fprintf(GinkgoWriter, \"chdir dir: %s\\n\", err)\n\t}\n\n\tcmd.Env = append(os.Environ(), \"GO111MODULE=on\")\n\tcommand := strings.Join(cmd.Args, \" \")\n\tfmt.Fprintf(GinkgoWriter, \"running: %s\\n\", command)\n\toutput, err := cmd.CombinedOutput()\n\tif err != nil {\n\t\treturn output, fmt.Errorf(\"%s failed with error: (%v) %s\", command, err, string(output))\n\t}\n\n\treturn output, nil\n}\n\n// UninstallPrometheusOperator uninstalls the prometheus\nfunc UninstallPrometheusOperator() {\n\turl := fmt.Sprintf(prometheusOperatorURL, prometheusOperatorVersion)\n\tcmd := exec.Command(\"kubectl\", \"delete\", \"-f\", url)\n\tif _, err := Run(cmd); err != nil {\n\t\twarnError(err)\n\t}\n}\n\n// UninstallCertManager uninstalls the cert manager\nfunc UninstallCertManager() {\n\turl := fmt.Sprintf(certmanagerURLTmpl, certmanagerVersion)\n\tcmd := exec.Command(\"kubectl\", \"delete\", \"-f\", url)\n\tif _, err := Run(cmd); err != nil {\n\t\twarnError(err)\n\t}\n}\n\n// InstallCertManager installs the cert manager bundle.\nfunc InstallCertManager() error {\n\turl := fmt.Sprintf(certmanagerURLTmpl, certmanagerVersion)\n\tcmd := exec.Command(\"kubectl\", \"apply\", \"-f\", url)\n\tif _, err := Run(cmd); err != nil {\n\t\treturn err\n\t}\n\t// Wait for cert-manager-webhook to be ready, which can take time if cert-manager\n\t// was re-installed after uninstalling on a cluster.\n\tcmd = exec.Command(\"kubectl\", \"wait\", \"deployment.apps/cert-manager-webhook\",\n\t\t\"--for\", \"condition=Available\",\n\t\t\"--namespace\", \"cert-manager\",\n\t\t\"--timeout\", \"5m\",\n\t)\n\n\t_, err := Run(cmd)\n\treturn err\n}\n\n// LoadImageToKindCluster loads a local docker image to the kind cluster\nfunc LoadImageToKindClusterWithName(name string) error {\n\tcluster := \"kind\"\n\tif v, ok := os.LookupEnv(\"KIND_CLUSTER\"); ok {\n\t\tcluster = v\n\t}\n\tkindOptions := []string{\"load\", \"docker-image\", name, \"--name\", cluster}\n\tcmd := exec.Command(\"kind\", kindOptions...)\n\t_, err := Run(cmd)\n\treturn err\n}\n\n// GetNonEmptyLines converts given command output string into individual objects\n// according to line breakers, and ignores the empty elements in it.\nfunc GetNonEmptyLines(output string) []string {\n\tvar res []string\n\telements := strings.Split(output, \"\\n\")\n\tfor _, element := range elements {\n\t\tif element != \"\" {\n\t\t\tres = append(res, element)\n\t\t}\n\t}\n\n\treturn res\n}\n\n// GetProjectDir will return the directory where the project is\nfunc GetProjectDir() (string, error) {\n\twd, err := os.Getwd()\n\tif err != nil {\n\t\treturn wd, err\n\t}\n\twd = strings.Replace(wd, \"/test/e2e\", \"\", -1)\n\treturn wd, nil\n}\n\n// ReplaceInFile replaces all instances of old with new in the file at path.\nfunc ReplaceInFile(path, old, new string) error {\n\tinfo, err := os.Stat(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\t// false positive\n\t// nolint:gosec\n\tb, err := os.ReadFile(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif !strings.Contains(string(b), old) {\n\t\treturn errors.New(\"unable to find the content to be replaced\")\n\t}\n\ts := strings.Replace(string(b), old, new, -1)\n\terr = os.WriteFile(path, []byte(s), info.Mode())\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/.devcontainer/devcontainer.json",
    "content": "{\n  \"name\": \"Kubebuilder DevContainer\",\n  \"image\": \"golang:1.24\",\n  \"features\": {\n    \"ghcr.io/devcontainers/features/docker-in-docker:2\": {},\n    \"ghcr.io/devcontainers/features/git:1\": {}\n  },\n\n  \"runArgs\": [\"--network=host\"],\n\n  \"customizations\": {\n    \"vscode\": {\n      \"settings\": {\n        \"terminal.integrated.shell.linux\": \"/bin/bash\"\n      },\n      \"extensions\": [\n        \"ms-kubernetes-tools.vscode-kubernetes-tools\",\n        \"ms-azuretools.vscode-docker\"\n      ]\n    }\n  },\n\n  \"onCreateCommand\": \"bash .devcontainer/post-install.sh\"\n}\n\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/.devcontainer/post-install.sh",
    "content": "#!/bin/bash\nset -x\n\ncurl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64\nchmod +x ./kind\nmv ./kind /usr/local/bin/kind\n\ncurl -L -o kubebuilder https://go.kubebuilder.io/dl/latest/linux/amd64\nchmod +x kubebuilder\nmv kubebuilder /usr/local/bin/\n\nKUBECTL_VERSION=$(curl -L -s https://dl.k8s.io/release/stable.txt)\ncurl -LO \"https://dl.k8s.io/release/$KUBECTL_VERSION/bin/linux/amd64/kubectl\"\nchmod +x kubectl\nmv kubectl /usr/local/bin/kubectl\n\ndocker network create -d=bridge --subnet=172.19.0.0/24 kind\n\nkind version\nkubebuilder version\ndocker --version\ngo version\nkubectl version --client\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/.dockerignore",
    "content": "# More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file\n# Ignore build and test binaries.\nbin/\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/.github/workflows/lint.yml",
    "content": "name: Lint\n\non:\n  push:\n  pull_request:\n\njobs:\n  lint:\n    name: Run on Ubuntu\n    runs-on: ubuntu-latest\n    steps:\n      - name: Clone the code\n        uses: actions/checkout@v4\n\n      - name: Setup Go\n        uses: actions/setup-go@v5\n        with:\n          go-version-file: go.mod\n\n      - name: Run linter\n        uses: golangci/golangci-lint-action@v8\n        with:\n          version: v2.1.0\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/.github/workflows/test-e2e.yml",
    "content": "name: E2E Tests\n\non:\n  push:\n  pull_request:\n\njobs:\n  test-e2e:\n    name: Run on Ubuntu\n    runs-on: ubuntu-latest\n    steps:\n      - name: Clone the code\n        uses: actions/checkout@v4\n\n      - name: Setup Go\n        uses: actions/setup-go@v5\n        with:\n          go-version-file: go.mod\n\n      - name: Install the latest version of kind\n        run: |\n          curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64\n          chmod +x ./kind\n          sudo mv ./kind /usr/local/bin/kind\n\n      - name: Verify kind installation\n        run: kind version\n\n      - name: Running Test e2e\n        run: |\n          go mod tidy\n          make test-e2e\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/.github/workflows/test.yml",
    "content": "name: Tests\n\non:\n  push:\n  pull_request:\n\njobs:\n  test:\n    name: Run on Ubuntu\n    runs-on: ubuntu-latest\n    steps:\n      - name: Clone the code\n        uses: actions/checkout@v4\n\n      - name: Setup Go\n        uses: actions/setup-go@v5\n        with:\n          go-version-file: go.mod\n\n      - name: Running Tests\n        run: |\n          go mod tidy\n          make test\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/.gitignore",
    "content": "# Binaries for programs and plugins\n*.exe\n*.exe~\n*.dll\n*.so\n*.dylib\nbin/*\nDockerfile.cross\n\n# Test binary, built with `go test -c`\n*.test\n\n# Output of the go coverage tool, specifically when used with LiteIDE\n*.out\n\n# Go workspace file\ngo.work\n\n# Kubernetes Generated files - skip generated files, except for vendored files\n!vendor/**/zz_generated.*\n\n# editor and IDE paraphernalia\n.idea\n.vscode\n*.swp\n*.swo\n*~\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/.golangci.yml",
    "content": "version: \"2\"\nrun:\n  allow-parallel-runners: true\nlinters:\n  default: none\n  enable:\n    - copyloopvar\n    - dupl\n    - errcheck\n    - ginkgolinter\n    - goconst\n    - gocyclo\n    - govet\n    - ineffassign\n    - lll\n    - misspell\n    - nakedret\n    - prealloc\n    - revive\n    - staticcheck\n    - unconvert\n    - unparam\n    - unused\n  settings:\n    revive:\n      rules:\n        - name: comment-spacings\n        - name: import-shadowing\n  exclusions:\n    generated: lax\n    rules:\n      - linters:\n          - lll\n        path: api/*\n      - linters:\n          - dupl\n          - lll\n        path: internal/*\n    paths:\n      - third_party$\n      - builtin$\n      - examples$\nformatters:\n  enable:\n    - gofmt\n    - goimports\n  exclusions:\n    generated: lax\n    paths:\n      - third_party$\n      - builtin$\n      - examples$\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/Dockerfile",
    "content": "# Build the manager binary\nFROM golang:1.24 AS builder\nARG TARGETOS\nARG TARGETARCH\n\nWORKDIR /workspace\n# Copy the Go Modules manifests\nCOPY go.mod go.mod\nCOPY go.sum go.sum\n# cache deps before building and copying source so that we don't need to re-download as much\n# and so that source changes don't invalidate our downloaded layer\nRUN go mod download\n\n# Copy the go source\nCOPY cmd/main.go cmd/main.go\nCOPY api/ api/\nCOPY internal/ internal/\n\nCOPY monitoring/ monitoring/\n# Build\n# the GOARCH has not a default value to allow the binary be built according to the host where the command\n# was called. For example, if we call make docker-build in a local env which has the Apple Silicon M1 SO\n# the docker BUILDPLATFORM arg will be linux/arm64 when for Apple x86 it will be linux/amd64. Therefore,\n# by leaving it empty we can ensure that the container and binary shipped on it will have the same platform.\nRUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o manager cmd/main.go\n\n# Use distroless as minimal base image to package the manager binary\n# Refer to https://github.com/GoogleContainerTools/distroless for more details\nFROM gcr.io/distroless/static:nonroot\nWORKDIR /\nCOPY --from=builder /workspace/manager .\nUSER 65532:65532\n\nENTRYPOINT [\"/manager\"]\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/Makefile",
    "content": "# VERSION defines the project version for the bundle.\n# Update this value when you upgrade the version of your project.\n# To re-generate a bundle for another specific version without changing the standard setup, you can:\n# - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2)\n# - use environment variables to overwrite this value (e.g export VERSION=0.0.2)\nVERSION ?= 0.0.1\n\n# CHANNELS define the bundle channels used in the bundle.\n# Add a new line here if you would like to change its default config. (E.g CHANNELS = \"candidate,fast,stable\")\n# To re-generate a bundle for other specific channels without changing the standard setup, you can:\n# - use the CHANNELS as arg of the bundle target (e.g make bundle CHANNELS=candidate,fast,stable)\n# - use environment variables to overwrite this value (e.g export CHANNELS=\"candidate,fast,stable\")\nifneq ($(origin CHANNELS), undefined)\nBUNDLE_CHANNELS := --channels=$(CHANNELS)\nendif\n\n# DEFAULT_CHANNEL defines the default channel used in the bundle.\n# Add a new line here if you would like to change its default config. (E.g DEFAULT_CHANNEL = \"stable\")\n# To re-generate a bundle for any other default channel without changing the default setup, you can:\n# - use the DEFAULT_CHANNEL as arg of the bundle target (e.g make bundle DEFAULT_CHANNEL=stable)\n# - use environment variables to overwrite this value (e.g export DEFAULT_CHANNEL=\"stable\")\nifneq ($(origin DEFAULT_CHANNEL), undefined)\nBUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL)\nendif\nBUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL)\n\n# IMAGE_TAG_BASE defines the docker.io namespace and part of the image name for remote images.\n# This variable is used to construct full image tags for bundle and catalog images.\n#\n# For example, running 'make bundle-build bundle-push catalog-build catalog-push' will build and push both\n# example.com/memcached-operator-bundle:$VERSION and example.com/memcached-operator-catalog:$VERSION.\nIMAGE_TAG_BASE ?= example.com/memcached-operator\n\n# BUNDLE_IMG defines the image:tag used for the bundle.\n# You can use it as an arg. (E.g make bundle-build BUNDLE_IMG=<some-registry>/<project-name-bundle>:<tag>)\nBUNDLE_IMG ?= $(IMAGE_TAG_BASE)-bundle:v$(VERSION)\n\n# BUNDLE_GEN_FLAGS are the flags passed to the operator-sdk generate bundle command\nBUNDLE_GEN_FLAGS ?= -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS)\n\n# USE_IMAGE_DIGESTS defines if images are resolved via tags or digests\n# You can enable this value if you would like to use SHA Based Digests\n# To enable set flag to true\nUSE_IMAGE_DIGESTS ?= false\nifeq ($(USE_IMAGE_DIGESTS), true)\n\tBUNDLE_GEN_FLAGS += --use-image-digests\nendif\n\n# Set the Operator SDK version to use. By default, what is installed on the system is used.\n# This is useful for CI or a project to utilize a specific version of the operator-sdk toolkit.\nOPERATOR_SDK_VERSION ?= v1.42.2\n# Image URL to use all building/pushing image targets\nIMG ?= controller:latest\n\n# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)\nifeq (,$(shell go env GOBIN))\nGOBIN=$(shell go env GOPATH)/bin\nelse\nGOBIN=$(shell go env GOBIN)\nendif\n\n# CONTAINER_TOOL defines the container tool to be used for building images.\n# Be aware that the target commands are only tested with Docker which is\n# scaffolded by default. However, you might want to replace it to use other\n# tools. (i.e. podman)\nCONTAINER_TOOL ?= docker\n\n# Setting SHELL to bash allows bash commands to be executed by recipes.\n# Options are set to exit when a recipe line exits non-zero or a piped command fails.\nSHELL = /usr/bin/env bash -o pipefail\n.SHELLFLAGS = -ec\n\n.PHONY: all\nall: build\n\n##@ General\n\n# The help target prints out all targets with their descriptions organized\n# beneath their categories. The categories are represented by '##@' and the\n# target descriptions by '##'. The awk command is responsible for reading the\n# entire set of makefiles included in this invocation, looking for lines of the\n# file as xyz: ## something, and then pretty-format the target and help. Then,\n# if there's a line with ##@ something, that gets pretty-printed as a category.\n# More info on the usage of ANSI control characters for terminal formatting:\n# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters\n# More info on the awk command:\n# http://linuxcommand.org/lc3_adv_awk.php\n\n.PHONY: help\nhelp: ## Display this help.\n\t@awk 'BEGIN {FS = \":.*##\"; printf \"\\nUsage:\\n  make \\033[36m<target>\\033[0m\\n\"} /^[a-zA-Z_0-9-]+:.*?##/ { printf \"  \\033[36m%-15s\\033[0m %s\\n\", $$1, $$2 } /^##@/ { printf \"\\n\\033[1m%s\\033[0m\\n\", substr($$0, 5) } ' $(MAKEFILE_LIST)\n\n##@ Development\n\n.PHONY: manifests\nmanifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.\n\t$(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths=\"./...\" output:crd:artifacts:config=config/crd/bases\n\n.PHONY: generate\ngenerate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.\n\t$(CONTROLLER_GEN) object:headerFile=\"hack/boilerplate.go.txt\" paths=\"./...\"\n\n.PHONY: fmt\nfmt: ## Run go fmt against code.\n\tgo fmt ./...\n\n.PHONY: vet\nvet: ## Run go vet against code.\n\tgo vet ./...\n\n.PHONY: test\ntest: manifests generate fmt vet setup-envtest ## Run tests.\n\tKUBEBUILDER_ASSETS=\"$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)\"  go test $(shell go list ./... | grep -v /test/) -coverprofile cover.out\n\n# TODO(user): To use a different vendor for e2e tests, modify the setup under 'tests/e2e'.\n# The default setup assumes Kind is pre-installed and builds/loads the Manager Docker image locally.\n# CertManager is installed by default; skip with:\n# - CERT_MANAGER_INSTALL_SKIP=true\nKIND_CLUSTER ?= memcached-operator-test-e2e\n\n.PHONY: setup-test-e2e\nsetup-test-e2e: ## Set up a Kind cluster for e2e tests if it does not exist\n\t@command -v $(KIND) >/dev/null 2>&1 || { \\\n\t\techo \"Kind is not installed. Please install Kind manually.\"; \\\n\t\texit 1; \\\n\t}\n\t@case \"$$($(KIND) get clusters)\" in \\\n\t\t*\"$(KIND_CLUSTER)\"*) \\\n\t\t\techo \"Kind cluster '$(KIND_CLUSTER)' already exists. Skipping creation.\" ;; \\\n\t\t*) \\\n\t\t\techo \"Creating Kind cluster '$(KIND_CLUSTER)'...\"; \\\n\t\t\t$(KIND) create cluster --name $(KIND_CLUSTER) ;; \\\n\tesac\n\n.PHONY: test-e2e\ntest-e2e: setup-test-e2e manifests generate fmt vet ## Run the e2e tests. Expected an isolated environment using Kind.\n\tKIND_CLUSTER=$(KIND_CLUSTER) go test ./test/e2e/ -v -ginkgo.v\n\t$(MAKE) cleanup-test-e2e\n\n.PHONY: cleanup-test-e2e\ncleanup-test-e2e: ## Tear down the Kind cluster used for e2e tests\n\t@$(KIND) delete cluster --name $(KIND_CLUSTER)\n\n.PHONY: lint\nlint: golangci-lint ## Run golangci-lint linter\n\t$(GOLANGCI_LINT) run\n\n.PHONY: lint-fix\nlint-fix: golangci-lint ## Run golangci-lint linter and perform fixes\n\t$(GOLANGCI_LINT) run --fix\n\n.PHONY: lint-config\nlint-config: golangci-lint ## Verify golangci-lint linter configuration\n\t$(GOLANGCI_LINT) config verify\n\n##@ Build\n\n.PHONY: build\nbuild: manifests generate fmt vet ## Build manager binary.\n\tgo build -o bin/manager cmd/main.go\n\n.PHONY: run\nrun: manifests generate fmt vet ## Run a controller from your host.\n\tgo run ./cmd/main.go\n\n# If you wish to build the manager image targeting other platforms you can use the --platform flag.\n# (i.e. docker build --platform linux/arm64). However, you must enable docker buildKit for it.\n# More info: https://docs.docker.com/develop/develop-images/build_enhancements/\n.PHONY: docker-build\ndocker-build: ## Build docker image with the manager.\n\t$(CONTAINER_TOOL) build -t ${IMG} .\n\n.PHONY: docker-push\ndocker-push: ## Push docker image with the manager.\n\t$(CONTAINER_TOOL) push ${IMG}\n\n# PLATFORMS defines the target platforms for the manager image be built to provide support to multiple\n# architectures. (i.e. make docker-buildx IMG=myregistry/mypoperator:0.0.1). To use this option you need to:\n# - be able to use docker buildx. More info: https://docs.docker.com/build/buildx/\n# - have enabled BuildKit. More info: https://docs.docker.com/develop/develop-images/build_enhancements/\n# - be able to push the image to your registry (i.e. if you do not set a valid value via IMG=<myregistry/image:<tag>> then the export will fail)\n# To adequately provide solutions that are compatible with multiple platforms, you should consider using this option.\nPLATFORMS ?= linux/arm64,linux/amd64,linux/s390x,linux/ppc64le\n.PHONY: docker-buildx\ndocker-buildx: ## Build and push docker image for the manager for cross-platform support\n\t# copy existing Dockerfile and insert --platform=${BUILDPLATFORM} into Dockerfile.cross, and preserve the original Dockerfile\n\tsed -e '1 s/\\(^FROM\\)/FROM --platform=\\$$\\{BUILDPLATFORM\\}/; t' -e ' 1,// s//FROM --platform=\\$$\\{BUILDPLATFORM\\}/' Dockerfile > Dockerfile.cross\n\t- $(CONTAINER_TOOL) buildx create --name memcached-operator-builder\n\t$(CONTAINER_TOOL) buildx use memcached-operator-builder\n\t- $(CONTAINER_TOOL) buildx build --push --platform=$(PLATFORMS) --tag ${IMG} -f Dockerfile.cross .\n\t- $(CONTAINER_TOOL) buildx rm memcached-operator-builder\n\trm Dockerfile.cross\n\n.PHONY: build-installer\nbuild-installer: manifests generate kustomize ## Generate a consolidated YAML with CRDs and deployment.\n\tmkdir -p dist\n\tcd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}\n\t$(KUSTOMIZE) build config/default > dist/install.yaml\n\n##@ Deployment\n\nifndef ignore-not-found\n  ignore-not-found = false\nendif\n\n.PHONY: install\ninstall: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config.\n\t$(KUSTOMIZE) build config/crd | $(KUBECTL) apply -f -\n\n.PHONY: uninstall\nuninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.\n\t$(KUSTOMIZE) build config/crd | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f -\n\n.PHONY: deploy\ndeploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.\n\tcd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}\n\t$(KUSTOMIZE) build config/default | $(KUBECTL) apply -f -\n\n.PHONY: undeploy\nundeploy: kustomize ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.\n\t$(KUSTOMIZE) build config/default | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f -\nLDFLAGS            ?= -w -s\n\nbuild-prom-spec-dumper: ## Build binary from source\n\tgo build -ldflags=\"${LDFLAGS}\" -o _out/rule-spec-dumper ./monitoring/prom-rule-ci/rule-spec-dumper.go\n\ncurrent-dir := $(realpath .)\n\n# Unit testing for the operator alerts and recording rules\n# rule-spec-dumper dumps the prometheus rule spec to a temp _out/rule-spec-dumper file which prom-rules-tests runs against\nprom-rules-verify: build-prom-spec-dumper\n\t./monitoring/prom-rule-ci/verify-rules.sh \\\n\t\t\"${current-dir}/_out/rule-spec-dumper\" \\\n\t\t\"${current-dir}/monitoring/prom-rule-ci/prom-rules-tests.yaml\"\n\n\n\n##@ Dependencies\n\n## Location to install dependencies to\nLOCALBIN ?= $(shell pwd)/bin\n$(LOCALBIN):\n\tmkdir -p $(LOCALBIN)\n\n## Tool Binaries\nKUBECTL ?= kubectl\nKIND ?= kind\nKUSTOMIZE ?= $(LOCALBIN)/kustomize\nCONTROLLER_GEN ?= $(LOCALBIN)/controller-gen\nENVTEST ?= $(LOCALBIN)/setup-envtest\nGOLANGCI_LINT = $(LOCALBIN)/golangci-lint\n\n## Tool Versions\nKUSTOMIZE_VERSION ?= v5.6.0\nCONTROLLER_TOOLS_VERSION ?= v0.18.0\n#ENVTEST_VERSION is the version of controller-runtime release branch to fetch the envtest setup script (i.e. release-0.20)\nENVTEST_VERSION ?= $(shell go list -m -f \"{{ .Version }}\" sigs.k8s.io/controller-runtime | awk -F'[v.]' '{printf \"release-%d.%d\", $$2, $$3}')\n#ENVTEST_K8S_VERSION is the version of Kubernetes to use for setting up ENVTEST binaries (i.e. 1.31)\nENVTEST_K8S_VERSION ?= $(shell go list -m -f \"{{ .Version }}\" k8s.io/api | awk -F'[v.]' '{printf \"1.%d\", $$3}')\nGOLANGCI_LINT_VERSION ?= v2.1.0\n\n.PHONY: kustomize\nkustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary.\n$(KUSTOMIZE): $(LOCALBIN)\n\t$(call go-install-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v5,$(KUSTOMIZE_VERSION))\n\n.PHONY: controller-gen\ncontroller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary.\n$(CONTROLLER_GEN): $(LOCALBIN)\n\t$(call go-install-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen,$(CONTROLLER_TOOLS_VERSION))\n\n.PHONY: setup-envtest\nsetup-envtest: envtest ## Download the binaries required for ENVTEST in the local bin directory.\n\t@echo \"Setting up envtest binaries for Kubernetes version $(ENVTEST_K8S_VERSION)...\"\n\t@$(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path || { \\\n\t\techo \"Error: Failed to set up envtest binaries for version $(ENVTEST_K8S_VERSION).\"; \\\n\t\texit 1; \\\n\t}\n\n.PHONY: envtest\nenvtest: $(ENVTEST) ## Download setup-envtest locally if necessary.\n$(ENVTEST): $(LOCALBIN)\n\t$(call go-install-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest,$(ENVTEST_VERSION))\n\n.PHONY: golangci-lint\ngolangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary.\n$(GOLANGCI_LINT): $(LOCALBIN)\n\t$(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/v2/cmd/golangci-lint,$(GOLANGCI_LINT_VERSION))\n\n# go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist\n# $1 - target path with name of binary\n# $2 - package url which can be installed\n# $3 - specific version of package\ndefine go-install-tool\n@[ -f \"$(1)-$(3)\" ] || { \\\nset -e; \\\npackage=$(2)@$(3) ;\\\necho \"Downloading $${package}\" ;\\\nrm -f $(1) || true ;\\\nGOBIN=$(LOCALBIN) go install $${package} ;\\\nmv $(1) $(1)-$(3) ;\\\n} ;\\\nln -sf $(1)-$(3) $(1)\nendef\n\n.PHONY: operator-sdk\nOPERATOR_SDK ?= $(LOCALBIN)/operator-sdk\noperator-sdk: ## Download operator-sdk locally if necessary.\nifeq (,$(wildcard $(OPERATOR_SDK)))\nifeq (, $(shell which operator-sdk 2>/dev/null))\n\t@{ \\\n\tset -e ;\\\n\tmkdir -p $(dir $(OPERATOR_SDK)) ;\\\n\tOS=$(shell go env GOOS) && ARCH=$(shell go env GOARCH) && \\\n\tcurl -sSLo $(OPERATOR_SDK) https://github.com/operator-framework/operator-sdk/releases/download/$(OPERATOR_SDK_VERSION)/operator-sdk_$${OS}_$${ARCH} ;\\\n\tchmod +x $(OPERATOR_SDK) ;\\\n\t}\nelse\nOPERATOR_SDK = $(shell which operator-sdk)\nendif\nendif\n\n.PHONY: bundle\nbundle: manifests kustomize operator-sdk ## Generate bundle manifests and metadata, then validate generated files.\n\t$(OPERATOR_SDK) generate kustomize manifests --interactive=false -q\n\tcd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG)\n\t$(KUSTOMIZE) build config/manifests | $(OPERATOR_SDK) generate bundle $(BUNDLE_GEN_FLAGS)\n\t$(OPERATOR_SDK) bundle validate ./bundle\n\n.PHONY: bundle-build\nbundle-build: ## Build the bundle image.\n\t$(CONTAINER_TOOL) build -f bundle.Dockerfile -t $(BUNDLE_IMG) .\n\n.PHONY: bundle-push\nbundle-push: ## Push the bundle image.\n\t$(MAKE) docker-push IMG=$(BUNDLE_IMG)\n\n.PHONY: opm\nOPM = $(LOCALBIN)/opm\nopm: ## Download opm locally if necessary.\nifeq (,$(wildcard $(OPM)))\nifeq (,$(shell which opm 2>/dev/null))\n\t@{ \\\n\tset -e ;\\\n\tmkdir -p $(dir $(OPM)) ;\\\n\tOS=$(shell go env GOOS) && ARCH=$(shell go env GOARCH) && \\\n\tcurl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/v1.55.0/$${OS}-$${ARCH}-opm ;\\\n\tchmod +x $(OPM) ;\\\n\t}\nelse\nOPM = $(shell which opm)\nendif\nendif\n\n# A comma-separated list of bundle images (e.g. make catalog-build BUNDLE_IMGS=example.com/operator-bundle:v0.1.0,example.com/operator-bundle:v0.2.0).\n# These images MUST exist in a registry and be pull-able.\nBUNDLE_IMGS ?= $(BUNDLE_IMG)\n\n# The image tag given to the resulting catalog image (e.g. make catalog-build CATALOG_IMG=example.com/operator-catalog:v0.2.0).\nCATALOG_IMG ?= $(IMAGE_TAG_BASE)-catalog:v$(VERSION)\n\n# Set CATALOG_BASE_IMG to an existing catalog image tag to add $BUNDLE_IMGS to that image.\nifneq ($(origin CATALOG_BASE_IMG), undefined)\nFROM_INDEX_OPT := --from-index $(CATALOG_BASE_IMG)\nendif\n\n# Build a catalog image by adding bundle images to an empty catalog using the operator package manager tool, 'opm'.\n# This recipe invokes 'opm' in 'semver' bundle add mode. For more information on add modes, see:\n# https://github.com/operator-framework/community-operators/blob/7f1438c/docs/packaging-operator.md#updating-your-existing-operator\n.PHONY: catalog-build\ncatalog-build: opm ## Build a catalog image.\n\t$(OPM) index add --container-tool $(CONTAINER_TOOL) --mode semver --tag $(CATALOG_IMG) --bundles $(BUNDLE_IMGS) $(FROM_INDEX_OPT)\n\n# Push the catalog image.\n.PHONY: catalog-push\ncatalog-push: ## Push a catalog image.\n\t$(MAKE) docker-push IMG=$(CATALOG_IMG)\n\n##@ Generate the metrics documentation\n.PHONY: generate-metricsdocs\ngenerate-metricsdocs:\n\tmkdir -p $(shell pwd)/docs/monitoring\n\tgo run -ldflags=\"${LDFLAGS}\" ./monitoring/metricsdocs > docs/monitoring/metrics.md\n\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/PROJECT",
    "content": "# Code generated by tool. DO NOT EDIT.\n# This file is used to track the info used to scaffold your project\n# and allow the plugins properly work.\n# More info: https://book.kubebuilder.io/reference/project-config.html\ndomain: example.com\nlayout:\n- go.kubebuilder.io/v4\nplugins:\n  deploy-image.go.kubebuilder.io/v1-alpha:\n    resources:\n    - domain: example.com\n      group: cache\n      kind: Memcached\n      options:\n        containerCommand: memcached,-m=64,-o,modern,-v\n        containerPort: \"11211\"\n        image: memcached:1.4.36-alpine\n        runAsUser: \"1001\"\n      version: v1alpha1\n  manifests.sdk.operatorframework.io/v2: {}\n  scorecard.sdk.operatorframework.io/v2: {}\nprojectName: memcached-operator\nrepo: github.com/example/memcached-operator\nresources:\n- api:\n    crdVersion: v1\n    namespaced: true\n  controller: true\n  domain: example.com\n  group: cache\n  kind: Memcached\n  path: github.com/example/memcached-operator/api/v1alpha1\n  version: v1alpha1\n  webhooks:\n    defaulting: true\n    webhookVersion: v1\nversion: \"3\"\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/README.md",
    "content": "# memcached-operator\n// TODO(user): Add simple overview of use/purpose\n\n## Description\n// TODO(user): An in-depth paragraph about your project and overview of use\n\n## Getting Started\n\n### Prerequisites\n- go version v1.24.0+\n- docker version 17.03+.\n- kubectl version v1.11.3+.\n- Access to a Kubernetes v1.11.3+ cluster.\n\n### To Deploy on the cluster\n**Build and push your image to the location specified by `IMG`:**\n\n```sh\nmake docker-build docker-push IMG=<some-registry>/memcached-operator:tag\n```\n\n**NOTE:** This image ought to be published in the personal registry you specified.\nAnd it is required to have access to pull the image from the working environment.\nMake sure you have the proper permission to the registry if the above commands don’t work.\n\n**Install the CRDs into the cluster:**\n\n```sh\nmake install\n```\n\n**Deploy the Manager to the cluster with the image specified by `IMG`:**\n\n```sh\nmake deploy IMG=<some-registry>/memcached-operator:tag\n```\n\n> **NOTE**: If you encounter RBAC errors, you may need to grant yourself cluster-admin\nprivileges or be logged in as admin.\n\n**Create instances of your solution**\nYou can apply the samples (examples) from the config/sample:\n\n```sh\nkubectl apply -k config/samples/\n```\n\n>**NOTE**: Ensure that the samples has default values to test it out.\n\n### To Uninstall\n**Delete the instances (CRs) from the cluster:**\n\n```sh\nkubectl delete -k config/samples/\n```\n\n**Delete the APIs(CRDs) from the cluster:**\n\n```sh\nmake uninstall\n```\n\n**UnDeploy the controller from the cluster:**\n\n```sh\nmake undeploy\n```\n\n## Project Distribution\n\nFollowing the options to release and provide this solution to the users.\n\n### By providing a bundle with all YAML files\n\n1. Build the installer for the image built and published in the registry:\n\n```sh\nmake build-installer IMG=<some-registry>/memcached-operator:tag\n```\n\n**NOTE:** The makefile target mentioned above generates an 'install.yaml'\nfile in the dist directory. This file contains all the resources built\nwith Kustomize, which are necessary to install this project without its\ndependencies.\n\n2. Using the installer\n\nUsers can just run 'kubectl apply -f <URL for YAML BUNDLE>' to install\nthe project, i.e.:\n\n```sh\nkubectl apply -f https://raw.githubusercontent.com/<org>/memcached-operator/<tag or branch>/dist/install.yaml\n```\n\n### By providing a Helm Chart\n\n1. Build the chart using the optional helm plugin\n\n```sh\noperator-sdk edit --plugins=helm/v1-alpha\n```\n\n2. See that a chart was generated under 'dist/chart', and users\ncan obtain this solution from there.\n\n**NOTE:** If you change the project, you need to update the Helm Chart\nusing the same command above to sync the latest changes. Furthermore,\nif you create webhooks, you need to use the above command with\nthe '--force' flag and manually ensure that any custom configuration\npreviously added to 'dist/chart/values.yaml' or 'dist/chart/manager/manager.yaml'\nis manually re-applied afterwards.\n\n## Contributing\n// TODO(user): Add detailed information on how you would like others to contribute to this project\n\n**NOTE:** Run `make help` for more information on all potential `make` targets\n\nMore information can be found via the [Kubebuilder Documentation](https://book.kubebuilder.io/introduction.html)\n\n## License\n\nCopyright 2026.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/api/v1alpha1/groupversion_info.go",
    "content": "/*\nCopyright 2026.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\n// Package v1alpha1 contains API Schema definitions for the cache v1alpha1 API group.\n// +kubebuilder:object:generate=true\n// +groupName=cache.example.com\npackage v1alpha1\n\nimport (\n\t\"k8s.io/apimachinery/pkg/runtime/schema\"\n\t\"sigs.k8s.io/controller-runtime/pkg/scheme\"\n)\n\nvar (\n\t// GroupVersion is group version used to register these objects.\n\tGroupVersion = schema.GroupVersion{Group: \"cache.example.com\", Version: \"v1alpha1\"}\n\n\t// SchemeBuilder is used to add go types to the GroupVersionKind scheme.\n\tSchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}\n\n\t// AddToScheme adds the types in this group-version to the given scheme.\n\tAddToScheme = SchemeBuilder.AddToScheme\n)\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/api/v1alpha1/memcached_types.go",
    "content": "/*\nCopyright 2026.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage v1alpha1\n\nimport (\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n)\n\n// EDIT THIS FILE!  THIS IS SCAFFOLDING FOR YOU TO OWN!\n// NOTE: json tags are required.  Any new fields you add must have json tags for the fields to be serialized.\n\n// MemcachedSpec defines the desired state of Memcached\ntype MemcachedSpec struct {\n\t// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster\n\t// Important: Run \"make\" to regenerate code after modifying this file\n\n\t// The following markers will use OpenAPI v3 schema to validate the value\n\t// More info: https://book.kubebuilder.io/reference/markers/crd-validation.html\n\t// +kubebuilder:validation:Minimum=1\n\t// +kubebuilder:validation:Maximum=3\n\t// +kubebuilder:validation:ExclusiveMaximum=false\n\n\t// Size defines the number of Memcached instances\n\t// +operator-sdk:csv:customresourcedefinitions:type=spec\n\tSize int32 `json:\"size,omitempty\"`\n\n\t// Port defines the port that will be used to init the container with the image\n\t// +operator-sdk:csv:customresourcedefinitions:type=spec\n\tContainerPort int32 `json:\"containerPort,omitempty\"`\n}\n\n// MemcachedStatus defines the observed state of Memcached\ntype MemcachedStatus struct {\n\t// Represents the observations of a Memcached's current state.\n\t// Memcached.status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\"\n\t// Memcached.status.conditions.status are one of True, False, Unknown.\n\t// Memcached.status.conditions.reason the value should be a CamelCase string and producers of specific\n\t// condition types may define expected values and meanings for this field, and whether the values\n\t// are considered a guaranteed API.\n\t// Memcached.status.conditions.Message is a human readable message indicating details about the transition.\n\t// For further information see: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties\n\n\t// Conditions store the status conditions of the Memcached instances\n\t// +operator-sdk:csv:customresourcedefinitions:type=status\n\tConditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n}\n\n// +kubebuilder:object:root=true\n// +kubebuilder:subresource:status\n// +operator-sdk:csv:customresourcedefinitions:resources={{Deployment,v1,memcached-deployment}}\n\n// Memcached is the Schema for the memcacheds API\ntype Memcached struct {\n\tmetav1.TypeMeta   `json:\",inline\"`\n\tmetav1.ObjectMeta `json:\"metadata,omitempty\"`\n\n\tSpec   MemcachedSpec   `json:\"spec,omitempty\"`\n\tStatus MemcachedStatus `json:\"status,omitempty\"`\n}\n\n// +kubebuilder:object:root=true\n\n// MemcachedList contains a list of Memcached\ntype MemcachedList struct {\n\tmetav1.TypeMeta `json:\",inline\"`\n\tmetav1.ListMeta `json:\"metadata,omitempty\"`\n\tItems           []Memcached `json:\"items\"`\n}\n\nfunc init() {\n\tSchemeBuilder.Register(&Memcached{}, &MemcachedList{})\n}\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go",
    "content": "//go:build !ignore_autogenerated\n\n/*\nCopyright 2026.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\n// Code generated by controller-gen. DO NOT EDIT.\n\npackage v1alpha1\n\nimport (\n\t\"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\truntime \"k8s.io/apimachinery/pkg/runtime\"\n)\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *Memcached) DeepCopyInto(out *Memcached) {\n\t*out = *in\n\tout.TypeMeta = in.TypeMeta\n\tin.ObjectMeta.DeepCopyInto(&out.ObjectMeta)\n\tout.Spec = in.Spec\n\tin.Status.DeepCopyInto(&out.Status)\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Memcached.\nfunc (in *Memcached) DeepCopy() *Memcached {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(Memcached)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.\nfunc (in *Memcached) DeepCopyObject() runtime.Object {\n\tif c := in.DeepCopy(); c != nil {\n\t\treturn c\n\t}\n\treturn nil\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *MemcachedList) DeepCopyInto(out *MemcachedList) {\n\t*out = *in\n\tout.TypeMeta = in.TypeMeta\n\tin.ListMeta.DeepCopyInto(&out.ListMeta)\n\tif in.Items != nil {\n\t\tin, out := &in.Items, &out.Items\n\t\t*out = make([]Memcached, len(*in))\n\t\tfor i := range *in {\n\t\t\t(*in)[i].DeepCopyInto(&(*out)[i])\n\t\t}\n\t}\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MemcachedList.\nfunc (in *MemcachedList) DeepCopy() *MemcachedList {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(MemcachedList)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.\nfunc (in *MemcachedList) DeepCopyObject() runtime.Object {\n\tif c := in.DeepCopy(); c != nil {\n\t\treturn c\n\t}\n\treturn nil\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *MemcachedSpec) DeepCopyInto(out *MemcachedSpec) {\n\t*out = *in\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MemcachedSpec.\nfunc (in *MemcachedSpec) DeepCopy() *MemcachedSpec {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(MemcachedSpec)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n\n// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.\nfunc (in *MemcachedStatus) DeepCopyInto(out *MemcachedStatus) {\n\t*out = *in\n\tif in.Conditions != nil {\n\t\tin, out := &in.Conditions, &out.Conditions\n\t\t*out = make([]v1.Condition, len(*in))\n\t\tfor i := range *in {\n\t\t\t(*in)[i].DeepCopyInto(&(*out)[i])\n\t\t}\n\t}\n}\n\n// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MemcachedStatus.\nfunc (in *MemcachedStatus) DeepCopy() *MemcachedStatus {\n\tif in == nil {\n\t\treturn nil\n\t}\n\tout := new(MemcachedStatus)\n\tin.DeepCopyInto(out)\n\treturn out\n}\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/bundle/manifests/cache.example.com_memcacheds.yaml",
    "content": "apiVersion: apiextensions.k8s.io/v1\nkind: CustomResourceDefinition\nmetadata:\n  annotations:\n    controller-gen.kubebuilder.io/version: v0.18.0\n  creationTimestamp: null\n  name: memcacheds.cache.example.com\nspec:\n  group: cache.example.com\n  names:\n    kind: Memcached\n    listKind: MemcachedList\n    plural: memcacheds\n    singular: memcached\n  scope: Namespaced\n  versions:\n  - name: v1alpha1\n    schema:\n      openAPIV3Schema:\n        description: Memcached is the Schema for the memcacheds API\n        properties:\n          apiVersion:\n            description: |-\n              APIVersion defines the versioned schema of this representation of an object.\n              Servers should convert recognized schemas to the latest internal value, and\n              may reject unrecognized values.\n              More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources\n            type: string\n          kind:\n            description: |-\n              Kind is a string value representing the REST resource this object represents.\n              Servers may infer this from the endpoint the client submits requests to.\n              Cannot be updated.\n              In CamelCase.\n              More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds\n            type: string\n          metadata:\n            type: object\n          spec:\n            description: MemcachedSpec defines the desired state of Memcached\n            properties:\n              containerPort:\n                description: Port defines the port that will be used to init the container\n                  with the image\n                format: int32\n                type: integer\n              size:\n                description: Size defines the number of Memcached instances\n                format: int32\n                maximum: 3\n                minimum: 1\n                type: integer\n            type: object\n          status:\n            description: MemcachedStatus defines the observed state of Memcached\n            properties:\n              conditions:\n                description: Conditions store the status conditions of the Memcached\n                  instances\n                items:\n                  description: Condition contains details for one aspect of the current\n                    state of this API Resource.\n                  properties:\n                    lastTransitionTime:\n                      description: |-\n                        lastTransitionTime is the last time the condition transitioned from one status to another.\n                        This should be when the underlying condition changed.  If that is not known, then using the time when the API field changed is acceptable.\n                      format: date-time\n                      type: string\n                    message:\n                      description: |-\n                        message is a human readable message indicating details about the transition.\n                        This may be an empty string.\n                      maxLength: 32768\n                      type: string\n                    observedGeneration:\n                      description: |-\n                        observedGeneration represents the .metadata.generation that the condition was set based upon.\n                        For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date\n                        with respect to the current state of the instance.\n                      format: int64\n                      minimum: 0\n                      type: integer\n                    reason:\n                      description: |-\n                        reason contains a programmatic identifier indicating the reason for the condition's last transition.\n                        Producers of specific condition types may define expected values and meanings for this field,\n                        and whether the values are considered a guaranteed API.\n                        The value should be a CamelCase string.\n                        This field may not be empty.\n                      maxLength: 1024\n                      minLength: 1\n                      pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$\n                      type: string\n                    status:\n                      description: status of the condition, one of True, False, Unknown.\n                      enum:\n                      - \"True\"\n                      - \"False\"\n                      - Unknown\n                      type: string\n                    type:\n                      description: type of condition in CamelCase or in foo.example.com/CamelCase.\n                      maxLength: 316\n                      pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$\n                      type: string\n                  required:\n                  - lastTransitionTime\n                  - message\n                  - reason\n                  - status\n                  - type\n                  type: object\n                type: array\n            type: object\n        type: object\n    served: true\n    storage: true\n    subresources:\n      status: {}\nstatus:\n  acceptedNames:\n    kind: \"\"\n    plural: \"\"\n  conditions: null\n  storedVersions: null\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-monitor_monitoring.coreos.com_v1_servicemonitor.yaml",
    "content": "apiVersion: monitoring.coreos.com/v1\nkind: ServiceMonitor\nmetadata:\n  labels:\n    app.kubernetes.io/managed-by: kustomize\n    app.kubernetes.io/name: memcached-operator\n    control-plane: controller-manager\n  name: memcached-operator-controller-manager-metrics-monitor\nspec:\n  endpoints:\n  - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token\n    path: /metrics\n    port: https\n    scheme: https\n    tlsConfig:\n      insecureSkipVerify: true\n      serverName: memcached-operator-controller-manager-metrics-service.memcached-operator-system\n  selector:\n    matchLabels:\n      app.kubernetes.io/name: memcached-operator\n      control-plane: controller-manager\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-service_v1_service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  creationTimestamp: null\n  labels:\n    app.kubernetes.io/managed-by: kustomize\n    app.kubernetes.io/name: memcached-operator\n    control-plane: controller-manager\n  name: memcached-operator-controller-manager-metrics-service\nspec:\n  ports:\n  - name: https\n    port: 8443\n    protocol: TCP\n    targetPort: 8443\n  selector:\n    app.kubernetes.io/name: memcached-operator\n    control-plane: controller-manager\nstatus:\n  loadBalancer: {}\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/bundle/manifests/memcached-operator-memcached-admin-role_rbac.authorization.k8s.io_v1_clusterrole.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  creationTimestamp: null\n  labels:\n    app.kubernetes.io/managed-by: kustomize\n    app.kubernetes.io/name: memcached-operator\n  name: memcached-operator-memcached-admin-role\nrules:\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds\n  verbs:\n  - '*'\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds/status\n  verbs:\n  - get\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/bundle/manifests/memcached-operator-memcached-editor-role_rbac.authorization.k8s.io_v1_clusterrole.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  creationTimestamp: null\n  labels:\n    app.kubernetes.io/managed-by: kustomize\n    app.kubernetes.io/name: memcached-operator\n  name: memcached-operator-memcached-editor-role\nrules:\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds/status\n  verbs:\n  - get\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/bundle/manifests/memcached-operator-memcached-viewer-role_rbac.authorization.k8s.io_v1_clusterrole.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  creationTimestamp: null\n  labels:\n    app.kubernetes.io/managed-by: kustomize\n    app.kubernetes.io/name: memcached-operator\n  name: memcached-operator-memcached-viewer-role\nrules:\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds\n  verbs:\n  - get\n  - list\n  - watch\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds/status\n  verbs:\n  - get\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/bundle/manifests/memcached-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  creationTimestamp: null\n  name: memcached-operator-metrics-reader\nrules:\n- nonResourceURLs:\n  - /metrics\n  verbs:\n  - get\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/bundle/manifests/memcached-operator-prometheus-role-binding_rbac.authorization.k8s.io_v1_rolebinding.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: RoleBinding\nmetadata:\n  creationTimestamp: null\n  name: memcached-operator-prometheus-role-binding\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: Role\n  name: memcached-operator-prometheus-role\nsubjects:\n- kind: ServiceAccount\n  name: prometheus-k8s\n  namespace: monitoring\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/bundle/manifests/memcached-operator-prometheus-role_rbac.authorization.k8s.io_v1_role.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: Role\nmetadata:\n  creationTimestamp: null\n  name: memcached-operator-prometheus-role\nrules:\n- apiGroups:\n  - \"\"\n  resources:\n  - services\n  - endpoints\n  - pods\n  verbs:\n  - get\n  - list\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/bundle/manifests/memcached-operator-webhook-service_v1_service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  creationTimestamp: null\n  labels:\n    app.kubernetes.io/managed-by: kustomize\n    app.kubernetes.io/name: memcached-operator\n  name: memcached-operator-webhook-service\nspec:\n  ports:\n  - port: 443\n    protocol: TCP\n    targetPort: 9443\n  selector:\n    app.kubernetes.io/name: memcached-operator\n    control-plane: controller-manager\nstatus:\n  loadBalancer: {}\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml",
    "content": "apiVersion: operators.coreos.com/v1alpha1\nkind: ClusterServiceVersion\nmetadata:\n  annotations:\n    alm-examples: |-\n      [\n        {\n          \"apiVersion\": \"cache.example.com/v1alpha1\",\n          \"kind\": \"Memcached\",\n          \"metadata\": {\n            \"labels\": {\n              \"app.kubernetes.io/managed-by\": \"kustomize\",\n              \"app.kubernetes.io/name\": \"memcached-operator\"\n            },\n            \"name\": \"memcached-sample\"\n          },\n          \"spec\": {\n            \"containerPort\": 11211,\n            \"size\": 1\n          }\n        }\n      ]\n    capabilities: Basic Install\n    createdAt: \"2022-11-08T17:26:37Z\"\n  name: memcached-operator.v0.0.1\n  namespace: placeholder\nspec:\n  apiservicedefinitions: {}\n  customresourcedefinitions:\n    owned:\n    - description: Memcached is the Schema for the memcacheds API\n      displayName: Memcached\n      kind: Memcached\n      name: memcacheds.cache.example.com\n      resources:\n      - kind: Deployment\n        name: memcached-deployment\n        version: v1\n      specDescriptors:\n      - description: Port defines the port that will be used to init the container\n          with the image\n        displayName: Container Port\n        path: containerPort\n      - description: Size defines the number of Memcached instances\n        displayName: Size\n        path: size\n      statusDescriptors:\n      - description: Conditions store the status conditions of the Memcached instances\n        displayName: Conditions\n        path: conditions\n      version: v1alpha1\n  description: Memcached Operator description. TODO.\n  displayName: Memcached Operator\n  icon:\n  - base64data: \"\"\n    mediatype: \"\"\n  install:\n    spec:\n      clusterPermissions:\n      - rules:\n        - apiGroups:\n          - \"\"\n          resources:\n          - events\n          verbs:\n          - create\n          - patch\n        - apiGroups:\n          - \"\"\n          resources:\n          - pods\n          verbs:\n          - get\n          - list\n          - watch\n        - apiGroups:\n          - apps\n          resources:\n          - deployments\n          verbs:\n          - create\n          - delete\n          - get\n          - list\n          - patch\n          - update\n          - watch\n        - apiGroups:\n          - cache.example.com\n          resources:\n          - memcacheds\n          verbs:\n          - create\n          - delete\n          - get\n          - list\n          - patch\n          - update\n          - watch\n        - apiGroups:\n          - cache.example.com\n          resources:\n          - memcacheds/finalizers\n          verbs:\n          - update\n        - apiGroups:\n          - cache.example.com\n          resources:\n          - memcacheds/status\n          verbs:\n          - get\n          - patch\n          - update\n        - apiGroups:\n          - monitoring.coreos.com\n          resources:\n          - prometheusrules\n          verbs:\n          - create\n          - delete\n          - get\n          - list\n          - update\n          - watch\n        - apiGroups:\n          - authentication.k8s.io\n          resources:\n          - tokenreviews\n          verbs:\n          - create\n        - apiGroups:\n          - authorization.k8s.io\n          resources:\n          - subjectaccessreviews\n          verbs:\n          - create\n        serviceAccountName: memcached-operator-controller-manager\n      deployments:\n      - label:\n          app.kubernetes.io/managed-by: kustomize\n          app.kubernetes.io/name: memcached-operator\n          control-plane: controller-manager\n        name: memcached-operator-controller-manager\n        spec:\n          replicas: 1\n          selector:\n            matchLabels:\n              app.kubernetes.io/name: memcached-operator\n              control-plane: controller-manager\n          strategy: {}\n          template:\n            metadata:\n              annotations:\n                kubectl.kubernetes.io/default-container: manager\n              labels:\n                app.kubernetes.io/name: memcached-operator\n                control-plane: controller-manager\n            spec:\n              containers:\n              - args:\n                - --metrics-bind-address=:8443\n                - --leader-elect\n                - --health-probe-bind-address=:8081\n                - --metrics-cert-path=/tmp/k8s-metrics-server/metrics-certs\n                - --webhook-cert-path=/tmp/k8s-webhook-server/serving-certs\n                command:\n                - /manager\n                env:\n                - name: MEMCACHED_IMAGE\n                  value: memcached:1.4.36-alpine\n                image: quay.io/example/memcached-operator:v0.0.1\n                livenessProbe:\n                  httpGet:\n                    path: /healthz\n                    port: 8081\n                  initialDelaySeconds: 15\n                  periodSeconds: 20\n                name: manager\n                ports:\n                - containerPort: 9443\n                  name: webhook-server\n                  protocol: TCP\n                readinessProbe:\n                  httpGet:\n                    path: /readyz\n                    port: 8081\n                  initialDelaySeconds: 5\n                  periodSeconds: 10\n                resources:\n                  limits:\n                    cpu: 500m\n                    memory: 128Mi\n                  requests:\n                    cpu: 10m\n                    memory: 64Mi\n                securityContext:\n                  allowPrivilegeEscalation: false\n                  capabilities:\n                    drop:\n                    - ALL\n                volumeMounts:\n                - mountPath: /tmp/k8s-webhook-server/serving-certs\n                  name: webhook-certs\n                  readOnly: true\n              securityContext:\n                runAsNonRoot: true\n                seccompProfile:\n                  type: RuntimeDefault\n              serviceAccountName: memcached-operator-controller-manager\n              terminationGracePeriodSeconds: 10\n              volumes:\n              - name: webhook-certs\n                secret:\n                  secretName: webhook-server-cert\n      permissions:\n      - rules:\n        - apiGroups:\n          - \"\"\n          resources:\n          - configmaps\n          verbs:\n          - get\n          - list\n          - watch\n          - create\n          - update\n          - patch\n          - delete\n        - apiGroups:\n          - coordination.k8s.io\n          resources:\n          - leases\n          verbs:\n          - get\n          - list\n          - watch\n          - create\n          - update\n          - patch\n          - delete\n        - apiGroups:\n          - \"\"\n          resources:\n          - events\n          verbs:\n          - create\n          - patch\n        serviceAccountName: memcached-operator-controller-manager\n    strategy: deployment\n  installModes:\n  - supported: false\n    type: OwnNamespace\n  - supported: false\n    type: SingleNamespace\n  - supported: false\n    type: MultiNamespace\n  - supported: true\n    type: AllNamespaces\n  keywords:\n  - memcached-operator\n  links:\n  - name: Memcached Operator\n    url: https://memcached-operator.domain\n  maintainers:\n  - email: your@email.com\n    name: Maintainer Name\n  maturity: alpha\n  provider:\n    name: Provider Name\n    url: https://your.domain\n  version: 0.0.1\n  webhookdefinitions:\n  - admissionReviewVersions:\n    - v1\n    containerPort: 443\n    deploymentName: memcached-operator-controller-manager\n    failurePolicy: Fail\n    generateName: mmemcached-v1alpha1.kb.io\n    rules:\n    - apiGroups:\n      - cache.example.com\n      apiVersions:\n      - v1alpha1\n      operations:\n      - CREATE\n      - UPDATE\n      resources:\n      - memcacheds\n    sideEffects: None\n    targetPort: 9443\n    type: MutatingAdmissionWebhook\n    webhookPath: /mutate-cache-example-com-v1alpha1-memcached\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/bundle/metadata/annotations.yaml",
    "content": "annotations:\n  # Core bundle annotations.\n  operators.operatorframework.io.bundle.mediatype.v1: registry+v1\n  operators.operatorframework.io.bundle.manifests.v1: manifests/\n  operators.operatorframework.io.bundle.metadata.v1: metadata/\n  operators.operatorframework.io.bundle.package.v1: memcached-operator\n  operators.operatorframework.io.bundle.channels.v1: alpha\n\n  # Annotations for testing.\n  operators.operatorframework.io.test.mediatype.v1: scorecard+v1\n  operators.operatorframework.io.test.config.v1: tests/scorecard/\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/bundle/tests/scorecard/config.yaml",
    "content": "apiVersion: scorecard.operatorframework.io/v1alpha3\nkind: Configuration\nmetadata:\n  name: config\nstages:\n- parallel: true\n  tests:\n  - entrypoint:\n    - scorecard-test\n    - basic-check-spec\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: basic\n      test: basic-check-spec-test\n    storage:\n      spec:\n        mountPath: {}\n  - entrypoint:\n    - scorecard-test\n    - olm-bundle-validation\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: olm\n      test: olm-bundle-validation-test\n    storage:\n      spec:\n        mountPath: {}\n  - entrypoint:\n    - scorecard-test\n    - olm-crds-have-validation\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: olm\n      test: olm-crds-have-validation-test\n    storage:\n      spec:\n        mountPath: {}\n  - entrypoint:\n    - scorecard-test\n    - olm-crds-have-resources\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: olm\n      test: olm-crds-have-resources-test\n    storage:\n      spec:\n        mountPath: {}\n  - entrypoint:\n    - scorecard-test\n    - olm-spec-descriptors\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: olm\n      test: olm-spec-descriptors-test\n    storage:\n      spec:\n        mountPath: {}\n  - entrypoint:\n    - scorecard-test\n    - olm-status-descriptors\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: olm\n      test: olm-status-descriptors-test\n    storage:\n      spec:\n        mountPath: {}\nstorage:\n  spec:\n    mountPath: {}\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/bundle.Dockerfile",
    "content": "FROM scratch\n\n# Core bundle labels.\nLABEL operators.operatorframework.io.bundle.mediatype.v1=registry+v1\nLABEL operators.operatorframework.io.bundle.manifests.v1=manifests/\nLABEL operators.operatorframework.io.bundle.metadata.v1=metadata/\nLABEL operators.operatorframework.io.bundle.package.v1=memcached-operator\nLABEL operators.operatorframework.io.bundle.channels.v1=alpha\n\n# Labels for testing.\nLABEL operators.operatorframework.io.test.mediatype.v1=scorecard+v1\nLABEL operators.operatorframework.io.test.config.v1=tests/scorecard/\n\n# Copy files to locations specified by labels.\nCOPY bundle/manifests /manifests/\nCOPY bundle/metadata /metadata/\nCOPY bundle/tests/scorecard /tests/scorecard/\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/cmd/main.go",
    "content": "/*\nCopyright 2026.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage main\n\nimport (\n\t\"crypto/tls\"\n\t\"flag\"\n\t\"os\"\n\t\"path/filepath\"\n\n\t// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)\n\t// to ensure that exec-entrypoint and run can make use of them.\n\t_ \"k8s.io/client-go/plugin/pkg/client/auth\"\n\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\tutilruntime \"k8s.io/apimachinery/pkg/util/runtime\"\n\tclientgoscheme \"k8s.io/client-go/kubernetes/scheme\"\n\tctrl \"sigs.k8s.io/controller-runtime\"\n\t\"sigs.k8s.io/controller-runtime/pkg/certwatcher\"\n\t\"sigs.k8s.io/controller-runtime/pkg/healthz\"\n\t\"sigs.k8s.io/controller-runtime/pkg/log/zap\"\n\n\tmonitoringv1 \"github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1\"\n\n\t\"sigs.k8s.io/controller-runtime/pkg/metrics/filters\"\n\tmetricsserver \"sigs.k8s.io/controller-runtime/pkg/metrics/server\"\n\t\"sigs.k8s.io/controller-runtime/pkg/webhook\"\n\n\tcachev1alpha1 \"github.com/example/memcached-operator/api/v1alpha1\"\n\t\"github.com/example/memcached-operator/internal/controller\"\n\t\"github.com/example/memcached-operator/monitoring\"\n\n\twebhookv1alpha1 \"github.com/example/memcached-operator/internal/webhook/v1alpha1\"\n\t// +kubebuilder:scaffold:imports\n)\n\nvar (\n\tscheme   = runtime.NewScheme()\n\tsetupLog = ctrl.Log.WithName(\"setup\")\n)\n\nfunc init() {\n\tutilruntime.Must(clientgoscheme.AddToScheme(scheme))\n\n\tutilruntime.Must(cachev1alpha1.AddToScheme(scheme))\n\n\tutilruntime.Must(monitoringv1.AddToScheme(scheme))\n\n\tmonitoring.RegisterMetrics()\n\t// +kubebuilder:scaffold:scheme\n}\n\n// nolint:gocyclo\nfunc main() {\n\tvar metricsAddr string\n\tvar metricsCertPath, metricsCertName, metricsCertKey string\n\tvar webhookCertPath, webhookCertName, webhookCertKey string\n\tvar enableLeaderElection bool\n\tvar probeAddr string\n\tvar secureMetrics bool\n\tvar enableHTTP2 bool\n\tvar tlsOpts []func(*tls.Config)\n\tflag.StringVar(&metricsAddr, \"metrics-bind-address\", \"0\", \"The address the metrics endpoint binds to. \"+\n\t\t\"Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.\")\n\tflag.StringVar(&probeAddr, \"health-probe-bind-address\", \":8081\", \"The address the probe endpoint binds to.\")\n\tflag.BoolVar(&enableLeaderElection, \"leader-elect\", false,\n\t\t\"Enable leader election for controller manager. \"+\n\t\t\t\"Enabling this will ensure there is only one active controller manager.\")\n\tflag.BoolVar(&secureMetrics, \"metrics-secure\", true,\n\t\t\"If set, the metrics endpoint is served securely via HTTPS. Use --metrics-secure=false to use HTTP instead.\")\n\tflag.StringVar(&webhookCertPath, \"webhook-cert-path\", \"\", \"The directory that contains the webhook certificate.\")\n\tflag.StringVar(&webhookCertName, \"webhook-cert-name\", \"tls.crt\", \"The name of the webhook certificate file.\")\n\tflag.StringVar(&webhookCertKey, \"webhook-cert-key\", \"tls.key\", \"The name of the webhook key file.\")\n\tflag.StringVar(&metricsCertPath, \"metrics-cert-path\", \"\",\n\t\t\"The directory that contains the metrics server certificate.\")\n\tflag.StringVar(&metricsCertName, \"metrics-cert-name\", \"tls.crt\", \"The name of the metrics server certificate file.\")\n\tflag.StringVar(&metricsCertKey, \"metrics-cert-key\", \"tls.key\", \"The name of the metrics server key file.\")\n\tflag.BoolVar(&enableHTTP2, \"enable-http2\", false,\n\t\t\"If set, HTTP/2 will be enabled for the metrics and webhook servers\")\n\topts := zap.Options{\n\t\tDevelopment: true,\n\t}\n\topts.BindFlags(flag.CommandLine)\n\tflag.Parse()\n\n\tctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))\n\n\t// if the enable-http2 flag is false (the default), http/2 should be disabled\n\t// due to its vulnerabilities. More specifically, disabling http/2 will\n\t// prevent from being vulnerable to the HTTP/2 Stream Cancellation and\n\t// Rapid Reset CVEs. For more information see:\n\t// - https://github.com/advisories/GHSA-qppj-fm5r-hxr3\n\t// - https://github.com/advisories/GHSA-4374-p667-p6c8\n\tdisableHTTP2 := func(c *tls.Config) {\n\t\tsetupLog.Info(\"disabling http/2\")\n\t\tc.NextProtos = []string{\"http/1.1\"}\n\t}\n\n\tif !enableHTTP2 {\n\t\ttlsOpts = append(tlsOpts, disableHTTP2)\n\t}\n\n\t// Create watchers for metrics and webhooks certificates\n\tvar metricsCertWatcher, webhookCertWatcher *certwatcher.CertWatcher\n\n\t// Initial webhook TLS options\n\twebhookTLSOpts := tlsOpts\n\n\tif len(webhookCertPath) > 0 {\n\t\tsetupLog.Info(\"Initializing webhook certificate watcher using provided certificates\",\n\t\t\t\"webhook-cert-path\", webhookCertPath, \"webhook-cert-name\", webhookCertName, \"webhook-cert-key\", webhookCertKey)\n\n\t\tvar err error\n\t\twebhookCertWatcher, err = certwatcher.New(\n\t\t\tfilepath.Join(webhookCertPath, webhookCertName),\n\t\t\tfilepath.Join(webhookCertPath, webhookCertKey),\n\t\t)\n\t\tif err != nil {\n\t\t\tsetupLog.Error(err, \"Failed to initialize webhook certificate watcher\")\n\t\t\tos.Exit(1)\n\t\t}\n\n\t\twebhookTLSOpts = append(webhookTLSOpts, func(config *tls.Config) {\n\t\t\tconfig.GetCertificate = webhookCertWatcher.GetCertificate\n\t\t})\n\t}\n\n\twebhookServer := webhook.NewServer(webhook.Options{\n\t\tTLSOpts: webhookTLSOpts,\n\t})\n\n\t// Metrics endpoint is enabled in 'config/default/kustomization.yaml'. The Metrics options configure the server.\n\t// More info:\n\t// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.21.0/pkg/metrics/server\n\t// - https://book.kubebuilder.io/reference/metrics.html\n\tmetricsServerOptions := metricsserver.Options{\n\t\tBindAddress:   metricsAddr,\n\t\tSecureServing: secureMetrics,\n\t\tTLSOpts:       tlsOpts,\n\t}\n\n\tif secureMetrics {\n\t\t// FilterProvider is used to protect the metrics endpoint with authn/authz.\n\t\t// These configurations ensure that only authorized users and service accounts\n\t\t// can access the metrics endpoint. The RBAC are configured in 'config/rbac/kustomization.yaml'. More info:\n\t\t// https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.21.0/pkg/metrics/filters#WithAuthenticationAndAuthorization\n\t\tmetricsServerOptions.FilterProvider = filters.WithAuthenticationAndAuthorization\n\t}\n\n\t// If the certificate is not specified, controller-runtime will automatically\n\t// generate self-signed certificates for the metrics server. While convenient for development and testing,\n\t// this setup is not recommended for production.\n\t//\n\t// TODO(user): If you enable certManager, uncomment the following lines:\n\t// - [METRICS-WITH-CERTS] at config/default/kustomization.yaml to generate and use certificates\n\t// managed by cert-manager for the metrics server.\n\t// - [PROMETHEUS-WITH-CERTS] at config/prometheus/kustomization.yaml for TLS certification.\n\tif len(metricsCertPath) > 0 {\n\t\tsetupLog.Info(\"Initializing metrics certificate watcher using provided certificates\",\n\t\t\t\"metrics-cert-path\", metricsCertPath, \"metrics-cert-name\", metricsCertName, \"metrics-cert-key\", metricsCertKey)\n\n\t\tvar err error\n\t\tmetricsCertWatcher, err = certwatcher.New(\n\t\t\tfilepath.Join(metricsCertPath, metricsCertName),\n\t\t\tfilepath.Join(metricsCertPath, metricsCertKey),\n\t\t)\n\t\tif err != nil {\n\t\t\tsetupLog.Error(err, \"to initialize metrics certificate watcher\", \"error\", err)\n\t\t\tos.Exit(1)\n\t\t}\n\n\t\tmetricsServerOptions.TLSOpts = append(metricsServerOptions.TLSOpts, func(config *tls.Config) {\n\t\t\tconfig.GetCertificate = metricsCertWatcher.GetCertificate\n\t\t})\n\t}\n\n\tmgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{\n\t\tScheme:                 scheme,\n\t\tMetrics:                metricsServerOptions,\n\t\tWebhookServer:          webhookServer,\n\t\tHealthProbeBindAddress: probeAddr,\n\t\tLeaderElection:         enableLeaderElection,\n\t\tLeaderElectionID:       \"86f835c3.example.com\",\n\t\t// LeaderElectionReleaseOnCancel defines if the leader should step down voluntarily\n\t\t// when the Manager ends. This requires the binary to immediately end when the\n\t\t// Manager is stopped, otherwise, this setting is unsafe. Setting this significantly\n\t\t// speeds up voluntary leader transitions as the new leader don't have to wait\n\t\t// LeaseDuration time first.\n\t\t//\n\t\t// In the default scaffold provided, the program ends immediately after\n\t\t// the manager stops, so would be fine to enable this option. However,\n\t\t// if you are doing or is intended to do any operation such as perform cleanups\n\t\t// after the manager stops then its usage might be unsafe.\n\t\t// LeaderElectionReleaseOnCancel: true,\n\t})\n\tif err != nil {\n\t\tsetupLog.Error(err, \"unable to start manager\")\n\t\tos.Exit(1)\n\t}\n\n\tif err := (&controller.MemcachedReconciler{\n\t\tClient: mgr.GetClient(),\n\t\tScheme: mgr.GetScheme(),\n\t\t// Add a Recorder to the reconciler.\n\t\t// This allows the operator author to emit events during reconcilliation.\n\t\tRecorder: mgr.GetEventRecorderFor(\"memcached-controller\"),\n\t}).SetupWithManager(mgr); err != nil {\n\t\tsetupLog.Error(err, \"unable to create controller\", \"controller\", \"Memcached\")\n\t\tos.Exit(1)\n\t}\n\t// nolint:goconst\n\tif os.Getenv(\"ENABLE_WEBHOOKS\") != \"false\" {\n\t\tif err := webhookv1alpha1.SetupMemcachedWebhookWithManager(mgr); err != nil {\n\t\t\tsetupLog.Error(err, \"unable to create webhook\", \"webhook\", \"Memcached\")\n\t\t\tos.Exit(1)\n\t\t}\n\t}\n\t// +kubebuilder:scaffold:builder\n\n\tif metricsCertWatcher != nil {\n\t\tsetupLog.Info(\"Adding metrics certificate watcher to manager\")\n\t\tif err := mgr.Add(metricsCertWatcher); err != nil {\n\t\t\tsetupLog.Error(err, \"unable to add metrics certificate watcher to manager\")\n\t\t\tos.Exit(1)\n\t\t}\n\t}\n\n\tif webhookCertWatcher != nil {\n\t\tsetupLog.Info(\"Adding webhook certificate watcher to manager\")\n\t\tif err := mgr.Add(webhookCertWatcher); err != nil {\n\t\t\tsetupLog.Error(err, \"unable to add webhook certificate watcher to manager\")\n\t\t\tos.Exit(1)\n\t\t}\n\t}\n\n\tif err := mgr.AddHealthzCheck(\"healthz\", healthz.Ping); err != nil {\n\t\tsetupLog.Error(err, \"unable to set up health check\")\n\t\tos.Exit(1)\n\t}\n\tif err := mgr.AddReadyzCheck(\"readyz\", healthz.Ping); err != nil {\n\t\tsetupLog.Error(err, \"unable to set up ready check\")\n\t\tos.Exit(1)\n\t}\n\n\tsetupLog.Info(\"starting manager\")\n\tif err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {\n\t\tsetupLog.Error(err, \"problem running manager\")\n\t\tos.Exit(1)\n\t}\n}\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/certmanager/certificate-metrics.yaml",
    "content": "# The following manifests contain a self-signed issuer CR and a metrics certificate CR.\n# More document can be found at https://docs.cert-manager.io\napiVersion: cert-manager.io/v1\nkind: Certificate\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: metrics-certs  # this name should match the one appeared in kustomizeconfig.yaml\n  namespace: system\nspec:\n  dnsNames:\n  # SERVICE_NAME and SERVICE_NAMESPACE will be substituted by kustomize\n  # replacements in the config/default/kustomization.yaml file.\n  - SERVICE_NAME.SERVICE_NAMESPACE.svc\n  - SERVICE_NAME.SERVICE_NAMESPACE.svc.cluster.local\n  issuerRef:\n    kind: Issuer\n    name: selfsigned-issuer\n  secretName: metrics-server-cert\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/certmanager/certificate-webhook.yaml",
    "content": "# The following manifests contain a self-signed issuer CR and a certificate CR.\n# More document can be found at https://docs.cert-manager.io\napiVersion: cert-manager.io/v1\nkind: Certificate\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: serving-cert  # this name should match the one appeared in kustomizeconfig.yaml\n  namespace: system\nspec:\n  # SERVICE_NAME and SERVICE_NAMESPACE will be substituted by kustomize\n  # replacements in the config/default/kustomization.yaml file.\n  dnsNames:\n  - SERVICE_NAME.SERVICE_NAMESPACE.svc\n  - SERVICE_NAME.SERVICE_NAMESPACE.svc.cluster.local\n  issuerRef:\n    kind: Issuer\n    name: selfsigned-issuer\n  secretName: webhook-server-cert\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/certmanager/issuer.yaml",
    "content": "# The following manifest contains a self-signed issuer CR.\n# More information can be found at https://docs.cert-manager.io\n# WARNING: Targets CertManager v1.0. Check https://cert-manager.io/docs/installation/upgrading/ for breaking changes.\napiVersion: cert-manager.io/v1\nkind: Issuer\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: selfsigned-issuer\n  namespace: system\nspec:\n  selfSigned: {}\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/certmanager/kustomization.yaml",
    "content": "resources:\n- issuer.yaml\n- certificate-webhook.yaml\n- certificate-metrics.yaml\n\nconfigurations:\n- kustomizeconfig.yaml\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/certmanager/kustomizeconfig.yaml",
    "content": "# This configuration is for teaching kustomize how to update name ref substitution\nnameReference:\n- kind: Issuer\n  group: cert-manager.io\n  fieldSpecs:\n  - kind: Certificate\n    group: cert-manager.io\n    path: spec/issuerRef/name\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/crd/bases/cache.example.com_memcacheds.yaml",
    "content": "---\napiVersion: apiextensions.k8s.io/v1\nkind: CustomResourceDefinition\nmetadata:\n  annotations:\n    controller-gen.kubebuilder.io/version: v0.18.0\n  name: memcacheds.cache.example.com\nspec:\n  group: cache.example.com\n  names:\n    kind: Memcached\n    listKind: MemcachedList\n    plural: memcacheds\n    singular: memcached\n  scope: Namespaced\n  versions:\n  - name: v1alpha1\n    schema:\n      openAPIV3Schema:\n        description: Memcached is the Schema for the memcacheds API\n        properties:\n          apiVersion:\n            description: |-\n              APIVersion defines the versioned schema of this representation of an object.\n              Servers should convert recognized schemas to the latest internal value, and\n              may reject unrecognized values.\n              More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources\n            type: string\n          kind:\n            description: |-\n              Kind is a string value representing the REST resource this object represents.\n              Servers may infer this from the endpoint the client submits requests to.\n              Cannot be updated.\n              In CamelCase.\n              More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds\n            type: string\n          metadata:\n            type: object\n          spec:\n            description: MemcachedSpec defines the desired state of Memcached\n            properties:\n              containerPort:\n                description: Port defines the port that will be used to init the container\n                  with the image\n                format: int32\n                type: integer\n              size:\n                description: Size defines the number of Memcached instances\n                format: int32\n                maximum: 3\n                minimum: 1\n                type: integer\n            type: object\n          status:\n            description: MemcachedStatus defines the observed state of Memcached\n            properties:\n              conditions:\n                description: Conditions store the status conditions of the Memcached\n                  instances\n                items:\n                  description: Condition contains details for one aspect of the current\n                    state of this API Resource.\n                  properties:\n                    lastTransitionTime:\n                      description: |-\n                        lastTransitionTime is the last time the condition transitioned from one status to another.\n                        This should be when the underlying condition changed.  If that is not known, then using the time when the API field changed is acceptable.\n                      format: date-time\n                      type: string\n                    message:\n                      description: |-\n                        message is a human readable message indicating details about the transition.\n                        This may be an empty string.\n                      maxLength: 32768\n                      type: string\n                    observedGeneration:\n                      description: |-\n                        observedGeneration represents the .metadata.generation that the condition was set based upon.\n                        For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date\n                        with respect to the current state of the instance.\n                      format: int64\n                      minimum: 0\n                      type: integer\n                    reason:\n                      description: |-\n                        reason contains a programmatic identifier indicating the reason for the condition's last transition.\n                        Producers of specific condition types may define expected values and meanings for this field,\n                        and whether the values are considered a guaranteed API.\n                        The value should be a CamelCase string.\n                        This field may not be empty.\n                      maxLength: 1024\n                      minLength: 1\n                      pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$\n                      type: string\n                    status:\n                      description: status of the condition, one of True, False, Unknown.\n                      enum:\n                      - \"True\"\n                      - \"False\"\n                      - Unknown\n                      type: string\n                    type:\n                      description: type of condition in CamelCase or in foo.example.com/CamelCase.\n                      maxLength: 316\n                      pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$\n                      type: string\n                  required:\n                  - lastTransitionTime\n                  - message\n                  - reason\n                  - status\n                  - type\n                  type: object\n                type: array\n            type: object\n        type: object\n    served: true\n    storage: true\n    subresources:\n      status: {}\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/crd/kustomization.yaml",
    "content": "# This kustomization.yaml is not intended to be run by itself,\n# since it depends on service name and namespace that are out of this kustomize package.\n# It should be run by config/default\nresources:\n- bases/cache.example.com_memcacheds.yaml\n# +kubebuilder:scaffold:crdkustomizeresource\n\npatches:\n# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix.\n# patches here are for enabling the conversion webhook for each CRD\n# +kubebuilder:scaffold:crdkustomizewebhookpatch\n\n# [WEBHOOK] To enable webhook, uncomment the following section\n# the following config is for teaching kustomize how to do kustomization for CRDs.\n#configurations:\n#- kustomizeconfig.yaml\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/crd/kustomizeconfig.yaml",
    "content": "# This file is for teaching kustomize how to substitute name and namespace reference in CRD\nnameReference:\n- kind: Service\n  version: v1\n  fieldSpecs:\n  - kind: CustomResourceDefinition\n    version: v1\n    group: apiextensions.k8s.io\n    path: spec/conversion/webhook/clientConfig/service/name\n\nnamespace:\n- kind: CustomResourceDefinition\n  version: v1\n  group: apiextensions.k8s.io\n  path: spec/conversion/webhook/clientConfig/service/namespace\n  create: false\n\nvarReference:\n- path: metadata/annotations\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/default/cert_metrics_manager_patch.yaml",
    "content": "# This patch adds the args, volumes, and ports to allow the manager to use the metrics-server certs.\n\n# Add the volumeMount for the metrics-server certs\n- op: add\n  path: /spec/template/spec/containers/0/volumeMounts/-\n  value:\n    mountPath: /tmp/k8s-metrics-server/metrics-certs\n    name: metrics-certs\n    readOnly: true\n\n# Add the --metrics-cert-path argument for the metrics server\n- op: add\n  path: /spec/template/spec/containers/0/args/-\n  value: --metrics-cert-path=/tmp/k8s-metrics-server/metrics-certs\n\n# Add the metrics-server certs volume configuration\n- op: add\n  path: /spec/template/spec/volumes/-\n  value:\n    name: metrics-certs\n    secret:\n      secretName: metrics-server-cert\n      optional: false\n      items:\n        - key: ca.crt\n          path: ca.crt\n        - key: tls.crt\n          path: tls.crt\n        - key: tls.key\n          path: tls.key\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/default/kustomization.yaml",
    "content": "# Adds namespace to all resources.\nnamespace: memcached-operator-system\n\n# Value of this field is prepended to the\n# names of all resources, e.g. a deployment named\n# \"wordpress\" becomes \"alices-wordpress\".\n# Note that it should also match with the prefix (text before '-') of the namespace\n# field above.\nnamePrefix: memcached-operator-\n\n# Labels to add to all resources and selectors.\n#labels:\n#- includeSelectors: true\n#  pairs:\n#    someName: someValue\n\nresources:\n- ../crd\n- ../rbac\n- ../manager\n# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in\n# crd/kustomization.yaml\n- ../webhook\n# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required.\n- ../certmanager\n# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'.\n- ../prometheus\n# [METRICS] Expose the controller manager metrics service.\n- metrics_service.yaml\n# [NETWORK POLICY] Protect the /metrics endpoint and Webhook Server with NetworkPolicy.\n# Only Pod(s) running a namespace labeled with 'metrics: enabled' will be able to gather the metrics.\n# Only CR(s) which requires webhooks and are applied on namespaces labeled with 'webhooks: enabled' will\n# be able to communicate with the Webhook Server.\n#- ../network-policy\n\n# Uncomment the patches line if you enable Metrics\npatches:\n# [METRICS] The following patch will enable the metrics endpoint using HTTPS and the port :8443.\n# More info: https://book.kubebuilder.io/reference/metrics\n- path: manager_metrics_patch.yaml\n  target:\n    kind: Deployment\n\n# Uncomment the patches line if you enable Metrics and CertManager\n# [METRICS-WITH-CERTS] To enable metrics protected with certManager, uncomment the following line.\n# This patch will protect the metrics with certManager self-signed certs.\n- path: cert_metrics_manager_patch.yaml\n  target:\n    kind: Deployment\n\n# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in\n# crd/kustomization.yaml\n- path: manager_webhook_patch.yaml\n  target:\n    kind: Deployment\n\n# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix.\n# Uncomment the following replacements to add the cert-manager CA injection annotations\nreplacements:\n - source: # Uncomment the following block to enable certificates for metrics\n     kind: Service\n     version: v1\n     name: controller-manager-metrics-service\n     fieldPath: metadata.name\n   targets:\n     - select:\n         kind: Certificate\n         group: cert-manager.io\n         version: v1\n         name: metrics-certs\n       fieldPaths:\n         - spec.dnsNames.0\n         - spec.dnsNames.1\n       options:\n         delimiter: '.'\n         index: 0\n         create: true\n     - select: # Uncomment the following to set the Service name for TLS config in Prometheus ServiceMonitor\n         kind: ServiceMonitor\n         group: monitoring.coreos.com\n         version: v1\n         name: controller-manager-metrics-monitor\n       fieldPaths:\n         - spec.endpoints.0.tlsConfig.serverName\n       options:\n         delimiter: '.'\n         index: 0\n         create: true\n\n - source:\n     kind: Service\n     version: v1\n     name: controller-manager-metrics-service\n     fieldPath: metadata.namespace\n   targets:\n     - select:\n         kind: Certificate\n         group: cert-manager.io\n         version: v1\n         name: metrics-certs\n       fieldPaths:\n         - spec.dnsNames.0\n         - spec.dnsNames.1\n       options:\n         delimiter: '.'\n         index: 1\n         create: true\n     - select: # Uncomment the following to set the Service namespace for TLS in Prometheus ServiceMonitor\n         kind: ServiceMonitor\n         group: monitoring.coreos.com\n         version: v1\n         name: controller-manager-metrics-monitor\n       fieldPaths:\n         - spec.endpoints.0.tlsConfig.serverName\n       options:\n         delimiter: '.'\n         index: 1\n         create: true\n\n - source: # Uncomment the following block if you have any webhook\n     kind: Service\n     version: v1\n     name: webhook-service\n     fieldPath: .metadata.name # Name of the service\n   targets:\n     - select:\n         kind: Certificate\n         group: cert-manager.io\n         version: v1\n         name: serving-cert\n       fieldPaths:\n         - .spec.dnsNames.0\n         - .spec.dnsNames.1\n       options:\n         delimiter: '.'\n         index: 0\n         create: true\n - source:\n     kind: Service\n     version: v1\n     name: webhook-service\n     fieldPath: .metadata.namespace # Namespace of the service\n   targets:\n     - select:\n         kind: Certificate\n         group: cert-manager.io\n         version: v1\n         name: serving-cert\n       fieldPaths:\n         - .spec.dnsNames.0\n         - .spec.dnsNames.1\n       options:\n         delimiter: '.'\n         index: 1\n         create: true\n\n# - source: # Uncomment the following block if you have a ValidatingWebhook (--programmatic-validation)\n#     kind: Certificate\n#     group: cert-manager.io\n#     version: v1\n#     name: serving-cert # This name should match the one in certificate.yaml\n#     fieldPath: .metadata.namespace # Namespace of the certificate CR\n#   targets:\n#     - select:\n#         kind: ValidatingWebhookConfiguration\n#       fieldPaths:\n#         - .metadata.annotations.[cert-manager.io/inject-ca-from]\n#       options:\n#         delimiter: '/'\n#         index: 0\n#         create: true\n# - source:\n#     kind: Certificate\n#     group: cert-manager.io\n#     version: v1\n#     name: serving-cert\n#     fieldPath: .metadata.name\n#   targets:\n#     - select:\n#         kind: ValidatingWebhookConfiguration\n#       fieldPaths:\n#         - .metadata.annotations.[cert-manager.io/inject-ca-from]\n#       options:\n#         delimiter: '/'\n#         index: 1\n#         create: true\n#\n - source: # Uncomment the following block if you have a DefaultingWebhook (--defaulting )\n     kind: Certificate\n     group: cert-manager.io\n     version: v1\n     name: serving-cert\n     fieldPath: .metadata.namespace # Namespace of the certificate CR\n   targets:\n     - select:\n         kind: MutatingWebhookConfiguration\n       fieldPaths:\n         - .metadata.annotations.[cert-manager.io/inject-ca-from]\n       options:\n         delimiter: '/'\n         index: 0\n         create: true\n - source:\n     kind: Certificate\n     group: cert-manager.io\n     version: v1\n     name: serving-cert\n     fieldPath: .metadata.name\n   targets:\n     - select:\n         kind: MutatingWebhookConfiguration\n       fieldPaths:\n         - .metadata.annotations.[cert-manager.io/inject-ca-from]\n       options:\n         delimiter: '/'\n         index: 1\n         create: true\n\n# - source: # Uncomment the following block if you have a ConversionWebhook (--conversion)\n#     kind: Certificate\n#     group: cert-manager.io\n#     version: v1\n#     name: serving-cert\n#     fieldPath: .metadata.namespace # Namespace of the certificate CR\n#   targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD.\n# +kubebuilder:scaffold:crdkustomizecainjectionns\n# - source:\n#     kind: Certificate\n#     group: cert-manager.io\n#     version: v1\n#     name: serving-cert\n#     fieldPath: .metadata.name\n#   targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD.\n# +kubebuilder:scaffold:crdkustomizecainjectionname\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/default/manager_metrics_patch.yaml",
    "content": "# This patch adds the args to allow exposing the metrics endpoint using HTTPS\n- op: add\n  path: /spec/template/spec/containers/0/args/0\n  value: --metrics-bind-address=:8443\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/default/manager_webhook_patch.yaml",
    "content": "# This patch ensures the webhook certificates are properly mounted in the manager container.\n# It configures the necessary arguments, volumes, volume mounts, and container ports.\n\n# Add the --webhook-cert-path argument for configuring the webhook certificate path\n- op: add\n  path: /spec/template/spec/containers/0/args/-\n  value: --webhook-cert-path=/tmp/k8s-webhook-server/serving-certs\n\n# Add the volumeMount for the webhook certificates\n- op: add\n  path: /spec/template/spec/containers/0/volumeMounts/-\n  value:\n    mountPath: /tmp/k8s-webhook-server/serving-certs\n    name: webhook-certs\n    readOnly: true\n\n# Add the port configuration for the webhook server\n- op: add\n  path: /spec/template/spec/containers/0/ports/-\n  value:\n    containerPort: 9443\n    name: webhook-server\n    protocol: TCP\n\n# Add the volume configuration for the webhook certificates\n- op: add\n  path: /spec/template/spec/volumes/-\n  value:\n    name: webhook-certs\n    secret:\n      secretName: webhook-server-cert\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/default/metrics_service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    control-plane: controller-manager\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: controller-manager-metrics-service\n  namespace: system\nspec:\n  ports:\n  - name: https\n    port: 8443\n    protocol: TCP\n    targetPort: 8443\n  selector:\n    control-plane: controller-manager\n    app.kubernetes.io/name: memcached-operator\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/manager/kustomization.yaml",
    "content": "resources:\n- manager.yaml\napiVersion: kustomize.config.k8s.io/v1beta1\nkind: Kustomization\nimages:\n- name: controller\n  newName: quay.io/example/memcached-operator\n  newTag: v0.0.1\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/manager/manager.yaml",
    "content": "apiVersion: v1\nkind: Namespace\nmetadata:\n  labels:\n    control-plane: controller-manager\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: system\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: controller-manager\n  namespace: system\n  labels:\n    control-plane: controller-manager\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\nspec:\n  selector:\n    matchLabels:\n      control-plane: controller-manager\n      app.kubernetes.io/name: memcached-operator\n  replicas: 1\n  template:\n    metadata:\n      annotations:\n        kubectl.kubernetes.io/default-container: manager\n      labels:\n        control-plane: controller-manager\n        app.kubernetes.io/name: memcached-operator\n    spec:\n      # TODO(user): Uncomment the following code to configure the nodeAffinity expression\n      # according to the platforms which are supported by your solution.\n      # It is considered best practice to support multiple architectures. You can\n      # build your manager image using the makefile target docker-buildx.\n      # affinity:\n      #   nodeAffinity:\n      #     requiredDuringSchedulingIgnoredDuringExecution:\n      #       nodeSelectorTerms:\n      #         - matchExpressions:\n      #           - key: kubernetes.io/arch\n      #             operator: In\n      #             values:\n      #               - amd64\n      #               - arm64\n      #               - ppc64le\n      #               - s390x\n      #           - key: kubernetes.io/os\n      #             operator: In\n      #             values:\n      #               - linux\n      securityContext:\n        # Projects are configured by default to adhere to the \"restricted\" Pod Security Standards.\n        # This ensures that deployments meet the highest security requirements for Kubernetes.\n        # For more details, see: https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted\n        runAsNonRoot: true\n        seccompProfile:\n          type: RuntimeDefault\n      containers:\n      - command:\n        - /manager\n        args:\n          - --leader-elect\n          - --health-probe-bind-address=:8081\n        image: controller:latest\n        name: manager\n        env:\n        - name: MEMCACHED_IMAGE\n          value: memcached:1.4.36-alpine\n        ports: []\n        securityContext:\n          allowPrivilegeEscalation: false\n          capabilities:\n            drop:\n            - \"ALL\"\n        livenessProbe:\n          httpGet:\n            path: /healthz\n            port: 8081\n          initialDelaySeconds: 15\n          periodSeconds: 20\n        readinessProbe:\n          httpGet:\n            path: /readyz\n            port: 8081\n          initialDelaySeconds: 5\n          periodSeconds: 10\n        # TODO(user): Configure the resources accordingly based on the project requirements.\n        # More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/\n        resources:\n          limits:\n            cpu: 500m\n            memory: 128Mi\n          requests:\n            cpu: 10m\n            memory: 64Mi\n        volumeMounts: []\n      volumes: []\n      serviceAccountName: controller-manager\n      terminationGracePeriodSeconds: 10\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml",
    "content": "apiVersion: operators.coreos.com/v1alpha1\nkind: ClusterServiceVersion\nmetadata:\n  annotations:\n    alm-examples: '[]'\n    capabilities: Basic Install\n  name: memcached-operator.v0.0.0\n  namespace: placeholder\nspec:\n  apiservicedefinitions: {}\n  customresourcedefinitions:\n    owned:\n    - description: Memcached is the Schema for the memcacheds API\n      displayName: Memcached\n      kind: Memcached\n      name: memcacheds.cache.example.com\n      resources:\n      - kind: Deployment\n        name: memcached-deployment\n        version: v1\n      specDescriptors:\n      - description: Port defines the port that will be used to init the container\n          with the image\n        displayName: Container Port\n        path: containerPort\n      - description: Size defines the number of Memcached instances\n        displayName: Size\n        path: size\n      statusDescriptors:\n      - description: Conditions store the status conditions of the Memcached instances\n        displayName: Conditions\n        path: conditions\n      version: v1alpha1\n  description: Memcached Operator description. TODO.\n  displayName: Memcached Operator\n  icon:\n  - base64data: \"\"\n    mediatype: \"\"\n  install:\n    spec:\n      deployments: null\n    strategy: \"\"\n  installModes:\n  - supported: false\n    type: OwnNamespace\n  - supported: false\n    type: SingleNamespace\n  - supported: false\n    type: MultiNamespace\n  - supported: true\n    type: AllNamespaces\n  keywords:\n  - memcached-operator\n  links:\n  - name: Memcached Operator\n    url: https://memcached-operator.domain\n  maintainers:\n  - email: your@email.com\n    name: Maintainer Name\n  maturity: alpha\n  provider:\n    name: Provider Name\n    url: https://your.domain\n  version: 0.0.0\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/manifests/kustomization.yaml",
    "content": "# These resources constitute the fully configured set of manifests\n# used to generate the 'manifests/' directory in a bundle.\nresources:\n- bases/memcached-operator.clusterserviceversion.yaml\n- ../default\n- ../samples\n- ../scorecard\n\n# [WEBHOOK] To enable webhooks, uncomment all the sections with [WEBHOOK] prefix.\n# Do NOT uncomment sections with prefix [CERTMANAGER], as OLM does not support cert-manager.\n# These patches remove the unnecessary \"cert\" volume and its manager container volumeMount.\npatches:\n- target:\n    group: apps\n    version: v1\n    kind: Deployment\n    name: controller-manager\n    namespace: system\n  patch: |-\n    # Remove the manager container's \"cert\" volumeMount, since OLM will create and mount a set of certs.\n    # Update the indices in this path if adding or removing containers/volumeMounts in the manager's Deployment.\n    - op: remove\n\n      path: /spec/template/spec/containers/0/volumeMounts/0\n    # Remove the \"cert\" volume, since OLM will create and mount a set of certs.\n    # Update the indices in this path if adding or removing volumes in the manager's Deployment.\n    - op: remove\n      path: /spec/template/spec/volumes/0\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/network-policy/allow-metrics-traffic.yaml",
    "content": "# This NetworkPolicy allows ingress traffic\n# with Pods running on namespaces labeled with 'metrics: enabled'. Only Pods on those\n# namespaces are able to gather data from the metrics endpoint.\napiVersion: networking.k8s.io/v1\nkind: NetworkPolicy\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: allow-metrics-traffic\n  namespace: system\nspec:\n  podSelector:\n    matchLabels:\n      control-plane: controller-manager\n      app.kubernetes.io/name: memcached-operator\n  policyTypes:\n    - Ingress\n  ingress:\n    # This allows ingress traffic from any namespace with the label metrics: enabled\n    - from:\n      - namespaceSelector:\n          matchLabels:\n            metrics: enabled  # Only from namespaces with this label\n      ports:\n        - port: 8443\n          protocol: TCP\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/network-policy/allow-webhook-traffic.yaml",
    "content": "# This NetworkPolicy allows ingress traffic to your webhook server running\n# as part of the controller-manager from specific namespaces and pods. CR(s) which uses webhooks\n# will only work when applied in namespaces labeled with 'webhook: enabled'\napiVersion: networking.k8s.io/v1\nkind: NetworkPolicy\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: allow-webhook-traffic\n  namespace: system\nspec:\n  podSelector:\n    matchLabels:\n      control-plane: controller-manager\n      app.kubernetes.io/name: memcached-operator\n  policyTypes:\n    - Ingress\n  ingress:\n    # This allows ingress traffic from any namespace with the label webhook: enabled\n    - from:\n      - namespaceSelector:\n          matchLabels:\n            webhook: enabled # Only from namespaces with this label\n      ports:\n        - port: 443\n          protocol: TCP\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/network-policy/kustomization.yaml",
    "content": "resources:\n- allow-webhook-traffic.yaml\n- allow-metrics-traffic.yaml\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/prometheus/kustomization.yaml",
    "content": "resources:\n- monitor.yaml\n\n# [PROMETHEUS-WITH-CERTS] The following patch configures the ServiceMonitor in ../prometheus\n# to securely reference certificates created and managed by cert-manager.\n# Additionally, ensure that you uncomment the [METRICS WITH CERTMANAGER] patch under config/default/kustomization.yaml\n# to mount the \"metrics-server-cert\" secret in the Manager Deployment.\n#patches:\n#  - path: monitor_tls_patch.yaml\n#    target:\n#      kind: ServiceMonitor\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/prometheus/monitor.yaml",
    "content": "# Prometheus Monitor Service (Metrics)\napiVersion: monitoring.coreos.com/v1\nkind: ServiceMonitor\nmetadata:\n  labels:\n    control-plane: controller-manager\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: controller-manager-metrics-monitor\n  namespace: system\nspec:\n  endpoints:\n    - path: /metrics\n      port: https # Ensure this is the name of the port that exposes HTTPS metrics\n      scheme: https\n      bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token\n      tlsConfig:\n        # TODO(user): The option insecureSkipVerify: true is not recommended for production since it disables\n        # certificate verification, exposing the system to potential man-in-the-middle attacks.\n        # For production environments, it is recommended to use cert-manager for automatic TLS certificate management.\n        # To apply this configuration, enable cert-manager and use the patch located at config/prometheus/servicemonitor_tls_patch.yaml,\n        # which securely references the certificate from the 'metrics-server-cert' secret.\n        insecureSkipVerify: true\n  selector:\n    matchLabels:\n      control-plane: controller-manager\n      app.kubernetes.io/name: memcached-operator\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/prometheus/monitor_tls_patch.yaml",
    "content": "# Patch for Prometheus ServiceMonitor to enable secure TLS configuration\n# using certificates managed by cert-manager\n- op: replace\n  path: /spec/endpoints/0/tlsConfig\n  value:\n    # SERVICE_NAME and SERVICE_NAMESPACE will be substituted by kustomize\n    serverName: SERVICE_NAME.SERVICE_NAMESPACE.svc\n    insecureSkipVerify: false\n    ca:\n      secret:\n        name: metrics-server-cert\n        key: ca.crt\n    cert:\n      secret:\n        name: metrics-server-cert\n        key: tls.crt\n    keySecret:\n      name: metrics-server-cert\n      key: tls.key\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/rbac/kustomization.yaml",
    "content": "resources:\n# All RBAC will be applied under this service account in\n# the deployment namespace. You may comment out this resource\n# if your manager will use a service account that exists at\n# runtime. Be sure to update RoleBinding and ClusterRoleBinding\n# subjects if changing service account names.\n- service_account.yaml\n- role.yaml\n- role_binding.yaml\n- leader_election_role.yaml\n- leader_election_role_binding.yaml\n- prometheus_role.yaml\n- prometheus_role_binding.yaml\n# The following RBAC configurations are used to protect\n# the metrics endpoint with authn/authz. These configurations\n# ensure that only authorized users and service accounts\n# can access the metrics endpoint. Comment the following\n# permissions if you want to disable this protection.\n# More info: https://book.kubebuilder.io/reference/metrics.html\n- metrics_auth_role.yaml\n- metrics_auth_role_binding.yaml\n- metrics_reader_role.yaml\n# For each CRD, \"Admin\", \"Editor\" and \"Viewer\" roles are scaffolded by\n# default, aiding admins in cluster management. Those roles are\n# not used by the memcached-operator itself. You can comment the following lines\n# if you do not want those helpers be installed with your Project.\n- memcached_admin_role.yaml\n- memcached_editor_role.yaml\n- memcached_viewer_role.yaml\n\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/rbac/leader_election_role.yaml",
    "content": "# permissions to do leader election.\napiVersion: rbac.authorization.k8s.io/v1\nkind: Role\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: leader-election-role\nrules:\n- apiGroups:\n  - \"\"\n  resources:\n  - configmaps\n  verbs:\n  - get\n  - list\n  - watch\n  - create\n  - update\n  - patch\n  - delete\n- apiGroups:\n  - coordination.k8s.io\n  resources:\n  - leases\n  verbs:\n  - get\n  - list\n  - watch\n  - create\n  - update\n  - patch\n  - delete\n- apiGroups:\n  - \"\"\n  resources:\n  - events\n  verbs:\n  - create\n  - patch\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/rbac/leader_election_role_binding.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: RoleBinding\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: leader-election-rolebinding\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: Role\n  name: leader-election-role\nsubjects:\n- kind: ServiceAccount\n  name: controller-manager\n  namespace: system\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/rbac/memcached_admin_role.yaml",
    "content": "# This rule is not used by the project memcached-operator itself.\n# It is provided to allow the cluster admin to help manage permissions for users.\n#\n# Grants full permissions ('*') over cache.example.com.\n# This role is intended for users authorized to modify roles and bindings within the cluster,\n# enabling them to delegate specific permissions to other users or groups as needed.\n\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: memcached-admin-role\nrules:\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds\n  verbs:\n  - '*'\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds/status\n  verbs:\n  - get\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/rbac/memcached_editor_role.yaml",
    "content": "# This rule is not used by the project memcached-operator itself.\n# It is provided to allow the cluster admin to help manage permissions for users.\n#\n# Grants permissions to create, update, and delete resources within the cache.example.com.\n# This role is intended for users who need to manage these resources\n# but should not control RBAC or manage permissions for others.\n\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: memcached-editor-role\nrules:\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds/status\n  verbs:\n  - get\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/rbac/memcached_viewer_role.yaml",
    "content": "# This rule is not used by the project memcached-operator itself.\n# It is provided to allow the cluster admin to help manage permissions for users.\n#\n# Grants read-only access to cache.example.com resources.\n# This role is intended for users who need visibility into these resources\n# without permissions to modify them. It is ideal for monitoring purposes and limited-access viewing.\n\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: memcached-viewer-role\nrules:\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds\n  verbs:\n  - get\n  - list\n  - watch\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds/status\n  verbs:\n  - get\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/rbac/metrics_auth_role.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  name: metrics-auth-role\nrules:\n- apiGroups:\n  - authentication.k8s.io\n  resources:\n  - tokenreviews\n  verbs:\n  - create\n- apiGroups:\n  - authorization.k8s.io\n  resources:\n  - subjectaccessreviews\n  verbs:\n  - create\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/rbac/metrics_auth_role_binding.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n  name: metrics-auth-rolebinding\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: metrics-auth-role\nsubjects:\n- kind: ServiceAccount\n  name: controller-manager\n  namespace: system\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/rbac/metrics_reader_role.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  name: metrics-reader\nrules:\n- nonResourceURLs:\n  - \"/metrics\"\n  verbs:\n  - get\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/rbac/prometheus_role.yaml",
    "content": "---\napiVersion: rbac.authorization.k8s.io/v1\nkind: Role\nmetadata:\n  name: prometheus-role\n  namespace: system\nrules:\n  - apiGroups: [\"\"]\n    resources:\n      - services\n      - endpoints\n      - pods\n    verbs: [\"get\", \"list\"]\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/rbac/prometheus_role_binding.yaml",
    "content": "---\napiVersion: rbac.authorization.k8s.io/v1\nkind: RoleBinding\nmetadata:\n  name: prometheus-role-binding\n  namespace: system\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: Role\n  name: prometheus-role\nsubjects:\n- kind: ServiceAccount\n  name: prometheus-k8s\n  namespace: monitoring\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/rbac/role.yaml",
    "content": "---\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  name: manager-role\nrules:\n- apiGroups:\n  - \"\"\n  resources:\n  - events\n  verbs:\n  - create\n  - patch\n- apiGroups:\n  - \"\"\n  resources:\n  - pods\n  verbs:\n  - get\n  - list\n  - watch\n- apiGroups:\n  - apps\n  resources:\n  - deployments\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds/finalizers\n  verbs:\n  - update\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds/status\n  verbs:\n  - get\n  - patch\n  - update\n- apiGroups:\n  - monitoring.coreos.com\n  resources:\n  - prometheusrules\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - update\n  - watch\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/rbac/role_binding.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: manager-rolebinding\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: manager-role\nsubjects:\n- kind: ServiceAccount\n  name: controller-manager\n  namespace: system\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/rbac/service_account.yaml",
    "content": "apiVersion: v1\nkind: ServiceAccount\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: controller-manager\n  namespace: system\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml",
    "content": "apiVersion: cache.example.com/v1alpha1\nkind: Memcached\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: memcached-sample\nspec:\n  # TODO(user): edit the following value to ensure the number\n  # of Pods/Instances your Operand must have on cluster\n  size: 1\n\n  # TODO(user): edit the following value to ensure the container has the right port to be initialized\n  containerPort: 11211\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/samples/kustomization.yaml",
    "content": "## Append samples of your project ##\nresources:\n- cache_v1alpha1_memcached.yaml\n# +kubebuilder:scaffold:manifestskustomizesamples\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/scorecard/bases/config.yaml",
    "content": "apiVersion: scorecard.operatorframework.io/v1alpha3\nkind: Configuration\nmetadata:\n  name: config\nstages:\n- parallel: true\n  tests: []\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/scorecard/kustomization.yaml",
    "content": "resources:\n- bases/config.yaml\napiVersion: kustomize.config.k8s.io/v1beta1\nkind: Kustomization\npatches:\n- path: patches/basic.config.yaml\n  target:\n    group: scorecard.operatorframework.io\n    kind: Configuration\n    name: config\n    version: v1alpha3\n- path: patches/olm.config.yaml\n  target:\n    group: scorecard.operatorframework.io\n    kind: Configuration\n    name: config\n    version: v1alpha3\n# +kubebuilder:scaffold:patches\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/scorecard/patches/basic.config.yaml",
    "content": "- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - scorecard-test\n    - basic-check-spec\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: basic\n      test: basic-check-spec-test\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/scorecard/patches/olm.config.yaml",
    "content": "- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - scorecard-test\n    - olm-bundle-validation\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: olm\n      test: olm-bundle-validation-test\n- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - scorecard-test\n    - olm-crds-have-validation\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: olm\n      test: olm-crds-have-validation-test\n- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - scorecard-test\n    - olm-crds-have-resources\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: olm\n      test: olm-crds-have-resources-test\n- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - scorecard-test\n    - olm-spec-descriptors\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: olm\n      test: olm-spec-descriptors-test\n- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - scorecard-test\n    - olm-status-descriptors\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: olm\n      test: olm-status-descriptors-test\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/webhook/kustomization.yaml",
    "content": "resources:\n- manifests.yaml\n- service.yaml\n\nconfigurations:\n- kustomizeconfig.yaml\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/webhook/kustomizeconfig.yaml",
    "content": "# the following config is for teaching kustomize where to look at when substituting nameReference.\n# It requires kustomize v2.1.0 or newer to work properly.\nnameReference:\n- kind: Service\n  version: v1\n  fieldSpecs:\n  - kind: MutatingWebhookConfiguration\n    group: admissionregistration.k8s.io\n    path: webhooks/clientConfig/service/name\n  - kind: ValidatingWebhookConfiguration\n    group: admissionregistration.k8s.io\n    path: webhooks/clientConfig/service/name\n\nnamespace:\n- kind: MutatingWebhookConfiguration\n  group: admissionregistration.k8s.io\n  path: webhooks/clientConfig/service/namespace\n  create: true\n- kind: ValidatingWebhookConfiguration\n  group: admissionregistration.k8s.io\n  path: webhooks/clientConfig/service/namespace\n  create: true\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/webhook/manifests.yaml",
    "content": "---\napiVersion: admissionregistration.k8s.io/v1\nkind: MutatingWebhookConfiguration\nmetadata:\n  name: mutating-webhook-configuration\nwebhooks:\n- admissionReviewVersions:\n  - v1\n  clientConfig:\n    service:\n      name: webhook-service\n      namespace: system\n      path: /mutate-cache-example-com-v1alpha1-memcached\n  failurePolicy: Fail\n  name: mmemcached-v1alpha1.kb.io\n  rules:\n  - apiGroups:\n    - cache.example.com\n    apiVersions:\n    - v1alpha1\n    operations:\n    - CREATE\n    - UPDATE\n    resources:\n    - memcacheds\n  sideEffects: None\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/config/webhook/service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: webhook-service\n  namespace: system\nspec:\n  ports:\n    - port: 443\n      protocol: TCP\n      targetPort: 9443\n  selector:\n    control-plane: controller-manager\n    app.kubernetes.io/name: memcached-operator\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/docs/monitoring/metrics.md",
    "content": "# Operator Metrics\nThis document aims to help users that are not familiar with metrics exposed by this operator.\nThe metrics documentation is auto-generated by the utility tool \"monitoring/metricsdocs\" and reflects all of the metrics that are exposed by the operator.\n\n## Operator Metrics List\n### memcached_deployment_size_undesired_count_total\nTotal number of times the deployment size was not as desired. Type: Counter.\n## Developing new metrics\nAfter developing new metrics or changing old ones, please run \"make generate-metricsdocs\" to regenerate this document.\n\nIf you feel that the new metric doesn't follow these rules, please change \"monitoring/metricsdocs\" according to your needs.\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/docs/monitoring/runbooks/memcachedDeploymentSizeUndesired.md",
    "content": "# MemcachedDeploymentSizeUndesired\n\n## Meaning\nMemcachedDeploymentSizeUndesired is triggered when the number of available\n<code>memcached-sample</code> replicas doesn't match the requested configuration.\n\n## Impact\nUnavailability of distributed memory object caching system in the cluster.\n\n## Diagnosis\n- Check memcached-sample's pod namespace:\n\n  <code>export NAMESPACE=\"$(kubectl get deployment -A | grep memcached-sample | awk '{print $1}')\"</code>\n\n- Observe the status of the memcached-sample deployment:\n\n  <code>kubectl get deploy memcached-sample -n $NAMESPACE -o yaml</code>\n\n- Observe the logs of the memcached manager pod, to see why it cannot create the memcached-sample pods.\n\n   <code>kubectl get logs <memcached-operator-controller-manager-pod> -n memcached-operator-system</code>\n\n## Mitigation\nThere can be several reasons. Like:\n- Node resource exhaustion\n- Not enough memory on the cluster\n- Nodes are down\n\nTry to identify the root cause and fix it."
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/docs/monitoring/runbooks/memcachedOperatorDown.md",
    "content": "# MemcachedOperatorDown\n\n## Meaning\nNo running memcached-operator-controller-manager pods were detected in the last 5 min.\n\n## Impact\nComplete failure in the <code>Memcached</code> CR lifecycle management.\ni.e. launching a new <code>Memcached</code> instance or shutting down an existing one.\n## Diagnosis\n- Observe the status of the memcached-operator-controller-manager deployment:\n\n  <code>kubectl get deploy memcached-operator-controller-manager -n mecmached-operator-system -o yaml</code>\n\n## Mitigation\nThere can be several reasons for the memcached-operator-controller-manager pod to be down, identify the root cause and fix it.\n\n- Check the status of the memcached-operator-controller-manager deployment to\nfind out more information. The following command will provide the associated events and show if there are any issues with pulling an image, crashing pod, etc.\n\n<code>kubectl describe deploy memcached-operator-controller-manager -n memcached-operator-system</code>\n\n- Check if there are issues with the nodes. For example, if they are in a NotReady state.\n\n  </code>kubectl get nodes</code>\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/go.mod",
    "content": "module github.com/example/memcached-operator\n\ngo 1.24.0\n\nrequire (\n\tgithub.com/onsi/ginkgo/v2 v2.22.0\n\tgithub.com/onsi/gomega v1.36.1\n\tgithub.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.59.0\n\tgithub.com/prometheus/client_golang v1.22.0\n\tk8s.io/api v0.33.0\n\tk8s.io/apimachinery v0.33.0\n\tk8s.io/client-go v0.33.0\n\tk8s.io/utils v0.0.0-20241104100929-3ea5e8cea738\n\tsigs.k8s.io/controller-runtime v0.21.0\n)\n\nrequire (\n\tcel.dev/expr v0.19.1 // indirect\n\tgithub.com/antlr4-go/antlr/v4 v4.13.0 // indirect\n\tgithub.com/beorn7/perks v1.0.1 // indirect\n\tgithub.com/blang/semver/v4 v4.0.0 // indirect\n\tgithub.com/cenkalti/backoff/v4 v4.3.0 // indirect\n\tgithub.com/cespare/xxhash/v2 v2.3.0 // indirect\n\tgithub.com/davecgh/go-spew v1.1.1 // indirect\n\tgithub.com/emicklei/go-restful/v3 v3.11.0 // indirect\n\tgithub.com/evanphx/json-patch v5.6.0+incompatible // indirect\n\tgithub.com/evanphx/json-patch/v5 v5.9.11 // indirect\n\tgithub.com/felixge/httpsnoop v1.0.4 // indirect\n\tgithub.com/fsnotify/fsnotify v1.7.0 // indirect\n\tgithub.com/fxamacker/cbor/v2 v2.7.0 // indirect\n\tgithub.com/go-logr/logr v1.4.2 // indirect\n\tgithub.com/go-logr/stdr v1.2.2 // indirect\n\tgithub.com/go-logr/zapr v1.3.0 // indirect\n\tgithub.com/go-openapi/jsonpointer v0.21.0 // indirect\n\tgithub.com/go-openapi/jsonreference v0.20.2 // indirect\n\tgithub.com/go-openapi/swag v0.23.0 // indirect\n\tgithub.com/go-task/slim-sprig/v3 v3.0.0 // indirect\n\tgithub.com/gogo/protobuf v1.3.2 // indirect\n\tgithub.com/google/btree v1.1.3 // indirect\n\tgithub.com/google/cel-go v0.23.2 // indirect\n\tgithub.com/google/gnostic-models v0.6.9 // indirect\n\tgithub.com/google/go-cmp v0.7.0 // indirect\n\tgithub.com/google/pprof v0.0.0-20241029153458-d1b30febd7db // indirect\n\tgithub.com/google/uuid v1.6.0 // indirect\n\tgithub.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 // indirect\n\tgithub.com/inconshreveable/mousetrap v1.1.0 // indirect\n\tgithub.com/josharian/intern v1.0.0 // indirect\n\tgithub.com/json-iterator/go v1.1.12 // indirect\n\tgithub.com/mailru/easyjson v0.7.7 // indirect\n\tgithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect\n\tgithub.com/modern-go/reflect2 v1.0.2 // indirect\n\tgithub.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect\n\tgithub.com/pkg/errors v0.9.1 // indirect\n\tgithub.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect\n\tgithub.com/prometheus/client_model v0.6.1 // indirect\n\tgithub.com/prometheus/common v0.62.0 // indirect\n\tgithub.com/prometheus/procfs v0.15.1 // indirect\n\tgithub.com/spf13/cobra v1.8.1 // indirect\n\tgithub.com/spf13/pflag v1.0.5 // indirect\n\tgithub.com/stoewer/go-strcase v1.3.0 // indirect\n\tgithub.com/x448/float16 v0.8.4 // indirect\n\tgo.opentelemetry.io/auto/sdk v1.1.0 // indirect\n\tgo.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 // indirect\n\tgo.opentelemetry.io/otel v1.33.0 // indirect\n\tgo.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 // indirect\n\tgo.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0 // indirect\n\tgo.opentelemetry.io/otel/metric v1.33.0 // indirect\n\tgo.opentelemetry.io/otel/sdk v1.33.0 // indirect\n\tgo.opentelemetry.io/otel/trace v1.33.0 // indirect\n\tgo.opentelemetry.io/proto/otlp v1.4.0 // indirect\n\tgo.uber.org/multierr v1.11.0 // indirect\n\tgo.uber.org/zap v1.27.0 // indirect\n\tgolang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect\n\tgolang.org/x/net v0.38.0 // indirect\n\tgolang.org/x/oauth2 v0.27.0 // indirect\n\tgolang.org/x/sync v0.12.0 // indirect\n\tgolang.org/x/sys v0.31.0 // indirect\n\tgolang.org/x/term v0.30.0 // indirect\n\tgolang.org/x/text v0.23.0 // indirect\n\tgolang.org/x/time v0.9.0 // indirect\n\tgolang.org/x/tools v0.26.0 // indirect\n\tgomodules.xyz/jsonpatch/v2 v2.4.0 // indirect\n\tgoogle.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 // indirect\n\tgoogle.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 // indirect\n\tgoogle.golang.org/grpc v1.68.1 // indirect\n\tgoogle.golang.org/protobuf v1.36.5 // indirect\n\tgopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect\n\tgopkg.in/inf.v0 v0.9.1 // indirect\n\tgopkg.in/yaml.v3 v3.0.1 // indirect\n\tk8s.io/apiextensions-apiserver v0.33.0 // indirect\n\tk8s.io/apiserver v0.33.0 // indirect\n\tk8s.io/component-base v0.33.0 // indirect\n\tk8s.io/klog/v2 v2.130.1 // indirect\n\tk8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect\n\tsigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 // indirect\n\tsigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect\n\tsigs.k8s.io/randfill v1.0.0 // indirect\n\tsigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect\n\tsigs.k8s.io/yaml v1.4.0 // indirect\n)\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/go.sum",
    "content": "cel.dev/expr v0.19.1 h1:NciYrtDRIR0lNCnH1LFJegdjspNx9fI59O7TWcua/W4=\ncel.dev/expr v0.19.1/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw=\ngithub.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=\ngithub.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g=\ngithub.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=\ngithub.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=\ngithub.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=\ngithub.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=\ngithub.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=\ngithub.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=\ngithub.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=\ngithub.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=\ngithub.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=\ngithub.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=\ngithub.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=\ngithub.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U=\ngithub.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=\ngithub.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU=\ngithub.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM=\ngithub.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=\ngithub.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=\ngithub.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=\ngithub.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=\ngithub.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=\ngithub.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=\ngithub.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=\ngithub.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=\ngithub.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=\ngithub.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=\ngithub.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=\ngithub.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=\ngithub.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg=\ngithub.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=\ngithub.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=\ngithub.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=\ngithub.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=\ngithub.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=\ngithub.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=\ngithub.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=\ngithub.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=\ngithub.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=\ngithub.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=\ngithub.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=\ngithub.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=\ngithub.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=\ngithub.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=\ngithub.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=\ngithub.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=\ngithub.com/google/cel-go v0.23.2 h1:UdEe3CvQh3Nv+E/j9r1Y//WO0K0cSyD7/y0bzyLIMI4=\ngithub.com/google/cel-go v0.23.2/go.mod h1:52Pb6QsDbC5kvgxvZhiL9QX1oZEkcUF/ZqaPx1J5Wwo=\ngithub.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=\ngithub.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw=\ngithub.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=\ngithub.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=\ngithub.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=\ngithub.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=\ngithub.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=\ngithub.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=\ngithub.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo=\ngithub.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=\ngithub.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=\ngithub.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 h1:TmHmbvxPmaegwhDubVz0lICL0J5Ka2vwTzhoePEXsGE=\ngithub.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0/go.mod h1:qztMSjm835F2bXf+5HKAPIS5qsmQDqZna/PgVt4rWtI=\ngithub.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=\ngithub.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=\ngithub.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=\ngithub.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=\ngithub.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=\ngithub.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=\ngithub.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=\ngithub.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=\ngithub.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=\ngithub.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=\ngithub.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=\ngithub.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=\ngithub.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=\ngithub.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=\ngithub.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=\ngithub.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=\ngithub.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=\ngithub.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=\ngithub.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=\ngithub.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=\ngithub.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=\ngithub.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=\ngithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=\ngithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=\ngithub.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=\ngithub.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=\ngithub.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=\ngithub.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=\ngithub.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg=\ngithub.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=\ngithub.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw=\ngithub.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=\ngithub.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=\ngithub.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=\ngithub.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.59.0 h1:1aAICc8gsk8Sy/1wzbOwCXbC+DvJBqBoStdkX3zVgm0=\ngithub.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.59.0/go.mod h1:MNl09GdaKb/vE8QdcCWyICDV7XAbGX6gKKQAS43XW1c=\ngithub.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=\ngithub.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=\ngithub.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=\ngithub.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=\ngithub.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=\ngithub.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=\ngithub.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=\ngithub.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=\ngithub.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=\ngithub.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=\ngithub.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=\ngithub.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=\ngithub.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=\ngithub.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=\ngithub.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=\ngithub.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs=\ngithub.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=\ngithub.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=\ngithub.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=\ngithub.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=\ngithub.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=\ngithub.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=\ngithub.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=\ngithub.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=\ngithub.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=\ngithub.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=\ngithub.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=\ngithub.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=\ngithub.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=\ngo.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=\ngo.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=\ngo.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 h1:yd02MEjBdJkG3uabWP9apV+OuWRIXGDuJEUJbOHmCFU=\ngo.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q=\ngo.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw=\ngo.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I=\ngo.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 h1:Vh5HayB/0HHfOQA7Ctx69E/Y/DcQSMPpKANYVMQ7fBA=\ngo.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0/go.mod h1:cpgtDBaqD/6ok/UG0jT15/uKjAY8mRA53diogHBg3UI=\ngo.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0 h1:5pojmb1U1AogINhN3SurB+zm/nIcusopeBNp42f45QM=\ngo.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0/go.mod h1:57gTHJSE5S1tqg+EKsLPlTWhpHMsWlVmer+LA926XiA=\ngo.opentelemetry.io/otel/metric v1.33.0 h1:r+JOocAyeRVXD8lZpjdQjzMadVZp2M4WmQ+5WtEnklQ=\ngo.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M=\ngo.opentelemetry.io/otel/sdk v1.33.0 h1:iax7M131HuAm9QkZotNHEfstof92xM+N8sr3uHXc2IM=\ngo.opentelemetry.io/otel/sdk v1.33.0/go.mod h1:A1Q5oi7/9XaMlIWzPSxLRWOI8nG3FnzHJNbiENQuihM=\ngo.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s=\ngo.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck=\ngo.opentelemetry.io/proto/otlp v1.4.0 h1:TA9WRvW6zMwP+Ssb6fLoUIuirti1gGbP28GcKG1jgeg=\ngo.opentelemetry.io/proto/otlp v1.4.0/go.mod h1:PPBWZIP98o2ElSqI35IHfu7hIhSwvc5N38Jw8pXuGFY=\ngo.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=\ngo.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=\ngo.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=\ngo.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=\ngo.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=\ngo.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=\ngolang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=\ngolang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=\ngolang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=\ngolang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=\ngolang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=\ngolang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=\ngolang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=\ngolang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=\ngolang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=\ngolang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=\ngolang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=\ngolang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=\ngolang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=\ngolang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=\ngolang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=\ngolang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=\ngolang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=\ngolang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=\ngolang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=\ngolang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=\ngolang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=\ngolang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=\ngolang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=\ngolang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=\ngolang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=\ngolang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw=\ngomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=\ngoogle.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 h1:CkkIfIt50+lT6NHAVoRYEyAvQGFM7xEwXUUywFvEb3Q=\ngoogle.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576/go.mod h1:1R3kvZ1dtP3+4p4d3G8uJ8rFk/fWlScl38vanWACI08=\ngoogle.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 h1:8ZmaLZE4XWrtU3MyClkYqqtl6Oegr3235h7jxsDyqCY=\ngoogle.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU=\ngoogle.golang.org/grpc v1.68.1 h1:oI5oTa11+ng8r8XMMN7jAOmWfPZWbYpCFaMUTACxkM0=\ngoogle.golang.org/grpc v1.68.1/go.mod h1:+q1XYFJjShcqn0QZHvCyeR4CXPA+llXIeUIfIe00waw=\ngoogle.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=\ngoogle.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=\ngopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=\ngopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=\ngopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=\ngopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=\ngopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=\ngopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=\ngopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\nk8s.io/api v0.33.0 h1:yTgZVn1XEe6opVpP1FylmNrIFWuDqe2H0V8CT5gxfIU=\nk8s.io/api v0.33.0/go.mod h1:CTO61ECK/KU7haa3qq8sarQ0biLq2ju405IZAd9zsiM=\nk8s.io/apiextensions-apiserver v0.33.0 h1:d2qpYL7Mngbsc1taA4IjJPRJ9ilnsXIrndH+r9IimOs=\nk8s.io/apiextensions-apiserver v0.33.0/go.mod h1:VeJ8u9dEEN+tbETo+lFkwaaZPg6uFKLGj5vyNEwwSzc=\nk8s.io/apimachinery v0.33.0 h1:1a6kHrJxb2hs4t8EE5wuR/WxKDwGN1FKH3JvDtA0CIQ=\nk8s.io/apimachinery v0.33.0/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=\nk8s.io/apiserver v0.33.0 h1:QqcM6c+qEEjkOODHppFXRiw/cE2zP85704YrQ9YaBbc=\nk8s.io/apiserver v0.33.0/go.mod h1:EixYOit0YTxt8zrO2kBU7ixAtxFce9gKGq367nFmqI8=\nk8s.io/client-go v0.33.0 h1:UASR0sAYVUzs2kYuKn/ZakZlcs2bEHaizrrHUZg0G98=\nk8s.io/client-go v0.33.0/go.mod h1:kGkd+l/gNGg8GYWAPr0xF1rRKvVWvzh9vmZAMXtaKOg=\nk8s.io/component-base v0.33.0 h1:Ot4PyJI+0JAD9covDhwLp9UNkUja209OzsJ4FzScBNk=\nk8s.io/component-base v0.33.0/go.mod h1:aXYZLbw3kihdkOPMDhWbjGCO6sg+luw554KP51t8qCU=\nk8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=\nk8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=\nk8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=\nk8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8=\nk8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro=\nk8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=\nsigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM=\nsigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=\nsigs.k8s.io/controller-runtime v0.21.0 h1:CYfjpEuicjUecRk+KAeyYh+ouUBn4llGyDYytIGcJS8=\nsigs.k8s.io/controller-runtime v0.21.0/go.mod h1:OSg14+F65eWqIu4DceX7k/+QRAbTTvxeQSNSOQpukWM=\nsigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8=\nsigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo=\nsigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=\nsigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=\nsigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=\nsigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW1TdblaLVAc=\nsigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=\nsigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=\nsigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/hack/boilerplate.go.txt",
    "content": "/*\nCopyright 2026.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/internal/controller/memcached_controller.go",
    "content": "/*\nCopyright 2026.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage controller\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"reflect\"\n\t\"strings\"\n\t\"time\"\n\n\tappsv1 \"k8s.io/api/apps/v1\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\tapierrors \"k8s.io/apimachinery/pkg/api/errors\"\n\t\"k8s.io/apimachinery/pkg/api/meta\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\t\"k8s.io/apimachinery/pkg/types\"\n\t\"k8s.io/client-go/tools/record\"\n\t\"k8s.io/utils/ptr\"\n\tctrl \"sigs.k8s.io/controller-runtime\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client\"\n\t\"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil\"\n\tlogf \"sigs.k8s.io/controller-runtime/pkg/log\"\n\n\tmonitoringv1 \"github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1\"\n\n\tcachev1alpha1 \"github.com/example/memcached-operator/api/v1alpha1\"\n\t\"github.com/example/memcached-operator/monitoring\"\n)\n\nconst memcachedFinalizer = \"cache.example.com/finalizer\"\nconst ruleName = \"memcached-operator-rules\"\nconst namespace = \"memcached-operator-system\"\n\n// Definitions to manage status conditions\nconst (\n\t// typeAvailableMemcached represents the status of the Deployment reconciliation\n\ttypeAvailableMemcached = \"Available\"\n\t// typeDegradedMemcached represents the status used when the custom resource is deleted and the finalizer operations are yet to occur.\n\ttypeDegradedMemcached = \"Degraded\"\n)\n\n// MemcachedReconciler reconciles a Memcached object\ntype MemcachedReconciler struct {\n\tclient.Client\n\tScheme   *runtime.Scheme\n\tRecorder record.EventRecorder\n}\n\n// The following markers are used to generate the rules permissions (RBAC) on config/rbac using controller-gen\n// when the command <make manifests> is executed.\n// To know more about markers see: https://book.kubebuilder.io/reference/markers.html\n\n// +kubebuilder:rbac:groups=cache.example.com,resources=memcacheds,verbs=get;list;watch;create;update;patch;delete\n// +kubebuilder:rbac:groups=cache.example.com,resources=memcacheds/status,verbs=get;update;patch\n// +kubebuilder:rbac:groups=cache.example.com,resources=memcacheds/finalizers,verbs=update\n// +kubebuilder:rbac:groups=core,resources=events,verbs=create;patch\n// +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete\n// +kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;watch\n// +kubebuilder:rbac:groups=monitoring.coreos.com,resources=prometheusrules,verbs=get;list;watch;create;update;delete\n\n// Reconcile is part of the main kubernetes reconciliation loop which aims to\n// move the current state of the cluster closer to the desired state.\n// It is essential for the controller's reconciliation loop to be idempotent. By following the Operator\n// pattern you will create Controllers which provide a reconcile function\n// responsible for synchronizing resources until the desired state is reached on the cluster.\n// Breaking this recommendation goes against the design principles of controller-runtime.\n// and may lead to unforeseen consequences such as resources becoming stuck and requiring manual intervention.\n// For further info:\n// - About Operator Pattern: https://kubernetes.io/docs/concepts/extend-kubernetes/operator/\n// - About Controllers: https://kubernetes.io/docs/concepts/architecture/controller/\n// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.21.0/pkg/reconcile\nfunc (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {\n\tlog := logf.FromContext(ctx)\n\n\t// Check if prometheus rule already exists, if not create a new one\n\tfoundRule := &monitoringv1.PrometheusRule{}\n\terr := r.Get(ctx, types.NamespacedName{Name: ruleName, Namespace: namespace}, foundRule)\n\tif err != nil && apierrors.IsNotFound(err) {\n\t\t// Define a new prometheus rule\n\t\tprometheusRule := monitoring.NewPrometheusRule(namespace)\n\t\tif err := r.Create(ctx, prometheusRule); err != nil {\n\t\t\tlog.Error(err, \"Failed to create prometheus rule\")\n\t\t\treturn ctrl.Result{}, nil\n\t\t}\n\t}\n\n\tif err == nil {\n\t\t// Check if prometheus rule spec was changed, if so set as desired\n\t\tdesiredRuleSpec := monitoring.NewPrometheusRuleSpec()\n\t\tif !reflect.DeepEqual(foundRule.Spec.DeepCopy(), desiredRuleSpec) {\n\t\t\tdesiredRuleSpec.DeepCopyInto(&foundRule.Spec)\n\t\t\tif r.Update(ctx, foundRule); err != nil {\n\t\t\t\tlog.Error(err, \"Failed to update prometheus rule\")\n\t\t\t\treturn ctrl.Result{}, nil\n\t\t\t}\n\t\t}\n\t}\n\n\t// Fetch the Memcached instance\n\t// The purpose is check if the Custom Resource for the Kind Memcached\n\t// is applied on the cluster if not we return nil to stop the reconciliation\n\tmemcached := &cachev1alpha1.Memcached{}\n\terr = r.Get(ctx, req.NamespacedName, memcached)\n\tif err != nil {\n\t\tif apierrors.IsNotFound(err) {\n\t\t\t// If the custom resource is not found then it usually means that it was deleted or not created\n\t\t\t// In this way, we will stop the reconciliation\n\t\t\tlog.Info(\"memcached resource not found. Ignoring since object must be deleted\")\n\t\t\treturn ctrl.Result{}, nil\n\t\t}\n\t\t// Error reading the object - requeue the request.\n\t\tlog.Error(err, \"Failed to get memcached\")\n\t\treturn ctrl.Result{}, err\n\t}\n\n\t// Let's just set the status as Unknown when no status is available\n\tif len(memcached.Status.Conditions) == 0 {\n\t\tmeta.SetStatusCondition(&memcached.Status.Conditions, metav1.Condition{Type: typeAvailableMemcached, Status: metav1.ConditionUnknown, Reason: \"Reconciling\", Message: \"Starting reconciliation\"})\n\t\tif err = r.Status().Update(ctx, memcached); err != nil {\n\t\t\tlog.Error(err, \"Failed to update Memcached status\")\n\t\t\treturn ctrl.Result{}, err\n\t\t}\n\n\t\t// Let's re-fetch the memcached Custom Resource after updating the status\n\t\t// so that we have the latest state of the resource on the cluster and we will avoid\n\t\t// raising the error \"the object has been modified, please apply\n\t\t// your changes to the latest version and try again\" which would re-trigger the reconciliation\n\t\t// if we try to update it again in the following operations\n\t\tif err := r.Get(ctx, req.NamespacedName, memcached); err != nil {\n\t\t\tlog.Error(err, \"Failed to re-fetch memcached\")\n\t\t\treturn ctrl.Result{}, err\n\t\t}\n\t}\n\n\t// Let's add a finalizer. Then, we can define some operations which should\n\t// occur before the custom resource is deleted.\n\t// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/finalizers\n\tif !controllerutil.ContainsFinalizer(memcached, memcachedFinalizer) {\n\t\tlog.Info(\"Adding Finalizer for Memcached\")\n\t\tif ok := controllerutil.AddFinalizer(memcached, memcachedFinalizer); !ok {\n\t\t\terr = fmt.Errorf(\"finalizer for Memcached was not added\")\n\t\t\tlog.Error(err, \"Failed to add finalizer for Memcached\")\n\t\t\treturn ctrl.Result{}, err\n\t\t}\n\n\t\tif err = r.Update(ctx, memcached); err != nil {\n\t\t\tlog.Error(err, \"Failed to update custom resource to add finalizer\")\n\t\t\treturn ctrl.Result{}, err\n\t\t}\n\t}\n\n\t// Check if the Memcached instance is marked to be deleted, which is\n\t// indicated by the deletion timestamp being set.\n\tisMemcachedMarkedToBeDeleted := memcached.GetDeletionTimestamp() != nil\n\tif isMemcachedMarkedToBeDeleted {\n\t\tif controllerutil.ContainsFinalizer(memcached, memcachedFinalizer) {\n\t\t\tlog.Info(\"Performing Finalizer Operations for Memcached before delete CR\")\n\n\t\t\t// Let's add here a status \"Downgrade\" to reflect that this resource began its process to be terminated.\n\t\t\tmeta.SetStatusCondition(&memcached.Status.Conditions, metav1.Condition{Type: typeDegradedMemcached,\n\t\t\t\tStatus: metav1.ConditionUnknown, Reason: \"Finalizing\",\n\t\t\t\tMessage: fmt.Sprintf(\"Performing finalizer operations for the custom resource: %s \", memcached.Name)})\n\n\t\t\tif err := r.Status().Update(ctx, memcached); err != nil {\n\t\t\t\tlog.Error(err, \"Failed to update Memcached status\")\n\t\t\t\treturn ctrl.Result{}, err\n\t\t\t}\n\n\t\t\t// Perform all operations required before removing the finalizer and allow\n\t\t\t// the Kubernetes API to remove the custom resource.\n\t\t\tr.doFinalizerOperationsForMemcached(memcached)\n\n\t\t\t// TODO(user): If you add operations to the doFinalizerOperationsForMemcached method\n\t\t\t// then you need to ensure that all worked fine before deleting and updating the Downgrade status\n\t\t\t// otherwise, you should requeue here.\n\n\t\t\t// Re-fetch the memcached Custom Resource before updating the status\n\t\t\t// so that we have the latest state of the resource on the cluster and we will avoid\n\t\t\t// raising the error \"the object has been modified, please apply\n\t\t\t// your changes to the latest version and try again\" which would re-trigger the reconciliation\n\t\t\tif err := r.Get(ctx, req.NamespacedName, memcached); err != nil {\n\t\t\t\tlog.Error(err, \"Failed to re-fetch memcached\")\n\t\t\t\treturn ctrl.Result{}, err\n\t\t\t}\n\n\t\t\tmeta.SetStatusCondition(&memcached.Status.Conditions, metav1.Condition{Type: typeDegradedMemcached,\n\t\t\t\tStatus: metav1.ConditionTrue, Reason: \"Finalizing\",\n\t\t\t\tMessage: fmt.Sprintf(\"Finalizer operations for custom resource %s name were successfully accomplished\", memcached.Name)})\n\n\t\t\tif err := r.Status().Update(ctx, memcached); err != nil {\n\t\t\t\tlog.Error(err, \"Failed to update Memcached status\")\n\t\t\t\treturn ctrl.Result{}, err\n\t\t\t}\n\n\t\t\tlog.Info(\"Removing Finalizer for Memcached after successfully perform the operations\")\n\t\t\tif ok := controllerutil.RemoveFinalizer(memcached, memcachedFinalizer); !ok {\n\t\t\t\terr = fmt.Errorf(\"finalizer for Memcached was not removed\")\n\t\t\t\tlog.Error(err, \"Failed to remove finalizer for Memcached\")\n\t\t\t\treturn ctrl.Result{}, err\n\t\t\t}\n\n\t\t\tif err := r.Update(ctx, memcached); err != nil {\n\t\t\t\tlog.Error(err, \"Failed to remove finalizer for Memcached\")\n\t\t\t\treturn ctrl.Result{}, err\n\t\t\t}\n\t\t}\n\t\treturn ctrl.Result{}, nil\n\t}\n\n\t// Check if the deployment already exists, if not create a new one\n\tfound := &appsv1.Deployment{}\n\terr = r.Get(ctx, types.NamespacedName{Name: memcached.Name, Namespace: memcached.Namespace}, found)\n\tif err != nil && apierrors.IsNotFound(err) {\n\t\t// Define a new deployment\n\t\tdep, err := r.deploymentForMemcached(memcached)\n\t\tif err != nil {\n\t\t\tlog.Error(err, \"Failed to define new Deployment resource for Memcached\")\n\n\t\t\t// The following implementation will update the status\n\t\t\tmeta.SetStatusCondition(&memcached.Status.Conditions, metav1.Condition{Type: typeAvailableMemcached,\n\t\t\t\tStatus: metav1.ConditionFalse, Reason: \"Reconciling\",\n\t\t\t\tMessage: fmt.Sprintf(\"Failed to create Deployment for the custom resource (%s): (%s)\", memcached.Name, err)})\n\n\t\t\tif err := r.Status().Update(ctx, memcached); err != nil {\n\t\t\t\tlog.Error(err, \"Failed to update Memcached status\")\n\t\t\t\treturn ctrl.Result{}, err\n\t\t\t}\n\n\t\t\treturn ctrl.Result{}, err\n\t\t}\n\n\t\tlog.Info(\"Creating a new Deployment\",\n\t\t\t\"Deployment.Namespace\", dep.Namespace, \"Deployment.Name\", dep.Name)\n\t\tif err = r.Create(ctx, dep); err != nil {\n\t\t\tlog.Error(err, \"Failed to create new Deployment\",\n\t\t\t\t\"Deployment.Namespace\", dep.Namespace, \"Deployment.Name\", dep.Name)\n\t\t\treturn ctrl.Result{}, err\n\t\t}\n\n\t\t// Deployment created successfully\n\t\t// We will requeue the reconciliation so that we can ensure the state\n\t\t// and move forward for the next operations\n\t\treturn ctrl.Result{RequeueAfter: time.Minute}, nil\n\t} else if err != nil {\n\t\tlog.Error(err, \"Failed to get Deployment\")\n\t\t// Let's return the error for the reconciliation be re-triggered again\n\t\treturn ctrl.Result{}, err\n\t}\n\n\t// The CRD API defines that the Memcached type have a MemcachedSpec.Size field\n\t// to set the quantity of Deployment instances to the desired state on the cluster.\n\t// Therefore, the following code will ensure the Deployment size is the same as defined\n\t// via the Size spec of the Custom Resource which we are reconciling.\n\tsize := memcached.Spec.Size\n\tif *found.Spec.Replicas != size {\n\t\t// Increment MemcachedDeploymentSizeUndesiredCountTotal metric by 1\n\t\tmonitoring.MemcachedDeploymentSizeUndesiredCountTotal.Inc()\n\t\tfound.Spec.Replicas = &size\n\t\tif err = r.Update(ctx, found); err != nil {\n\t\t\tlog.Error(err, \"Failed to update Deployment\",\n\t\t\t\t\"Deployment.Namespace\", found.Namespace, \"Deployment.Name\", found.Name)\n\n\t\t\t// Re-fetch the memcached Custom Resource before updating the status\n\t\t\t// so that we have the latest state of the resource on the cluster and we will avoid\n\t\t\t// raising the error \"the object has been modified, please apply\n\t\t\t// your changes to the latest version and try again\" which would re-trigger the reconciliation\n\t\t\tif err := r.Get(ctx, req.NamespacedName, memcached); err != nil {\n\t\t\t\tlog.Error(err, \"Failed to re-fetch memcached\")\n\t\t\t\treturn ctrl.Result{}, err\n\t\t\t}\n\n\t\t\t// The following implementation will update the status\n\t\t\tmeta.SetStatusCondition(&memcached.Status.Conditions, metav1.Condition{Type: typeAvailableMemcached,\n\t\t\t\tStatus: metav1.ConditionFalse, Reason: \"Resizing\",\n\t\t\t\tMessage: fmt.Sprintf(\"Failed to update the size for the custom resource (%s): (%s)\", memcached.Name, err)})\n\n\t\t\tif err := r.Status().Update(ctx, memcached); err != nil {\n\t\t\t\tlog.Error(err, \"Failed to update Memcached status\")\n\t\t\t\treturn ctrl.Result{}, err\n\t\t\t}\n\n\t\t\treturn ctrl.Result{}, err\n\t\t}\n\n\t\t// Now, that we update the size we want to requeue the reconciliation\n\t\t// so that we can ensure that we have the latest state of the resource before\n\t\t// update. Also, it will help ensure the desired state on the cluster\n\t\treturn ctrl.Result{Requeue: true}, nil\n\t}\n\n\t// The following implementation will update the status\n\tmeta.SetStatusCondition(&memcached.Status.Conditions, metav1.Condition{Type: typeAvailableMemcached,\n\t\tStatus: metav1.ConditionTrue, Reason: \"Reconciling\",\n\t\tMessage: fmt.Sprintf(\"Deployment for custom resource (%s) with %d replicas created successfully\", memcached.Name, size)})\n\n\tif err := r.Status().Update(ctx, memcached); err != nil {\n\t\tlog.Error(err, \"Failed to update Memcached status\")\n\t\treturn ctrl.Result{}, err\n\t}\n\n\treturn ctrl.Result{}, nil\n}\n\n// finalizeMemcached will perform the required operations before delete the CR.\nfunc (r *MemcachedReconciler) doFinalizerOperationsForMemcached(cr *cachev1alpha1.Memcached) {\n\t// TODO(user): Add the cleanup steps that the operator\n\t// needs to do before the CR can be deleted. Examples\n\t// of finalizers include performing backups and deleting\n\t// resources that are not owned by this CR, like a PVC.\n\n\t// Note: It is not recommended to use finalizers with the purpose of deleting resources which are\n\t// created and managed in the reconciliation. These ones, such as the Deployment created on this reconcile,\n\t// are defined as dependent of the custom resource. See that we use the method ctrl.SetControllerReference.\n\t// to set the ownerRef which means that the Deployment will be deleted by the Kubernetes API.\n\t// More info: https://kubernetes.io/docs/tasks/administer-cluster/use-cascading-deletion/\n\n\t// The following implementation will raise an event\n\tr.Recorder.Event(cr, \"Warning\", \"Deleting\",\n\t\tfmt.Sprintf(\"Custom Resource %s is being deleted from the namespace %s\",\n\t\t\tcr.Name,\n\t\t\tcr.Namespace))\n}\n\n// deploymentForMemcached returns a Memcached Deployment object\nfunc (r *MemcachedReconciler) deploymentForMemcached(\n\tmemcached *cachev1alpha1.Memcached) (*appsv1.Deployment, error) {\n\tls := labelsForMemcached()\n\treplicas := memcached.Spec.Size\n\n\t// Get the Operand image\n\timage, err := imageForMemcached()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tdep := &appsv1.Deployment{\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      memcached.Name,\n\t\t\tNamespace: memcached.Namespace,\n\t\t},\n\t\tSpec: appsv1.DeploymentSpec{\n\t\t\tReplicas: &replicas,\n\t\t\tSelector: &metav1.LabelSelector{\n\t\t\t\tMatchLabels: ls,\n\t\t\t},\n\t\t\tTemplate: corev1.PodTemplateSpec{\n\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\tLabels: ls,\n\t\t\t\t},\n\t\t\t\tSpec: corev1.PodSpec{\n\t\t\t\t\t// TODO(user): Uncomment the following code to configure the nodeAffinity expression\n\t\t\t\t\t// according to the platforms which are supported by your solution. It is considered\n\t\t\t\t\t// best practice to support multiple architectures. build your manager image using the\n\t\t\t\t\t// makefile target docker-buildx. Also, you can use docker manifest inspect <image>\n\t\t\t\t\t// to check what are the platforms supported.\n\t\t\t\t\t// More info: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity\n\t\t\t\t\t// Affinity: &corev1.Affinity{\n\t\t\t\t\t//\t NodeAffinity: &corev1.NodeAffinity{\n\t\t\t\t\t//\t\t RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{\n\t\t\t\t\t//\t\t\t NodeSelectorTerms: []corev1.NodeSelectorTerm{\n\t\t\t\t\t//\t\t\t\t {\n\t\t\t\t\t//\t\t\t\t\t MatchExpressions: []corev1.NodeSelectorRequirement{\n\t\t\t\t\t//\t\t\t\t\t\t {\n\t\t\t\t\t//\t\t\t\t\t\t\t Key:      \"kubernetes.io/arch\",\n\t\t\t\t\t//\t\t\t\t\t\t\t Operator: \"In\",\n\t\t\t\t\t//\t\t\t\t\t\t\t Values:   []string{\"amd64\", \"arm64\", \"ppc64le\", \"s390x\"},\n\t\t\t\t\t//\t\t\t\t\t\t },\n\t\t\t\t\t//\t\t\t\t\t\t {\n\t\t\t\t\t//\t\t\t\t\t\t\t Key:      \"kubernetes.io/os\",\n\t\t\t\t\t//\t\t\t\t\t\t\t Operator: \"In\",\n\t\t\t\t\t//\t\t\t\t\t\t\t Values:   []string{\"linux\"},\n\t\t\t\t\t//\t\t\t\t\t\t },\n\t\t\t\t\t//\t\t\t\t\t },\n\t\t\t\t\t//\t\t\t\t },\n\t\t\t\t\t//\t\t \t },\n\t\t\t\t\t//\t\t },\n\t\t\t\t\t//\t },\n\t\t\t\t\t// },\n\t\t\t\t\tSecurityContext: &corev1.PodSecurityContext{\n\t\t\t\t\t\tRunAsNonRoot: ptr.To(true),\n\t\t\t\t\t\t// The memcached image does not use a non-zero numeric user as the default user.\n\t\t\t\t\t\t// Due to RunAsNonRoot field being set to true, we need to force the user in the\n\t\t\t\t\t\t// container to a non-zero numeric user. We do this using the RunAsUser field.\n\t\t\t\t\t\t// However, if you are looking to provide solution for K8s vendors like OpenShift\n\t\t\t\t\t\t// be aware that you cannot run under its restricted-v2 SCC if you set this value.\n\t\t\t\t\t\t// IMPORTANT: seccomProfile was introduced with Kubernetes 1.19\n\t\t\t\t\t\t// If you are looking for to produce solutions to be supported\n\t\t\t\t\t\t// on lower versions you must remove this option.\n\t\t\t\t\t\tSeccompProfile: &corev1.SeccompProfile{\n\t\t\t\t\t\t\tType: corev1.SeccompProfileTypeRuntimeDefault,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tContainers: []corev1.Container{{\n\t\t\t\t\t\tImage:           image,\n\t\t\t\t\t\tName:            \"memcached\",\n\t\t\t\t\t\tImagePullPolicy: corev1.PullIfNotPresent,\n\t\t\t\t\t\t// Ensure restrictive context for the container\n\t\t\t\t\t\t// More info: https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted\n\t\t\t\t\t\tSecurityContext: &corev1.SecurityContext{\n\t\t\t\t\t\t\t// WARNING: Ensure that the image used defines an UserID in the Dockerfile\n\t\t\t\t\t\t\t// otherwise the Pod will not run and will fail with \"container has runAsNonRoot and image has non-numeric user\"\".\n\t\t\t\t\t\t\t// If you want your workloads admitted in namespaces enforced with the restricted mode in OpenShift/OKD vendors\n\t\t\t\t\t\t\t// then, you MUST ensure that the Dockerfile defines a User ID OR you MUST leave the \"RunAsNonRoot\" and\n\t\t\t\t\t\t\t// \"RunAsUser\" fields empty.\n\t\t\t\t\t\t\tRunAsNonRoot:             ptr.To(true),\n\t\t\t\t\t\t\tRunAsUser:                ptr.To(int64(1001)),\n\t\t\t\t\t\t\tAllowPrivilegeEscalation: ptr.To(false),\n\t\t\t\t\t\t\tCapabilities: &corev1.Capabilities{\n\t\t\t\t\t\t\t\tDrop: []corev1.Capability{\n\t\t\t\t\t\t\t\t\t\"ALL\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tPorts: []corev1.ContainerPort{{\n\t\t\t\t\t\t\tContainerPort: memcached.Spec.ContainerPort,\n\t\t\t\t\t\t\tName:          \"memcached\",\n\t\t\t\t\t\t}},\n\t\t\t\t\t\tCommand: []string{\"memcached\", \"-m=64\", \"-o\", \"modern\", \"-v\"},\n\t\t\t\t\t}},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\t// Set the ownerRef for the Deployment\n\t// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/owners-dependents/\n\tif err := ctrl.SetControllerReference(memcached, dep, r.Scheme); err != nil {\n\t\treturn nil, err\n\t}\n\treturn dep, nil\n}\n\n// labelsForMemcached returns the labels for selecting the resources\n// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/\nfunc labelsForMemcached() map[string]string {\n\tvar imageTag string\n\timage, err := imageForMemcached()\n\tif err == nil {\n\t\timageTag = strings.Split(image, \":\")[1]\n\t}\n\treturn map[string]string{\n\t\t\"app.kubernetes.io/name\":       \"memcached-operator\",\n\t\t\"app.kubernetes.io/version\":    imageTag,\n\t\t\"app.kubernetes.io/managed-by\": \"MemcachedController\",\n\t}\n}\n\n// imageForMemcached gets the Operand image which is managed by this controller\n// from the MEMCACHED_IMAGE environment variable defined in the config/manager/manager.yaml\nfunc imageForMemcached() (string, error) {\n\tvar imageEnvVar = \"MEMCACHED_IMAGE\"\n\timage, found := os.LookupEnv(imageEnvVar)\n\tif !found {\n\t\treturn \"\", fmt.Errorf(\"unable to find %s environment variable with the image\", imageEnvVar)\n\t}\n\treturn image, nil\n}\n\n// SetupWithManager sets up the controller with the Manager.\n// The whole idea is to be watching the resources that matter for the controller.\n// When a resource that the controller is interested in changes, the Watch triggers\n// the controller’s reconciliation loop, ensuring that the actual state of the resource\n// matches the desired state as defined in the controller’s logic.\n//\n// Notice how we configured the Manager to monitor events such as the creation, update,\n// or deletion of a Custom Resource (CR) of the Memcached kind, as well as any changes\n// to the Deployment that the controller manages and owns.\nfunc (r *MemcachedReconciler) SetupWithManager(mgr ctrl.Manager) error {\n\treturn ctrl.NewControllerManagedBy(mgr).\n\t\t// Watch the Memcached CR(s) and trigger reconciliation whenever it\n\t\t// is created, updated, or deleted\n\t\tFor(&cachev1alpha1.Memcached{}).\n\t\tNamed(\"memcached\").\n\t\t// Watch the Deployment managed by the MemcachedReconciler. If any changes occur to the Deployment\n\t\t// owned and managed by this controller, it will trigger reconciliation, ensuring that the cluster\n\t\t// state aligns with the desired state. See that the ownerRef was set when the Deployment was created.\n\t\tOwns(&appsv1.Deployment{}).\n\t\tComplete(r)\n}\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/internal/controller/memcached_controller_test.go",
    "content": "/*\nCopyright 2026.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage controller\n\nimport (\n\t\"context\"\n\t\"os\"\n\t\"time\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\n\tappsv1 \"k8s.io/api/apps/v1\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\t\"k8s.io/apimachinery/pkg/api/errors\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/types\"\n\t\"sigs.k8s.io/controller-runtime/pkg/reconcile\"\n\n\tcachev1alpha1 \"github.com/example/memcached-operator/api/v1alpha1\"\n)\n\nvar _ = Describe(\"Memcached controller\", func() {\n\tContext(\"Memcached controller test\", func() {\n\n\t\tconst MemcachedName = \"test-memcached\"\n\n\t\tctx := context.Background()\n\n\t\tnamespace := &corev1.Namespace{\n\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\tName:      MemcachedName,\n\t\t\t\tNamespace: MemcachedName,\n\t\t\t},\n\t\t}\n\n\t\ttypeNamespacedName := types.NamespacedName{\n\t\t\tName:      MemcachedName,\n\t\t\tNamespace: MemcachedName,\n\t\t}\n\t\tmemcached := &cachev1alpha1.Memcached{}\n\n\t\tSetDefaultEventuallyTimeout(2 * time.Minute)\n\t\tSetDefaultEventuallyPollingInterval(time.Second)\n\n\t\tBeforeEach(func() {\n\t\t\tBy(\"Creating the Namespace to perform the tests\")\n\t\t\terr := k8sClient.Create(ctx, namespace)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"Setting the Image ENV VAR which stores the Operand image\")\n\t\t\terr = os.Setenv(\"MEMCACHED_IMAGE\", \"example.com/image:test\")\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"creating the custom resource for the Kind Memcached\")\n\t\t\terr = k8sClient.Get(ctx, typeNamespacedName, memcached)\n\t\t\tif err != nil && errors.IsNotFound(err) {\n\t\t\t\t// Let's mock our custom resource at the same way that we would\n\t\t\t\t// apply on the cluster the manifest under config/samples\n\t\t\t\tmemcached := &cachev1alpha1.Memcached{\n\t\t\t\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\t\t\t\tName:      MemcachedName,\n\t\t\t\t\t\tNamespace: namespace.Name,\n\t\t\t\t\t},\n\t\t\t\t\tSpec: cachev1alpha1.MemcachedSpec{\n\t\t\t\t\t\tSize:          1,\n\t\t\t\t\t\tContainerPort: 11211,\n\t\t\t\t\t},\n\t\t\t\t}\n\n\t\t\t\terr = k8sClient.Create(ctx, memcached)\n\t\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t\t}\n\t\t})\n\n\t\tAfterEach(func() {\n\t\t\tBy(\"removing the custom resource for the Kind Memcached\")\n\t\t\tfound := &cachev1alpha1.Memcached{}\n\t\t\terr := k8sClient.Get(ctx, typeNamespacedName, found)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tEventually(func(g Gomega) {\n\t\t\t\tg.Expect(k8sClient.Delete(context.TODO(), found)).To(Succeed())\n\t\t\t}).Should(Succeed())\n\n\t\t\t// TODO(user): Attention if you improve this code by adding other context test you MUST\n\t\t\t// be aware of the current delete namespace limitations.\n\t\t\t// More info: https://book.kubebuilder.io/reference/envtest.html#testing-considerations\n\t\t\tBy(\"Deleting the Namespace to perform the tests\")\n\t\t\t_ = k8sClient.Delete(ctx, namespace)\n\n\t\t\tBy(\"Removing the Image ENV VAR which stores the Operand image\")\n\t\t\t_ = os.Unsetenv(\"MEMCACHED_IMAGE\")\n\t\t})\n\n\t\tIt(\"should successfully reconcile a custom resource for Memcached\", func() {\n\t\t\tBy(\"Checking if the custom resource was successfully created\")\n\t\t\tEventually(func(g Gomega) {\n\t\t\t\tfound := &cachev1alpha1.Memcached{}\n\t\t\t\tExpect(k8sClient.Get(ctx, typeNamespacedName, found)).To(Succeed())\n\t\t\t}).Should(Succeed())\n\n\t\t\tBy(\"Reconciling the custom resource created\")\n\t\t\tmemcachedReconciler := &MemcachedReconciler{\n\t\t\t\tClient: k8sClient,\n\t\t\t\tScheme: k8sClient.Scheme(),\n\t\t\t}\n\n\t\t\t_, err := memcachedReconciler.Reconcile(ctx, reconcile.Request{\n\t\t\t\tNamespacedName: typeNamespacedName,\n\t\t\t})\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"Checking if Deployment was successfully created in the reconciliation\")\n\t\t\tEventually(func(g Gomega) {\n\t\t\t\tfound := &appsv1.Deployment{}\n\t\t\t\tg.Expect(k8sClient.Get(ctx, typeNamespacedName, found)).To(Succeed())\n\t\t\t}).Should(Succeed())\n\n\t\t\tBy(\"Reconciling the custom resource again\")\n\t\t\t_, err = memcachedReconciler.Reconcile(ctx, reconcile.Request{\n\t\t\t\tNamespacedName: typeNamespacedName,\n\t\t\t})\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"Checking the latest Status Condition added to the Memcached instance\")\n\t\t\tExpect(k8sClient.Get(ctx, typeNamespacedName, memcached)).To(Succeed())\n\t\t\tvar conditions []metav1.Condition\n\t\t\tExpect(memcached.Status.Conditions).To(ContainElement(\n\t\t\t\tHaveField(\"Type\", Equal(typeAvailableMemcached)), &conditions))\n\t\t\tExpect(conditions).To(HaveLen(1), \"Multiple conditions of type %s\", typeAvailableMemcached)\n\t\t\tExpect(conditions[0].Status).To(Equal(metav1.ConditionTrue), \"condition %s\", typeAvailableMemcached)\n\t\t\tExpect(conditions[0].Reason).To(Equal(\"Reconciling\"), \"condition %s\", typeAvailableMemcached)\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/internal/controller/suite_test.go",
    "content": "/*\nCopyright 2026.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage controller\n\nimport (\n\t\"context\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\n\t\"k8s.io/client-go/kubernetes/scheme\"\n\t\"k8s.io/client-go/rest\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client\"\n\t\"sigs.k8s.io/controller-runtime/pkg/envtest\"\n\tlogf \"sigs.k8s.io/controller-runtime/pkg/log\"\n\t\"sigs.k8s.io/controller-runtime/pkg/log/zap\"\n\n\tcachev1alpha1 \"github.com/example/memcached-operator/api/v1alpha1\"\n\t// +kubebuilder:scaffold:imports\n)\n\n// These tests use Ginkgo (BDD-style Go testing framework). Refer to\n// http://onsi.github.io/ginkgo/ to learn more about Ginkgo.\n\nvar (\n\tctx       context.Context\n\tcancel    context.CancelFunc\n\ttestEnv   *envtest.Environment\n\tcfg       *rest.Config\n\tk8sClient client.Client\n)\n\nfunc TestControllers(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\n\tRunSpecs(t, \"Controller Suite\")\n}\n\nvar _ = BeforeSuite(func() {\n\tlogf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true)))\n\n\tctx, cancel = context.WithCancel(context.TODO())\n\n\tvar err error\n\terr = cachev1alpha1.AddToScheme(scheme.Scheme)\n\tExpect(err).NotTo(HaveOccurred())\n\n\t// +kubebuilder:scaffold:scheme\n\n\tBy(\"bootstrapping test environment\")\n\ttestEnv = &envtest.Environment{\n\t\tCRDDirectoryPaths:     []string{filepath.Join(\"..\", \"..\", \"config\", \"crd\", \"bases\")},\n\t\tErrorIfCRDPathMissing: true,\n\t}\n\n\t// Retrieve the first found binary directory to allow running tests from IDEs\n\tif getFirstFoundEnvTestBinaryDir() != \"\" {\n\t\ttestEnv.BinaryAssetsDirectory = getFirstFoundEnvTestBinaryDir()\n\t}\n\n\t// cfg is defined in this file globally.\n\tcfg, err = testEnv.Start()\n\tExpect(err).NotTo(HaveOccurred())\n\tExpect(cfg).NotTo(BeNil())\n\n\tk8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme})\n\tExpect(err).NotTo(HaveOccurred())\n\tExpect(k8sClient).NotTo(BeNil())\n})\n\nvar _ = AfterSuite(func() {\n\tBy(\"tearing down the test environment\")\n\tcancel()\n\terr := testEnv.Stop()\n\tExpect(err).NotTo(HaveOccurred())\n})\n\n// getFirstFoundEnvTestBinaryDir locates the first binary in the specified path.\n// ENVTEST-based tests depend on specific binaries, usually located in paths set by\n// controller-runtime. When running tests directly (e.g., via an IDE) without using\n// Makefile targets, the 'BinaryAssetsDirectory' must be explicitly configured.\n//\n// This function streamlines the process by finding the required binaries, similar to\n// setting the 'KUBEBUILDER_ASSETS' environment variable. To ensure the binaries are\n// properly set up, run 'make setup-envtest' beforehand.\nfunc getFirstFoundEnvTestBinaryDir() string {\n\tbasePath := filepath.Join(\"..\", \"..\", \"bin\", \"k8s\")\n\tentries, err := os.ReadDir(basePath)\n\tif err != nil {\n\t\tlogf.Log.Error(err, \"Failed to read directory\", \"path\", basePath)\n\t\treturn \"\"\n\t}\n\tfor _, entry := range entries {\n\t\tif entry.IsDir() {\n\t\t\treturn filepath.Join(basePath, entry.Name())\n\t\t}\n\t}\n\treturn \"\"\n}\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/internal/webhook/v1alpha1/memcached_webhook.go",
    "content": "/*\nCopyright 2026.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage v1alpha1\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\tctrl \"sigs.k8s.io/controller-runtime\"\n\tlogf \"sigs.k8s.io/controller-runtime/pkg/log\"\n\t\"sigs.k8s.io/controller-runtime/pkg/webhook\"\n\n\tcachev1alpha1 \"github.com/example/memcached-operator/api/v1alpha1\"\n)\n\n// nolint:unused\n// log is for logging in this package.\nvar memcachedlog = logf.Log.WithName(\"memcached-resource\")\n\n// SetupMemcachedWebhookWithManager registers the webhook for Memcached in the manager.\nfunc SetupMemcachedWebhookWithManager(mgr ctrl.Manager) error {\n\treturn ctrl.NewWebhookManagedBy(mgr).For(&cachev1alpha1.Memcached{}).\n\t\tWithDefaulter(&MemcachedCustomDefaulter{}).\n\t\tComplete()\n}\n\n// TODO(user): EDIT THIS FILE!  THIS IS SCAFFOLDING FOR YOU TO OWN!\n\n// +kubebuilder:webhook:path=/mutate-cache-example-com-v1alpha1-memcached,mutating=true,failurePolicy=fail,sideEffects=None,groups=cache.example.com,resources=memcacheds,verbs=create;update,versions=v1alpha1,name=mmemcached-v1alpha1.kb.io,admissionReviewVersions=v1\n\n// MemcachedCustomDefaulter struct is responsible for setting default values on the custom resource of the\n// Kind Memcached when those are created or updated.\n//\n// NOTE: The +kubebuilder:object:generate=false marker prevents controller-gen from generating DeepCopy methods,\n// as it is used only for temporary operations and does not need to be deeply copied.\ntype MemcachedCustomDefaulter struct {\n\t// TODO(user): Add more fields as needed for defaulting\n}\n\nvar _ webhook.CustomDefaulter = &MemcachedCustomDefaulter{}\n\n// Default implements webhook.CustomDefaulter so a webhook will be registered for the Kind Memcached.\nfunc (d *MemcachedCustomDefaulter) Default(_ context.Context, obj runtime.Object) error {\n\tmemcached, ok := obj.(*cachev1alpha1.Memcached)\n\n\tif !ok {\n\t\treturn fmt.Errorf(\"expected an Memcached object but got %T\", obj)\n\t}\n\tmemcachedlog.Info(\"Defaulting for Memcached\", \"name\", memcached.GetName())\n\n\tif memcached.Spec.Size == 0 {\n\t\tmemcached.Spec.Size = 3\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/internal/webhook/v1alpha1/memcached_webhook_test.go",
    "content": "/*\nCopyright 2026.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage v1alpha1\n\nimport (\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\n\tcachev1alpha1 \"github.com/example/memcached-operator/api/v1alpha1\"\n\t// TODO (user): Add any additional imports if needed\n)\n\nvar _ = Describe(\"Memcached Webhook\", func() {\n\tvar (\n\t\tobj       *cachev1alpha1.Memcached\n\t\toldObj    *cachev1alpha1.Memcached\n\t\tdefaulter MemcachedCustomDefaulter\n\t)\n\n\tBeforeEach(func() {\n\t\tobj = &cachev1alpha1.Memcached{}\n\t\toldObj = &cachev1alpha1.Memcached{}\n\t\tdefaulter = MemcachedCustomDefaulter{}\n\t\tExpect(defaulter).NotTo(BeNil(), \"Expected defaulter to be initialized\")\n\t\tExpect(oldObj).NotTo(BeNil(), \"Expected oldObj to be initialized\")\n\t\tExpect(obj).NotTo(BeNil(), \"Expected obj to be initialized\")\n\t\t// TODO (user): Add any setup logic common to all tests\n\t})\n\n\tAfterEach(func() {\n\t\t// TODO (user): Add any teardown logic common to all tests\n\t})\n\n\tContext(\"When creating Memcached under Defaulting Webhook\", func() {\n\t\t// TODO (user): Add logic for defaulting webhooks\n\t\t// Example:\n\t\t// It(\"Should apply defaults when a required field is empty\", func() {\n\t\t//     By(\"simulating a scenario where defaults should be applied\")\n\t\t//     obj.SomeFieldWithDefault = \"\"\n\t\t//     By(\"calling the Default method to apply defaults\")\n\t\t//     defaulter.Default(ctx, obj)\n\t\t//     By(\"checking that the default values are set\")\n\t\t//     Expect(obj.SomeFieldWithDefault).To(Equal(\"default_value\"))\n\t\t// })\n\t})\n\n})\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/internal/webhook/v1alpha1/webhook_suite_test.go",
    "content": "/*\nCopyright 2026.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage v1alpha1\n\nimport (\n\t\"context\"\n\t\"crypto/tls\"\n\t\"fmt\"\n\t\"net\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\t\"time\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n\n\t\"k8s.io/client-go/kubernetes/scheme\"\n\t\"k8s.io/client-go/rest\"\n\tctrl \"sigs.k8s.io/controller-runtime\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client\"\n\t\"sigs.k8s.io/controller-runtime/pkg/envtest\"\n\tlogf \"sigs.k8s.io/controller-runtime/pkg/log\"\n\t\"sigs.k8s.io/controller-runtime/pkg/log/zap\"\n\tmetricsserver \"sigs.k8s.io/controller-runtime/pkg/metrics/server\"\n\t\"sigs.k8s.io/controller-runtime/pkg/webhook\"\n\n\tcachev1alpha1 \"github.com/example/memcached-operator/api/v1alpha1\"\n\t// +kubebuilder:scaffold:imports\n)\n\n// These tests use Ginkgo (BDD-style Go testing framework). Refer to\n// http://onsi.github.io/ginkgo/ to learn more about Ginkgo.\n\nvar (\n\tctx       context.Context\n\tcancel    context.CancelFunc\n\tk8sClient client.Client\n\tcfg       *rest.Config\n\ttestEnv   *envtest.Environment\n)\n\nfunc TestAPIs(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\n\tRunSpecs(t, \"Webhook Suite\")\n}\n\nvar _ = BeforeSuite(func() {\n\tlogf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true)))\n\n\tctx, cancel = context.WithCancel(context.TODO())\n\n\tvar err error\n\terr = cachev1alpha1.AddToScheme(scheme.Scheme)\n\tExpect(err).NotTo(HaveOccurred())\n\n\t// +kubebuilder:scaffold:scheme\n\n\tBy(\"bootstrapping test environment\")\n\ttestEnv = &envtest.Environment{\n\t\tCRDDirectoryPaths:     []string{filepath.Join(\"..\", \"..\", \"..\", \"config\", \"crd\", \"bases\")},\n\t\tErrorIfCRDPathMissing: false,\n\n\t\tWebhookInstallOptions: envtest.WebhookInstallOptions{\n\t\t\tPaths: []string{filepath.Join(\"..\", \"..\", \"..\", \"config\", \"webhook\")},\n\t\t},\n\t}\n\n\t// Retrieve the first found binary directory to allow running tests from IDEs\n\tif getFirstFoundEnvTestBinaryDir() != \"\" {\n\t\ttestEnv.BinaryAssetsDirectory = getFirstFoundEnvTestBinaryDir()\n\t}\n\n\t// cfg is defined in this file globally.\n\tcfg, err = testEnv.Start()\n\tExpect(err).NotTo(HaveOccurred())\n\tExpect(cfg).NotTo(BeNil())\n\n\tk8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme})\n\tExpect(err).NotTo(HaveOccurred())\n\tExpect(k8sClient).NotTo(BeNil())\n\n\t// start webhook server using Manager.\n\twebhookInstallOptions := &testEnv.WebhookInstallOptions\n\tmgr, err := ctrl.NewManager(cfg, ctrl.Options{\n\t\tScheme: scheme.Scheme,\n\t\tWebhookServer: webhook.NewServer(webhook.Options{\n\t\t\tHost:    webhookInstallOptions.LocalServingHost,\n\t\t\tPort:    webhookInstallOptions.LocalServingPort,\n\t\t\tCertDir: webhookInstallOptions.LocalServingCertDir,\n\t\t}),\n\t\tLeaderElection: false,\n\t\tMetrics:        metricsserver.Options{BindAddress: \"0\"},\n\t})\n\tExpect(err).NotTo(HaveOccurred())\n\n\terr = SetupMemcachedWebhookWithManager(mgr)\n\tExpect(err).NotTo(HaveOccurred())\n\n\t// +kubebuilder:scaffold:webhook\n\n\tgo func() {\n\t\tdefer GinkgoRecover()\n\t\terr = mgr.Start(ctx)\n\t\tExpect(err).NotTo(HaveOccurred())\n\t}()\n\n\t// wait for the webhook server to get ready.\n\tdialer := &net.Dialer{Timeout: time.Second}\n\taddrPort := fmt.Sprintf(\"%s:%d\", webhookInstallOptions.LocalServingHost, webhookInstallOptions.LocalServingPort)\n\tEventually(func() error {\n\t\tconn, err := tls.DialWithDialer(dialer, \"tcp\", addrPort, &tls.Config{InsecureSkipVerify: true})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\treturn conn.Close()\n\t}).Should(Succeed())\n})\n\nvar _ = AfterSuite(func() {\n\tBy(\"tearing down the test environment\")\n\tcancel()\n\terr := testEnv.Stop()\n\tExpect(err).NotTo(HaveOccurred())\n})\n\n// getFirstFoundEnvTestBinaryDir locates the first binary in the specified path.\n// ENVTEST-based tests depend on specific binaries, usually located in paths set by\n// controller-runtime. When running tests directly (e.g., via an IDE) without using\n// Makefile targets, the 'BinaryAssetsDirectory' must be explicitly configured.\n//\n// This function streamlines the process by finding the required binaries, similar to\n// setting the 'KUBEBUILDER_ASSETS' environment variable. To ensure the binaries are\n// properly set up, run 'make setup-envtest' beforehand.\nfunc getFirstFoundEnvTestBinaryDir() string {\n\tbasePath := filepath.Join(\"..\", \"..\", \"..\", \"bin\", \"k8s\")\n\tentries, err := os.ReadDir(basePath)\n\tif err != nil {\n\t\tlogf.Log.Error(err, \"Failed to read directory\", \"path\", basePath)\n\t\treturn \"\"\n\t}\n\tfor _, entry := range entries {\n\t\tif entry.IsDir() {\n\t\t\treturn filepath.Join(basePath, entry.Name())\n\t\t}\n\t}\n\treturn \"\"\n}\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/monitoring/alerts.go",
    "content": "/*\nCopyright 2026.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage monitoring\n\nimport (\n\tmonitoringv1 \"github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/util/intstr\"\n)\n\nconst (\n\truleName                     = \"memcached-operator-rules\"\n\talertRuleGroup               = \"memcached.rules\"\n\tdeploymentSizeUndesiredAlert = \"MemcachedDeploymentSizeUndesired\"\n\toperatorDownAlert            = \"MemcachedOperatorDown\"\n\toperatorUpTotalRecordingRule = \"memcached_operator_up_total\"\n\trunbookURLBasePath           = \"https://github.com/operator-framework/operator-sdk/tree/master/testdata/go/v4/monitoring/memcached-operator/docs/monitoring/runbooks/\"\n)\n\n// NewPrometheusRule creates new PrometheusRule(CR) for the operator to have alerts and recording rules\nfunc NewPrometheusRule(namespace string) *monitoringv1.PrometheusRule {\n\treturn &monitoringv1.PrometheusRule{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tAPIVersion: monitoringv1.SchemeGroupVersion.String(),\n\t\t\tKind:       \"PrometheusRule\",\n\t\t},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      ruleName,\n\t\t\tNamespace: namespace,\n\t\t},\n\t\tSpec: *NewPrometheusRuleSpec(),\n\t}\n}\n\n// NewPrometheusRuleSpec creates PrometheusRuleSpec for alerts and recording rules\nfunc NewPrometheusRuleSpec() *monitoringv1.PrometheusRuleSpec {\n\treturn &monitoringv1.PrometheusRuleSpec{\n\t\tGroups: []monitoringv1.RuleGroup{{\n\t\t\tName: alertRuleGroup,\n\t\t\tRules: []monitoringv1.Rule{\n\t\t\t\tcreateDeploymentSizeUndesiredAlertRule(),\n\t\t\t\tcreateOperatorDownAlertRule(),\n\t\t\t\tcreateOperatorUpTotalRecordingRule(),\n\t\t\t},\n\t\t}},\n\t}\n}\n\n// createDeploymentSizeUndesiredAlertRule creates MemcachedDeploymentSizeUndesired alert rule\nfunc createDeploymentSizeUndesiredAlertRule() monitoringv1.Rule {\n\treturn monitoringv1.Rule{\n\t\tAlert: deploymentSizeUndesiredAlert,\n\t\tExpr:  intstr.FromString(\"increase(memcached_deployment_size_undesired_count_total[5m]) >= 3\"),\n\t\tAnnotations: map[string]string{\n\t\t\t\"description\": \"Memcached-sample deployment size was not as desired more than 3 times in the last 5 minutes.\",\n\t\t},\n\t\tLabels: map[string]string{\n\t\t\t\"severity\":    \"warning\",\n\t\t\t\"runbook_url\": runbookURLBasePath + \"MemcachedDeploymentSizeUndesired.md\",\n\t\t},\n\t}\n}\n\n// createOperatorDownAlertRule creates MemcachedOperatorDown alert rule\nfunc createOperatorDownAlertRule() monitoringv1.Rule {\n\treturn monitoringv1.Rule{\n\t\tAlert: operatorDownAlert,\n\t\tExpr:  intstr.FromString(\"memcached_operator_up_total == 0\"),\n\t\tAnnotations: map[string]string{\n\t\t\t\"description\": \"No running memcached-operator pods were detected in the last 5 min.\",\n\t\t},\n\t\tFor: \"5m\",\n\t\tLabels: map[string]string{\n\t\t\t\"severity\":    \"critical\",\n\t\t\t\"runbook_url\": runbookURLBasePath + \"MemcachedOperatorDown.md\",\n\t\t},\n\t}\n}\n\n// createOperatorUpTotalRecordingRule creates memcached_operator_up_total recording rule\nfunc createOperatorUpTotalRecordingRule() monitoringv1.Rule {\n\treturn monitoringv1.Rule{\n\t\tRecord: operatorUpTotalRecordingRule,\n\t\tExpr:   intstr.FromString(\"sum(up{pod=~'memcached-operator-controller-manager-.*'} or vector(0))\"),\n\t}\n}\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/monitoring/metrics.go",
    "content": "/*\nCopyright 2026.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage monitoring\n\nimport (\n\t\"github.com/prometheus/client_golang/prometheus\"\n\t\"sigs.k8s.io/controller-runtime/pkg/metrics\"\n)\n\n// MetricDescription is an exported struct that defines the metric description (Name, Help)\n// as a new type named MetricDescription.\ntype MetricDescription struct {\n\tName string\n\tHelp string\n\tType string\n}\n\n// metricsDescription is a map of string keys (metrics) to MetricDescription values (Name, Help).\nvar metricDescription = map[string]MetricDescription{\n\t\"MemcachedDeploymentSizeUndesiredCountTotal\": {\n\t\tName: \"memcached_deployment_size_undesired_count_total\",\n\t\tHelp: \"Total number of times the deployment size was not as desired.\",\n\t\tType: \"Counter\",\n\t},\n}\n\nvar (\n\t// MemcachedDeploymentSizeUndesiredCountTotal will count how many times was required\n\t// to perform the operation to ensure that the number of replicas on the cluster\n\t// is the same as the quantity desired and specified via the custom resource size spec.\n\tMemcachedDeploymentSizeUndesiredCountTotal = prometheus.NewCounter(\n\t\tprometheus.CounterOpts{\n\t\t\tName: metricDescription[\"MemcachedDeploymentSizeUndesiredCountTotal\"].Name,\n\t\t\tHelp: metricDescription[\"MemcachedDeploymentSizeUndesiredCountTotal\"].Help,\n\t\t},\n\t)\n)\n\n// RegisterMetrics will register metrics with the global prometheus registry\nfunc RegisterMetrics() {\n\tmetrics.Registry.MustRegister(MemcachedDeploymentSizeUndesiredCountTotal)\n}\n\n// ListMetrics will create a slice with the metrics available in metricDescription\nfunc ListMetrics() []MetricDescription {\n\tv := make([]MetricDescription, 0, len(metricDescription))\n\t// Insert value (Name, Help) for each metric\n\tfor _, value := range metricDescription {\n\t\tv = append(v, value)\n\t}\n\n\treturn v\n}\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/monitoring/metricsdocs/metricsdocs.go",
    "content": "/*\nCopyright 2026.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage main\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"sort\"\n\t\"text/template\"\n\n\t\"github.com/example/memcached-operator/monitoring\"\n)\n\nfunc main() {\n\tmetricDescriptions := monitoring.ListMetrics()\n\tsort.Slice(metricDescriptions, func(i, j int) bool {\n\t\treturn metricDescriptions[i].Name < metricDescriptions[j].Name\n\t})\n\n\ttmpl, err := template.New(\"Operator metrics\").Parse(\"# Operator Metrics\\n\" +\n\t\t\"This document aims to help users that are not familiar with metrics exposed by this operator.\\n\" +\n\t\t\"The metrics documentation is auto-generated by the utility tool \\\"monitoring/metricsdocs\\\" and reflects all of the metrics that are exposed by the operator.\\n\\n\" +\n\t\t\"## Operator Metrics List\" +\n\t\t\"{{range .}}\\n\" +\n\t\t\"### {{.Name}}\\n\" +\n\t\t\"{{.Help}} \" +\n\t\t\"Type: {{.Type}}.\\n\" +\n\t\t\"{{end}}\" +\n\t\t\"## Developing new metrics\\n\" +\n\t\t\"After developing new metrics or changing old ones, please run \\\"make generate-metricsdocs\\\" to regenerate this document.\\n\\n\" +\n\t\t\"If you feel that the new metric doesn't follow these rules, please change \\\"monitoring/metricsdocs\\\" according to your needs.\")\n\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// generate the template using the sorted list of metrics\n\tvar buf bytes.Buffer\n\tif err := tmpl.Execute(&buf, metricDescriptions); err != nil {\n\t\tpanic(err)\n\t}\n\n\t// print the generated metrics documentation\n\tfmt.Println(buf.String())\n}\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/monitoring/prom-rule-ci/prom-rules-tests.yaml",
    "content": "---\n# Prometheus official unit-testing documentation - https://prometheus.io/docs/prometheus/latest/configuration/unit_testing_rules/\n# rule_files contains the list of files to be tested\nrule_files:\n  - /tmp/rules.verify\n\n# group_eval_order contains the list of groups to be tested\ngroup_eval_order:\n  - memcached.rules\n\ntests:\n# for each time frame based on the interval, we define the metrics values\n  - interval: 1m\n    input_series:\n      - series: 'memcached_deployment_size_undesired_count_total'\n        # time:  0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15\n        values: \"0 0 0 1 2 3 3 3 3 3  3  3  3  4  5  6\"\n      - series: 'memcached_operator_up_total'\n        # time:  0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15\n        values: \"0 0 0 0 0 0 1 1 1 1  0  0  0  0  0  0\"\n\n# then, we evaluate the alerts behaviour in the eval_time we choose\n    alert_rule_test:\n      # it must not trigger before 5m\n      - eval_time: 4m\n        alertname: MemcachedDeploymentSizeUndesired\n        exp_alerts: []\n      - eval_time: 4m\n        alertname: MemcachedOperatorDown\n        exp_alerts: []\n      # it must trigger after 5m\n      - eval_time: 5m\n        alertname: MemcachedDeploymentSizeUndesired\n        exp_alerts:\n          - exp_annotations:\n              description: \"Memcached-sample deployment size was not as desired more than 3 times in the last 5 minutes.\"\n            exp_labels:\n              severity: \"warning\"\n              runbook_url: \"https://github.com/operator-framework/operator-sdk/tree/master/testdata/go/v4/monitoring/memcached-operator/docs/monitoring/runbooks/MemcachedDeploymentSizeUndesired.md\"\n      - eval_time: 5m\n        alertname: MemcachedOperatorDown\n        exp_alerts:\n          - exp_annotations:\n              description: \"No running memcached-operator pods were detected in the last 5 min.\"\n            exp_labels:\n              severity: \"critical\"\n              runbook_url: \"https://github.com/operator-framework/operator-sdk/tree/master/testdata/go/v4/monitoring/memcached-operator/docs/monitoring/runbooks/MemcachedOperatorDown.md\"\n      # it must not trigger before 15m\n      - eval_time: 14m\n        alertname: MemcachedDeploymentSizeUndesired\n        exp_alerts: [ ]\n      - eval_time: 14m\n        alertname: MemcachedOperatorDown\n        exp_alerts: [ ]\n      # it must trigger after 15m\n      - eval_time: 15m\n        alertname: MemcachedDeploymentSizeUndesired\n        exp_alerts:\n          - exp_annotations:\n              description: \"Memcached-sample deployment size was not as desired more than 3 times in the last 5 minutes.\"\n            exp_labels:\n              severity: \"warning\"\n              runbook_url: \"https://github.com/operator-framework/operator-sdk/tree/master/testdata/go/v4/monitoring/memcached-operator/docs/monitoring/runbooks/MemcachedDeploymentSizeUndesired.md\"\n      - eval_time: 15m\n        alertname: MemcachedOperatorDown\n        exp_alerts:\n          - exp_annotations:\n              description: \"No running memcached-operator pods were detected in the last 5 min.\"\n            exp_labels:\n              severity: \"critical\"\n              runbook_url: \"https://github.com/operator-framework/operator-sdk/tree/master/testdata/go/v4/monitoring/memcached-operator/docs/monitoring/runbooks/MemcachedOperatorDown.md\"\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/monitoring/prom-rule-ci/rule-spec-dumper.go",
    "content": "/*\nCopyright 2026.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"os\"\n\n\t\"github.com/example/memcached-operator/monitoring\"\n)\n\nfunc verifyArgs(args []string) error {\n\tnumOfArgs := len(os.Args[1:])\n\tif numOfArgs != 1 {\n\t\treturn fmt.Errorf(\"expected exactly 1 argument, got: %d\", numOfArgs)\n\t}\n\treturn nil\n}\n\nfunc main() {\n\tif err := verifyArgs(os.Args); err != nil {\n\t\tfmt.Printf(\"ERROR: %v\\n\", err)\n\t\tos.Exit(1)\n\t}\n\n\ttargetFile := os.Args[1]\n\n\tpromRuleSpec := monitoring.NewPrometheusRuleSpec()\n\tb, err := json.Marshal(promRuleSpec)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\terr = ioutil.WriteFile(targetFile, b, 0644)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n}\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/monitoring/prom-rule-ci/verify-rules.sh",
    "content": "#!/bin/bash -e\n\nreadonly PROM_IMAGE=\"docker.io/prom/prometheus:v2.15.2\"\n\nfunction cleanup() {\n    local cleanup_files=(\"${@:?}\")\n    for file in \"${cleanup_files[@]}\"; do\n        rm -f \"$file\"\n    done\n}\n\nfunction lint() {\n    local target_file=\"${1:?}\"\n    docker run --rm --entrypoint=/bin/promtool \\\n        -v \"$target_file\":/tmp/rules.verify:ro \"$PROM_IMAGE\" \\\n        check rules /tmp/rules.verify\n}\n\nfunction unit_test() {\n    local target_file=\"${1:?}\"\n    local tests_file=\"${2:?}\"\n    docker run --rm --entrypoint=/bin/promtool \\\n        -v \"$tests_file\":/tmp/rules.test:ro \\\n        -v \"$target_file\":/tmp/rules.verify:ro \\\n        \"$PROM_IMAGE\" \\\n        test rules /tmp/rules.test\n}\n\nfunction main() {\n    local prom_spec_dumper=\"${1:?}\"\n    local tests_file=\"${2:?}\"\n    local target_file\n    target_file=\"$(mktemp --tmpdir -u tmp.prom_rules.XXXXX)\"\n    trap \"cleanup $target_file\" RETURN EXIT INT\n    \"$prom_spec_dumper\" \"$target_file\"\n    echo \"INFO: Rules file content:\"\n    cat \"$target_file\"\n    echo\n    lint \"$target_file\"\n    unit_test \"$target_file\" \"$tests_file\"\n}\n\nmain \"$@\"\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/test/e2e/e2e_suite_test.go",
    "content": "/*\nCopyright 2022.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage e2e\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t. \"github.com/onsi/ginkgo/v2\"\n\t. \"github.com/onsi/gomega\"\n)\n\n// Run e2e tests using the Ginkgo runner.\nfunc TestE2E(t *testing.T) {\n\tRegisterFailHandler(Fail)\n\tfmt.Fprintf(GinkgoWriter, \"Starting Memcached Operator suite\\n\")\n\tRunSpecs(t, \"Memcached e2e suite\")\n}\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/test/e2e/e2e_test.go",
    "content": "/*\nCopyright 2022.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage e2e\n\nimport (\n\t\"bufio\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t//nolint:golint\n\t//nolint:revive\n\t. \"github.com/onsi/ginkgo/v2\"\n\n\t//nolint:golint\n\t//nolint:revive\n\t. \"github.com/onsi/gomega\"\n\n\t\"github.com/example/memcached-operator/test/utils\"\n)\n\n// constant parts of the file\nconst (\n\tnamespace                                      = \"memcached-operator-system\"\n\tmemcachedDeploymentSizeUndesiredCountTotalName = \"memcached_deployment_size_undesired_count_total\"\n\ttokenRequestRawString                          = \"{\\\"apiVersion\\\": \\\"authentication.k8s.io/v1\\\", \\\"kind\\\": \\\"TokenRequest\\\"}\"\n)\n\n// tokenRequest is a trimmed down version of the authentication.k8s.io/v1/TokenRequest Type\n// that we want to use for extracting the token.\ntype tokenRequest struct {\n\tStatus struct {\n\t\tToken string \"json:\\\"token\\\"\"\n\t} \"json:\\\"status\\\"\"\n}\n\nvar _ = Describe(\"memcached\", Ordered, func() {\n\tBeforeAll(func() {\n\t\t// The prometheus and the certmanager are installed in this test\n\t\t// because the Memcached sample has this option enable and\n\t\t// when we try to apply the manifests both will be required to be installed\n\t\tBy(\"installing prometheus operator\")\n\t\tExpect(utils.InstallPrometheusOperator()).To(Succeed())\n\n\t\tBy(\"installing the cert-manager\")\n\t\tExpect(utils.InstallCertManager()).To(Succeed())\n\n\t\t// The namespace can be created when we run make install\n\t\t// However, in this test we want ensure that the solution\n\t\t// can run in a ns labeled as restricted. Therefore, we are\n\t\t// creating the namespace an lebeling it.\n\t\tBy(\"creating manager namespace\")\n\t\tcmd := exec.Command(\"kubectl\", \"create\", \"ns\", namespace)\n\t\t_, _ = utils.Run(cmd)\n\n\t\t// Now, let's ensure that all namespaces can raise an Warn when we apply the manifests\n\t\t// and that the namespace where the Operator and Operand will run are enforced as\n\t\t// restricted so that we can ensure that both can be admitted and run with the enforcement\n\t\tBy(\"labeling all namespaces to warn when we apply the manifest if would violate the PodStandards\")\n\t\tcmd = exec.Command(\"kubectl\", \"label\", \"--overwrite\", \"ns\", \"--all\",\n\t\t\t\"pod-security.kubernetes.io/audit=restricted\",\n\t\t\t\"pod-security.kubernetes.io/enforce-version=v1.24\",\n\t\t\t\"pod-security.kubernetes.io/warn=restricted\")\n\t\t_, err := utils.Run(cmd)\n\t\tExpectWithOffset(1, err).NotTo(HaveOccurred())\n\n\t\tBy(\"labeling enforce the namespace where the Operator and Operand(s) will run\")\n\t\tcmd = exec.Command(\"kubectl\", \"label\", \"--overwrite\", \"ns\", namespace,\n\t\t\t\"pod-security.kubernetes.io/audit=restricted\",\n\t\t\t\"pod-security.kubernetes.io/enforce-version=v1.24\",\n\t\t\t\"pod-security.kubernetes.io/enforce=restricted\")\n\t\t_, err = utils.Run(cmd)\n\t\tExpect(err).To(Not(HaveOccurred()))\n\t})\n\n\tAfterAll(func() {\n\t\tBy(\"uninstalling the Prometheus manager bundle\")\n\t\tutils.UninstallPrometheusOperator()\n\n\t\tBy(\"uninstalling the cert-manager bundle\")\n\t\tutils.UninstallCertManager()\n\n\t\tBy(\"removing manager namespace\")\n\t\tcmd := exec.Command(\"kubectl\", \"create\", \"ns\", namespace)\n\t\t_, _ = utils.Run(cmd)\n\t})\n\n\tContext(\"Memcached Operator\", func() {\n\t\tIt(\"should run successfully\", func() {\n\t\t\tvar controllerPodName string\n\t\t\tvar err error\n\t\t\tprojectDir, _ := utils.GetProjectDir()\n\n\t\t\t// operatorImage stores the name of the image used in the example\n\t\t\tvar operatorImage = \"example.com/memcached-operator:v0.0.1\"\n\n\t\t\tBy(\"building the manager(Operator) image\")\n\t\t\tcmd := exec.Command(\"make\", \"docker-build\", fmt.Sprintf(\"IMG=%s\", operatorImage))\n\t\t\t_, err = utils.Run(cmd)\n\t\t\tExpectWithOffset(1, err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"loading the manager(Operator) image on Kind\")\n\t\t\terr = utils.LoadImageToKindClusterWithName(operatorImage)\n\t\t\tExpectWithOffset(1, err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"installing CRDs\")\n\t\t\tcmd = exec.Command(\"make\", \"install\")\n\t\t\t_, err = utils.Run(cmd)\n\t\t\tExpectWithOffset(1, err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"deploying the controller-manager\")\n\t\t\tcmd = exec.Command(\"make\", \"deploy\", fmt.Sprintf(\"IMG=%s\", operatorImage))\n\t\t\toutputMake, err := utils.Run(cmd)\n\t\t\tExpectWithOffset(1, err).NotTo(HaveOccurred())\n\n\t\t\tBy(\"validating that manager Pod/container(s) are restricted\")\n\t\t\tExpectWithOffset(1, outputMake).NotTo(ContainSubstring(\"Warning: would violate PodSecurity\"))\n\n\t\t\tBy(\"validating that the controller-manager pod is running as expected\")\n\t\t\tverifyControllerUp := func() error {\n\t\t\t\t// Get pod name\n\t\t\t\tcmd = exec.Command(\"kubectl\", \"get\",\n\t\t\t\t\t\"pods\", \"-l\", \"control-plane=controller-manager\",\n\t\t\t\t\t\"-o\", \"go-template={{ range .items }}{{ if not .metadata.deletionTimestamp }}{{ .metadata.name }}\"+\n\t\t\t\t\t\t\"{{ \\\"\\\\n\\\" }}{{ end }}{{ end }}\",\n\t\t\t\t\t\"-n\", namespace,\n\t\t\t\t)\n\t\t\t\tpodOutput, err := utils.Run(cmd)\n\t\t\t\tExpectWithOffset(2, err).NotTo(HaveOccurred())\n\t\t\t\tpodNames := utils.GetNonEmptyLines(string(podOutput))\n\t\t\t\tif len(podNames) != 1 {\n\t\t\t\t\treturn fmt.Errorf(\"expect 1 controller pods running, but got %d\", len(podNames))\n\t\t\t\t}\n\t\t\t\tcontrollerPodName = podNames[0]\n\t\t\t\tExpectWithOffset(2, controllerPodName).Should(ContainSubstring(\"controller-manager\"))\n\n\t\t\t\t// Validate pod status\n\t\t\t\tcmd = exec.Command(\"kubectl\", \"get\",\n\t\t\t\t\t\"pods\", controllerPodName, \"-o\", \"jsonpath={.status.phase}\",\n\t\t\t\t\t\"-n\", namespace,\n\t\t\t\t)\n\t\t\t\tstatus, err := utils.Run(cmd)\n\t\t\t\tExpectWithOffset(2, err).NotTo(HaveOccurred())\n\t\t\t\tif string(status) != \"Running\" {\n\t\t\t\t\treturn fmt.Errorf(\"controller pod in %s status\", status)\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tEventuallyWithOffset(1, verifyControllerUp, time.Minute, time.Second).Should(Succeed())\n\n\t\t\tBy(\"creating an instance of the Memcached Operand(CR)\")\n\t\t\tEventuallyWithOffset(1, func() error {\n\t\t\t\tcmd = exec.Command(\"kubectl\", \"apply\", \"-f\", filepath.Join(projectDir,\n\t\t\t\t\t\"config/samples/cache_v1alpha1_memcached.yaml\"), \"-n\", namespace)\n\t\t\t\t_, err = utils.Run(cmd)\n\t\t\t\treturn err\n\t\t\t}, time.Minute, time.Second).Should(Succeed())\n\n\t\t\tBy(\"validating that pod(s) status.phase=Running\")\n\t\t\tgetMemcachedPodStatus := func() error {\n\t\t\t\tcmd = exec.Command(\"kubectl\", \"get\",\n\t\t\t\t\t\"pods\", \"-l\", \"app.kubernetes.io/name=memcached-operator\",\n\t\t\t\t\t\"-o\", \"jsonpath={.items[*].status}\", \"-n\", namespace,\n\t\t\t\t)\n\t\t\t\tstatus, err := utils.Run(cmd)\n\t\t\t\tfmt.Println(string(status))\n\t\t\t\tExpectWithOffset(2, err).NotTo(HaveOccurred())\n\t\t\t\tif !strings.Contains(string(status), \"\\\"phase\\\":\\\"Running\\\"\") {\n\t\t\t\t\treturn fmt.Errorf(\"memcached pod in %s status\", status)\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tEventuallyWithOffset(1, getMemcachedPodStatus, time.Minute, time.Second).Should(Succeed())\n\n\t\t\tBy(\"validating that the status of the custom resource created is updated or not\")\n\t\t\tgetStatus := func() error {\n\t\t\t\tcmd = exec.Command(\"kubectl\", \"get\", \"memcached\",\n\t\t\t\t\t\"memcached-sample\", \"-o\", \"jsonpath={.status.conditions}\",\n\t\t\t\t\t\"-n\", namespace,\n\t\t\t\t)\n\t\t\t\tstatus, err := utils.Run(cmd)\n\t\t\t\tfmt.Println(string(status))\n\t\t\t\tExpectWithOffset(2, err).NotTo(HaveOccurred())\n\t\t\t\tif !strings.Contains(string(status), \"Available\") {\n\t\t\t\t\treturn fmt.Errorf(\"status condition with type Available should be set\")\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tEventually(getStatus, time.Minute, time.Second).Should(Succeed())\n\t\t})\n\t})\n\n\tContext(\"Memcached Operator metrics\", Ordered, func() {\n\t\tBeforeAll(func() {\n\t\t\tBy(\"granting permissions to access the metrics\")\n\t\t\tcmd := exec.Command(\"kubectl\",\n\t\t\t\t\"create\", \"clusterrolebinding\", \"metrics-memcached-operator\",\n\t\t\t\t\"--clusterrole=memcached-operator-metrics-reader\",\n\t\t\t\tfmt.Sprintf(\"--serviceaccount=%s:memcached-operator-controller-manager\", namespace))\n\t\t\t_, err := utils.Run(cmd)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t})\n\n\t\tAfterAll(func() {\n\t\t\tBy(\"removing permissions to access the metrics\")\n\t\t\tcmd := exec.Command(\"kubectl\", \"delete\",\n\t\t\t\t\"clusterrolebinding\", \"metrics-memcached-operator\")\n\t\t\t_, err := utils.Run(cmd)\n\t\t\tExpect(err).NotTo(HaveOccurred())\n\t\t})\n\n\t\tIt(\"MemcachedDeploymentSizeUndesiredCountTotal should be increased when scaling the Memcached deployment\", func() {\n\t\t\tinitialMetricValue := getMetricValue(memcachedDeploymentSizeUndesiredCountTotalName)\n\n\t\t\tnumberOfScales := 5\n\t\t\tBy(fmt.Sprintf(\"scaling memcached-samle deployment %d times\", numberOfScales))\n\t\t\tscaleMemcachedSampleDeployment(numberOfScales)\n\n\t\t\tBy(fmt.Sprintf(\"validating MemcachedDeploymentSizeUndesiredCountTotal has increased by %d\", numberOfScales))\n\t\t\tfinalMetricValue := getMetricValue(memcachedDeploymentSizeUndesiredCountTotalName)\n\t\t\tExpect(finalMetricValue).Should(BeNumerically(\">=\", initialMetricValue+numberOfScales))\n\t\t})\n\t})\n})\n\n// getMetricValue will reach the Memcached operator metrics endpoint, validate the metric and extract its value\nfunc getMetricValue(metricName string) int {\n\t// reach the metrics endpoint and validate the metric exists\n\tmetricsEndpoint := curlMetrics()\n\tExpectWithOffset(1, metricsEndpoint).Should(ContainSubstring(metricName))\n\n\t// extract the metric value\n\tmetricValue, err := strconv.Atoi(parseMetricValue(metricsEndpoint, metricName))\n\tExpectWithOffset(1, err).NotTo(HaveOccurred())\n\n\treturn metricValue\n}\n\n// curlMetrics curl's the /metrics endpoint, returning all logs once a 200 status is returned.\nfunc curlMetrics() string {\n\tBy(\"reading the metrics token\")\n\t// Filter token query by service account in case more than one exists in a namespace.\n\ttoken, err := serviceAccountToken()\n\tExpectWithOffset(2, err).NotTo(HaveOccurred())\n\tExpectWithOffset(2, len(token)).To(BeNumerically(\">\", 0))\n\n\tBy(\"creating a curl pod\")\n\tcmd := exec.Command(\"kubectl\", \"run\", \"curl\", \"--image=curlimages/curl:7.68.0\",\n\t\t\"--restart=OnFailure\", \"-n\", \"default\", \"--\", \"curl\", \"-v\", \"-k\", \"-H\",\n\t\tfmt.Sprintf(\"Authorization: Bearer %s\", strings.TrimSpace(token)),\n\t\tfmt.Sprintf(\"https://memcached-operator-controller-manager-metrics-service.%s.svc:8443/metrics\", namespace))\n\t_, err = utils.Run(cmd)\n\tExpectWithOffset(2, err).NotTo(HaveOccurred())\n\n\tBy(\"validating that the curl pod is running as expected\")\n\tverifyCurlUp := func() error {\n\t\t// Validate pod status\n\t\tcmd := exec.Command(\"kubectl\", \"get\", \"pods\", \"curl\",\n\t\t\t\"-o\", \"jsonpath={.status.phase}\", \"-n\", \"default\")\n\t\tstatusOutput, err := utils.Run(cmd)\n\t\tstatus := string(statusOutput)\n\t\tExpectWithOffset(3, err).NotTo(HaveOccurred())\n\t\tif status != \"Completed\" && status != \"Succeeded\" {\n\t\t\treturn fmt.Errorf(\"curl pod in %s status\", status)\n\t\t}\n\t\treturn nil\n\t}\n\tEventuallyWithOffset(2, verifyCurlUp, 240*time.Second, time.Second).Should(Succeed())\n\n\tBy(\"validating that the metrics endpoint is serving as expected\")\n\tvar metricsEndpoint string\n\tgetCurlLogs := func() string {\n\t\tcmd = exec.Command(\"kubectl\", \"logs\", \"curl\", \"-n\", \"default\")\n\t\tmetricsEndpointOutput, err := utils.Run(cmd)\n\t\tExpectWithOffset(3, err).NotTo(HaveOccurred())\n\t\tmetricsEndpoint = string(metricsEndpointOutput)\n\t\treturn metricsEndpoint\n\t}\n\tEventuallyWithOffset(2, getCurlLogs, 10*time.Second, time.Second).Should(ContainSubstring(\"< HTTP/2 200\"))\n\n\tBy(\"cleaning up the curl pod\")\n\tcmd = exec.Command(\"kubectl\", \"delete\",\n\t\t\"pods/curl\", \"-n\", \"default\")\n\t_, err = utils.Run(cmd)\n\tExpectWithOffset(3, err).NotTo(HaveOccurred())\n\n\treturn metricsEndpoint\n}\n\n// serviceAccountToken provides a helper function that can provide you with a service account\n// token that you can use to interact with the service. This function leverages the k8s'\n// TokenRequest API in raw format in order to make it generic for all version of the k8s that\n// is currently being supported in kubebuilder test infra.\n// TokenRequest API returns the token in raw JWT format itself. There is no conversion required.\nfunc serviceAccountToken() (out string, err error) {\n\tBy(\"Creating the ServiceAccount token\")\n\tsecretName := \"memcached-operator-controller-manager-token-request\"\n\tprojectDir, _ := utils.GetProjectDir()\n\ttokenRequestFile := filepath.Join(projectDir, \"/test/e2e/\", secretName)\n\terr = os.WriteFile(tokenRequestFile, []byte(tokenRequestRawString), os.FileMode(0o755))\n\tif err != nil {\n\t\treturn out, err\n\t}\n\tvar rawJson string\n\tEventually(func() error {\n\t\t// Output of this is already a valid JWT token. No need to covert this from base64 to string format\n\t\tcmd := exec.Command(\"kubectl\", \"create\", \"--raw\",\n\t\t\tfmt.Sprintf(\"/api/v1/namespaces/%s/serviceaccounts/memcached-operator-controller-manager/token\", namespace),\n\t\t\t\"-f\", tokenRequestFile,\n\t\t)\n\t\trawJsonOutput, err := utils.Run(cmd)\n\t\trawJson = string(rawJsonOutput)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tvar token tokenRequest\n\t\terr = json.Unmarshal([]byte(rawJson), &token)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tout = token.Status.Token\n\t\treturn nil\n\t}, time.Minute, time.Second).Should(Succeed())\n\n\treturn out, err\n}\n\n// parseMetricValue will parse the metric value from the metrics endpoint\nfunc parseMetricValue(metricsEndpoint string, metricName string) string {\n\tr := strings.NewReader(metricsEndpoint)\n\tscan := bufio.NewScanner(r)\n\tfor scan.Scan() {\n\t\tmetricLine := scan.Text()\n\t\tif strings.HasPrefix(metricLine, metricName) {\n\t\t\tsplit := strings.Split(metricLine, \" \")\n\t\t\treturn split[1]\n\t\t}\n\t}\n\treturn \"\"\n}\n\n// scaleMemcachedSampleDeployment will scale memcached-sample deployment 'numberOfScales' times\nfunc scaleMemcachedSampleDeployment(numberOfScales int) {\n\tfor i := 1; i <= numberOfScales; i++ {\n\t\tcmd := exec.Command(\"kubectl\", \"scale\", \"--replicas=3\",\n\t\t\t\"deployment\", \"memcached-sample\", \"-n\", namespace)\n\t\t_, err := utils.Run(cmd)\n\t\tExpectWithOffset(1, err).NotTo(HaveOccurred())\n\t\ttime.Sleep(10 * time.Second)\n\t}\n}\n\nconst monitoringImportFragment = \"\\\"github.com/example/memcached-operator/monitoring\\\"\"\n\nconst incMemcachedDeploymentSizeUndesiredCountTotalFragment = \"monitoring.MemcachedDeploymentSizeUndesiredCountTotal.Inc()\"\n\nconst registerMetricsFragment = \"monitoring.RegisterMetrics()\"\n"
  },
  {
    "path": "testdata/go/v4/monitoring/memcached-operator/test/utils/utils.go",
    "content": "/*\nCopyright 2022.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage utils\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strings\"\n\n\t. \"github.com/onsi/ginkgo/v2\" //nolint:golint,revive\n)\n\nconst (\n\tprometheusOperatorVersion = \"0.51\"\n\tprometheusOperatorURL     = \"https://raw.githubusercontent.com/prometheus-operator/\" +\n\t\t\"prometheus-operator/release-%s/bundle.yaml\"\n\n\tcertmanagerVersion = \"v1.5.3\"\n\tcertmanagerURLTmpl = \"https://github.com/jetstack/cert-manager/releases/download/%s/cert-manager.yaml\"\n)\n\nfunc warnError(err error) {\n\tfmt.Fprintf(GinkgoWriter, \"warning: %v\\n\", err)\n}\n\n// InstallPrometheusOperator installs the prometheus Operator to be used to export the enabled metrics.\nfunc InstallPrometheusOperator() error {\n\turl := fmt.Sprintf(prometheusOperatorURL, prometheusOperatorVersion)\n\tcmd := exec.Command(\"kubectl\", \"apply\", \"-f\", url)\n\t_, err := Run(cmd)\n\treturn err\n}\n\n// Run executes the provided command within this context\nfunc Run(cmd *exec.Cmd) ([]byte, error) {\n\tdir, _ := GetProjectDir()\n\tcmd.Dir = dir\n\tfmt.Fprintf(GinkgoWriter, \"running dir: %s\\n\", cmd.Dir)\n\n\t// To allow make commands be executed from the project directory which is subdir on SDK repo\n\t// TODO:(user) You might not need the following code\n\tif err := os.Chdir(cmd.Dir); err != nil {\n\t\tfmt.Fprintf(GinkgoWriter, \"chdir dir: %s\\n\", err)\n\t}\n\n\tcmd.Env = append(os.Environ(), \"GO111MODULE=on\")\n\tcommand := strings.Join(cmd.Args, \" \")\n\tfmt.Fprintf(GinkgoWriter, \"running: %s\\n\", command)\n\toutput, err := cmd.CombinedOutput()\n\tif err != nil {\n\t\treturn output, fmt.Errorf(\"%s failed with error: (%v) %s\", command, err, string(output))\n\t}\n\n\treturn output, nil\n}\n\n// UninstallPrometheusOperator uninstalls the prometheus\nfunc UninstallPrometheusOperator() {\n\turl := fmt.Sprintf(prometheusOperatorURL, prometheusOperatorVersion)\n\tcmd := exec.Command(\"kubectl\", \"delete\", \"-f\", url)\n\tif _, err := Run(cmd); err != nil {\n\t\twarnError(err)\n\t}\n}\n\n// UninstallCertManager uninstalls the cert manager\nfunc UninstallCertManager() {\n\turl := fmt.Sprintf(certmanagerURLTmpl, certmanagerVersion)\n\tcmd := exec.Command(\"kubectl\", \"delete\", \"-f\", url)\n\tif _, err := Run(cmd); err != nil {\n\t\twarnError(err)\n\t}\n}\n\n// InstallCertManager installs the cert manager bundle.\nfunc InstallCertManager() error {\n\turl := fmt.Sprintf(certmanagerURLTmpl, certmanagerVersion)\n\tcmd := exec.Command(\"kubectl\", \"apply\", \"-f\", url)\n\tif _, err := Run(cmd); err != nil {\n\t\treturn err\n\t}\n\t// Wait for cert-manager-webhook to be ready, which can take time if cert-manager\n\t// was re-installed after uninstalling on a cluster.\n\tcmd = exec.Command(\"kubectl\", \"wait\", \"deployment.apps/cert-manager-webhook\",\n\t\t\"--for\", \"condition=Available\",\n\t\t\"--namespace\", \"cert-manager\",\n\t\t\"--timeout\", \"5m\",\n\t)\n\n\t_, err := Run(cmd)\n\treturn err\n}\n\n// LoadImageToKindCluster loads a local docker image to the kind cluster\nfunc LoadImageToKindClusterWithName(name string) error {\n\tcluster := \"kind\"\n\tif v, ok := os.LookupEnv(\"KIND_CLUSTER\"); ok {\n\t\tcluster = v\n\t}\n\tkindOptions := []string{\"load\", \"docker-image\", name, \"--name\", cluster}\n\tcmd := exec.Command(\"kind\", kindOptions...)\n\t_, err := Run(cmd)\n\treturn err\n}\n\n// GetNonEmptyLines converts given command output string into individual objects\n// according to line breakers, and ignores the empty elements in it.\nfunc GetNonEmptyLines(output string) []string {\n\tvar res []string\n\telements := strings.Split(output, \"\\n\")\n\tfor _, element := range elements {\n\t\tif element != \"\" {\n\t\t\tres = append(res, element)\n\t\t}\n\t}\n\n\treturn res\n}\n\n// GetProjectDir will return the directory where the project is\nfunc GetProjectDir() (string, error) {\n\twd, err := os.Getwd()\n\tif err != nil {\n\t\treturn wd, err\n\t}\n\twd = strings.Replace(wd, \"/test/e2e\", \"\", -1)\n\treturn wd, nil\n}\n\n// ReplaceInFile replaces all instances of old with new in the file at path.\nfunc ReplaceInFile(path, old, new string) error {\n\tinfo, err := os.Stat(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\t// false positive\n\t// nolint:gosec\n\tb, err := os.ReadFile(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif !strings.Contains(string(b), old) {\n\t\treturn errors.New(\"unable to find the content to be replaced\")\n\t}\n\ts := strings.Replace(string(b), old, new, -1)\n\terr = os.WriteFile(path, []byte(s), info.Mode())\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "testdata/helm/memcached-operator/.gitignore",
    "content": "\n# Binaries for programs and plugins\n*.exe\n*.exe~\n*.dll\n*.so\n*.dylib\nbin\n\n# editor and IDE paraphernalia\n.idea\n*.swp\n*.swo\n*~\n"
  },
  {
    "path": "testdata/helm/memcached-operator/Dockerfile",
    "content": "# Build the manager binary\nFROM quay.io/operator-framework/helm-operator:v1.42.2\n\nENV HOME=/opt/helm\nCOPY watches.yaml ${HOME}/watches.yaml\nCOPY helm-charts  ${HOME}/helm-charts\nWORKDIR ${HOME}\n"
  },
  {
    "path": "testdata/helm/memcached-operator/Makefile",
    "content": "# VERSION defines the project version for the bundle.\n# Update this value when you upgrade the version of your project.\n# To re-generate a bundle for another specific version without changing the standard setup, you can:\n# - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2)\n# - use environment variables to overwrite this value (e.g export VERSION=0.0.2)\nVERSION ?= 0.0.1\n\n# CHANNELS define the bundle channels used in the bundle.\n# Add a new line here if you would like to change its default config. (E.g CHANNELS = \"candidate,fast,stable\")\n# To re-generate a bundle for other specific channels without changing the standard setup, you can:\n# - use the CHANNELS as arg of the bundle target (e.g make bundle CHANNELS=candidate,fast,stable)\n# - use environment variables to overwrite this value (e.g export CHANNELS=\"candidate,fast,stable\")\nifneq ($(origin CHANNELS), undefined)\nBUNDLE_CHANNELS := --channels=$(CHANNELS)\nendif\n\n# DEFAULT_CHANNEL defines the default channel used in the bundle.\n# Add a new line here if you would like to change its default config. (E.g DEFAULT_CHANNEL = \"stable\")\n# To re-generate a bundle for any other default channel without changing the default setup, you can:\n# - use the DEFAULT_CHANNEL as arg of the bundle target (e.g make bundle DEFAULT_CHANNEL=stable)\n# - use environment variables to overwrite this value (e.g export DEFAULT_CHANNEL=\"stable\")\nifneq ($(origin DEFAULT_CHANNEL), undefined)\nBUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL)\nendif\nBUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL)\n\n# IMAGE_TAG_BASE defines the docker.io namespace and part of the image name for remote images.\n# This variable is used to construct full image tags for bundle and catalog images.\n#\n# For example, running 'make bundle-build bundle-push catalog-build catalog-push' will build and push both\n# example.com/memcached-operator-bundle:$VERSION and example.com/memcached-operator-catalog:$VERSION.\nIMAGE_TAG_BASE ?= example.com/memcached-operator\n\n# BUNDLE_IMG defines the image:tag used for the bundle.\n# You can use it as an arg. (E.g make bundle-build BUNDLE_IMG=<some-registry>/<project-name-bundle>:<tag>)\nBUNDLE_IMG ?= $(IMAGE_TAG_BASE)-bundle:v$(VERSION)\n\n# BUNDLE_GEN_FLAGS are the flags passed to the operator-sdk generate bundle command\nBUNDLE_GEN_FLAGS ?= -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS)\n\n# USE_IMAGE_DIGESTS defines if images are resolved via tags or digests\n# You can enable this value if you would like to use SHA Based Digests\n# To enable set flag to true\nUSE_IMAGE_DIGESTS ?= false\nifeq ($(USE_IMAGE_DIGESTS), true)\n\tBUNDLE_GEN_FLAGS += --use-image-digests\nendif\n\n# Set the Operator SDK version to use. By default, what is installed on the system is used.\n# This is useful for CI or a project to utilize a specific version of the operator-sdk toolkit.\nOPERATOR_SDK_VERSION ?= v1.42.2\n\n# Container tool to use for building and pushing images\nCONTAINER_TOOL ?= docker\n\n# Image URL to use all building/pushing image targets\nIMG ?= controller:latest\n\n.PHONY: all\nall: docker-build\n\n##@ General\n\n# The help target prints out all targets with their descriptions organized\n# beneath their categories. The categories are represented by '##@' and the\n# target descriptions by '##'. The awk commands is responsible for reading the\n# entire set of makefiles included in this invocation, looking for lines of the\n# file as xyz: ## something, and then pretty-format the target and help. Then,\n# if there's a line with ##@ something, that gets pretty-printed as a category.\n# More info on the usage of ANSI control characters for terminal formatting:\n# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters\n# More info on the awk command:\n# http://linuxcommand.org/lc3_adv_awk.php\n\n.PHONY: help\nhelp: ## Display this help.\n\t@awk 'BEGIN {FS = \":.*##\"; printf \"\\nUsage:\\n  make \\033[36m<target>\\033[0m\\n\"} /^[a-zA-Z_0-9-]+:.*?##/ { printf \"  \\033[36m%-15s\\033[0m %s\\n\", $$1, $$2 } /^##@/ { printf \"\\n\\033[1m%s\\033[0m\\n\", substr($$0, 5) } ' $(MAKEFILE_LIST)\n\n##@ Build\n\n.PHONY: run\nrun: helm-operator ## Run against the configured Kubernetes cluster in ~/.kube/config\n\t$(HELM_OPERATOR) run\n\n.PHONY: docker-build\ndocker-build: ## Build docker image with the manager.\n\t$(CONTAINER_TOOL) build -t ${IMG} .\n\n.PHONY: docker-push\ndocker-push: ## Push docker image with the manager.\n\t$(CONTAINER_TOOL) push ${IMG}\n\n# PLATFORMS defines the target platforms for  the manager image be build to provide support to multiple\n# architectures. (i.e. make docker-buildx IMG=myregistry/mypoperator:0.0.1). To use this option you need to:\n# - able to use docker buildx . More info: https://docs.docker.com/build/buildx/\n# - have enable BuildKit, More info: https://docs.docker.com/develop/develop-images/build_enhancements/\n# - be able to push the image for your registry (i.e. if you do not inform a valid value via IMG=<myregistry/image:<tag>> than the export will fail)\n# To properly provided solutions that supports more than one platform you should use this option.\nPLATFORMS ?= linux/arm64,linux/amd64,linux/s390x,linux/ppc64le\n.PHONY: docker-buildx\ndocker-buildx: ## Build and push docker image for the manager for cross-platform support\n\t- $(CONTAINER_TOOL) buildx create --name project-v3-builder\n\t$(CONTAINER_TOOL) buildx use project-v3-builder\n\t- $(CONTAINER_TOOL) buildx build --push --platform=$(PLATFORMS) --tag ${IMG} -f Dockerfile .\n\t- $(CONTAINER_TOOL) buildx rm project-v3-builder\n\n##@ Deployment\n\n.PHONY: install\ninstall: kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config.\n\t$(KUSTOMIZE) build config/crd | kubectl apply -f -\n\n.PHONY: uninstall\nuninstall: kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config.\n\t$(KUSTOMIZE) build config/crd | kubectl delete -f -\n\n.PHONY: deploy\ndeploy: kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.\n\tcd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}\n\t$(KUSTOMIZE) build config/default | kubectl apply -f -\n\n.PHONY: undeploy\nundeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config.\n\t$(KUSTOMIZE) build config/default | kubectl delete -f -\n\nOS := $(shell uname -s | tr '[:upper:]' '[:lower:]')\nARCH := $(shell uname -m | sed 's/x86_64/amd64/' | sed 's/aarch64/arm64/')\n\n.PHONY: kustomize\nKUSTOMIZE = $(shell pwd)/bin/kustomize\nkustomize: ## Download kustomize locally if necessary.\nifeq (,$(wildcard $(KUSTOMIZE)))\nifeq (,$(shell which kustomize 2>/dev/null))\n\t@{ \\\n\tset -e ;\\\n\tmkdir -p $(dir $(KUSTOMIZE)) ;\\\n\tcurl -sSLo - https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v5.6.0/kustomize_v5.6.0_$(OS)_$(ARCH).tar.gz | \\\n\ttar xzf - -C bin/ ;\\\n\t}\nelse\nKUSTOMIZE = $(shell which kustomize)\nendif\nendif\n\n.PHONY: helm-operator\nHELM_OPERATOR = $(shell pwd)/bin/helm-operator\nhelm-operator: ## Download helm-operator locally if necessary, preferring the $(pwd)/bin path over global if both exist.\nifeq (,$(wildcard $(HELM_OPERATOR)))\nifeq (,$(shell which helm-operator 2>/dev/null))\n\t@{ \\\n\tset -e ;\\\n\tmkdir -p $(dir $(HELM_OPERATOR)) ;\\\n\tcurl -sSLo $(HELM_OPERATOR) https://github.com/operator-framework/operator-sdk/releases/download/v1.42.2/helm-operator_$(OS)_$(ARCH) ;\\\n\tchmod +x $(HELM_OPERATOR) ;\\\n\t}\nelse\nHELM_OPERATOR = $(shell which helm-operator)\nendif\nendif\n\n.PHONY: operator-sdk\nOPERATOR_SDK ?= $(LOCALBIN)/operator-sdk\noperator-sdk: ## Download operator-sdk locally if necessary.\nifeq (,$(wildcard $(OPERATOR_SDK)))\nifeq (, $(shell which operator-sdk 2>/dev/null))\n\t@{ \\\n\tset -e ;\\\n\tmkdir -p $(dir $(OPERATOR_SDK)) ;\\\n\tcurl -sSLo $(OPERATOR_SDK) https://github.com/operator-framework/operator-sdk/releases/download/$(OPERATOR_SDK_VERSION)/operator-sdk_$(OS)_$(ARCH) ;\\\n\tchmod +x $(OPERATOR_SDK) ;\\\n\t}\nelse\nOPERATOR_SDK = $(shell which operator-sdk)\nendif\nendif\n\n\n.PHONY: bundle\nbundle: kustomize operator-sdk ## Generate bundle manifests and metadata, then validate generated files.\n\t$(OPERATOR_SDK) generate kustomize manifests --interactive=false -q\n\tcd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG)\n\t$(KUSTOMIZE) build config/manifests | $(OPERATOR_SDK) generate bundle $(BUNDLE_GEN_FLAGS)\n\t$(OPERATOR_SDK) bundle validate ./bundle\n\n.PHONY: bundle-build\nbundle-build: ## Build the bundle image.\n\t$(CONTAINER_TOOL) build -f bundle.Dockerfile -t $(BUNDLE_IMG) .\n\n.PHONY: bundle-push\nbundle-push: ## Push the bundle image.\n\t$(MAKE) docker-push IMG=$(BUNDLE_IMG)\n\n.PHONY: opm\nOPM = $(LOCALBIN)/opm\nopm: ## Download opm locally if necessary.\nifeq (,$(wildcard $(OPM)))\nifeq (,$(shell which opm 2>/dev/null))\n\t@{ \\\n\tset -e ;\\\n\tmkdir -p $(dir $(OPM)) ;\\\n\tcurl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/v1.55.0/$(OS)-$(ARCH)-opm ;\\\n\tchmod +x $(OPM) ;\\\n\t}\nelse\nOPM = $(shell which opm)\nendif\nendif\n\n# A comma-separated list of bundle images (e.g. make catalog-build BUNDLE_IMGS=example.com/operator-bundle:v0.1.0,example.com/operator-bundle:v0.2.0).\n# These images MUST exist in a registry and be pull-able.\nBUNDLE_IMGS ?= $(BUNDLE_IMG)\n\n# The image tag given to the resulting catalog image (e.g. make catalog-build CATALOG_IMG=example.com/operator-catalog:v0.2.0).\nCATALOG_IMG ?= $(IMAGE_TAG_BASE)-catalog:v$(VERSION)\n\n# Set CATALOG_BASE_IMG to an existing catalog image tag to add $BUNDLE_IMGS to that image.\nifneq ($(origin CATALOG_BASE_IMG), undefined)\nFROM_INDEX_OPT := --from-index $(CATALOG_BASE_IMG)\nendif\n\n# Build a catalog image by adding bundle images to an empty catalog using the operator package manager tool, 'opm'.\n# This recipe invokes 'opm' in 'semver' bundle add mode. For more information on add modes, see:\n# https://github.com/operator-framework/community-operators/blob/7f1438c/docs/packaging-operator.md#updating-your-existing-operator\n.PHONY: catalog-build\ncatalog-build: opm ## Build a catalog image.\n\t$(OPM) index add --container-tool $(CONTAINER_TOOL) --mode semver --tag $(CATALOG_IMG) --bundles $(BUNDLE_IMGS) $(FROM_INDEX_OPT)\n\n# Push the catalog image.\n.PHONY: catalog-push\ncatalog-push: ## Push a catalog image.\n\t$(MAKE) docker-push IMG=$(CATALOG_IMG)\n"
  },
  {
    "path": "testdata/helm/memcached-operator/PROJECT",
    "content": "# Code generated by tool. DO NOT EDIT.\n# This file is used to track the info used to scaffold your project\n# and allow the plugins properly work.\n# More info: https://book.kubebuilder.io/reference/project-config.html\ndomain: example.com\nlayout:\n- helm.sdk.operatorframework.io/v1\nplugins:\n  manifests.sdk.operatorframework.io/v2: {}\n  scorecard.sdk.operatorframework.io/v2: {}\nprojectName: memcached-operator\nresources:\n- api:\n    crdVersion: v1\n    namespaced: true\n  domain: example.com\n  group: cache\n  kind: Memcached\n  version: v1alpha1\nversion: \"3\"\n"
  },
  {
    "path": "testdata/helm/memcached-operator/bundle/manifests/cache.example.com_memcacheds.yaml",
    "content": "apiVersion: apiextensions.k8s.io/v1\nkind: CustomResourceDefinition\nmetadata:\n  creationTimestamp: null\n  name: memcacheds.cache.example.com\nspec:\n  group: cache.example.com\n  names:\n    kind: Memcached\n    listKind: MemcachedList\n    plural: memcacheds\n    singular: memcached\n  scope: Namespaced\n  versions:\n  - name: v1alpha1\n    schema:\n      openAPIV3Schema:\n        description: Memcached is the Schema for the memcacheds API\n        properties:\n          apiVersion:\n            description: 'APIVersion defines the versioned schema of this representation\n              of an object. Servers should convert recognized schemas to the latest\n              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'\n            type: string\n          kind:\n            description: 'Kind is a string value representing the REST resource this\n              object represents. Servers may infer this from the endpoint the client\n              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'\n            type: string\n          metadata:\n            type: object\n          spec:\n            description: Spec defines the desired state of Memcached\n            type: object\n            x-kubernetes-preserve-unknown-fields: true\n          status:\n            description: Status defines the observed state of Memcached\n            type: object\n            x-kubernetes-preserve-unknown-fields: true\n        type: object\n    served: true\n    storage: true\n    subresources:\n      status: {}\nstatus:\n  acceptedNames:\n    kind: \"\"\n    plural: \"\"\n  conditions: null\n  storedVersions: null\n"
  },
  {
    "path": "testdata/helm/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-monitor_monitoring.coreos.com_v1_servicemonitor.yaml",
    "content": "apiVersion: monitoring.coreos.com/v1\nkind: ServiceMonitor\nmetadata:\n  labels:\n    app.kubernetes.io/managed-by: kustomize\n    app.kubernetes.io/name: memcached-operator\n    control-plane: controller-manager\n  name: memcached-operator-controller-manager-metrics-monitor\nspec:\n  endpoints:\n  - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token\n    path: /metrics\n    port: https\n    scheme: https\n    tlsConfig:\n      insecureSkipVerify: true\n  selector:\n    matchLabels:\n      app.kubernetes.io/name: memcached-operator\n      control-plane: controller-manager\n"
  },
  {
    "path": "testdata/helm/memcached-operator/bundle/manifests/memcached-operator-controller-manager-metrics-service_v1_service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  creationTimestamp: null\n  labels:\n    app.kubernetes.io/managed-by: kustomize\n    app.kubernetes.io/name: memcached-operator\n    control-plane: controller-manager\n  name: memcached-operator-controller-manager-metrics-service\nspec:\n  ports:\n  - name: https\n    port: 8443\n    protocol: TCP\n    targetPort: 8443\n  selector:\n    app.kubernetes.io/name: memcached-operator\n    control-plane: controller-manager\nstatus:\n  loadBalancer: {}\n"
  },
  {
    "path": "testdata/helm/memcached-operator/bundle/manifests/memcached-operator-memcached-admin-role_rbac.authorization.k8s.io_v1_clusterrole.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  creationTimestamp: null\n  labels:\n    app.kubernetes.io/managed-by: kustomize\n    app.kubernetes.io/name: memcached-operator\n  name: memcached-operator-memcached-admin-role\nrules:\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds\n  verbs:\n  - '*'\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds/status\n  verbs:\n  - get\n"
  },
  {
    "path": "testdata/helm/memcached-operator/bundle/manifests/memcached-operator-memcached-editor-role_rbac.authorization.k8s.io_v1_clusterrole.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  creationTimestamp: null\n  labels:\n    app.kubernetes.io/managed-by: kustomize\n    app.kubernetes.io/name: memcached-operator\n  name: memcached-operator-memcached-editor-role\nrules:\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds/status\n  verbs:\n  - get\n"
  },
  {
    "path": "testdata/helm/memcached-operator/bundle/manifests/memcached-operator-memcached-viewer-role_rbac.authorization.k8s.io_v1_clusterrole.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  creationTimestamp: null\n  labels:\n    app.kubernetes.io/managed-by: kustomize\n    app.kubernetes.io/name: memcached-operator\n  name: memcached-operator-memcached-viewer-role\nrules:\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds\n  verbs:\n  - get\n  - list\n  - watch\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds/status\n  verbs:\n  - get\n"
  },
  {
    "path": "testdata/helm/memcached-operator/bundle/manifests/memcached-operator-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  creationTimestamp: null\n  name: memcached-operator-metrics-reader\nrules:\n- nonResourceURLs:\n  - /metrics\n  verbs:\n  - get\n"
  },
  {
    "path": "testdata/helm/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml",
    "content": "apiVersion: operators.coreos.com/v1alpha1\nkind: ClusterServiceVersion\nmetadata:\n  annotations:\n    alm-examples: |-\n      [\n        {\n          \"apiVersion\": \"cache.example.com/v1alpha1\",\n          \"kind\": \"Memcached\",\n          \"metadata\": {\n            \"name\": \"memcached-sample\"\n          },\n          \"spec\": {\n            \"AntiAffinity\": \"soft\",\n            \"affinity\": {},\n            \"extraContainers\": \"\",\n            \"extraVolumes\": \"\",\n            \"image\": \"memcached:1.5.20\",\n            \"kind\": \"StatefulSet\",\n            \"memcached\": {\n              \"extendedOptions\": \"modern\",\n              \"extraArgs\": [],\n              \"maxItemMemory\": 64,\n              \"verbosity\": \"v\"\n            },\n            \"metrics\": {\n              \"enabled\": false,\n              \"image\": \"quay.io/prometheus/memcached-exporter:v0.6.0\",\n              \"resources\": {},\n              \"serviceMonitor\": {\n                \"enabled\": false,\n                \"interval\": \"15s\"\n              }\n            },\n            \"nodeSelector\": {},\n            \"pdbMinAvailable\": 2,\n            \"podAnnotations\": {},\n            \"replicaCount\": 3,\n            \"resources\": {\n              \"requests\": {\n                \"cpu\": \"50m\",\n                \"memory\": \"64Mi\"\n              }\n            },\n            \"securityContext\": {\n              \"enabled\": false,\n              \"fsGroup\": 1001,\n              \"runAsUser\": 1001\n            },\n            \"serviceAnnotations\": {},\n            \"tolerations\": {},\n            \"updateStrategy\": {\n              \"type\": \"RollingUpdate\"\n            }\n          }\n        }\n      ]\n    capabilities: Basic Install\n    createdAt: \"2022-11-08T17:26:37Z\"\n  name: memcached-operator.v0.0.1\n  namespace: placeholder\nspec:\n  apiservicedefinitions: {}\n  customresourcedefinitions:\n    owned:\n    - kind: Memcached\n      name: memcacheds.cache.example.com\n      version: v1alpha1\n  description: Memcached Operator description. TODO.\n  displayName: Memcached Operator\n  icon:\n  - base64data: \"\"\n    mediatype: \"\"\n  install:\n    spec:\n      clusterPermissions:\n      - rules:\n        - apiGroups:\n          - \"\"\n          resources:\n          - namespaces\n          verbs:\n          - get\n        - apiGroups:\n          - \"\"\n          resources:\n          - secrets\n          verbs:\n          - '*'\n        - apiGroups:\n          - \"\"\n          resources:\n          - events\n          verbs:\n          - create\n        - apiGroups:\n          - cache.example.com\n          resources:\n          - memcacheds\n          - memcacheds/status\n          - memcacheds/finalizers\n          verbs:\n          - create\n          - delete\n          - get\n          - list\n          - patch\n          - update\n          - watch\n        - apiGroups:\n          - \"\"\n          resources:\n          - pods\n          - services\n          - services/finalizers\n          - endpoints\n          - persistentvolumeclaims\n          - events\n          - configmaps\n          - secrets\n          verbs:\n          - create\n          - delete\n          - get\n          - list\n          - patch\n          - update\n          - watch\n        - apiGroups:\n          - apps\n          resources:\n          - deployments\n          - daemonsets\n          - replicasets\n          - statefulsets\n          verbs:\n          - create\n          - delete\n          - get\n          - list\n          - patch\n          - update\n          - watch\n        - apiGroups:\n          - \"\"\n          resources:\n          - namespaces\n          verbs:\n          - get\n        - apiGroups:\n          - \"\"\n          resources:\n          - secrets\n          verbs:\n          - '*'\n        - apiGroups:\n          - \"\"\n          resources:\n          - events\n          verbs:\n          - create\n        - apiGroups:\n          - cache.example.com\n          resources:\n          - memcacheds\n          - memcacheds/status\n          - memcacheds/finalizers\n          verbs:\n          - create\n          - delete\n          - get\n          - list\n          - patch\n          - update\n          - watch\n        - apiGroups:\n          - \"\"\n          resources:\n          - pods\n          - services\n          - services/finalizers\n          - endpoints\n          - persistentvolumeclaims\n          - events\n          - configmaps\n          - secrets\n          verbs:\n          - create\n          - delete\n          - get\n          - list\n          - patch\n          - update\n          - watch\n        - apiGroups:\n          - apps\n          resources:\n          - deployments\n          - daemonsets\n          - replicasets\n          - statefulsets\n          verbs:\n          - create\n          - delete\n          - get\n          - list\n          - patch\n          - update\n          - watch\n        - apiGroups:\n          - policy\n          resources:\n          - events\n          - poddisruptionbudgets\n          verbs:\n          - create\n          - delete\n          - get\n          - list\n          - patch\n          - update\n          - watch\n        - apiGroups:\n          - \"\"\n          resources:\n          - serviceaccounts\n          - services\n          verbs:\n          - create\n          - delete\n          - get\n          - list\n          - patch\n          - update\n          - watch\n        - apiGroups:\n          - authentication.k8s.io\n          resources:\n          - tokenreviews\n          verbs:\n          - create\n        - apiGroups:\n          - authorization.k8s.io\n          resources:\n          - subjectaccessreviews\n          verbs:\n          - create\n        serviceAccountName: memcached-operator-controller-manager\n      deployments:\n      - label:\n          app.kubernetes.io/managed-by: kustomize\n          app.kubernetes.io/name: memcached-operator\n          control-plane: controller-manager\n        name: memcached-operator-controller-manager\n        spec:\n          replicas: 1\n          selector:\n            matchLabels:\n              app.kubernetes.io/name: memcached-operator\n              control-plane: controller-manager\n          strategy: {}\n          template:\n            metadata:\n              annotations:\n                kubectl.kubernetes.io/default-container: manager\n              labels:\n                app.kubernetes.io/name: memcached-operator\n                control-plane: controller-manager\n            spec:\n              containers:\n              - args:\n                - --metrics-require-rbac\n                - --metrics-secure\n                - --metrics-bind-address=:8443\n                - --leader-elect\n                - --leader-election-id=memcached-operator\n                - --health-probe-bind-address=:8081\n                image: quay.io/example/memcached-operator:v0.0.1\n                livenessProbe:\n                  httpGet:\n                    path: /healthz\n                    port: 8081\n                  initialDelaySeconds: 15\n                  periodSeconds: 20\n                name: manager\n                readinessProbe:\n                  httpGet:\n                    path: /readyz\n                    port: 8081\n                  initialDelaySeconds: 5\n                  periodSeconds: 10\n                resources:\n                  limits:\n                    cpu: 500m\n                    memory: 128Mi\n                  requests:\n                    cpu: 10m\n                    memory: 64Mi\n                securityContext:\n                  allowPrivilegeEscalation: false\n                  capabilities:\n                    drop:\n                    - ALL\n              securityContext:\n                runAsNonRoot: true\n                seccompProfile:\n                  type: RuntimeDefault\n              serviceAccountName: memcached-operator-controller-manager\n              terminationGracePeriodSeconds: 10\n      permissions:\n      - rules:\n        - apiGroups:\n          - \"\"\n          resources:\n          - configmaps\n          verbs:\n          - get\n          - list\n          - watch\n          - create\n          - update\n          - patch\n          - delete\n        - apiGroups:\n          - coordination.k8s.io\n          resources:\n          - leases\n          verbs:\n          - get\n          - list\n          - watch\n          - create\n          - update\n          - patch\n          - delete\n        - apiGroups:\n          - \"\"\n          resources:\n          - events\n          verbs:\n          - create\n          - patch\n        serviceAccountName: memcached-operator-controller-manager\n    strategy: deployment\n  installModes:\n  - supported: false\n    type: OwnNamespace\n  - supported: false\n    type: SingleNamespace\n  - supported: false\n    type: MultiNamespace\n  - supported: true\n    type: AllNamespaces\n  keywords:\n  - memcached-operator\n  links:\n  - name: Memcached Operator\n    url: https://memcached-operator.domain\n  maintainers:\n  - email: your@email.com\n    name: Maintainer Name\n  maturity: alpha\n  provider:\n    name: Provider Name\n    url: https://your.domain\n  version: 0.0.1\n"
  },
  {
    "path": "testdata/helm/memcached-operator/bundle/metadata/annotations.yaml",
    "content": "annotations:\n  # Core bundle annotations.\n  operators.operatorframework.io.bundle.mediatype.v1: registry+v1\n  operators.operatorframework.io.bundle.manifests.v1: manifests/\n  operators.operatorframework.io.bundle.metadata.v1: metadata/\n  operators.operatorframework.io.bundle.package.v1: memcached-operator\n  operators.operatorframework.io.bundle.channels.v1: alpha\n\n  # Annotations for testing.\n  operators.operatorframework.io.test.mediatype.v1: scorecard+v1\n  operators.operatorframework.io.test.config.v1: tests/scorecard/\n"
  },
  {
    "path": "testdata/helm/memcached-operator/bundle/tests/scorecard/config.yaml",
    "content": "apiVersion: scorecard.operatorframework.io/v1alpha3\nkind: Configuration\nmetadata:\n  name: config\nstages:\n- parallel: true\n  tests:\n  - entrypoint:\n    - scorecard-test\n    - basic-check-spec\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: basic\n      test: basic-check-spec-test\n    storage:\n      spec:\n        mountPath: {}\n  - entrypoint:\n    - scorecard-test\n    - olm-bundle-validation\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: olm\n      test: olm-bundle-validation-test\n    storage:\n      spec:\n        mountPath: {}\n  - entrypoint:\n    - scorecard-test\n    - olm-crds-have-validation\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: olm\n      test: olm-crds-have-validation-test\n    storage:\n      spec:\n        mountPath: {}\n  - entrypoint:\n    - scorecard-test\n    - olm-crds-have-resources\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: olm\n      test: olm-crds-have-resources-test\n    storage:\n      spec:\n        mountPath: {}\n  - entrypoint:\n    - scorecard-test\n    - olm-spec-descriptors\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: olm\n      test: olm-spec-descriptors-test\n    storage:\n      spec:\n        mountPath: {}\n  - entrypoint:\n    - scorecard-test\n    - olm-status-descriptors\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: olm\n      test: olm-status-descriptors-test\n    storage:\n      spec:\n        mountPath: {}\nstorage:\n  spec:\n    mountPath: {}\n"
  },
  {
    "path": "testdata/helm/memcached-operator/bundle.Dockerfile",
    "content": "FROM scratch\n\n# Core bundle labels.\nLABEL operators.operatorframework.io.bundle.mediatype.v1=registry+v1\nLABEL operators.operatorframework.io.bundle.manifests.v1=manifests/\nLABEL operators.operatorframework.io.bundle.metadata.v1=metadata/\nLABEL operators.operatorframework.io.bundle.package.v1=memcached-operator\nLABEL operators.operatorframework.io.bundle.channels.v1=alpha\n\n# Labels for testing.\nLABEL operators.operatorframework.io.test.mediatype.v1=scorecard+v1\nLABEL operators.operatorframework.io.test.config.v1=tests/scorecard/\n\n# Copy files to locations specified by labels.\nCOPY bundle/manifests /manifests/\nCOPY bundle/metadata /metadata/\nCOPY bundle/tests/scorecard /tests/scorecard/\n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/crd/bases/cache.example.com_memcacheds.yaml",
    "content": "---\napiVersion: apiextensions.k8s.io/v1\nkind: CustomResourceDefinition\nmetadata:\n  name: memcacheds.cache.example.com\nspec:\n  group: cache.example.com\n  names:\n    kind: Memcached\n    listKind: MemcachedList\n    plural: memcacheds\n    singular: memcached\n  scope: Namespaced\n  versions:\n  - name: v1alpha1\n    schema:\n      openAPIV3Schema:\n        description: Memcached is the Schema for the memcacheds API\n        properties:\n          apiVersion:\n            description: 'APIVersion defines the versioned schema of this representation\n              of an object. Servers should convert recognized schemas to the latest\n              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'\n            type: string\n          kind:\n            description: 'Kind is a string value representing the REST resource this\n              object represents. Servers may infer this from the endpoint the client\n              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'\n            type: string\n          metadata:\n            type: object\n          spec:\n            description: Spec defines the desired state of Memcached\n            type: object\n            x-kubernetes-preserve-unknown-fields: true\n          status:\n            description: Status defines the observed state of Memcached\n            type: object\n            x-kubernetes-preserve-unknown-fields: true\n        type: object\n    served: true\n    storage: true\n    subresources:\n      status: {}\n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/crd/kustomization.yaml",
    "content": "# This kustomization.yaml is not intended to be run by itself,\n# since it depends on service name and namespace that are out of this kustomize package.\n# It should be run by config/default\nresources:\n- bases/cache.example.com_memcacheds.yaml\n# +kubebuilder:scaffold:crdkustomizeresource\n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/default/kustomization.yaml",
    "content": "# Adds namespace to all resources.\nnamespace: memcached-operator-system\n\n# Value of this field is prepended to the\n# names of all resources, e.g. a deployment named\n# \"wordpress\" becomes \"alices-wordpress\".\n# Note that it should also match with the prefix (text before '-') of the namespace\n# field above.\nnamePrefix: memcached-operator-\n\n# Labels to add to all resources and selectors.\n#labels:\n#- includeSelectors: true\n#  pairs:\n#    someName: someValue\n\nresources:\n- ../crd\n- ../rbac\n- ../manager\n# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'.\n- ../prometheus\n# [METRICS] Expose the controller manager metrics service.\n- metrics_service.yaml\n# [NETWORK POLICY] Protect the /metrics endpoint and Webhook Server with NetworkPolicy.\n# Only Pod(s) running a namespace labeled with 'metrics: enabled' will be able to gather the metrics.\n# Only CR(s) which requires webhooks and are applied on namespaces labeled with 'webhooks: enabled' will\n# be able to communicate with the Webhook Server.\n#- ../network-policy\n\n# Uncomment the patches line if you enable Metrics\npatches:\n# [METRICS] The following patch will enable the metrics endpoint using HTTPS and the port :8443.\n# More info: https://book.kubebuilder.io/reference/metrics\n- path: manager_metrics_patch.yaml\n  target:\n    kind: Deployment\n\n\n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/default/manager_metrics_patch.yaml",
    "content": "# This patch adds the args to allow exposing the metrics endpoint using HTTPS\n- op: add\n  path: /spec/template/spec/containers/0/args/0\n  value: --metrics-bind-address=:8443\n# This patch adds the args to allow securing the metrics endpoint\n- op: add\n  path: /spec/template/spec/containers/0/args/0\n  value: --metrics-secure\n# This patch adds the args to allow RBAC-based authn/authz the metrics endpoint\n- op: add\n  path: /spec/template/spec/containers/0/args/0\n  value: --metrics-require-rbac\n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/default/metrics_service.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  labels:\n    control-plane: controller-manager\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: controller-manager-metrics-service\n  namespace: system\nspec:\n  ports:\n  - name: https\n    port: 8443\n    protocol: TCP\n    targetPort: 8443\n  selector:\n    control-plane: controller-manager\n    app.kubernetes.io/name: memcached-operator\n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/manager/kustomization.yaml",
    "content": "resources:\n- manager.yaml\napiVersion: kustomize.config.k8s.io/v1beta1\nkind: Kustomization\nimages:\n- name: controller\n  newName: quay.io/example/memcached-operator\n  newTag: v0.0.1\n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/manager/manager.yaml",
    "content": "apiVersion: v1\nkind: Namespace\nmetadata:\n  labels:\n    control-plane: controller-manager\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: system\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: controller-manager\n  namespace: system\n  labels:\n    control-plane: controller-manager\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\nspec:\n  selector:\n    matchLabels:\n      control-plane: controller-manager\n      app.kubernetes.io/name: memcached-operator\n  replicas: 1\n  template:\n    metadata:\n      annotations:\n        kubectl.kubernetes.io/default-container: manager\n      labels:\n        control-plane: controller-manager\n        app.kubernetes.io/name: memcached-operator\n    spec:\n      # TODO(user): Uncomment the following code to configure the nodeAffinity expression\n      # according to the platforms which are supported by your solution.\n      # It is considered best practice to support multiple architectures. You can\n      # build your manager image using the makefile target docker-buildx.\n      # affinity:\n      #   nodeAffinity:\n      #     requiredDuringSchedulingIgnoredDuringExecution:\n      #       nodeSelectorTerms:\n      #         - matchExpressions:\n      #           - key: kubernetes.io/arch\n      #             operator: In\n      #             values:\n      #               - amd64\n      #               - arm64\n      #               - ppc64le\n      #               - s390x\n      #           - key: kubernetes.io/os\n      #             operator: In\n      #             values:\n      #               - linux\n      securityContext:\n        # Projects are configured by default to adhere to the \"restricted\" Pod Security Standards.\n        # This ensures that deployments meet the highest security requirements for Kubernetes.\n        # For more details, see: https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted\n        runAsNonRoot: true\n        seccompProfile:\n          type: RuntimeDefault\n      containers:\n      - args:\n          - --leader-elect\n          - --leader-election-id=memcached-operator\n          - --health-probe-bind-address=:8081\n        image: controller:latest\n        name: manager\n        ports: []\n        securityContext:\n          allowPrivilegeEscalation: false\n          capabilities:\n            drop:\n            - \"ALL\"\n        livenessProbe:\n          httpGet:\n            path: /healthz\n            port: 8081\n          initialDelaySeconds: 15\n          periodSeconds: 20\n        readinessProbe:\n          httpGet:\n            path: /readyz\n            port: 8081\n          initialDelaySeconds: 5\n          periodSeconds: 10\n        # TODO(user): Configure the resources accordingly based on the project requirements.\n        # More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/\n        resources:\n          limits:\n            cpu: 500m\n            memory: 128Mi\n          requests:\n            cpu: 10m\n            memory: 64Mi\n        volumeMounts: []\n      volumes: []\n      serviceAccountName: controller-manager\n      terminationGracePeriodSeconds: 10\n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml",
    "content": "apiVersion: operators.coreos.com/v1alpha1\nkind: ClusterServiceVersion\nmetadata:\n  annotations:\n    alm-examples: '[]'\n    capabilities: Basic Install\n  name: memcached-operator.v0.0.0\n  namespace: placeholder\nspec:\n  apiservicedefinitions: {}\n  customresourcedefinitions: {}\n  description: Memcached Operator description. TODO.\n  displayName: Memcached Operator\n  icon:\n  - base64data: \"\"\n    mediatype: \"\"\n  install:\n    spec:\n      deployments: null\n    strategy: \"\"\n  installModes:\n  - supported: false\n    type: OwnNamespace\n  - supported: false\n    type: SingleNamespace\n  - supported: false\n    type: MultiNamespace\n  - supported: true\n    type: AllNamespaces\n  keywords:\n  - memcached-operator\n  links:\n  - name: Memcached Operator\n    url: https://memcached-operator.domain\n  maintainers:\n  - email: your@email.com\n    name: Maintainer Name\n  maturity: alpha\n  provider:\n    name: Provider Name\n    url: https://your.domain\n  version: 0.0.0\n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/manifests/kustomization.yaml",
    "content": "# These resources constitute the fully configured set of manifests\n# used to generate the 'manifests/' directory in a bundle.\nresources:\n- bases/memcached-operator.clusterserviceversion.yaml\n- ../default\n- ../samples\n- ../scorecard\n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/network-policy/allow-metrics-traffic.yaml",
    "content": "# This NetworkPolicy allows ingress traffic\n# with Pods running on namespaces labeled with 'metrics: enabled'. Only Pods on those\n# namespaces are able to gather data from the metrics endpoint.\napiVersion: networking.k8s.io/v1\nkind: NetworkPolicy\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: allow-metrics-traffic\n  namespace: system\nspec:\n  podSelector:\n    matchLabels:\n      control-plane: controller-manager\n      app.kubernetes.io/name: memcached-operator\n  policyTypes:\n    - Ingress\n  ingress:\n    # This allows ingress traffic from any namespace with the label metrics: enabled\n    - from:\n      - namespaceSelector:\n          matchLabels:\n            metrics: enabled  # Only from namespaces with this label\n      ports:\n        - port: 8443\n          protocol: TCP\n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/network-policy/kustomization.yaml",
    "content": "resources:\n- allow-metrics-traffic.yaml\n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/prometheus/kustomization.yaml",
    "content": "resources:\n- monitor.yaml\n\n\n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/prometheus/monitor.yaml",
    "content": "# Prometheus Monitor Service (Metrics)\napiVersion: monitoring.coreos.com/v1\nkind: ServiceMonitor\nmetadata:\n  labels:\n    control-plane: controller-manager\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: controller-manager-metrics-monitor\n  namespace: system\nspec:\n  endpoints:\n    - path: /metrics\n      port: https # Ensure this is the name of the port that exposes HTTPS metrics\n      scheme: https\n      bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token\n      tlsConfig:\n        # TODO(user): The option insecureSkipVerify: true is not recommended for production since it disables\n        # certificate verification, exposing the system to potential man-in-the-middle attacks.\n        # For production environments, it is recommended to use cert-manager for automatic TLS certificate management.\n        # To apply this configuration, enable cert-manager and use the patch located at config/prometheus/servicemonitor_tls_patch.yaml,\n        # which securely references the certificate from the 'metrics-server-cert' secret.\n        insecureSkipVerify: true\n  selector:\n    matchLabels:\n      control-plane: controller-manager\n      app.kubernetes.io/name: memcached-operator\n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/rbac/kustomization.yaml",
    "content": "resources:\n# All RBAC will be applied under this service account in\n# the deployment namespace. You may comment out this resource\n# if your manager will use a service account that exists at\n# runtime. Be sure to update RoleBinding and ClusterRoleBinding\n# subjects if changing service account names.\n- service_account.yaml\n- role.yaml\n- role_binding.yaml\n- leader_election_role.yaml\n- leader_election_role_binding.yaml\n# The following RBAC configurations are used to protect\n# the metrics endpoint with authn/authz. These configurations\n# ensure that only authorized users and service accounts\n# can access the metrics endpoint. Comment the following\n# permissions if you want to disable this protection.\n# More info: https://book.kubebuilder.io/reference/metrics.html\n- metrics_auth_role.yaml\n- metrics_auth_role_binding.yaml\n- metrics_reader_role.yaml\n# For each CRD, \"Admin\", \"Editor\" and \"Viewer\" roles are scaffolded by\n# default, aiding admins in cluster management. Those roles are\n# not used by the memcached-operator itself. You can comment the following lines\n# if you do not want those helpers be installed with your Project.\n- memcached_admin_role.yaml\n- memcached_editor_role.yaml\n- memcached_viewer_role.yaml\n\n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/rbac/leader_election_role.yaml",
    "content": "# permissions to do leader election.\napiVersion: rbac.authorization.k8s.io/v1\nkind: Role\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: leader-election-role\nrules:\n- apiGroups:\n  - \"\"\n  resources:\n  - configmaps\n  verbs:\n  - get\n  - list\n  - watch\n  - create\n  - update\n  - patch\n  - delete\n- apiGroups:\n  - coordination.k8s.io\n  resources:\n  - leases\n  verbs:\n  - get\n  - list\n  - watch\n  - create\n  - update\n  - patch\n  - delete\n- apiGroups:\n  - \"\"\n  resources:\n  - events\n  verbs:\n  - create\n  - patch\n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/rbac/leader_election_role_binding.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: RoleBinding\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: leader-election-rolebinding\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: Role\n  name: leader-election-role\nsubjects:\n- kind: ServiceAccount\n  name: controller-manager\n  namespace: system\n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/rbac/memcached_admin_role.yaml",
    "content": "# This rule is not used by the project memcached-operator itself.\n# It is provided to allow the cluster admin to help manage permissions for users.\n#\n# Grants full permissions ('*') over cache.example.com.\n# This role is intended for users authorized to modify roles and bindings within the cluster,\n# enabling them to delegate specific permissions to other users or groups as needed.\n\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: memcached-admin-role\nrules:\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds\n  verbs:\n  - '*'\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds/status\n  verbs:\n  - get\n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/rbac/memcached_editor_role.yaml",
    "content": "# This rule is not used by the project memcached-operator itself.\n# It is provided to allow the cluster admin to help manage permissions for users.\n#\n# Grants permissions to create, update, and delete resources within the cache.example.com.\n# This role is intended for users who need to manage these resources\n# but should not control RBAC or manage permissions for others.\n\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: memcached-editor-role\nrules:\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds/status\n  verbs:\n  - get\n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/rbac/memcached_viewer_role.yaml",
    "content": "# This rule is not used by the project memcached-operator itself.\n# It is provided to allow the cluster admin to help manage permissions for users.\n#\n# Grants read-only access to cache.example.com resources.\n# This role is intended for users who need visibility into these resources\n# without permissions to modify them. It is ideal for monitoring purposes and limited-access viewing.\n\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: memcached-viewer-role\nrules:\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds\n  verbs:\n  - get\n  - list\n  - watch\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds/status\n  verbs:\n  - get\n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/rbac/metrics_auth_role.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  name: metrics-auth-role\nrules:\n- apiGroups:\n  - authentication.k8s.io\n  resources:\n  - tokenreviews\n  verbs:\n  - create\n- apiGroups:\n  - authorization.k8s.io\n  resources:\n  - subjectaccessreviews\n  verbs:\n  - create\n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/rbac/metrics_auth_role_binding.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n  name: metrics-auth-rolebinding\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: metrics-auth-role\nsubjects:\n- kind: ServiceAccount\n  name: controller-manager\n  namespace: system\n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/rbac/metrics_reader_role.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  name: metrics-reader\nrules:\n- nonResourceURLs:\n  - \"/metrics\"\n  verbs:\n  - get\n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/rbac/role.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  name: manager-role\nrules:\n##\n## Base operator rules\n##\n# We need to get namespaces so the operator can read namespaces to ensure they exist\n- apiGroups:\n  - \"\"\n  resources:\n  - namespaces\n  verbs:\n  - get\n# We need to manage Helm release secrets\n- apiGroups:\n  - \"\"\n  resources:\n  - secrets\n  verbs:\n  - \"*\"\n# We need to create events on CRs about things happening during reconciliation\n- apiGroups:\n  - \"\"\n  resources:\n  - events\n  verbs:\n  - create\n\n##\n## Rules for cache.example.com/v1alpha1, Kind: Memcached\n##\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds\n  - memcacheds/status\n  - memcacheds/finalizers\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n- apiGroups:\n  - \"\"\n  resources:\n  - pods\n  - services\n  - services/finalizers\n  - endpoints\n  - persistentvolumeclaims\n  - events\n  - configmaps\n  - secrets\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n- apiGroups:\n  - apps\n  resources:\n  - deployments\n  - daemonsets\n  - replicasets\n  - statefulsets\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n\n\n##\n## Base operator rules\n##\n# We need to get namespaces so the operator can read namespaces to ensure they exist\n- apiGroups:\n  - \"\"\n  resources:\n  - namespaces\n  verbs:\n  - get\n# We need to manage Helm release secrets\n- apiGroups:\n  - \"\"\n  resources:\n  - secrets\n  verbs:\n  - \"*\"\n# We need to create events on CRs about things happening during reconciliation\n- apiGroups:\n  - \"\"\n  resources:\n  - events\n  verbs:\n  - create\n\n##\n## Rules for cache.example.com/v1alpha1, Kind: Memcached\n##\n- apiGroups:\n  - cache.example.com\n  resources:\n  - memcacheds\n  - memcacheds/status\n  - memcacheds/finalizers\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n- apiGroups:\n  - \"\"\n  resources:\n  - pods\n  - services\n  - services/finalizers\n  - endpoints\n  - persistentvolumeclaims\n  - events\n  - configmaps\n  - secrets\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n- apiGroups:\n  - apps\n  resources:\n  - deployments\n  - daemonsets\n  - replicasets\n  - statefulsets\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n\n\n##\n## Rules customized for cache.example.com/v1alpha1, Kind: Memcached\n##\n- apiGroups:\n  - policy\n  resources:\n  - events\n  - poddisruptionbudgets\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n- apiGroups:\n  - \"\"\n  resources:\n  - serviceaccounts\n  - services\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n\n#+kubebuilder:scaffold:rules\n\n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/rbac/role_binding.yaml",
    "content": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: manager-rolebinding\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: manager-role\nsubjects:\n- kind: ServiceAccount\n  name: controller-manager\n  namespace: system\n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/rbac/service_account.yaml",
    "content": "apiVersion: v1\nkind: ServiceAccount\nmetadata:\n  labels:\n    app.kubernetes.io/name: memcached-operator\n    app.kubernetes.io/managed-by: kustomize\n  name: controller-manager\n  namespace: system\n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml",
    "content": "apiVersion: cache.example.com/v1alpha1\nkind: Memcached\nmetadata:\n  name: memcached-sample\nspec:\n  # Default values copied from <project_dir>/helm-charts/memcached/values.yaml\n  AntiAffinity: soft\n  affinity: {}\n  extraContainers: \"\"\n  extraVolumes: \"\"\n  image: memcached:1.5.20\n  kind: StatefulSet\n  memcached:\n    extendedOptions: modern\n    extraArgs: []\n    maxItemMemory: 64\n    verbosity: v\n  metrics:\n    enabled: false\n    image: quay.io/prometheus/memcached-exporter:v0.6.0\n    resources: {}\n    serviceMonitor:\n      enabled: false\n      interval: 15s\n  nodeSelector: {}\n  pdbMinAvailable: 2\n  podAnnotations: {}\n  replicaCount: 3\n  resources:\n    requests:\n      cpu: 50m\n      memory: 64Mi\n  securityContext:\n    enabled: false\n    fsGroup: 1001\n    runAsUser: 1001\n  serviceAnnotations: {}\n  tolerations: {}\n  updateStrategy:\n    type: RollingUpdate\n  \n  \n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/samples/kustomization.yaml",
    "content": "## Append samples of your project ##\nresources:\n- cache_v1alpha1_memcached.yaml\n# +kubebuilder:scaffold:manifestskustomizesamples\n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/scorecard/bases/config.yaml",
    "content": "apiVersion: scorecard.operatorframework.io/v1alpha3\nkind: Configuration\nmetadata:\n  name: config\nstages:\n- parallel: true\n  tests: []\n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/scorecard/kustomization.yaml",
    "content": "resources:\n- bases/config.yaml\napiVersion: kustomize.config.k8s.io/v1beta1\nkind: Kustomization\npatches:\n- path: patches/basic.config.yaml\n  target:\n    group: scorecard.operatorframework.io\n    kind: Configuration\n    name: config\n    version: v1alpha3\n- path: patches/olm.config.yaml\n  target:\n    group: scorecard.operatorframework.io\n    kind: Configuration\n    name: config\n    version: v1alpha3\n# +kubebuilder:scaffold:patches\n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/scorecard/patches/basic.config.yaml",
    "content": "- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - scorecard-test\n    - basic-check-spec\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: basic\n      test: basic-check-spec-test\n"
  },
  {
    "path": "testdata/helm/memcached-operator/config/scorecard/patches/olm.config.yaml",
    "content": "- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - scorecard-test\n    - olm-bundle-validation\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: olm\n      test: olm-bundle-validation-test\n- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - scorecard-test\n    - olm-crds-have-validation\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: olm\n      test: olm-crds-have-validation-test\n- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - scorecard-test\n    - olm-crds-have-resources\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: olm\n      test: olm-crds-have-resources-test\n- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - scorecard-test\n    - olm-spec-descriptors\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: olm\n      test: olm-spec-descriptors-test\n- op: add\n  path: /stages/0/tests/-\n  value:\n    entrypoint:\n    - scorecard-test\n    - olm-status-descriptors\n    image: quay.io/operator-framework/scorecard-test:v1.42.2\n    labels:\n      suite: olm\n      test: olm-status-descriptors-test\n"
  },
  {
    "path": "testdata/helm/memcached-operator/helm-charts/memcached/.helmignore",
    "content": ".git\nOWNERS\n"
  },
  {
    "path": "testdata/helm/memcached-operator/helm-charts/memcached/Chart.yaml",
    "content": "apiVersion: v1\nappVersion: 1.5.20\ndescription: Free & open source, high-performance, distributed memory object caching\n  system.\nhome: http://memcached.org/\nicon: https://upload.wikimedia.org/wikipedia/en/thumb/2/27/Memcached.svg/1024px-Memcached.svg.png\nkeywords:\n- memcached\n- cache\nmaintainers:\n- email: gtaylor@gc-taylor.com\n  name: gtaylor\n- email: o.with@sportradar.com\n  name: olemarkus\n- email: k.aasan@sportradar.com\n  name: kennethaasan\nname: memcached\nsources:\n- https://github.com/docker-library/memcached\nversion: 0.0.2\n"
  },
  {
    "path": "testdata/helm/memcached-operator/helm-charts/memcached/README.md",
    "content": "# Memcached\n\n> [Memcached](https://memcached.org/) is an in-memory key-value store for small chunks of arbitrary data (strings, objects) from results of database calls, API calls, or page rendering.\n\nBased on the [memcached](https://github.com/bitnami/charts/tree/master/incubator/memcached) chart from the [Bitnami Charts](https://github.com/bitnami/charts) repository.\n\n## TL;DR;\n\n```bash\n$ helm install stable/memcached\n```\n\n## Introduction\n\nThis chart bootstraps a [Memcached](https://hub.docker.com/_/memcached/) deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager.\n\n## Installing the Chart\n\nTo install the chart with the release name `my-release`:\n\n```bash\n$ helm install --name my-release stable/memcached\n```\n\nThe command deploys Memcached on the Kubernetes cluster in the default configuration. The [configuration](#configuration) section lists the parameters that can be configured during installation.\n\n> **Tip**: List all releases using `helm list`\n\n## Uninstalling the Chart\n\nTo uninstall/delete the `my-release` deployment:\n\n```bash\n$ helm delete my-release\n```\n\nThe command removes all the Kubernetes components associated with the chart and deletes the release.\n\n## Configuration\n\nThe following table lists the configurable parameters of the Memcached chart and their default values.\n\n|      Parameter             |          Description            |                         Default                         |\n|----------------------------|---------------------------------|---------------------------------------------------------|\n| `image`                    | The image to pull and run       | A recent official memcached tag                         |\n| `imagePullPolicy`          | Image pull policy               | `Always` if `imageTag` is `latest`, else `IfNotPresent` |\n| `memcached.verbosity`      | Verbosity level (v, vv, or vvv) | Un-set.                                                 |\n| `memcached.maxItemMemory`  | Max memory for items (in MB)    | `64`                                                    |\n| `memcached.extraArgs`      | Additional memcached arguments  | `[]`                                                    |\n| `extraContainers`          | Container sidecar definition(s) as string | Un-set                                        |\n| `extraVolumes`             | Volume definitions to add as string | Un-set                                              |\n| `kind`                     | Install as StatefulSet or Deployment | StatefulSet                                        |\n| `podAnnotations`           | Map of annotations to add to the pod(s) | `{}`                                            |\n| `podLabels`                | Custom Labels to be applied to statefulset | Un-set                                       |\n| `nodeSelector`             | Simple pod scheduling control | `{}`                                                      |\n| `tolerations`              | Allow or deny specific node taints | `{}`                                                 |\n| `affinity`                 | Advanced pod scheduling control | `{}`                                                    |\n| `securityContext.enabled`  | Enable security context    | `true`                                                       |\n| `securityContext.fsGroup`  | Group ID for the container | `1001`                                                       |\n| `securityContext.runAsUser`| User ID for the container  | `1001`                                                       |\n| `updateStrategy.type`      | Update strategy for the StatefulSet/Deployment | `RollingUpdate`                          |\n| `priorityClassName  `      | Specifies the pod's priority class name        | Un-set                                   |\n\nThe above parameters map to `memcached` params. For more information please refer to the [Memcached documentation](https://github.com/memcached/memcached/wiki/ConfiguringServer).\n\nSpecify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example,\n\n```bash\n$ helm install --name my-release \\\n  --set memcached.verbosity=v \\\n    stable/memcached\n```\n\nThe above command sets the Memcached verbosity to `v`.\n\nAlternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example,\n\n```bash\n$ helm install --name my-release -f values.yaml stable/memcached\n```\n\n> **Tip**: You can use the default [values.yaml](values.yaml)\n\n## Upgrading to 3.x from a previous major version\nVersion 3.0.0 of this chart makes an incompatible change to the way StatefulSet/Deployment selectors are configured. If you try to upgrade from a previous major version, you will see an error like this:\n\n```\nError: UPGRADE FAILED: Deployment.apps \"mc-test-memcached\" is invalid: spec.template.metadata.labels: Invalid value: map[string]string{\"app\":\"mc-test-memcached\", \"chart\":\"memcached-3.0.0\", \"custom\":\"value\", \"heritage\":\"Tiller\", \"release\":\"mc-test\"}: `selector` does not match template `labels`\n```\n\nTo upgrade from a previous major version, you'll either need to perform a small manual fix or delete and reinstall the chart.\n\n### Upgrading with `kind: StatefulSet`\nIf you're using a StatefulSet, you'll have to manually delete it and allow Helm to re-create it. Run `kubectl delete --cascade=false sts name-goes-here` to delete the StatefulSet without deleting the pods. Once you've done this, upgrade the chart as normal, and the newly-created StatefulSet will adopt the old pods.\n\n### Upgrading with `kind: Deployment`\nIf you're using a Deployment, the manual fix is to remove all selectors from the spec except `app` and `release`.  Run `kubectl edit deploy name-goes-here`, and you should see a part like this in your editor about 20 lines down:\n\n```yaml\nspec:\n  progressDeadlineSeconds: 600\n  replicas: 1\n  revisionHistoryLimit: 2\n  selector:\n    matchLabels:\n      app: mc-test-memcached\n      chart: memcached-2.10.2\n      heritage: Tiller\n      release: mc-test\n```\n\nRemove the lines under `matchLabels` except `app: ...` and `release: ...`, and don't change any other lines. The part from above should look like this when you're done:\n\n```yaml\nspec:\n  progressDeadlineSeconds: 600\n  replicas: 1\n  revisionHistoryLimit: 2\n  selector:\n    matchLabels:\n      app: mc-test-memcached\n      release: mc-test\n```\n\nOnce you've done this, you can upgrade to 3.x with Helm as normal.\n\nIf you want prometheus-operator scrap all serviceMonitors in your cluster you need to set:\n```yaml\nprometheus:\n  prometheusSpec:\n    serviceMonitorSelectorNilUsesHelmValues: false\n```\nIf you want to be specific:\n```yaml\nprometheus:\n  prometheusSpec:\n    serviceMonitorSelector:\n      matchLabels:\n        app: memcached\n```\nYou can have more intel in prometheus-operator values and here [github](https://github.com/helm/charts/issues/11310#issuecomment-463486706)\n"
  },
  {
    "path": "testdata/helm/memcached-operator/helm-charts/memcached/templates/NOTES.txt",
    "content": "Memcached can be accessed via port 11211 on the following DNS name from within your cluster:\n{{ template \"memcached.fullname\" . }}.{{ .Release.Namespace }}.svc.cluster.local\n\nIf you'd like to test your instance, forward the port locally:\n\n  export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l \"app.kubernetes.io/name={{ include \"memcached.name\" . }},app.kubernetes.io/instance={{ .Release.Name }}\" -o jsonpath=\"{.items[0].metadata.name}\")\n  kubectl port-forward $POD_NAME 11211\n\nIn another tab, attempt to set a key:\n\n  $ echo -e 'set mykey 0 60 5\\r\\nhello\\r' | nc localhost 11211\n\nYou should see:\n\n  STORED\n"
  },
  {
    "path": "testdata/helm/memcached-operator/helm-charts/memcached/templates/_helpers.tpl",
    "content": "{{/* vim: set filetype=mustache: */}}\n{{/*\nExpand the name of the chart.\n*/}}\n{{- define \"memcached.name\" -}}\n{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix \"-\" -}}\n{{- end -}}\n\n{{/*\nCreate a default fully qualified app name.\nWe truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).\n*/}}\n{{- define \"memcached.fullname\" -}}\n{{- if .Values.fullnameOverride -}}\n{{- .Values.fullnameOverride | trunc 63 | trimSuffix \"-\" -}}\n{{- else -}}\n{{- $name := default .Chart.Name .Values.nameOverride -}}\n{{- if contains $name .Release.Name -}}\n{{- .Release.Name | trunc 63 | trimSuffix \"-\" -}}\n{{- else -}}\n{{- printf \"%s-%s\" .Release.Name $name | trunc 63 | trimSuffix \"-\" -}}\n{{- end -}}\n{{- end -}}\n{{- end -}}\n\n{{/*\nCommon labels\n*/}}\n{{- define \"memcached.labels\" -}}\napp.kubernetes.io/name: {{ include \"memcached.name\" . }}\nhelm.sh/chart: {{ include \"memcached.chart\" . }}\napp.kubernetes.io/instance: {{ .Release.Name }}\n{{- if .Chart.AppVersion }}\napp.kubernetes.io/version: {{ .Chart.AppVersion | quote }}\n{{- end }}\napp.kubernetes.io/managed-by: {{ .Release.Service }}\n{{- end -}}\n\n{{/*\nCreate chart name and version as used by the chart label.\n*/}}\n{{- define \"memcached.chart\" -}}\n{{- printf \"%s-%s\" .Chart.Name .Chart.Version | replace \"+\" \"_\" | trunc 63 | trimSuffix \"-\" -}}\n{{- end -}}\n"
  },
  {
    "path": "testdata/helm/memcached-operator/helm-charts/memcached/templates/pdb.yaml",
    "content": "apiVersion: policy/v1\nkind: PodDisruptionBudget\nmetadata:\n  name: {{ template \"memcached.fullname\" . }}\n  namespace: {{ .Release.Namespace }}\n  annotations:\n    helm.sh/hook: \"post-upgrade, post-install\"\n    helm.sh/hook-delete-policy: \"before-hook-creation\"\n  labels:\n{{ include \"memcached.labels\" . | indent 4 }}\nspec:\n  selector:\n    matchLabels:\n      app.kubernetes.io/name: {{ include \"memcached.name\" . }}\n      app.kubernetes.io/instance: {{ .Release.Name }}\n  minAvailable: {{ .Values.pdbMinAvailable }}\n"
  },
  {
    "path": "testdata/helm/memcached-operator/helm-charts/memcached/templates/statefulset.yaml",
    "content": "apiVersion: apps/v1\nkind: {{ .Values.kind }}\nmetadata:\n  name: {{ template \"memcached.fullname\" . }}\n  namespace: {{ .Release.Namespace }}\n  labels:\n{{ include \"memcached.labels\" . | indent 4 }}\nspec:\n  selector:\n    matchLabels:\n      app.kubernetes.io/name: {{ include \"memcached.name\" . }}\n      app.kubernetes.io/instance: {{ .Release.Name }}\n  {{- if eq .Values.kind \"StatefulSet\" }}\n  serviceName: {{ template \"memcached.fullname\" . }}\n  {{- end }}\n  replicas: {{ .Values.replicaCount }}\n  template:\n    metadata:\n      labels:\n        app.kubernetes.io/name: {{ include \"memcached.name\" . }}\n        app.kubernetes.io/instance: {{ .Release.Name }}\n{{- with .Values.podLabels }}\n{{ toYaml . | indent 8 }}\n{{- end}}\n{{- with .Values.podAnnotations }}\n      annotations:\n{{ toYaml . | indent 8 }}\n{{- end }}\n    spec:\n      {{- if .Values.securityContext.enabled }}\n      securityContext:\n        fsGroup: {{ .Values.securityContext.fsGroup }}\n        runAsNonRoot: true\n        seccompProfile:\n          type: RuntimeDefault\n      {{- end }}\n      affinity:\n        podAntiAffinity:\n        {{- if eq .Values.AntiAffinity \"hard\" }}\n          requiredDuringSchedulingIgnoredDuringExecution:\n          - topologyKey: \"kubernetes.io/hostname\"\n            labelSelector:\n              matchLabels:\n                app.kubernetes.io/name: {{ include \"memcached.name\" . }}\n                app.kubernetes.io/instance: {{ .Release.Name }}\n        {{- else if eq .Values.AntiAffinity \"soft\" }}\n          preferredDuringSchedulingIgnoredDuringExecution:\n          - weight: 5\n            podAffinityTerm:\n              topologyKey: \"kubernetes.io/hostname\"\n              labelSelector:\n                matchLabels:\n                  app.kubernetes.io/name: {{ include \"memcached.name\" . }}\n                  app.kubernetes.io/instance: {{ .Release.Name }}\n        {{- end }}\n      {{- if .Values.priorityClassName }}\n      priorityClassName: \"{{ .Values.priorityClassName }}\"\n      {{- end }}\n      containers:\n      - name: {{ template \"memcached.fullname\" . }}\n        image: {{ .Values.image }}\n        imagePullPolicy: {{ default \"\" .Values.imagePullPolicy | quote }}\n        {{- if .Values.securityContext.enabled }}\n        securityContext:\n          allowPrivilegeEscalation: false\n          runAsUser: {{ .Values.securityContext.runAsUser }}\n          capabilities:\n            drop:\n              - ALL\n        {{- end }}\n        command:\n        - memcached\n        - -m {{ .Values.memcached.maxItemMemory }}\n        {{- if .Values.memcached.extendedOptions }}\n        - -o\n        - {{ .Values.memcached.extendedOptions }}\n        {{- end }}\n        {{- if .Values.memcached.verbosity }}\n        - -{{ .Values.memcached.verbosity }}\n        {{- end }}\n{{- with .Values.memcached.extraArgs }}\n{{ toYaml . | indent 8 }}\n{{- end }}\n        ports:\n        - name: memcache\n          containerPort: 11211\n        livenessProbe:\n          tcpSocket:\n            port: memcache\n          initialDelaySeconds: 30\n          timeoutSeconds: 5\n        readinessProbe:\n          tcpSocket:\n            port: memcache\n          initialDelaySeconds: 5\n          timeoutSeconds: 1\n        resources:\n{{ toYaml .Values.resources | indent 10 }}\n{{- if .Values.metrics.enabled }}\n      - name: metrics\n        image: {{ .Values.metrics.image }}\n        imagePullPolicy: {{ default \"\" .Values.metrics.imagePullPolicy | quote }}\n        {{- if .Values.securityContext.enabled }}\n        securityContext:\n          runAsUser: {{ .Values.securityContext.runAsUser }}\n        {{- end }}\n        ports:\n        - name: metrics\n          containerPort: 9150\n        resources:\n{{ toYaml .Values.metrics.resources | indent 10 }}\n{{- end }}\n{{- with .Values.extraContainers }}\n{{ tpl . $ | indent 6 }}\n{{- end }}\n{{- with .Values.extraVolumes }}\n      volumes:\n{{ tpl . $ | indent 6 }}\n{{- end }}\n{{- with .Values.nodeSelector }}\n      nodeSelector:\n{{ toYaml . | trim | indent 8}}\n{{- end }}\n{{- with .Values.tolerations }}\n      tolerations:\n{{ toYaml . | trim | indent 8}}\n{{- end }}\n{{- with .Values.affinity }}\n      affinity:\n{{ toYaml . | trim | indent 8}}\n{{- end }}\n{{- if eq .Values.kind \"StatefulSet\" }}\n  updateStrategy:\n{{- else }}\n  strategy:\n{{- end }}\n    type: {{ .Values.updateStrategy.type }}\n    {{- if (eq \"Recreate\" .Values.updateStrategy.type) }}\n    rollingUpdate: null\n    {{- end }}\n"
  },
  {
    "path": "testdata/helm/memcached-operator/helm-charts/memcached/templates/svc.yaml",
    "content": "apiVersion: v1\nkind: Service\nmetadata:\n  name: {{ template \"memcached.fullname\" . }}\n  namespace: {{ .Release.Namespace }}\n  labels:\n{{ include \"memcached.labels\" . | indent 4 }}\n  annotations:\n{{ toYaml .Values.serviceAnnotations | indent 4 }}\nspec:\n  clusterIP: None\n  ports:\n  - name: memcache\n    port: 11211\n    targetPort: memcache\n{{- if .Values.metrics.enabled }}\n  - name: metrics\n    port: 9150\n    targetPort: metrics\n{{- end }}\n  selector:\n    app.kubernetes.io/name: {{ include \"memcached.name\" . }}\n    app.kubernetes.io/instance: {{ .Release.Name }}\n"
  },
  {
    "path": "testdata/helm/memcached-operator/helm-charts/memcached/values.yaml",
    "content": "## Memcached image and tag\n## ref: https://hub.docker.com/r/library/memcached/tags/\n##\nimage: memcached:1.5.20\n\n## Specify a imagePullPolicy\n## 'Always' if imageTag is 'latest', else set to 'IfNotPresent'\n## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images\n##\n# imagePullPolicy:\n#\n\n## Replica count\nreplicaCount: 3\n\n## Pod disruption budget minAvailable count\n## Ensure this value is lower than replicaCount in order to allow a worker\n## node to drain successfully\npdbMinAvailable: 2\n\n## Select AntiAffinity as either hard or soft, default is hard\nAntiAffinity: \"soft\"\n\nmemcached:\n  ## Various values that get set as command-line flags.\n  ## ref: https://github.com/memcached/memcached/wiki/ConfiguringServer#commandline-arguments\n  ##\n  maxItemMemory: 64\n  verbosity: v\n  extendedOptions: modern\n\n  ## Additional command line arguments to pass to memcached\n  ## E.g. to specify a maximum value size\n  ## extraArgs:\n  ##   - -I 2m\n  extraArgs: []\n\n## Define various attributes of the service\nserviceAnnotations: {}\n#  prometheus.io/scrape: \"true\"\n\n## StatefulSet or Deployment\nkind: StatefulSet\n\n## Update Strategy for the StatefulSet or Deployment\n## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies\n## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#updating-a-deployment\nupdateStrategy:\n  type: RollingUpdate\n\n## Configure resource requests and limits\n## ref: http://kubernetes.io/docs/user-guide/compute-resources/\n##\nresources:\n  requests:\n    memory: 64Mi\n    cpu: 50m\n\n## Key:value pair for assigning pod to specific sets of nodes\n## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/\nnodeSelector: {}\n\n## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/\ntolerations: {}\n\n## Advanced scheduling controls\n## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/\naffinity: {}\n\n## Memcached pod Security Context\n## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/\nsecurityContext:\n  enabled: true\n  fsGroup: 1001\n  runAsUser: 1001\n\nmetrics:\n  ## Expose memcached metrics in Prometheus format\n  enabled: false\n  serviceMonitor:\n    enabled: false\n    interval: 15s\n\n  ## Memcached exporter image and tag\n  image: quay.io/prometheus/memcached-exporter:v0.6.0\n\n  ## Specify a imagePullPolicy\n  ## 'Always' if imageTag is 'latest', else set to 'IfNotPresent'\n  ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images\n  ##\n  # imagePullPolicy: IfNotPresent\n\n  ## Configure resource requests and limits\n  ## ref: http://kubernetes.io/docs/user-guide/compute-resources/\n  ##\n  resources: {}\n\nextraContainers: |\n\nextraVolumes: |\n\n## Custom metadata labels to be applied to statefulset and pods\n# podLabels:\n#   foo: \"bar\"\n#   bar: \"foo\"\n\n# To be added to the server pod(s)\npodAnnotations: {}\n\n## Set pod priority class\n# priorityClassName: \"\"\n"
  },
  {
    "path": "testdata/helm/memcached-operator/watches.yaml",
    "content": "# Use the 'create api' subcommand to add watches to this file.\n- group: cache.example.com\n  version: v1alpha1\n  kind: Memcached\n  chart: helm-charts/memcached\n# +kubebuilder:scaffold:watch\n"
  },
  {
    "path": "tools/scripts/fetch",
    "content": "#!/usr/bin/env bash\n\nROOT=\"$( git rev-parse --show-toplevel )\"\nDEST=\"${ROOT}/tools/bin\"\n\nfetch() {\n  local tool=$1; shift\n  local ver=$1; shift\n\n  local arch=\"$(uname -m)\"\n  case \"$arch\" in\n    x86_64) arch=\"amd64\" ;;\n    aarch64) arch=\"arm64\" ;;\n    *);;\n  esac\n  local os=\"$(uname -s | awk '{ print tolower($0) }')\"\n\n  local ver_cmd=\"\"\n  local fetch_cmd=\"\"\n  case \"$tool\" in\n    \"golangci-lint\")\n      ver_cmd=\"${DEST}/golangci-lint --version 2>/dev/null | cut -d' ' -f4\"\n      fetch_cmd=\"curl -sSfL \\\"https://raw.githubusercontent.com/golangci/golangci-lint/v${ver}/install.sh\\\" | sh -s -- -b \\\"${DEST}\\\" \\\"v${ver}\\\"\"\n      ;;\n    \"kind\")\n      ver_cmd=\"${DEST}/kind --version 2>/dev/null | cut -d' ' -f3\"\n      fetch_cmd=\"(curl -sSfLo '${DEST}/kind' 'https://kind.sigs.k8s.io/dl/v${ver}/kind-${os}-${arch}' && chmod +x ${DEST}/kind)\"\n      ;;\n    \"kubectl\")\n      ver_cmd=\"${DEST}/kubectl version 2>/dev/null | grep Client | cut -d' ' -f5 | sed 's/\\w\\+:\\\"v\\(.*\\)\\\",/\\1/'\"\n      fetch_cmd=\"(curl -sSfLo '${DEST}/kubectl' 'https://dl.k8s.io/release/v${ver}/bin/${os}/${arch}/kubectl' && chmod +x ${DEST}/kubectl)\"\n      ;;\n    \"goreleaser\")\n      ver_cmd=\"${DEST}/goreleaser --version 2>/dev/null | grep version | cut -d' ' -f3\"\n      osCap=\"$(uname -s)\"\n      archBase=\"$(uname -m)\"\n      fetch_cmd=\"(curl -sSfLo '${DEST}/goreleaser.tar.gz' 'https://github.com/goreleaser/goreleaser/releases/download/v${ver}/goreleaser_${osCap}_${archBase}.tar.gz' && tar -xf $DEST/goreleaser.tar.gz -C $DEST)\"\n      ;;\n    *)\n      echo \"unknown tool $tool\"\n      return 1\n      ;;\n  esac\n\n  if [[ \"${ver}\" != \"$(eval ${ver_cmd})\" ]]; then\n    echo \"${tool} missing or not version '${ver}', downloading...\"\n    mkdir -p ${DEST}\n    eval ${fetch_cmd}\n  fi\n}\n\nfetch $@\n"
  },
  {
    "path": "tools/tools.go",
    "content": "// +build tools\n\npackage tools\n\nimport (\n\t_ \"github.com/maxbrunsfeld/counterfeiter/v6\"\n)\n"
  },
  {
    "path": "website/assets/scss/_breadcrumb.scss",
    "content": ".breadcrumb {\n    display: flex;\n    flex-wrap: wrap;\n    padding-left: 0rem;\n    padding-top: 0.75rem;\n\n    margin-bottom: $breadcrumb-margin-bottom;\n    list-style: none;\n    background-color: initial;\n    margin-left: 0px;\n    border-bottom-left-radius: 0rem;\n    border-top-left-radius: 0rem;\n  }\n\n.breadcrumb-item {\n    display: -ms-flexbox;\n    display: flex;\n}\n\n.breadcrumb-item + .breadcrumb-item {\n    padding-left: 0.5rem;\n  }\n  \n.breadcrumb-item + .breadcrumb-item::before {\n    display: inline-block;\n    padding-right: 0.5rem;\n    color: $breadcrumb-divider-color;\n    content: \"/\";\n}\n  \n.breadcrumb-item + .breadcrumb-item:hover::before {\n    text-decoration: underline;\n}\n  \n.breadcrumb-item + .breadcrumb-item:hover::before {\n    text-decoration: none;\n}\n  \n.breadcrumb-item.active {\n    color: $breadcrumb-active-color;;\n}"
  },
  {
    "path": "website/assets/scss/_docs.scss",
    "content": ".td-sidebar-nav .td-sidebar-link__page {\n    color: #222;\n}\n\n.of-docs__wrapper {\n    pre, p, ol, ul {\n        margin-bottom: var(--of--spacer--md);\n    }\n    ul {\n        list-style: disc;\n        margin-left: 2rem;\n    }\n    .td-sidebar-nav .td-sidebar-link__page {\n        font-weight: normal;\n    }\n    h1,h2,h3,h4,h5,h6 {\n        color: var(--of--Color--brand--200);\n        font-weight: 800;\n        letter-spacing: 2px;\n        margin: var(--of--spacer--md) 0 var(--of--spacer--sm);\n    }\n    \n    h5, h6 {\n        font-size: var(--of--FontSize--xs);\n    }\n    h4 {\n        font-size: var(--of--FontSize--sm);\n    }\n    h3 {\n        font-size: var(--of--FontSize--md);\n    }\n    h2 {\n        font-size: var(--of--FontSize--md);\n    }\n    h1 {\n        font-size: var(--of--FontSize--lg);\n    }\n    \n    @media (min-width: $ov--breakpoint--lg) {\n        h6 {\n            font-size: var(--of--FontSize--xs);\n        }\n        h5 {\n            font-size: var(--of--FontSize--xs);\n        }\n        h4 {\n            font-size: var(--of--FontSize--sm);\n        }\n        h3 {\n            font-size: var(--of--FontSize--md);\n        }\n        h2 {\n            font-size: var(--of--FontSize--lg);\n        }\n        h1 {\n            font-size: var(--of--FontSize--xl);\n        }\n    }\n}\n"
  },
  {
    "path": "website/assets/scss/_footer.scss",
    "content": ".of-footer-main {\n    background: var(--of--color-brand--300);\n    color: var(--of--color-white--100);\n    position: relative;\n    width: 100%;\n    @media (min-width: $ov--breakpoint--lg) {\n        display: grid;\n        grid-template-columns: minmax(50%, 600px) 1fr;\n        grid-gap: var(--of--spacer--xl);\n        grid-template-areas: \n        \"meta social\"\n        \"copy copy \"\n        ;\n\n    } \n    &:before {\n        content:'';\n        height: 5px;\n        width: 100%;\n        position: absolute;\n        top: 0;\n        left: 0;\n        background: linear-gradient(to right, var(--of--color-brand--50) 25%, var(--of--color-brand--100) 25%, var(--of--color-brand--100) 50%, var(--of--color-brand--100) 50%, var(--of--color-brand--200) 50%, var(--of--color-brand--200) 75%, var(--of--color-brand--300) 75%);\n    }\n    padding-top: var(--of--spacer--2xl);\n    .of-heading {\n        margin-bottom: var(--of--spacer--sm);\n    }\n    &__meta {\n        grid-area: meta;\n        padding: 0 var(--of--spacer--lg) var(--of--spacer--lg) var(--of--spacer--lg);\n        & > *:not(:last-child){\n            margin-bottom: var(--of--spacer--sm);\n        }\n        .of-link-list {\n            flex-direction: column;\n            @media (min-width: $ov--breakpoint--lg) {\n                flex-direction: row;\n            }\n        }\n        @media (min-width: $ov--breakpoint--lg) {\n            flex-direction: row;\n            padding: 0 0 0 var(--of--spacer--2xl);\n            .of-link-list__li {\n                \n                &:not(:last-of-type) {\n                    margin-right: var(--of--spacer--sm);\n                    border-right: 1px solid var(--of--color-brand--100);\n                    padding-right: var(--of--spacer--sm);\n                }             \n            }\n            .of-link-list__a {\n                text-decoration: underline;\n            }\n        }\n        img {\n            max-width: 200px;\n        }\n    }\n    &__social {\n        grid-area: social;\n        padding:var(--of--spacer--lg);\n        @media (min-width: $ov--breakpoint--lg){\n            padding:0;\n        }\n        .of-link-list {\n            &__li {\n                margin-right: var(--of--spacer--md);\n                display: flex;\n            }\n            &__a {\n                display: flex;\n                align-items: center;\n                font-size: 2rem;\n                &:hover, &:active, &:focus {\n                    text-decoration: none;\n                    opacity: .8;\n                }\n            }\n        }\n        input {\n            margin-bottom: var(--of--spacer--lg);\n            border-radius: var(--of--BorderRadius--lg);\n            border: none;\n            text-indent: 1ch;\n            min-width: 250px;\n        }\n    }\n    &__copyright {\n        grid-area: copy;\n        display: flex;\n        color: var(--of--color-white--100);\n        padding: var(--of--spacer--xl);\n        background: var(--of--color-black--300);\n        .of-link-list__li {\n            margin-left: var(--of--spacer--sm);\n        }\n    }\n    .of-link-list {\n        display: flex;\n        flex-wrap: wrap;\n    }\n    &__badge {\n        margin-left: auto;\n    }\n}"
  },
  {
    "path": "website/assets/scss/_functions.scss",
    "content": "$font_size: 16;\n@function rem($pixels){\n  @return $pixels / $font_size + rem;\n}"
  },
  {
    "path": "website/assets/scss/_global.scss",
    "content": "body {\n    margin-top: 100px;\n    @media (min-width: $ov--breakpoint--lg) {\n        margin-top: 72px;\n    }\n}\n\n.of-link-list {\n    display: flex;\n    a {\n    color: var(--of--color-white--100);\n    }\n}\n\n.of-link {\n    &--inline {\n        white-space: nowrap;\n    }    \n}\n\n.of-list {\n    list-style-type: disc;\n    margin-left: var(--of--spacer--lg);\n}\n\nol {\n    margin-left: var(--of--spacer--md);\n    list-style: none;\n    counter-reset: ordered-list-counter;\n li {\n  counter-increment: ordered-list-counter;\n  position: relative;\n}\n li::before {\n  position: absolute;\n  left: 0;\n  top: 0;\n}\n}\n.of-section-separator {\n    border-bottom: 2px solid var(--of--color-white--150);\n}\n\n.of-button {\n    border-radius: var(--of--BorderRadius--sm);\n    padding: var(--of--spacer--sm) var(--of--spacer--lg);\n    display: inline-flex;\n    border: var(--of--BorderWidth--sm) solid transparent;\n    transition: all .25s linear;\n    &:not(.of-button--tertiary){\n        @media (min-width: $ov--breakpoint--lg) {\n            padding: var(--of--spacer--md) var(--of--spacer--xl);\n        }\n    }\n    &--primary {\n        background: var(--of--color-brand--200);\n        color: var(--of--color-white--100);\n        &:hover,&:active,&:focus {\n            color: var(--of--color-white--100);\n            background: var(--of--color-brand--300);  \n        }\n    }\n    &--secondary {\n        background: rgba(255, 255, 255, .12);\n        color: var(--of--color-white--100);\n        -webkit-backdrop-filter: blur(10px);\n        backdrop-filter: blur(10px);\n        &:hover,&:active,&:focus {\n            color: var(--of--color-brand--200);\n            background: var(--of--color-white--100); \n        }\n    }\n\n    &--tertiary {\n        padding-left: 0;\n        display: flex;\n        align-content: center;\n        max-width: max-content;\n        color: var(--of--color-brand--200);\n        .of-button__icon {\n            margin-left: var(--of--spacer--md);\n            width: 20px;\n            height: 20px;\n            path {\n                fill: var(--of--color-brand--200);\n            }\n        }\n        &:hover,&:active,&:focus {\n            opacity: .8;\n            color: var(--of--color-brand--100);\n            .of-button__icon {\n                path {\n                    fill: var(--of--color-brand--100);\n                }\n            }\n        }\n    }\n    &:hover,&:active,&:focus {\n        text-decoration: none;\n    }\n}\n\n\n.of-section-page-develop {\n    & > .of-heading {\n        color: var(--of--color-brand--100);\n        padding: var(--of--spacer--lg);\n    @media (min-width: $ov--breakpoint--lg) {\n        padding:var(--of--spacer--2xl) var(--of--spacer--3xl) var(--of--spacer--md);\n    }\n    }\n    \n}\n\n.of-section-whats-operator {\n    padding: var(--of--spacer--lg);\n    @media (min-width: $ov--breakpoint--lg) {\n        padding:var(--of--spacer--xl) var(--of--spacer--3xl);\n        display:grid;\n        grid-template-columns: 1fr 1fr;\n        grid-template-areas: 'content video';\n        grid-gap: var(--of--spacer--sm);\n    }\n    .of-heading {\n        color: var(--of--color-brand--100);\n    }\n    &__content{\n        grid-area: content;\n        & *:not(.of-button) {\n            margin-bottom: var(--of--spacer--md);\n        }\n    }\n    &__video {\n        grid-area: video;\n    }\n\n}\n\n.of-section__contribute {\n    padding: var(--of--spacer--lg);\n    display: grid;\n    gap: var(--of--spacer--xl);\n    @media (min-width: $ov--breakpoint--lg) {\n    grid-template-columns: 1fr 4fr;\n    align-items: start;\n    gap: var(--of--spacer--2xl);\n    padding: var(--of--spacer--3xl);\n    &__content {\n        max-width: 60vw;\n    }\n    }\n    background: linear-gradient(to bottom, rgba(240,240,240,1) 0%, rgba(255,255,255,1) 100%);\n    &__header {\n        justify-self: start ;\n        padding:var(--of--spacer--sm) var(--of--spacer--md);\n        display: inline-flex;\n        align-items: center;\n        border: 3px solid var(--of--color-brand--300);\n        .of-heading {\n            color: var(--of--color-brand--300);\n            text-transform: uppercase;\n            font-weight: 800;\n            margin: 0;\n        }\n        svg {\n            margin-left: var(--of--spacer--md);\n        }\n    }\n    \n}\n\n.of-section--largetext {\n    padding: var(--of--spacer--lg);\n    \n    @media (min-width: $ov--breakpoint--lg) { \n    padding: var(--of--spacer--2xl) var(--of--spacer--3xl);\n    margin: 0 auto;\n    max-width: 1200px;\n    }\n    .of-heading {\n        text-transform: uppercase;\n        color: var(--of--color-brand--200);\n    }\n    &__item {\n        display: grid;\n        grid-template-columns: 1fr;\n        grid-template-areas:\n        'text'\n        'title'\n        'content'\n        'action';\n        margin-top: var(--of--spacer--md);\n        @media (min-width: $ov--breakpoint--lg) {  \n            grid-template-columns: 1fr 1fr;\n            grid-template-rows: max-content max-content;\n            margin: calc(var(--of--spacer--2xl) * 2) 0 calc(var(--of--spacer--3xl) * 2);\n            column-gap: var(--of--spacer--xl);\n            grid-template-areas:\n            'title text'\n            'content text'\n            'action text'\n            ;\n            &:nth-of-type(odd) {\n                & > *:not(.large-text) {\n                    margin-right: var(--of--spacer--lg);\n                }\n            }\n            &:nth-of-type(even) {\n                grid-template-areas:\n                'text title'\n                'text content'\n                'text action'\n                ;\n                & > *:not(.large-text) {\n                    margin-left: var(--of--spacer--lg);\n                }\n                .large-text {\n                    justify-self: end;\n                }\n            }\n        }\n        \n        &:nth-of-type(1){\n            .of-heading {\n                color: var(--of--color-brand--100);\n            }\n            .large-text {\n                color: var(--of--color-brand--100);\n            }\n        }\n        &:nth-of-type(2){\n            .of-heading {\n                color: var(--of--color-brand--200);\n            }\n            .large-text {\n                color: var(--of--color-brand--200);\n            }\n        }\n        &:nth-of-type(3){\n            .of-heading {\n                color: var(--of--color-brand--300);\n            }\n            .large-text {\n                color: var(--of--color-brand--300);\n            }\n        }\n        .of-heading {\n            margin-bottom: var(--of--spacer--md);\n            grid-area: title;\n        }\n        .of-section--largetext__content {\n            grid-area: content;\n            @media (min-width: $ov--breakpoint--lg) {\n            max-width: 550px;\n            }\n        }\n        .of-button {\n            grid-area: action;\n        }\n        .large-text {\n            color: var(--of--color-brand--100);\n            \n            font-weight: 800;\n            @media (min-width: $ov--breakpoint--lg) {\n            text-transform: uppercase;\n            justify-self: start;\n            text-align: right;\n            grid-area: text;\n            font-size: 5rem;\n            margin-top: var(--of--spacer--md);\n                span {\n                    width: 100%;\n                    display: block;\n                    line-height: 0;\n                    margin-bottom: calc(var(--of--spacer--2xl) *2.25);\n                }\n            }\n            \n        }\n    }\n    \n}\n\n.of-docs-list {\n    padding: var(--of--spacer--3xl);\n}\n\n.of-masthead--subpage {\n    background: var(--of--color-black--100) url(\"/build/images/bg-masthead-SDK.svg\") no-repeat;\n    background-size: 250px;\n    background-position: 115% 0;\n    min-height:135px;\n    display: flex; \n    align-items: center;\n    padding: 0 var(--of--spacer--lg);\n    @media (min-width: $ov--breakpoint--lg) {\n        background-size: 400px auto;\n        background-position: right -85px;\n        padding: 0 calc(var(--of--spacer--2xl) + var(--of--spacer--xl));\n    }\n    \n    \n}\n\n.of-masthead {\n    .of-heading {\n        color: var(--of--color-white--100);\n    }\n}\n\n.of-capability-content, .of-capability-level__item {   \n    width: 100%;\n    padding: 0 var(--of--spacer--xl);\n    \n    @media (min-width: $ov--breakpoint--lg) { \n        padding: 0 calc(var(--of--spacer--2xl) + var(--of--spacer--xl)) var(--of--spacer--2xl) calc(var(--of--spacer--2xl) + var(--of--spacer--xl));\n    }\n    & > .of-heading {\n        margin-bottom: var(--of--spacer--md);\n        color: var(--of--color-brand--200);\n    }\n    &__model {\n        margin-bottom: var(--of--spacer--xl);\n        @media (min-width: $ov--breakpoint--lg) {\n        grid-template-columns: 1fr 1fr 1fr 1fr 1fr;\n        display: grid;\n        h4, p {\n            padding: 0 var(--of--spacer--sm);\n        } \n    }\n        width: 100%;\n        max-width: 1250px;\n        li {\n            position: relative;\n            margin-bottom: var(--of--spacer--md); \n            @media (min-width: $ov--breakpoint--lg) {\n                padding-top: calc(var(--of--spacer--3xl) + var(--of--spacer--sm));\n            }\n        }\n        h3 {\n            color: var(--of--color-white--100);\n            background: var(--of--color-brand--300);\n            min-width: max-content;\n            padding: var(--of--spacer--sm);\n            display: flex;\n            overflow: hidden;\n            width: 100%;\n            text-transform: capitalize;\n            letter-spacing: -1px;\n            @media (min-width: $ov--breakpoint--lg) { \n                padding: 0 var(--of--spacer--2xl) 0 var(--of--spacer--2xl) ;\n                position: absolute;\n                top: 0;\n                span {\n                position: relative;\n                z-index: 10000;\n                width: 100%;\n                background: inherit;\n                padding: var(--of--spacer--md) 0;\n            }\n            &:before {\n                content:'';\n                position: absolute;\n                right: 15px;\n                z-index: 1000;\n                align-self: center;\n                border-right: 10px solid var(--of--color-white--100);\n                border-bottom: 10px solid var(--of--color-white--100);\n                background: inherit;\n                width: 70px; \n                height: 70px;\n                transform: rotate(-45deg);\n            }\n            &:after {\n                content:'';\n                z-index: 1;\n                height: 100%;\n                top: 0;\n                background: inherit;\n                position: absolute;\n            }\n            }\n        }\n        @media (min-width: $ov--breakpoint--lg) {\n        li:not(:first-child) {\n            h4, p {\n                margin-left: calc(var(--of--spacer--lg) * -1);\n            }\n            p{\n                padding-right: var(--of--spacer--xl);\n            }\n        }\n        li:not(:last-child) {\n            h3:after {\n                left: 100px;\n                width: 150px;\n            }\n        }\n        }\n        li:first-child {\n            @media (min-width: $ov--breakpoint--lg) {\n            p {\n                padding-right: var(--of--spacer--2xl);\n            }\n        }\n            h3 {\n                background: #6cb1b6;\n                &:after {\n                    background:#318c96;\n                }\n            }\n        }\n        li:nth-child(2) {\n            h3 {\n                background:#318c96;\n                &:after {\n                    background:#0e6875;\n                }\n            }\n        }\n        li:nth-child(3) {\n            h3 {\n                background:#0e6875;\n                &:after {\n                    background:#0a4b53;\n                }\n            }\n        }\n        li:nth-child(4) {\n            h3 {\n                background:#0a4b53;\n                &:after {\n                    background:#052f35;\n                }\n            }\n        }\n        li:last-child {\n            h3 {\n                background: #052f35;\n                &:after {                    \n                    right: -5px;\n                    width: 40px;\n                    background: var(--of--color-white--100);\n                }\n            }\n        }\n    }\n    h4 {\n        text-transform: capitalize;\n        margin: var(--of--spacer--md) 0;\n    }\n    \n}\n\n.of-page--faq {\n    h3 {\n        color: var(--of--color-brand--200);\n        text-transform: uppercase;\n        font-weight: 800;\n        letter-spacing: 2px;\n        &:not(:first-of-type) {\n            margin-top: var(--of--spacer--xl);\n            padding-top: var(--of--spacer--xl);\n            border-top: 2px solid var(--of--color-white--200);\n        }\n    }\n    & > * {\n        margin-bottom: var(--of--spacer--md);\n    }\n}\n\n.of-page--capabilities {\n    .of-capability-content, .of-capability-level__item {\n        margin: var(--of--spacer--2xl) 0 var(--of--spacer--sm) ;\n        padding-bottom: var(--of--spacer--2xl);\n    }\n}\n  \n  .of-capability-level__table {\n    border: 1px solid var(--of--color-white--200);\n    border-collapse: collapse;\n    margin: var(--of--spacer--md) 0 var(--of--spacer--xl);\n    width: 100%;\n    table-layout: fixed;\n    &__level-1 {\n        th, td::before {\n            background: #6cb1b6;\n        }\n    }\n    &__level-2 {\n        th, td::before {\n            background: #318c96;\n        }\n    }\n    &__level-3 {\n        th, td::before {\n            background: #0e6875;\n        }\n    }\n    &__level-4 {\n        th, td::before {\n            background: #0a4b53;\n        }\n    }\n    &__level-5 {\n        th, td::before {\n            background: #052f35;\n        }\n    }\n       \n      @media (min-width: $ov--breakpoint--lg) {\n        tr {\n            border: 1px solid var(--of--color-white--200);\n            td:first-of-type {\n                border-right: 2px solid var(--of--color-white--200);\n            }\n            & > * {\n                padding: var(--of--spacer--md);\n            }\n          }\n          \n        th {\n            padding: var(--of--spacer--md) var(--of--spacer--lg);\n            color: var(--of--color-white--100);\n            text-transform: uppercase;\n            &:first-of-type {\n                border-right: 2px solid var(--of--color-white--200);\n            }\n          }\n      }\n      @media (max-width: $ov--breakpoint--lg) {\n         \n          border: 0;\n      \n         thead {\n          border: none;\n          clip: rect(0 0 0 0);\n          height: 1px;\n          margin: -1px;\n          overflow: hidden;\n          padding: 0;\n          position: absolute;\n          width: 1px;\n        }\n        \n         tr {\n          display: block;\n          margin-bottom: .625em;\n        }\n        \n         td {\n          display: block;\n          margin-bottom: var(--of--spacer--md);\n          & > * {\n              padding: 0 var(--of--spacer--md);\n              vertical-align: top;\n          }\n        }\n        \n         td::before {\n          content: attr(data-label);\n          font-weight: bold;\n          text-transform: uppercase;\n          display: block;\n          margin-bottom: var(--of--spacer--md);\n          background: var(--of--color-brand--200);\n          color: var(--of--color-white--100);\n          padding: var(--of--spacer--sm) var(--of--spacer--md);\n        }\n        \n      }\n      a[aria-describedby=\"footnote-label\"] {\n        counter-increment: footnotes; /* 1 */\n        text-decoration: none; /* 2 */\n        color: inherit; /* 2 */\n        cursor: default; /* 2 */\n        outline: none; /* 2 */\n      }\n      \n    \n      a[aria-describedby=\"footnote-label\"]::after {\n        content: '[' counter(footnotes) ']'; /* 1 */\n        vertical-align: super; /* 2 */\n        font-size: 0.5em; /* 3 */\n        margin-left: 2px; /* 4 */\n        color: var(--of--color-brand--100); /* 5 */\n        text-decoration: underline; /* 5 */\n        cursor: pointer; /* 5 */\n      }\n      \n    \n      a[aria-describedby=\"footnote-label\"]:focus::after {\n        outline: thin dotted;\n        outline-offset: 2px;\n      }\n  }\n  \n\n\n .of-capability-level__table__footnotes {\n    counter-reset: footnotes;\n  }\n  \n.of-table-footnotes {\n    margin-bottom: var(--of--spacer--lg);\n}\n  \n.td-search-result {\n    padding: var(--of--spacer--xl);\n    max-width: 100vw;\n}\n"
  },
  {
    "path": "website/assets/scss/_header.scss",
    "content": ".of-header-main {\n    position: fixed;\n    top: 0;\n    min-height: 72px;\n    z-index: 10000;\n    display: grid;\n    grid-template-columns: max-content 1fr max-content;\n    align-items: center;\n    grid-template-areas:\n    \"brand search search\"\n    \"nav nav nav\";\n    \n    @media (min-width: $ov--breakpoint--lg) {\n        display: flex;\n        align-items: center;\n    }\n\n    background: var(--of--color-black--300);\n    width: 100%;\n    .of-brand {\n        grid-area: brand;\n        display: flex;\n        margin: var(--of--spacer--sm);\n        \n        @media (min-width: $ov--breakpoint--lg) {\n          &__picture {\n            min-width: 177px;\n          }\n            margin: 0 var(--of--spacer--xl);\n        }\n    }\n    .of-header-main__search {\n        grid-area: search;\n        width: 80%;\n        display: flex;\n        align-items: center;\n        justify-self: center;\n        @media (min-width: $ov--breakpoint--lg) {\n          width: auto;\n            margin: 0 var(--of--spacer--lg) 0 auto;\n        }\n        &__input {\n            border-radius: var(--of--BorderRadius--lg);\n            border: none;\n            width: 100%;\n            // padding: 0 var(--of--spacer--sm);\n            background: var(--of--color-white--100);\n        }\n    }\n}\n\n.of-nav-main {\n    grid-area: nav;\n  width: 100%;\n  @media (min-width: $ov--breakpoint--lg) {\n    width: auto;\n}\n&__items {\n  display: flex;\n  justify-content: space-around;\n\n}\n    .of-link-list {\n        display: grid;\n        grid-template-columns: 1fr 1fr;\n        grid-template-rows: min-content min-content;\n        @media (min-width: $ov--breakpoint--lg) {\n            display: flex; \n            margin: 0;   \n        }\n        \n        &__li {\n            @media (min-width: $ov--breakpoint--lg) {\n                border: none;\n            }\n            border: 1px solid var(--of--color-black--200);\n            &:nth-of-type(even),&:nth-of-type(odd) {\n                border-left: none;\n            }\n            &:nth-of-type(even) {\n                border-right: none;\n            }\n            &:not(:last-of-type):not(:nth-last-child(-n+2)){\n                border-bottom: none;\n            }\n                \n        }\n        &__a {\n            width: 100%;            \n            display: inline-block;\n            position: relative;\n            padding: var(--of--spacer--xs) var(--of--spacer--md);\n            transition: background .25s linear;\n            color: var(--of--color-white--100);\n            min-height: 45px;\n            @media (min-width: $ov--breakpoint--lg) {\n                width: auto;\n                padding: var(--of--spacer--lg) .9vw;\n                &.of-m-active, &:focus, &:hover {\n                  text-decoration: none;\n                  background: var(--of--color-brand--100);\n              }\n            }\n            // &.has-dropdown {\n            //   grid-area: link;\n            // }\n            \n        }\n    }\n}"
  },
  {
    "path": "website/assets/scss/_homepage.scss",
    "content": ".of-masthead--home {   \n    background: var(--of--color-black--100) url(\"/build/images/bg-masthead-SDK.svg\") no-repeat;\n    background-position: -22vw -30vw ;\n    background-size: 70% auto;\n    padding: calc(2 * var(--of--spacer--2xl)) var(--of--spacer--md) var(--of--spacer--xl);\n    @media (min-width: $ov--breakpoint--sm) {\n    background-position:-35vw 50.5%;\n    background-size: 100% auto;\n    display: grid;\n    grid-template-columns: 2fr 1fr 1fr 1fr;\n    grid-template-areas:\n    \". title title title\"\n    \". content content content\"\n    \". action-1 action-2 .\"\n    }\n    @media (min-width: $ov--breakpoint--lg) {\n        padding: var(--of--spacer--2xl) calc(var(--of--spacer--3xl) + var(--of--spacer--md))  var(--of--spacer--2xl);\n    }\n    .of-heading {\n        color: var(--of--color-white--100);\n        letter-spacing: normal;\n    }\n    &__title {\n        display: flex;\n        flex-direction: column;\n        line-height: 3rem;\n        font-weight: normal;\n        grid-area: title;\n        span {\n            &:first-of-type {\n                font-size: 2.625rem;\n            }\n            &:last-of-type {\n                font-size: 3.5625rem;\n            }\n        }\n    }\n    &__content {\n        @media (min-width: $ov--breakpoint--sm) {\n            max-width: 55vw;\n            margin: var(--of--spacer--xl) 0;\n        }\n        grid-area: content;\n        margin: var(--of--spacer--md) 0;\n        text-transform: none;\n    }\n    .of-button {\n        justify-self: start;\n        white-space: nowrap;\n        &:first-of-type {\n            grid-area: action-1;\n            margin-bottom: var(--of--spacer--md);\n        }\n        &+.of-button {\n            grid-area: action-2;\n        }\n    }\n}\n\n.of-section-page-intro {\n    display: flex;\n    flex-wrap: wrap;\n\n    &__header {\n        background: var(--of--color-white--200);\n        padding: var(--of--spacer--lg);\n        \n        @media (min-width: $ov--breakpoint--lg) {\n                padding: var(--of--spacer--2xl) 0 var(--of--spacer--2xl) calc(var(--of--spacer--2xl) + var(--of--spacer--xl));\n            &--overlay {\n                padding-bottom: calc(var(--of--spacer--3xl) + var(--of--spacer--3xl));\n                margin-bottom: calc(calc(var(--of--spacer--3xl) + var(--of--spacer--md) + 1px) * -1);\n            }\n        }\n        width: 100%;\n        & > * {\n            @media (min-width: $ov--breakpoint--lg) {\n                max-width: 55vw;\n            }\n        }\n        .of-heading {\n            color: var(--of--color-brand--200);\n        }\n    }\n    .of-heading {\n        margin-bottom: var(--of--spacer--sm);\n    }\n    &__content {\n        background: var(--of--color-white--100);\n        margin: var(--of--spacer--lg);\n        padding-bottom: var(--of--spacer--lg);\n        &:not(&--overlay){\n            &__columns {\n                padding: var(--of--spacer--lg);\n            }\n        }\n         \n        @media (min-width: $ov--breakpoint--lg) {\n            margin: var(--of--spacer--xl) calc(var(--of--spacer--2xl) + var(--of--spacer--xl)) var(--of--spacer--2xl) calc(var(--of--spacer--2xl) + var(--of--spacer--xl));\n            &--overlay {\n                border: 1px solid var(--of--color-white--200);\n                padding: var(--of--spacer--lg);\n                margin-top: 0;\n            }\n            &__columns {\n                column-count: 2;\n            column-gap: calc(var(--of--spacer--2xl) * 2);\n            margin-bottom: calc(var(--of--spacer--md) * -1);\n            padding-bottom: var(--of--spacer--xl);\n                > * {\n                    margin-bottom: var(--of--spacer--md);\n                }\n            }\n             \n        }\n    }\n    &__footer {\n        padding: 0 var(--of--spacer--xl) var(--of--spacer--xl);\n        @media (min-width: $ov--breakpoint--lg) {\n            padding: 0 calc(var(--of--spacer--2xl) + var(--of--spacer--xl)) var(--of--spacer--2xl)  calc(var(--of--spacer--2xl) + var(--of--spacer--xl));\n        }\n    }\n    &__items {\n        @media (min-width: $ov--breakpoint--lg) {\n            display: grid;\n            grid-template-columns: 1fr 1fr 1fr;\n            margin: 0 var(--of--spacer--2xl);\n        }\n        \n    }\n\n    &__item {\n        background: var(--of--color-white--100);\n        &__build {\n            .of-heading {\n                background: var(--of--color-brand--100);\n            }\n        }\n        &__manage {\n            .of-heading {\n                background: var(--of--color-brand--200);\n            }\n        }\n        &__discover {\n            .of-heading {\n                background: var(--of--color-brand--300);\n            }\n        }\n        &__content {\n            padding: var(--of--spacer--lg);\n            display: flex;\n            flex-direction: column;\n        }\n        .of-heading {\n            color: var(--of--color-white--100);\n            padding:var(--of--spacer--lg) var(--of--spacer--md);\n        }\n    }\n\n}\n\n.of-section-page-message {\n    background: var(--of--color-black--300);\n    color: #fff;\n    display: flex;\n    text-align: center;\n    flex-direction: column;\n    justify-content: center;\n    padding: var(--of--spacer--xl);\n    &__title {\n        margin-bottom: var(--of--spacer--md);\n    }\n\n}"
  },
  {
    "path": "website/assets/scss/_reset.scss",
    "content": "// Reset\n    html,\n    body,\n    p,\n    ol,\n    ul,\n    li,\n    dl,\n    dt,\n    dd,\n    blockquote,\n    figure,\n    fieldset,\n    legend,\n    textarea,\n    pre,\n    iframe,\n    hr,\n    h1,\n    h2,\n    h3,\n    h4,\n    h5,\n    h6 {\n      padding: 0;\n      margin: 0;\n    }\n  \n    html,\n    body {\n      height: 100%;\n    }\n  \n    h1,\n    h2,\n    h3,\n    h4,\n    h5,\n    h6 {\n      font-size: 100%;\n      font-weight: normal;\n    }\n  \n    ul {\n      list-style: none;\n    }\n  \n    button,\n    input,\n    optgroup,\n    select,\n    textarea {\n      margin: 0;\n      font-family: inherit;\n      font-size: 100%;\n      line-height: 1.5;\n    }\n  \n    img,\n    embed,\n    iframe,\n    object,\n    audio,\n    video {\n      max-width: 100%;\n      height: auto;\n    }\n  \n    iframe {\n      border: 0;\n    }\n  \n    table {\n      border-spacing: 0;\n      border-collapse: collapse;\n    }\n  \n    td,\n    th {\n      padding: 0;\n      text-align: left;\n    }\n    \n    *,\n    *::before,\n    *::after {\n      box-sizing: border-box;\n    }\n  \n  \n    body {\n      font-family:var(--of--font-family); \n      font-size: var(--of--FontSize--sm);\n      font-weight: normal;\n      line-height: 1.5;\n      text-align: left;\n      color: var(--of--color-black--100);\n    }\n  \n  a{\n    color: var(--of--color-brand--100);\n    text-decoration: none;\n    &:hover {\n      text-decoration: underline;\n    }\n  }\n  // a, a:before, a:after, button, button:before, button:after {\n  //     transition: var(--of--animation);\n  // }\n    button,\n    a {\n      cursor: pointer;\n    }\n  \n    button,\n    [type=\"button\"],\n    [type=\"reset\"],\n    [type=\"submit\"] {\n      // Remove the inner border and padding in Firefox.\n      &::-moz-focus-inner {\n        padding: 0;\n        border-style: none;\n      }\n  \n      // Restore the focus styles unset by the previous rule.\n      &:-moz-focusring {\n        outline: 1px dotted ButtonText;\n      }\n    }"
  },
  {
    "path": "website/assets/scss/_sidebar-tree.scss",
    "content": ".td-sidebar-nav {\n    padding-right: 0.5rem;\n    margin-right: -15px;\n    margin-left: -15px;\n\n    @include media-breakpoint-up(md) {\n        @supports (position: sticky) {\n            max-height: calc(100vh - 4rem);\n            overflow-y: auto;\n        }\n    }\n\n\n    @include media-breakpoint-up(md) {\n        display: block !important;\n    }\n\n\n    &__section {\n        li {\n            list-style: none;\n        }\n\n        ul {\n            padding: 0;\n            margin: 0;\n        }\n\n        @include media-breakpoint-up(md) {\n            & > ul {\n                padding-left: .5rem;\n            }\n        }\n\n\n        padding-left: 0;\n    }\n\n    &__section-title {\n        display: block;\n        font-weight: 550;\n\n        .active {\n            font-weight: 800;\n            color: $gray-900;\n        }\n\n        a {\n            color: $gray-700;\n        }\n    }\n\n    .td-sidebar-link {\n        display: block;\n        padding-bottom: 0.375rem;\n\n        &__page {\n            color: $gray-600;\n            font-weight: $font-weight-light;\n        }\n    }\n\n    a {\n        &:hover {\n            color: $blue;\n            text-decoration: none;\n        }\n\n        &.active {\n            font-weight: 800;\n            color: $gray-800;\n            \n        }\n    }\n\n    .dropdown {\n        a {\n            color: $gray-700;\n        }\n\n        .nav-link {\n             padding: 0 0 1rem;\n        }\n    }\n}\n\n.td-sidebar {\n    padding-top: 4rem;\n    margin-bottom: var(--of--spacer--md);\n    display:flex;\n    justify-content: center;\n    background: var(--of--color-white--200);\n    span {\n        margin-left: var(--of--spacer--md);\n        font-family: var(--of--font-family);\n    }\n    @include media-breakpoint-up(md) {\n        padding-top: var(--of--spacer--md);\n        padding-bottom: 4rem;\n        background-color: $td-sidebar-bg-color;\n        margin-bottom: 0;\n        padding-right: 1rem;\n        border-right: 1px solid $td-sidebar-border-color;\n    }\n\n    &__toggle {\n        line-height: 1;\n        color: $gray-900;\n        margin: 1rem;\n    }\n\n    &__search {\n        padding: 1rem 15px;\n        margin-right: -15px;\n        margin-left: -15px;\n    }\n\n    &__inner {\n        order: 0;\n\n        @include media-breakpoint-up(md) {\n            @supports (position: sticky) {\n                position: sticky;\n                top:71px;\n                z-index: 10;\n                height: calc(100vh - 6rem);\n            }\n        }\n\n\n        @include media-breakpoint-up(xl) {\n            flex: 0 1 320px;\n        }\n\n\n        .td-search-box {\n            width: 100%;\n        }\n\n        &__heading {\n            padding: var(--of--spacer--md);\n            background: var(--of--color-brand--300);\n            color: var(--of--color-white--100);\n            margin-left: -15px;\n            margin-right: -15px;\n        }\n    }\n}"
  },
  {
    "path": "website/assets/scss/_styles_project.scss",
    "content": "@import \"../../themes/docsy/assets/scss/support/functions\";\n@import \"../../themes/docsy/assets/scss/variables\";\n@import \"../../themes/docsy/assets/scss/support/mixins\";\n\n@import \"../../themes/docsy/assets/vendor/bootstrap/scss/bootstrap\";\n\n@import \"../../themes/docsy/assets/vendor/Font-Awesome/scss/fontawesome.scss\";\n@import \"../../themes/docsy/assets/vendor/Font-Awesome/scss/solid.scss\";\n@import \"../../themes/docsy/assets/vendor/Font-Awesome/scss/brands.scss\";\n\n@import \"../../themes/docsy/assets/scss/support/utilities\";\n@import \"../../themes/docsy/assets/scss/colors\";\n@import \"../../themes/docsy/assets/scss/boxes\";\n@import \"../../themes/docsy/assets/scss/blog\";\n@import \"../../themes/docsy/assets/scss/code\";\n@import \"../../themes/docsy/assets/scss/nav\";\n@import \"../../themes/docsy/assets/scss/sidebar-toc\";\n@import \"../../themes/docsy/assets/scss/buttons\";\n@import \"../../themes/docsy/assets/scss/alerts\";\n@import \"../../themes/docsy/assets/scss/content\";\n@import \"../../themes/docsy/assets/scss/search\";\n@import \"../../themes/docsy/assets/scss/main-container\";\n@import \"../../themes/docsy/assets/scss/blocks/blocks\";\n@import \"../../themes/docsy/assets/scss/section-index\";\n@import \"../../themes/docsy/assets/scss/pageinfo\";\n\n@if $td-enable-google-fonts {\n    @import url($web-font-path);\n}\n\nfooter {\n    min-height: 150px;\n\n    @include media-breakpoint-down(md) {\n         min-height: 200px;\n    }\n}\n\n// Adjust anchors vs the fixed menu.\n@include media-breakpoint-up(md) {\n    .td-offset-anchor:target {\n        display: block;\n        position: relative;\n        top: -4rem;\n        visibility: hidden;\n    }\n\n    h2[id]:before, h3[id]:before, h4[id]:before, h5[id]:before {\n        display: block;\n        content: \" \";\n        margin-top: -5rem;\n        height: 5rem;\n        visibility: hidden;\n    }\n}\n\n\n@import \"functions\";\n@import \"variables\";\n@import \"reset\";\n@import \"type\";\n@import \"sidebar-tree\";\n@import \"breadcrumb\";\n\n//components\n@import \"header\";\n@import \"footer\";\n\n//layout\n@import \"homepage\";\n@import \"docs\";\n\n//global\n@import \"global\";\n"
  },
  {
    "path": "website/assets/scss/_type.scss",
    "content": "//type\n.of-heading {\n    color: var(--of--Color--brand--200);\n    text-transform: uppercase;\n    font-weight: 800;\n    letter-spacing: 2px;\n}\n.of-heading--secondary {\n    color: var(--of--color-brand--200);\n    margin-bottom: var(--of--spacer--md);\n}\n.of-heading--xs, .of-heading--sm {\n    font-size: var(--of--FontSize--xs);\n}\n.of-heading--md {\n    font-size: var(--of--FontSize--sm);\n}\n.of-heading--lg {\n    font-size: var(--of--FontSize--md);\n}\n.of-heading--xl {\n    font-size: var(--of--FontSize--md);\n}\n.of-heading--2xl {\n    font-size: var(--of--FontSize--lg);\n}\n\n@media (min-width: $ov--breakpoint--lg) {\n    .of-heading--xs {\n        font-size: var(--of--FontSize--xs);\n    }\n    .of-heading--sm {\n        font-size: var(--of--FontSize--sm);\n    }\n    .of-heading--md {\n        font-size: var(--of--FontSize--md);\n    }\n    .of-heading--lg {\n        font-size: var(--of--FontSize--lg);\n    }\n    .of-heading--xl {\n        font-size: var(--of--FontSize--xl);\n    }\n    .of-heading--2xl {\n        font-size: var(--of--FontSize--2xl);\n    }\n}"
  },
  {
    "path": "website/assets/scss/_variables.scss",
    "content": ":root {\n    //type\n    --of--font-family: 'overpass', sans-serif;\n    --of--FontSize--xs:  .875rem; //14\n    --of--FontSize--sm:  1rem; //16\n    --of--FontSize--md:  1.125rem; //18\n    --of--FontSize--lg:  1.375rem; //22\n    --of--FontSize--xl:  1.5rem;//24\n    --of--FontSize--2xl: 2.625rem; //40\n  \n    //spacers\n    --of--spacer--xs:  .25rem; //4  purple\n    --of--spacer--sm:  .5rem; //8  light blue\n    --of--spacer--md:  1rem; //16  green\n    --of--spacer--lg:  1.5rem; //24  yellow\n    --of--spacer--xl:  2rem; //32  pink\n    --of--spacer--2xl: 3rem; //48 blue\n    --of--spacer--3xl:  4rem; //64  purple\n  \n    //color\n    --of--color-brand--50: #73C5C5;\n    --of--color-brand--100: #009596;\n    --of--color-brand--200: #005F60;\n    --of--color-brand--300: #003737;\n    --of--color-brand--400: #001F22;\n    --of--color-white--100: #FFF;\n    --of--color-white--150: #F0F0F0;\n    --of--color-white--200: #EDEDED;\n    --of--color-blue--100:  #dfe7f4;\n    --of--color-blue--200:  #cad3e5;\n    --of--color-grey--100:  #979797;\n    --of--color-grey--200:  #666;\n    --of--color-black--100: #040404;\n    --of--color-black--200: #202020;\n    --of--color-black--300: #000;\n  \n    //transparencies\n    --of--color-transparent-background--100: rgba(32,32,32,.90);\n  \n    //borders\n    --of--BorderWidth--sm: 2px;\n    --of--BorderWidth--lg: 4px;\n    --of--BorderRadius--sm: .1875rem;\n    --of--BorderRadius--md: .75rem;\n    --of--BorderRadius--lg: 40rem;\n   \n    //text\n    --of--Color--100: var(--of--color-white--100);\n    --of--Color--200: var(--of--color-white--200);\n    --of--Color--300: var(--of--color-brand--100);\n    --of--Color--400: var(--of--color-black--200);\n    --of--Color--500: var(--of--color-brand--400);\n    --of--Color--600: var(--of--color-brand--300);\n  \n  \n    --of--LineHeight--sm: 1.3;\n    --of--LineHeight--lg: 1.5;\n  \n    --of--FontWeight--100: 400;\n    --of--FontWeight--200: 700;\n  \n    //animation\n    --of--animation: all .15s linear;\n  \n    //shadows\n    --of--BoxShadow--sm: 0px 1px 4px rgba(0,0,0,0.5);\n  \n        //misc\n        --of--menu-offset: 56px;\n  }\n    //media queries (no custom properties as MQs :(\n      $ov--breakpoint--xs: 0;\n      $ov--breakpoint--sm: 576px;\n      $ov--breakpoint--md: 768px;\n      $ov--breakpoint--lg: 992px;\n      $ov--breakpoint--xl: 1200px;\n      $ov--breakpoint--2xl: 1450px;\n\n"
  },
  {
    "path": "website/config.toml",
    "content": "baseURL = \"/\"\nlanguageCode = \"en-us\"\ntitle = \"Operator SDK\"\n\n# Hugo allows theme composition (and inheritance). The precedence is from left to right.\ntheme = [\"docsy\"]\n\nenableRobotsTXT = true\n\n# Will give values to .Lastmod etc.\nenableGitInfo = true\n\n# Ignore drafts\nignoreFiles = [\"docs/kubebuilder\"]\n\n# Language settings\ncontentDir = \"content/en\"\ndefaultContentLanguage = \"en\"\ndefaultContentLanguageInSubdir = false\n# Useful when translating.\nenableMissingTranslationPlaceholders = true\n\ndisableKinds = [\"taxonomy\", \"taxonomyTerm\"]\n\n# Highlighting config\npygmentsCodeFences = true\npygmentsUseClasses = false\n# Use the new Chroma Go highlighter in Hugo.\npygmentsUseClassic = false\n#pygmentsOptions = \"linenos=table\"\n# See https://help.farbox.com/pygments.html\npygmentsStyle = \"tango\"\n\n# Configure how URLs look like per section.\n# [permalinks]\n# blog = \"/:section/:year/:month/:day/:slug/\"\n\n## Configuration for Goldmark markdown parser: https://github.com/yuin/goldmark\n[markup]\n  [markup.goldmark]\n    [markup.goldmark.renderer]\n      unsafe = true\n\n# Image processing configuration.\n[imaging]\nresampleFilter = \"CatmullRom\"\nquality = 75\nanchor = \"smart\"\n\n# [services]\n# [services.googleAnalytics]\n# Comment out the next line to disable GA tracking. Also disables the feature described in [params.ui.feedback].\n# id = \"UA-00000000-0\"\n\n# Language configuration\n[languages]\n[languages.en]\ndescription = \"Go, Ansible, or Helm SDK to simplify the implementation of the operator pattern\"\nlanguageName =\"English\"\n# Weight used for sorting.\nweight = 1\n\n# Everything below this are Site Params\n\n[params]\ncopyright = \"The Operator SDK Authors\"\n# privacy_policy = \"https://policies.google.com/privacy\"\n\n# First one is picked as the Twitter card image if not set on page.\n# images = [\"images/project-illustration.png\"]\n\n# Menu title if your navbar has a versions selector to access old versions of your site.\n# This menu appears only if you have at least one [params.versions] set.\nversion_menu = \"Releases\"\n\n# Repository configuration (URLs for in-page links to opening issues and suggesting changes)\ngithub_repo = \"https://github.com/operator-framework/operator-sdk\"\n\n# Specify a value here if your content directory is not in your repo's root directory\ngithub_subdir = \"website\"\n\n\n\n# Enable Algolia DocSearch\nalgolia_docsearch = true\n\n# Update archived_version to true when this version is no longer supported. `version` is only used by the archived banner.\nversion = \"FIXME_when_archived\"\narchived_version = false\nurl_latest_version = \"https://sdk.operatorframework.io\"\n\n[[params.versions]]\n  version = \"master\"\n  url = \"https://master.sdk.operatorframework.io\"\n  ##LATEST_RELEASE_KUBE_VERSION##\n  kube_version = \"1.33.1\"\n  ##LATEST_RELEASE_CLIENT_GO_VERSION##\n  client_go_version = \"v0.33.9\"\n\n[[params.versions]]\n  version = \"Latest Release\"\n  url = \"https://sdk.operatorframework.io\"\n  ##LATEST_RELEASE_KUBE_VERSION##\n  kube_version = \"1.33.1\"\n  ##LATEST_RELEASE_CLIENT_GO_VERSION##\n  client_go_version = \"v0.33.9\"\n\n##RELEASE_ADDME##\n\n[[params.versions]]\n  version = \"v1.42\"\n  url = \"https://v1-42-x.sdk.operatorframework.io\"\n  kube_version = \"1.33.1\"\n  client_go_version = \"v0.33.5\"\n\n[[params.versions]]\n  version = \"v1.41\"\n  url = \"https://v1-41-x.sdk.operatorframework.io\"\n  kube_version = \"1.33.1\"\n  client_go_version = \"v0.33.2\"\n\n[[params.versions]]\n  version = \"v1.40\"\n  url = \"https://v1-40-x.sdk.operatorframework.io\"\n  kube_version = \"1.32.0\"\n  client_go_version = \"v0.32.4\"\n\n[[params.versions]]\n  version = \"v1.39\"\n  url = \"https://v1-39-x.sdk.operatorframework.io\"\n  kube_version = \"1.31.0\"\n  client_go_version = \"v0.31.4\"\n\n[[params.versions]]\n  version = \"v1.38\"\n  url = \"https://v1-38-x.sdk.operatorframework.io\"\n  kube_version = \"1.30.0\"\n  client_go_version = \"v0.30.5\"\n\n[[params.versions]]\n  version = \"v1.37\"\n  url = \"https://v1-37-x.sdk.operatorframework.io\"\n  kube_version = \"1.29.0\"\n  client_go_version = \"v0.29.3\"\n\n[[params.versions]]\n  version = \"v1.36\"\n  url = \"https://v1-36-x.sdk.operatorframework.io\"\n  kube_version = \"1.29.0\"\n  client_go_version = \"v0.29.3\"\n\n[[params.versions]]\n  version = \"v1.35\"\n  url = \"https://v1-35-x.sdk.operatorframework.io\"\n  kube_version = \"1.28.0\"\n  client_go_version = \"v0.28.5\"\n\n[[params.versions]]\n  version = \"v1.34\"\n  url = \"https://v1-34-x.sdk.operatorframework.io\"\n  kube_version = \"1.28.0\"\n  client_go_version = \"v0.28.5\"\n\n[[params.versions]]\n  version = \"v1.33\"\n  url = \"https://v1-33-x.sdk.operatorframework.io\"\n  kube_version = \"1.27.0\"\n  client_go_version = \"v0.27.8\"\n\n[[params.versions]]\n  version = \"v1.32\"\n  url = \"https://v1-32-x.sdk.operatorframework.io\"\n  kube_version = \"1.26.0\"\n  client_go_version = \"v0.26.2\"\n\n[[params.versions]]\n  version = \"v1.31\"\n  url = \"https://v1-31-x.sdk.operatorframework.io\"\n  kube_version = \"1.26.0\"\n  client_go_version = \"v0.26.2\"\n\n[[params.versions]]\n  version = \"v1.30\"\n  url = \"https://v1-30-x.sdk.operatorframework.io\"\n  kube_version = \"1.26.0\"\n  client_go_version = \"v0.26.2\"\n\n[[params.versions]]\n  version = \"v1.29\"\n  url = \"https://v1-29-x.sdk.operatorframework.io\"\n  kube_version = \"1.26.0\"\n  client_go_version = \"v0.26.2\"\n\n[[params.versions]]\n  version = \"v1.28\"\n  url = \"https://v1-28-x.sdk.operatorframework.io\"\n  kube_version = \"1.26.0\"\n  client_go_version = \"v0.26.2\"\n\n[[params.versions]]\n  version = \"v1.27\"\n  url = \"https://v1-27-x.sdk.operatorframework.io\"\n  kube_version = \"1.25.0\"\n  client_go_version = \"v0.25.3\"\n\n[[params.versions]]\n  version = \"v1.26\"\n  url = \"https://v1-26-x.sdk.operatorframework.io\"\n  kube_version = \"1.25.0\"\n  client_go_version = \"v0.25.3\"\n\n[[params.versions]]\n  version = \"v1.25\"\n  url = \"https://github.com/operator-framework/operator-sdk/tree/v1.25.x/website/content/en/docs\"\n  kube_version = \"1.25.0\"\n  client_go_version = \"v0.25.3\"\n\n[[params.versions]]\n  version = \"v1.24\"\n  url = \"https://github.com/operator-framework/operator-sdk/tree/v1.24.x/website/content/en/docs\"\n  kube_version = \"1.24.2\"\n  client_go_version = \"v0.24.2\"\n\n[[params.versions]]\n  version = \"v1.23\"\n  url = \"https://github.com/operator-framework/operator-sdk/tree/v1.23.x/website/content/en/docs\"\n  kube_version = \"1.24.2\"\n  client_go_version = \"v0.24.2\"\n\n[[params.versions]]\n  version = \"v1.22\"\n  url = \"https://github.com/operator-framework/operator-sdk/tree/v1.22.x/website/content/en/docs\"\n  kube_version = \"1.24.1\"\n  client_go_version = \"v0.24.0\"\n\n[[params.versions]]\n  version = \"v1.21\"\n  url = \"https://github.com/operator-framework/operator-sdk/tree/v1.21.x/website/content/en/docs\"\n  kube_version = \"1.23\"\n  client_go_version = \"v0.23.5\"\n\n[[params.versions]]\n  version = \"v1.20\"\n  url = \"https://github.com/operator-framework/operator-sdk/tree/v1.20.x/website/content/en/docs\"\n  kube_version = \"1.23\"\n  client_go_version = \"v0.23.1\"\n\n[[params.versions]]\n  version = \"v1.19\"\n  url = \"https://github.com/operator-framework/operator-sdk/tree/v1.19.x/website/content/en/docs\"\n  kube_version = \"1.23\"\n  client_go_version = \"v0.23.1\"\n\n[[params.versions]]\n  version = \"v1.18\"\n  url = \"https://github.com/operator-framework/operator-sdk/tree/v1.18.x/website/content/en/docs\"\n  kube_version = \"1.21\"\n  client_go_version = \"v0.23.1\"\n\n[[params.versions]]\n  version = \"v1.17\"\n  url = \"https://github.com/operator-framework/operator-sdk/tree/v1.17.x/website/content/en/docs\"\n  kube_version = \"1.21\"\n  client_go_version = \"v0.23.1\"\n\n[[params.versions]]\n  version = \"v1.16\"\n  url = \"https://github.com/operator-framework/operator-sdk/tree/v1.16.x/website/content/en/docs\"\n  kube_version = \"1.21\"\n  client_go_version = \"v0.22.2\"\n\n[[params.versions]]\n  version = \"v1.15\"\n  url = \"https://github.com/operator-framework/operator-sdk/tree/v1.15.x/website/content/en/docs\"\n  kube_version = \"1.21\"\n  client_go_version = \"v0.22.2\"\n\n[[params.versions]]\n  version = \"v1.14\"\n  url = \"https://github.com/operator-framework/operator-sdk/tree/v1.14.x/website/content/en/docs\"\n  kube_version = \"1.21\"\n  client_go_version = \"v0.22.2\"\n\n[[params.versions]]\n  version = \"v1.13\"\n  url = \"https://github.com/operator-framework/operator-sdk/tree/v1.13.x/website/content/en/docs\"\n  kube_version = \"1.21\"\n  client_go_version = \"v0.22.1\"\n\n[[params.versions]]\n  version = \"v1.12\"\n  url = \"https://github.com/operator-framework/operator-sdk/tree/v1.12.x/website/content/en/docs\"\n  kube_version = \"1.21\"\n  client_go_version = \"v0.21.2\"\n\n[[params.versions]]\n  version = \"v1.11\"\n  url = \"https://github.com/operator-framework/operator-sdk/tree/v1.11.x/website/content/en/docs\"\n  kube_version = \"1.20.2\"\n  client_go_version = \"v0.21.2\"\n\n[[params.versions]]\n  version = \"v1.10\"\n  url = \"https://github.com/operator-framework/operator-sdk/tree/v1.10.x/website/content/en/docs\"\n  kube_version = \"1.20.2\"\n  client_go_version = \"v0.21.2\"\n\n[[params.versions]]\n  version = \"v1.9\"\n  url = \"https://github.com/operator-framework/operator-sdk/tree/v1.9.x/website/content/en/docs\"\n  kube_version = \"1.20.2\"\n  client_go_version = \"v0.20.2\"\n\n[[params.versions]]\n  version = \"v1.8\"\n  url = \"https://github.com/operator-framework/operator-sdk/tree/v1.8.x/website/content/en/docs\"\n  kube_version = \"1.20.2\"\n  client_go_version = \"v0.20.2\"\n\n[[params.versions]]\n  version = \"v1.7\"\n  url = \"https://github.com/operator-framework/operator-sdk/tree/v1.7.x/website/content/en/docs\"\n  kube_version = \"1.19.4\"\n  client_go_version = \"v0.20.2\"\n\n[[params.versions]]\n  version = \"v1.6\"\n  url = \"https://github.com/operator-framework/operator-sdk/tree/v1.6.x/website/content/en/docs\"\n  kube_version = \"1.19.4\"\n  client_go_version = \"v0.20.2\"\n\n[[params.versions]]\n  version = \"v1.5\"\n  url = \"https://github.com/operator-framework/operator-sdk/tree/v1.5.x/website/content/en/docs\"\n  kube_version = \"1.19.4\"\n  client_go_version = \"v0.20.2\"\n\n[[params.versions]]\n  version = \"v1.4\"\n  url = \"https://github.com/operator-framework/operator-sdk/tree/v1.4.x/website/content/en/docs\"\n  kube_version = \"1.19.4\"\n  client_go_version = \"v0.20.1\"\n\n[[params.versions]]\n  version = \"v1.3\"\n  url = \"https://github.com/operator-framework/operator-sdk/tree/v1.3.x/website/content/en/docs\"\n  kube_version = \"1.19.4\"\n  client_go_version = \"v0.19.4\"\n\n[[params.versions]]\n  version = \"v1.2\"\n  url = \"https://github.com/operator-framework/operator-sdk/tree/v1.2.x/website/content/en/docs\"\n  kube_version = \"1.18.8\"\n  client_go_version = \"v0.18.8\"\n\n[[params.versions]]\n  version = \"v1.1\"\n  url = \"https://github.com/operator-framework/operator-sdk/tree/v1.1.x/website/content/en/docs\"\n  kube_version = \"1.18.2\"\n  client_go_version = \"v0.18.8\"\n\n[[params.versions]]\n  version = \"v1.0\"\n  url = \"https://github.com/operator-framework/operator-sdk/tree/v1.0.x/website/content/en/docs\"\n  kube_version = \"1.18.2\"\n  client_go_version = \"v0.18.6\"\n\n[[params.versions]]\n  version = \"v0.19\"\n  url = \"https://github.com/operator-framework/operator-sdk/tree/v0.19.x/website/content/en/docs\"\n  kube_version = \"1.18.2\"\n  client_go_version = \"v12.0.0+incompatible\"\n\n[[params.versions]]\n  version = \"v0.18\"\n  url = \"https://github.com/operator-framework/operator-sdk/tree/v0.18.x/website/content/en/docs\"\n  kube_version = \"1.18.2\"\n  client_go_version = \"v12.0.0+incompatible\"\n\n[[params.versions]]\n  version = \"v0.17\"\n  url = \"https://github.com/operator-framework/operator-sdk/tree/v0.17.x/doc\"\n  kube_version = \"1.17.2\"\n  client_go_version = \"v12.0.0+incompatible\"\n\n# User interface configuration\n[params.ui]\n# Enable to show the side bar menu in its compact state.\nsidebar_menu_compact = true\n#  Set to true to disable breadcrumb navigation.\nbreadcrumb_disable = false\n#  Set to true to hide the sidebar search box (the top nav search box will still be displayed if search is enabled)\nsidebar_search_disable = true\n#  Set to false if you don't want to display a logo (/assets/icons/logo.svg) in the top nav bar\nnavbar_logo = true\n\n# Adds a H2 section titled \"Feedback\" to the bottom of each doc. The responses are sent to Google Analytics as events.\n# This feature depends on [services.googleAnalytics] and will be disabled if \"services.googleAnalytics.id\" is not set.\n# If you want this feature, but occasionally need to remove the \"Feedback\" section from a single page,\n# add \"hide_feedback: true\" to the page's front matter.\n[params.ui.feedback]\nenable = true\n# The responses that the user sees after clicking \"yes\" (the page was helpful) or \"no\" (the page was not helpful).\nyes = 'Glad to hear it! Please <a href=\"https://github.com/operator-framework/operator-sdk/issues/new\">tell us how we can improve</a>.'\nno = 'Sorry to hear that. Please <a href=\"https://github.com/operator-framework/operator-sdk/issues/new\">tell us how we can improve</a>.'\n\n[params.links]\n# End user relevant links. These will show up on left side of footer and in the community page if you have one.\n[[params.links.social]]\n\tname = \"Forum\"\n\turl = \"https://groups.google.com/forum/#!forum/operator-framework\"\n\ticon = \"fas fa-comment\"\n\n#[[params.links.social]]\n#\tname = \"twitter\"\n#\turl = \"https://example.org/mail\"\n#\ticon = \"fab fa-twitter\"\n\n#[[params.links.social]]\n#\tname = \"youtube\"\n#\turl = \"https://example.org/mail\"\n#\ticon = \"fab fa-youtube\"\n\n[[params.links.social]]\n\tname = \"github\"\n\turl = \"https://github.com/operator-framework/operator-sdk\"\n\ticon = \"fab fa-github\"\n\n#[[params.links.social]]\n#\tname = \"slack\"\n#\turl = \"https://example.org/mail\"\n#\ticon = \"fab fa-slack\"\n"
  },
  {
    "path": "website/content/en/_index.html",
    "content": "+++\ntitle = \"Operator SDK\"\n+++\n\n{{< blocks/cover image_anchor=\"top\" height=\"min\" color=\"primary\" title=\"Operator SDK\" >}}\n<div class=\"mx-auto\">\n\t<a class=\"btn btn-lg btn-primary mr-3 mb-4\" href=\"{{< relref \"/docs\" >}}\">\n\t\tLearn More<i class=\"fas fa-arrow-alt-circle-right ml-2\"></i>\n\t</a>\n\t<a class=\"btn btn-lg btn-secondary mr-3 mb-4\" href=\"https://github.com/operator-framework/operator-sdk/\">\n\t\tSource <i class=\"fab fa-github ml-2 \"></i>\n\t</a>\n\t<p class=\"lead mt-5\"><a href=https://kubernetes.io/docs/concepts/extend-kubernetes/operator/>Operators 🔗</a>\n\t\tare used to manage complex stateful applications on top of Kubernetes. The\n\t\tOperator SDK makes it easier to create them by providing high level APIs,\n\t\tuseful abstractions, and project scaffolding.\n\t</p>\n</div>\n{{< /blocks/cover >}}\n\n{{< blocks/lead height=\"auto\" color=\"white\" >}}\nThis project is a component of the [Operator\nFramework](https://github.com/operator-framework), an open source toolkit to\nmanage Kubernetes native applications, called Operators, in an effective,\nautomated, and scalable way. Read more in the [introduction blog\npost](https://www.openshift.com/blog/introducing-the-operator-framework.\n{{< /blocks/lead >}}\n"
  },
  {
    "path": "website/content/en/build/_index.html",
    "content": "---\ntitle: Build\nlinkTitle: Build\ndraft: false\nmenu:\n  main:\n    weight: 1\n\n---\n\n<section class=\"of-masthead of-masthead--subpage\">\n  <h1 class=\"of-heading of-heading--xl\">Building Operators using the Operator SDK</h1>\n</section>\n<section class=\"of-section-page-intro of-section-page-intro--overlay\">\n  <header class=\"of-section-page-intro__header\">\n    <h2 class=\"of-heading of-heading--md\">How can I write an Operator with Operator SDK?</h2>\n  <p>There are many ways to build an Operator with SDK. To get started building today, follow the steps in this quick start guide.</p>\n  </header>\n</section>\n\n         <main role=\"main\">\n          <section class=\"of-section-page-intro__content of-page--faq\">\n            <section class=\"of-section--largetext\">\n              <div class=\"of-section--largetext__item\">\n                  <h2 class=\"of-heading of-heading--xl\">Installing the SDK CLI</h2>\n                  <div class=\"of-section--largetext__content\">\n                    <p>Follow the steps in the <a href=\"/docs/installation/\">installation guide</a> to learn how to install the Operator SDK CLI tool. If you are using a release version of the SDK, make sure to follow the documentation for that version. You make use any of the following installation processes:</p>\n                  <ol class=\"of-list-ordered\">\n                    <li>Install the <a href=\"/docs/installation/#install-from-homebrew-macos\">Homebrew</a> (macOS)</li>\n                    <li>Install from <a href=\"/docs/installation/#install-from-github-release\">GitHub</a> release</li>\n                    <li>Compile and install from <a href=\"/docs/installation/#compile-and-install-from-master\">master</a></li>\n                  </ol>\n                  </div>\n                  <a href=\"/docs/installation/\" class=\"of-button of-button--tertiary\">Learn More\n                    <svg class=\"of-button__icon\" enable-background=\"new 0 0 22 22\" version=\"1.1\" viewBox=\"0 0 22 22\" xml:space=\"preserve\" xmlns=\"http://www.w3.org/2000/svg\">\n                        <path d=\"M19.5,8l-7.3-7.6c-0.4-0.4-1.1-0.4-1.5,0L9.3,1.8c-0.4,0.4-0.4,1.1,0,1.6l5.2,5.5H1.1C0.5,8.9,0,9.3,0,10V12  c0,0.6,0.5,1.1,1.1,1.1h13.5l-5.2,5.5c-0.4,0.4-0.4,1.1,0,1.6l1.4,1.5c0.4,0.4,1.1,0.4,1.5,0l9.4-9.9c0.4-0.4,0.4-1.1,0-1.6L19.5,8z  \"/>\n                        </svg>\n                  </a>\n                  <p class=\"large-text\"><span>homebrew, </span>\n                  <span>github, </span>\n                  <span>master.</span></p>\n              </div>\n              <div class=\"of-section--largetext__item\">\n                <h2 class=\"of-heading of-heading--xl\">READ THE USER GUIDES</h2>\n                <p class=\"of-section--largetext__content\">Operators can be created with the SDK using Ansible, Helm, or Go. Follow the one of the quickstart guides to dive in.</p>\n                <ul>\n                  <li><a href=\"/docs/building-operators/ansible/quickstart/\" class=\"of-button of-button--tertiary\">\n                      Ansible Quickstart\n                      <svg class=\"of-button__icon\" enable-background=\"new 0 0 22 22\" version=\"1.1\" viewBox=\"0 0 22 22\" xml:space=\"preserve\" xmlns=\"http://www.w3.org/2000/svg\">\n                          <path d=\"M19.5,8l-7.3-7.6c-0.4-0.4-1.1-0.4-1.5,0L9.3,1.8c-0.4,0.4-0.4,1.1,0,1.6l5.2,5.5H1.1C0.5,8.9,0,9.3,0,10V12  c0,0.6,0.5,1.1,1.1,1.1h13.5l-5.2,5.5c-0.4,0.4-0.4,1.1,0,1.6l1.4,1.5c0.4,0.4,1.1,0.4,1.5,0l9.4-9.9c0.4-0.4,0.4-1.1,0-1.6L19.5,8z  \"/>\n                      </svg>\n                    </a></li>\n                    <li><a href=\"/docs/building-operators/helm/quickstart/\" class=\"of-button of-button--tertiary\">\n                      Helm Quickstart\n                      <svg class=\"of-button__icon\" enable-background=\"new 0 0 22 22\" version=\"1.1\" viewBox=\"0 0 22 22\" xml:space=\"preserve\" xmlns=\"http://www.w3.org/2000/svg\">\n                          <path d=\"M19.5,8l-7.3-7.6c-0.4-0.4-1.1-0.4-1.5,0L9.3,1.8c-0.4,0.4-0.4,1.1,0,1.6l5.2,5.5H1.1C0.5,8.9,0,9.3,0,10V12  c0,0.6,0.5,1.1,1.1,1.1h13.5l-5.2,5.5c-0.4,0.4-0.4,1.1,0,1.6l1.4,1.5c0.4,0.4,1.1,0.4,1.5,0l9.4-9.9c0.4-0.4,0.4-1.1,0-1.6L19.5,8z  \"/>\n                      </svg>\n                      </a></li>\n                      <li><a href=\"/docs/building-operators/golang/quickstart/\" class=\"of-button of-button--tertiary\">\n                      Go Quickstart\n                      <svg class=\"of-button__icon\" enable-background=\"new 0 0 22 22\" version=\"1.1\" viewBox=\"0 0 22 22\" xml:space=\"preserve\" xmlns=\"http://www.w3.org/2000/svg\">\n                          <path d=\"M19.5,8l-7.3-7.6c-0.4-0.4-1.1-0.4-1.5,0L9.3,1.8c-0.4,0.4-0.4,1.1,0,1.6l5.2,5.5H1.1C0.5,8.9,0,9.3,0,10V12  c0,0.6,0.5,1.1,1.1,1.1h13.5l-5.2,5.5c-0.4,0.4-0.4,1.1,0,1.6l1.4,1.5c0.4,0.4,1.1,0.4,1.5,0l9.4-9.9c0.4-0.4,0.4-1.1,0-1.6L19.5,8z  \"/>\n                      </svg>\n                        </a></li>\n                </ul>\n                <p class=\"large-text\"><span>Go </span><span>Ansible </span><span>Helm</span></p>\n              </div>\n              <div class=\"of-section--largetext__item\">\n                <h2 class=\"of-heading of-heading--xl\">PUBLISH YOUR OPERATOR</h2>\n                <p class=\"of-section--largetext__content\">Learn about how you can package your Operator and share with the Kubernetes community using Operator Lifecycle Manager's package management.</p>\n                <a href=\"/docs/olm-integration/quickstart-bundle\" class=\"of-button of-button--tertiary\">Learn More\n                    <svg class=\"of-button__icon\" enable-background=\"new 0 0 22 22\" version=\"1.1\" viewBox=\"0 0 22 22\" xml:space=\"preserve\" xmlns=\"http://www.w3.org/2000/svg\">\n                      <path d=\"M19.5,8l-7.3-7.6c-0.4-0.4-1.1-0.4-1.5,0L9.3,1.8c-0.4,0.4-0.4,1.1,0,1.6l5.2,5.5H1.1C0.5,8.9,0,9.3,0,10V12  c0,0.6,0.5,1.1,1.1,1.1h13.5l-5.2,5.5c-0.4,0.4-0.4,1.1,0,1.6l1.4,1.5c0.4,0.4,1.1,0.4,1.5,0l9.4-9.9c0.4-0.4,0.4-1.1,0-1.6L19.5,8z  \"/>\n                    </svg>\n                </a>\n                <p class=\"large-text\"><span>package & </span><span>deploy </span></p>\n              </div>\n              <div class=\"of-section--largetext__item\">\n                <p class=\"large-text\"><span>evolve & </span><span>mature </span></p>\n                <h2 class=\"of-heading of-heading--xl\">LEVEL UP YOUR OPERATOR</h2>\n                <p class=\"of-section--largetext__content\">Learn about operator maturity and the requirements to approach full auto\n                  pilot.</p>\n                <a href=\"/docs/overview/operator-capabilities\" class=\"of-button of-button--tertiary\">Learn More\n                  <svg class=\"of-button__icon\" enable-background=\"new 0 0 22 22\" version=\"1.1\" viewBox=\"0 0 22 22\"\n                    xml:space=\"preserve\" xmlns=\"http://www.w3.org/2000/svg\">\n                    <path\n                      d=\"M19.5,8l-7.3-7.6c-0.4-0.4-1.1-0.4-1.5,0L9.3,1.8c-0.4,0.4-0.4,1.1,0,1.6l5.2,5.5H1.1C0.5,8.9,0,9.3,0,10V12  c0,0.6,0.5,1.1,1.1,1.1h13.5l-5.2,5.5c-0.4,0.4-0.4,1.1,0,1.6l1.4,1.5c0.4,0.4,1.1,0.4,1.5,0l9.4-9.9c0.4-0.4,0.4-1.1,0-1.6L19.5,8z  \" />\n                  </svg>\n                </a>\n              </div>\n          </section>\n          </section>\n          </main>\n"
  },
  {
    "path": "website/content/en/community/_index.md",
    "content": "---\ntitle: Community\n# menu:\n#   main:\n    # weight: 5\n---\n"
  },
  {
    "path": "website/content/en/docs/_index.md",
    "content": "---\ntitle: Operator SDK Documentation\nlinkTitle: Documentation\nmenu:\n  main:\n    weight: 2\n---\n\n"
  },
  {
    "path": "website/content/en/docs/advanced-topics/_index.md",
    "content": "---\ntitle: \"Advanced Topics\"\nlinkTitle: \"Advanced Topics\"\nweight: 9\ndate: 2021-10-05\ndescription: >\n  Advanced Topics.\n---\n"
  },
  {
    "path": "website/content/en/docs/advanced-topics/custom-bundle-validation.md",
    "content": "---\ntitle: Custom Bundle Validation\nweight: 80\n---\n\n## Summary\n\nOperator authors can now use \"external\" validators with the\n`operator-sdk bundle validate` command by using the\n`--alpha-select-external` flag. This feature enables Operator authors,\nusers, and registry pipelines to use custom validators. These custom\nvalidators can be written in any language.\n\n## Usage\n\nExternal validators can be used by specifying a list of local filepaths to\nexecutables using colons as path separators:\n\n```sh\n$ operator-sdk bundle validate \\\n--alpha-select-external path/validator1:path/validator2\n```\n\n## Writing a Custom Validator\n\nFor a validator to work with `operator-sdk bundle validate` each of the files must:\n1. Be executable with appropriate permissions\n1. Return JSON to STDOUT in the [`ManifestResult`][manifest_result] format.\n\n### Custom Validator from Scratch\n\nUsing the `errors` package from [`operator-framework/api`][of-api], we\ncan start by validating the correct number of arguments and marshaling a\n[`ManifestResult`][manifest_result] into STDOUT.\n\n`myvalidator/main.go`\n\n```go\npackage main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\n\t\"github.com/operator-framework/api/pkg/validation/errors\"\n)\n\nfunc main() {\n\n\t// we expect a single argument which is the bundle root.\n\t// usage: validator-poc <bundle root>\n\tif len(os.Args) < 2 {\n\t\tfmt.Printf(\"usage: %s <bundle root>\\n\", os.Args[0])\n\t\tos.Exit(1)\n\t}\n\n\tvar validatorErrors []errors.Error\n\tvar validatorWarnings []errors.Error\n\tresult := errors.ManifestResult{\n\t\tName:     \"Always Green Example\",\n\t\tErrors:   validatorErrors,\n\t\tWarnings: validatorWarnings,\n\t}\n\tprettyJSON, err := json.MarshalIndent(result, \"\", \"    \")\n\tif err != nil {\n\t\tfmt.Println(\"Invalid json\")\n\t\tos.Exit(1)\n\t}\n\tfmt.Printf(\"%s\\n\", string(prettyJSON))\n}\n```\n\nWhen executed on its own, this validator prints a JSON representation of\n[`ManifestResult`][manifest_result].\n\n```sh\ngo build -o myvalidator/main myvalidator/main.go && ./myvalidator/main\n\n{\n    \"Name\": \"Always Green Example\",\n    \"Errors\": null,\n    \"Warnings\": null\n}\n```\n\n```sh\n$ go build -o myvalidator/main myvalidator/main.go\n$ operator-sdk bundle validate ./bundle --alpha-select-external ./myvalidator/main\n```\n```\nINFO[0000] All validation tests have completed successfully\n```\n\nFrom here, custom validator authors can read in the bundle and make any\nassertions necessary.\n\nErrors and Warnings are both implementations of the `error` interface\nand need `ErrorType`, `Level`, `Field`, `BadValue`, and `Detail`, which\nare all initialized by arbitrary strings. When using Golang, validator\nauthors can use the [operator-framework/api][of-api] impementation of\n[errors and warnings][errors-pkg]\n\n```go\nvalidatorErrors = []errors.Error{errors.Error{\"someErrorType\", \"somelevel\", \"somefield\", \"somebadvalue\", \"somedetail\"}}\nvalidatorWarnings = []errors.Error{errors.Error{\"someWarningType\", \"somelevel\", \"somefield\", \"somebadvalue\", \"somedetail\"}}\n```\n\nWe can now rebuild and run the validator, which now shows errors.\n\n```sh\n$ go build -o myvalidator/main myvalidator/main.go\n$ operator-sdk bundle validate ./bundle --alpha-select-external ./myvalidator/main\n```\n```\nWARN[0000] somelevel: Field somefield, Value somebadvalue: somedetail\nERRO[0000] somelevel: Field somefield, Value somebadvalue: somedetail\n```\n\n### Composing Validators\n\nFor users wishing to use validators from\n[`operator-framework/api`][of-api] without being restricted to the\nversion that is built into the `operator-sdk` binary, it is possible to\ncreate a `main.go` that makes use of the [`validation`\npackage][of-validation] at an arbitrary version.\n\nCurrently, some of the code necessary requires copying code from\ninternal packages, which may someday become a library.\n\n`myvalidator/main.go`\n\n```go\npackage main\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\tapimanifests \"github.com/operator-framework/api/pkg/manifests\"\n\tapivalidation \"github.com/operator-framework/api/pkg/validation\"\n\tregistrybundle \"github.com/operator-framework/operator-registry/pkg/lib/bundle\"\n\tlog \"github.com/sirupsen/logrus\"\n\n\t\"github.com/spf13/afero\"\n\t\"sigs.k8s.io/yaml\"\n)\n\nfunc main() {\n\n\t// we expect a single argument which is the bundle root.\n\t// usage: validator-poc <bundle root>\n\tif len(os.Args) < 2 {\n\t\tfmt.Printf(\"usage: %s <bundle root>\\n\", os.Args[0])\n\t\tos.Exit(1)\n\t}\n\n\t// Read the bundle object and metadata from the passed in directory.\n\tbundle, _, err := getBundleDataFromDir(os.Args[1])\n\tif err != nil {\n\t\tfmt.Printf(\"problem getting bundle [%s] data, %v\\n\", os.Args[1], err)\n\t\tos.Exit(1)\n\t}\n\n\t// pass the objects to the validator\n\tobjs := bundle.ObjectsToValidate()\n\tfor _, obj := range bundle.Objects {\n\t\tobjs = append(objs, obj)\n\t}\n\tresults := apivalidation.GoodPracticesValidator.Validate(objs...)\n\n\t// take each of the ManifestResults and print to STDOUT\n\tfor _, result := range results {\n\t\tprettyJSON, err := json.MarshalIndent(result, \"\", \"    \")\n\t\tif err != nil {\n\t\t\t// should output JSON so that the call knows how to parse it\n\t\t\tfmt.Printf(\"XXX ERROR: %v\\n\", err)\n\t\t}\n\t\tfmt.Printf(\"%s\\n\", string(prettyJSON))\n\t}\n}\n\n// getBundleDataFromDir returns the bundle object and associated metadata from dir, if any.\nfunc getBundleDataFromDir(dir string) (*apimanifests.Bundle, string, error) {\n\t// Gather bundle metadata.\n\tmetadata, _, err := FindBundleMetadata(dir)\n\tif err != nil {\n\t\treturn nil, \"\", err\n\t}\n\tmanifestsDirName, hasLabel := metadata.GetManifestsDir()\n\tif !hasLabel {\n\t\tmanifestsDirName = registrybundle.ManifestsDir\n\t}\n\tmanifestsDir := filepath.Join(dir, manifestsDirName)\n\t// Detect mediaType.\n\tmediaType, err := registrybundle.GetMediaType(manifestsDir)\n\tif err != nil {\n\t\treturn nil, \"\", err\n\t}\n\t// Read the bundle.\n\tbundle, err := apimanifests.GetBundleFromDir(manifestsDir)\n\tif err != nil {\n\t\treturn nil, \"\", err\n\t}\n\treturn bundle, mediaType, nil\n}\n\n// -------------------------------------------------------\n// Everything below this line was copied code from the internal Operator SDK\n// registry package operator-sdk/internal/registry/labels.go. If this is\n// generally useful please file an issue to move this to a reuable library.\n// to make this a library or other reusable code.\n// -------------------------------------------------------\n\ntype MetadataNotFoundError string\n\nfunc (e MetadataNotFoundError) Error() string {\n\treturn fmt.Sprintf(\"metadata not found in %s\", string(e))\n}\n\n// Labels is a set of key:value labels from an operator-registry object.\ntype Labels map[string]string\n\n// GetManifestsDir returns the manifests directory name in ls using\n// a predefined key, or false if it does not exist.\nfunc (ls Labels) GetManifestsDir() (string, bool) {\n\tvalue, hasKey := ls[registrybundle.ManifestsLabel]\n\treturn filepath.Clean(value), hasKey\n}\n\n// FindBundleMetadata walks bundleRoot searching for metadata (ex. annotations.yaml),\n// and returns metadata and its path if found. If one is not found, an error is returned.\nfunc FindBundleMetadata(bundleRoot string) (Labels, string, error) {\n\treturn findBundleMetadata(afero.NewOsFs(), bundleRoot)\n}\n\nfunc findBundleMetadata(fs afero.Fs, bundleRoot string) (Labels, string, error) {\n\t// Check the default path first, and return annotations if they were found or an error if that error\n\t// is not because the path does not exist (it exists or there was an unmarshalling error).\n\tannotationsPath := filepath.Join(bundleRoot, registrybundle.MetadataDir, registrybundle.AnnotationsFile)\n\tannotations, err := readAnnotations(fs, annotationsPath)\n\tif (err == nil && len(annotations) != 0) || (err != nil && !errors.Is(err, os.ErrNotExist)) {\n\t\treturn annotations, annotationsPath, err\n\t}\n\n\t// Annotations are not at the default path, so search recursively.\n\tannotations = make(Labels)\n\tannotationsPath = \"\"\n\terr = afero.Walk(fs, bundleRoot, func(path string, info os.FileInfo, err error) error {\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\t// Skip directories and hidden files, or if annotations were already found.\n\t\tif len(annotations) != 0 || info.IsDir() || strings.HasPrefix(path, \".\") {\n\t\t\treturn nil\n\t\t}\n\n\t\tannotationsPath = path\n\t\t// Ignore this error, since we only care if any annotations are returned.\n\t\tif annotations, err = readAnnotations(fs, path); err != nil {\n\t\t\tlog.Debug(err)\n\t\t}\n\t\treturn nil\n\t})\n\tif err != nil {\n\t\treturn nil, \"\", err\n\t}\n\n\tif len(annotations) == 0 {\n\t\treturn nil, \"\", MetadataNotFoundError(bundleRoot)\n\t}\n\n\treturn annotations, annotationsPath, nil\n}\n\n// readAnnotations reads annotations from file(s) in bundleRoot and returns them as Labels.\nfunc readAnnotations(fs afero.Fs, annotationsPath string) (Labels, error) {\n\t// The annotations file is well-defined.\n\tb, err := afero.ReadFile(fs, annotationsPath)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Use the arbitrarily-labelled bundle representation of the annotations file\n\t// for forwards and backwards compatibility.\n\tannotations := registrybundle.AnnotationMetadata{\n\t\tAnnotations: make(Labels),\n\t}\n\tif err = yaml.Unmarshal(b, &annotations); err != nil {\n\t\treturn nil, fmt.Errorf(\"error unmarshalling potential bundle metadata %s: %v\", annotationsPath, err)\n\t}\n\n\treturn annotations.Annotations, nil\n}\n```\n\nThe `main.go` is then built into a binary and used with `operator-sdk bundle\nvalidate`\n\n```sh\n$ go build -o myvalidator/main myvalidator/main.go\n$ operator-sdk bundle validate ./bundle --alpha-select-external ./myvalidator/main\n```\n```\nWARN[0000] Warning: Value sandbox-op.v0.0.1: owned CRD \"sandboxes.sandbox.example.come\" has an empty description\nINFO[0000] All validation tests have completed successfully\n```\n[errors-pkg]: https://github.com/operator-framework/api/tree/master/pkg/validation/errors\n[manifest_result]: https://github.com/operator-framework/api/blob/master/pkg/validation/errors/error.go#L9-L16\n[of-api]: https://github.com/operator-framework/api\n[of-validation]: https://github.com/operator-framework/api/tree/master/pkg/validation\n"
  },
  {
    "path": "website/content/en/docs/advanced-topics/multi-arch.md",
    "content": "---\ntitle: Multiple Architectures\nlinkTitle: Multiple Architectures\nweight: 80\n---\n\n# Supporting Multiple Architectures\n\nAuthors may decide to distribute their bundles for various architectures: x86_64, aarch64, ppc64le, s390x, etc, to accommodate the diversity of Kubernetes clusters and reach a larger number of potential users. Each supported architecture requires compatible binaries. Binary compatibility is based on the **platform**, which is generally comprised of an operating system, a CPU architecture, and other architecture variants. For this guide, we will treat the CPU architecture as the platform differentiator.\n\nThat said, the same general advice would apply to supporting workloads on clusters of the same architecture but different operating systems (e.g. `linux/amd64`, `windows/amd64`). In this guide, we assume all workloads will be using the `linux` operating system.\n\n## Fundamentals\nThe basic principle of supporting multiple architectures is to ensure that each of your operator images is built for each of the architectures to be supported. From there, the images should be hosted in image registries as manifest lists. Finally, you'll need to update your distribution configuration to set which architectures are supported. This section explains each of these concepts in turn.\n\n### Building an Operator for Multiple Architectures\n[Kubebuilder][kubebuilder] explains how you can use `docker buildx` to build images for multiple architectures. Operator SDK leverages KubeBuilder to ensure that builds can be cross-platform from the start.\n\n### Manifest lists\nThe most straightforward way of building operators and operands supporting multiple architectures is to leverage manifest lists, specified by [Image Manifest V2, Schema 2][manifest_list] or [OCI Image Index][image_index]. A manifest list points to specific image manifests for one or more architectures.\n\nFor convenience tools like [buildah][buildah] allow to cross-build and manifest multi-arch containers on one host. For instance with buildah:\n\n```shell\nfor a in amd64 arm64 ppc64le s390x; do \\\n  buildah bud --manifest registry/username/repo:v1 --arch $a; \\\ndone\n```\n\nThis creates the manifest list, builds each image, and adds them to the manifest list.\n\nThe result can then be pushed to the desired registry.\n\n```shell\nbuildah push registry/username/repo:v1\n```\n\nDocker with [buildx][buildx] provides similar capabilities.\n\n```shell\ndocker buildx build --push --platform linux/amd64,linux/arm64,linux/ppc64le,linux/s390x --tag registry/username/repo:v1 .\n```\n\nSee [docker documentation][buildx_multiarch] for additional options.\n \n**Caveat**: the Dockerfile generated by the SDK for the operator explicitly references GOARCH=amd64 for go build. This can be amended to GOARCH=$TARGETARCH. Docker will automatically set the environment variable to the value specified by --platform. With buildah --build-arg will need to be used for the purpose.\n\n**Caveat**: When mirroring registries for disconnected installations (environments without internet connection) all the images referenced by a manifest list need to be copied, including images for architectures that may not be used in the environment.\n\n### Operator Lifecycle Manager\n\nFor operators distributed through the [Operator Lifecycle Manager (OLM)][olm]:\n\n* [Bundle images][bundle] are not architecture-specific. They contain only plaintext Kubernetes manifests and operator metadata.\n* All image references in the ClusterServiceVersion should be manifest lists containing the pointers to the image manifests for the supported architectures.\n* Labels for OS and architectures can be set in the CSV. Please refer to the [Operator Lifecycle Management Documentation][olm_multiarch] for details.\n\n## Supporting Clusters with Multi-Architecture Compute Nodes\nThe [Fundamentals]({{< relref \"#fundamentals\" >}}) above aim to guide authors on the key steps to building and distributing operators that can run on multiple architectures. These instructions are sufficient when your cluster's compute nodes share the same architecture. However, operator authors should also understand the implications of running their operators in a cluster with multi-architecture compute nodes since it is not always guaranteed that the architectures of the compute nodes will match the architectures supported by the operator.\n\n### Safe Scheduling Using Node Affinity\nNode affinity is a mechanism exposed in a Kubernetes pod template that allows a `PodSpec` author to instruct the scheduler to restrict a pod to run only on (or with a preference for) nodes that meet specific criteria. To ensure that pods are always scheduled to nodes of compatible architecture, it is a best practice for authors to set node affinity requirements to ensure their operators and operands will only schedule to the nodes with architectures available to the images in the pod. If you don't do this, a container scheduled to an incompatible node will immediately crash with an `exec format error`, which will ultimately lead to an `ImagePullBackoff` event as the pod is restarted only to crash again with the same error.\n\n#### Determining the Architectures Supported by an Image\nFor a given container image, you can check which architectures are supported by listing them by inspecting the manifest. Piping the output to the python `json.tool` module enables pretty-printed JSON output.\n```shell\n$ skopeo inspect --raw <image> | python -m 'json.tool'\n```\n\nHere's an example of architectures distributed for the Alpine Linux container image. Notice that both `linux/amd64` and `linux/arm64` are supported.\n```shell\n$ skopeo inspect --raw docker://alpine:latest | python -m 'json.tool'\n{\n    \"manifests\": [\n        {\n            \"digest\": \"sha256:c0669ef34cdc14332c0f1ab0c2c01acb91d96014b172f1a76f3a39e63d1f0bda\",\n            \"mediaType\": \"application/vnd.docker.distribution.manifest.v2+json\",\n            \"platform\": {\n                \"architecture\": \"amd64\",\n                \"os\": \"linux\"\n            },\n            \"size\": 528\n        },\n        ...\n        {\n            \"digest\": \"sha256:30e6d35703c578ee703230b9dc87ada2ba958c1928615ac8a674fcbbcbb0f281\",\n            \"mediaType\": \"application/vnd.docker.distribution.manifest.v2+json\",\n            \"platform\": {\n                \"architecture\": \"arm64\",\n                \"os\": \"linux\",\n                \"variant\": \"v8\"\n            },\n            \"size\": 528\n        },\n      ...\n```\n\nYou can also use `docker` to inspect the manifest, but beware that it will return `no such manifest` error if the referenced image is not actually a manifest list.\n```shell\n$ docker manifest inspect <image>\n```\n\nIf the above commands do not produce output with `manifests`, then it may be because the referenced name points to a single image rather than a manifest list. In this case, you can find the architecture by inspecting the image directly.\n```shell\n$ skopeo inspect <image>\n```\n\nThis example shows how to inspect a local image to determine the architecture.\n```shell\n$ skopeo inspect docker://alpine\n{\n    \"Name\": \"docker.io/library/alpine\",\n    ...\n    \"Architecture\": \"amd64\",\n    \"Os\": \"linux\",\n    ...\n}\n```\n\nAlternatively you can pull the image down and inspect it with `docker`.\n```shell\n$ docker pull <image> && docker inspect <image>\n```\n\n#### Setting Node-Affinity Criteria for Operators & Operands\n[Kubernetes provides a mechanism][affinity] called `nodeAffinity` which can be used to limit the possible node targets where a pod can be scheduled. The following example can be used to update a `PodSpec` or `PodTemplateSpec` to prevent the scheduling of pods on nodes of incompatible architecture. Here we compare the `kubernetes.io/arch` and `kubernetes.io/os` keys set on the node to ensure that the values match one of the supported `OS/architecture` pairs. This assumes that the referenced image points to a manifest list with references to images for each of the supported architectures. It is important to remember that `nodeAffinity` should be set anywhere a container reference is defined, including `Pod`, `Deployment`, `DaemonSet`, `StatefulSet`, or any other object that defines a `PodSpec` or `PodTemplateSpec`.\n\nThe list of architecture values should only include the architectures the operator supports. The full list of possible `GOARCH` values is [available here][goarch]. It should be noted that Kubernetes allows a user to specify both `requiredDuringSchedulingIgnoredDuringExecution` and `preferredDuringSchedulingIgnoredDuringExecution`. The syntax for each block is the same. At a minimum, an operator author should set the required terms since they protect against a pod being scheduled on an incompatible node. If the operator in question has much better performance on a subset of the supported architectures, it may also be prudent to set `preferredDuringSchedulingIgnoredDuringExecution` so that the optimal arches are selected first if they are available.\n\n##### Setting Node Affinity in a Kubernetes Manifest\nTo update the `PodSpec` and `PodTemplateSpec` objects of an operator and its operands, you will need to scan your operator for instances of these objects. Most of the time, these objects will be defined directly in a Kubernetes manifest `yaml`; however, for dynamically created workloads, these are sometimes embedded in the operator's logic directly.\n\nThe most common directory with `PodSpec` and `PodTemplateSpec` objects that will need to be updated will be in the operator's `config` directory. Additionally, if the operator is configured for OLM, there will likely be a deployment object in the `bundle/manifests/*.clusterserviceversion.yaml`.\n\n```yaml\naffinity:\n  nodeAffinity:\n    requiredDuringSchedulingIgnoredDuringExecution:\n      nodeSelectorTerms:\n      - matchExpressions:\n        - key: kubernetes.io/arch\n          operator: In\n          values:\n          - amd64\n          - arm64\n          - ppc64le\n          - s390x\n        - key: kubernetes.io/os\n            operator: In\n            values:\n              - linux\n```\n\n##### Setting Node Affinity in Golang\nWhile **Ansible** and **Helm** operators will usually define their operators and operands according to the syntax defined above directly in `yaml` files or directly in a role or variable template file, **Go** operators will sometimes embed the logic directly in the operator itself. Here is an example of how a `PodSpec` would be updated according to the syntax of the Go API.\n\n```go\nTemplate: corev1.PodTemplateSpec{\n    ...\n    Spec: corev1.PodSpec{\n        Affinity: &corev1.Affinity{\n            NodeAffinity: &corev1.NodeAffinity{\n                RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{\n                    NodeSelectorTerms: []corev1.NodeSelectorTerm{\n                        {\n                            MatchExpressions: []corev1.NodeSelectorRequirement{\n                                {\n                                    Key:      \"kubernetes.io/arch\",\n                                    Operator: \"In\",\n                                    Values:   []string{\"amd64\"},\n                                },\n                                {\n                                    Key:      \"kubernetes.io/os\",\n                                    Operator: \"In\",\n                                    Values:   []string{\"linux\"},\n                                },\n                            },\n                        },\n                    },\n                },\n            },\n        },\n        SecurityContext: &corev1.PodSecurityContext{\n            ...\n        },\n        Containers: []corev1.Container{{\n            ...\n        }},\n    },\n```\n\n##### Updating Operator Lifecycle Manager Configurations for Multi-Architecture Compute Nodes\nThe [Operator Lifecycle Manager (OLM)][olm] is often used to distribute operators via operator catalogs. The operator deployment object in an OLM integrated operator is defined in the `ClusterServiceVersion` yaml. It is important to **remember to set the node affinity block in each of the `spec.template.spec` under `spec.install.deployments`**.\n\nIf you're planning to distribute the operator via OLM, you can find more information in the [OLM guide for supporting multiarch][olm_multiarch].\n\n#### Overriding Affinity for an Operator Pod as a Cluster Admin\nA cluster admin might have some context that can be used to refine the scheduling requirements for the operator images specified in the deployment spec of the Cluster Service Version. To ensure the fine control of scheduling remains with the cluster admin, OLM provides a mechanism for [overriding the operator pod affinity configuration][olm_affinity_override] as part of the `Subscription` object.\n\n**Caveat**: No built-in affinity override controls exist that allow cluster admins to override affinity for operands. It is up to the operator author to determine whether this would be appropriate for one or more of their operands and what configuration options should be allowed.\n\n## Validating Your Operator's Multi-Architecture Readiness\nA [validator]({{< relref \"/docs/cli/operator-sdk_bundle_validate.md\" >}}) is available to help authors ensure that operators are defined according to the best practices. Because operands can be declared and defined in a variety of ways depending on the language used and structure of the operator, this validator focuses on verifying that the images defined in the CSV deployment spec are compliant with the fundamentals and best practices. It is up to the operator author to ensure that affinity best practices are also being followed for each operand's `PodSpec` and `PodTemplateSpec` definitions.\n\n```shell\n$ operator-sdk bundle validate ./bundle --select-optional name=multiarch\n```\n\n[affinity]: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/\n[buildah]: https://github.com/containers/buildah/blob/main/docs/buildah-build.1.md#building-an-multi-architecture-image-using-the---manifest-option-requires-emulation-software\n[buildx]: https://docs.docker.com/buildx/working-with-buildx/#build-multi-platform-images\n[buildx_multiarch]: https://docs.docker.com/buildx/working-with-buildx/#build-multi-platform-images\n[bundle]: https://olm.operatorframework.io/docs/glossary/#bundle\n[goarch]: https://github.com/golang/go/blob/master/src/internal/syslist/syslist.go\n[image_index]: https://github.com/opencontainers/image-spec/blob/main/image-index.md\n[kubebuilder]: https://github.com/kubernetes-sigs/kubebuilder/blob/master/docs/book/src/reference/platform.md#producing-projects-that-support-multiple-platforms\n[manifest_list]: https://docs.docker.com/registry/spec/manifest-v2-2/#manifest-list\n[olm]: https://olm.operatorframework.io/docs/\n[olm_multiarch]: https://olm.operatorframework.io/docs/advanced-tasks/ship-operator-supporting-multiarch/#multiple-architectures\n[olm_affinity_override]: https://olm.operatorframework.io/docs/advanced-tasks/overriding-operator-pod-affinity-configuration/#overriding-operator-pod-affinity-configuration"
  },
  {
    "path": "website/content/en/docs/advanced-topics/multi-sa.md",
    "content": "---\ntitle: Multiple Service Accounts\nlinkTitle: Multiple Service Accounts\nweight: 80\n---\n\n### Using Multiple Service Accounts\n\nThere may be a need to have multiple service accounts to provide only the necessary permissions to various objects that the operator creates on a Kubernetes cluster.\n\nThis can be accomplished by using the `--extra-service-accounts` flag when generating the bundle with `make bundle`.\n\n#### Updating the `Makefile` to use `--extra-service-accounts`\n\nUpdate the `bundle` target in the `Makefile` to add the `--extra-service-accounts` flag with the name of the desired service account. This ensures that the permissions and configurations do not get overwritten by `make bundle`.\nFor example, modify the line that contains `operator-sdk generate bundle` similar to below replacing `myOperator-name-additional-service-account` to the desired service account name appended to the operator name.\n\n```\nbundle: manifests kustomize operator-sdk ## Generate bundle manifests and metadata, then validate generated files.\n\toperator-sdk generate kustomize manifests -q\n\tcd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG)\n\t$(KUSTOMIZE) build config/manifests | operator-sdk generate bundle -q --overwrite --extra-service-accounts myOperator-name-additional-service-account --version $(VERSION) $(BUNDLE_METADATA_OPTS)\n\toperator-sdk bundle validate ./bundle\n```\n\nThe `--extra-service-accounts` flag takes a comma-separated list of strings, so you can add more than a single service account name if desired.\n\n#### Add RBAC configurations for `--extra-service-accounts`\n\nThese steps will need to be followed for every additional service account.\n\n1. Create a new service account file. For example:\n   ```\n   cat << EOF > config/rbac/additional_service_account.yaml\n   apiVersion: v1\n   kind: ServiceAccount\n   metadata:\n     name: additional-service-account\n     namespace: system\n   EOF\n   ```\n\n2. Create a role binding. In this example, it is a `ClusterRoleBinding`:\n   ```\n   cat << EOF > config/rbac/additional_role_binding.yaml\n   apiVersion: rbac.authorization.k8s.io/v1\n   kind: ClusterRoleBinding\n   metadata:\n     name: additional-service-account-rolebinding\n   roleRef:\n     apiGroup: rbac.authorization.k8s.io\n     kind: ClusterRole\n     name: additional-service-account-role\n   subjects:\n   - kind: ServiceAccount\n     name: additional-service-account\n     namespace: system\n   EOF\n   ```\n\n3. Create a role with desired permissions. In this example, it is a `ClusterRole` that provides permission to the `privileged` `SecurityContextConstraint` (`SCC`).\n   ```\n   cat << EOF > config/rbac/additional_role.yaml\n   apiVersion: rbac.authorization.k8s.io/v1\n   kind: ClusterRole\n   metadata:\n     creationTimestamp: null\n     name: additional-service-account-role\n   rules:\n   - apiGroups:\n     - security.openshift.io\n     resourceNames:\n     - privileged\n     resources:\n     - securitycontextconstraints\n     verbs:\n     - use\n   EOF\n   ```\n\n\n#### Update the RBAC `kustomization.yaml`\n\nMake sure to update the RBAC configuration `kustomization.yaml` file with the previously created RBAC `yaml` files.\nFor example:\n\n```\ncat << EOF >> config/rbac/kustomization.yaml\n\n# Add MyCustomObject service account\n- additional_service_account.yaml\n- additional_role.yaml\n- additional_role_binding.yaml\nEOF\n```\n\n"
  },
  {
    "path": "website/content/en/docs/best-practices/_index.md",
    "content": "---\ntitle: \"Best Practices\"\nlinkTitle: \"Best Practices\"\nweight: 10\ndescription: >\n    Best practices, conventions and recommendations to work with SDK\n---\n"
  },
  {
    "path": "website/content/en/docs/best-practices/best-practices.md",
    "content": "---\ntitle: \"Operator Best Practices\"\nlinkTitle: \"Best practices\"\nweight: 1\ndescription: This guide describes the best practices concepts to write operators.\n---\n\n## Development\n\nConsiderations for Operator developers:\n\n- An Operator should manage a single type of application, essentially following the UNIX principle: do one thing and do it well.\n\n- If an application consists of multiple tiers or components, multiple Operators should be written one for each of them. For example, if the application consists of Redis, AMQ, and MySQL, there should be 3 Operators, not one.\n\n- If there is significant orchestration and sequencing involved, an Operator should be written that represents the entire stack, in turn delegating to other Operators for orchestrating their part of it.\n\n- Operators should own a CRD and only one Operator should control a CRD on a cluster. Two Operators managing the same CRD is not a recommended best practice. An API that exists with multiple implementations is a typical example of a no-op Operator. The no-op Operator doesn't have any deployment or reconciliation loop to define the shared API and other Operators depend on this Operator to provide one implementation of the API, e.g. similar to PVCs or Ingress. \n\n- Inside an Operator, multiple controllers should be used if multiple CRDs are managed. This helps in separation of concerns and code readability. Note that this doesn't necessarily mean that we need to have one container image per controller, but rather one reconciliation loop (which could be running as part of the same Operator binary) per CRD.\n\n- An Operator shouldn't deploy or manage other operators (such patterns are known as meta or super operators or include CRDs in its Operands). It's the Operator Lifecycle Manager's job to manage the deployment and lifecycle of operators. For further information check [Dependency Resolution][Dependency Resolution].\n\n- If multiple operators are packaged and shipped as a single entity by the same CSV for example, then it is recommended to add all owned and required CRDs, as well as all deployments for operators that manage the owned CRDs, to the same CSV.\n\n- Writing an Operator involves using the Kubernetes API, which in most scenarios will be built using same boilerplate code. Use a framework like the Operator SDK to save yourself time with this and to also get a suite of tooling to ease development and testing.\n\n- Operators shouldn’t make any assumptions about the namespace they are deployed in and they should not use hard-coded names of resources that they expect to already exist.\n\n- Operators shouldn’t hard code the namespaces they are watching. This should be configurable - having no namespace supplied is interpreted as watching all namespaces\n\n- Semantic versioning (aka semver) should be used to version an Operator. Operators are long-running workloads on the cluster and its APIs are potentially in need of support over a longer period of time. Use the [semver.org guidelines](https://semver.org) to help determine when and how to bump versions when there are breaking or non-breaking changes.\n\n- Kubernetes API versioning guidelines should be used to version Operator CRDs. Use the [Kubernetes sig-architecture guidelines](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api_changes.md#so-you-want-to-change-the-api) to get best practices on when to bump versions and when breaking changes are acceptable.\n\n- When defining CRDs, you should use OpenAPI spec to create a structural schema for your CRDs.\n\n- Operators are instrumented to provide useful, actionable metrics to external systems (e.g. monitoring/alerting platforms).  Minimally, metrics should represent the software's health and key performance indicators, as well as support the creation of [service levels indicators](https://en.wikipedia.org/wiki/Service_level_indicator) such as throughput, latency, availability, errors, capacity, etc.\n\n- Operators may create objects as part of their operational duty. Object accumulation can consume unnecessary resources, slow down the API and clutter the user interface. As such it is important for operators to keep good hygiene and to clean up resources when they are not needed. Here are instructions on [how to handle cleanup on deletion][advanced-topics].\n\n### Summary\n\n- One Operator per managed application\n- Multiple operators should be used for complex, multi-tier application stacks\n- CRD can only be owned by a single Operator, shared CRDs should be owned by a separate Operator\n- One controller per custom resource definition\n- Use a tool like Operator SDK\n- Do not hard-code namespaces or resources names\n- Make watch namespace configurable\n- Use semver / observe Kubernetes guidelines on versioning APIs\n- Use OpenAPI spec with structural schema on CRDs\n- Operators expose metrics to external systems\n- Operators cleanup resources on deletion\n\n## Running On-Cluster\n\nConsiderations for on-cluster behavior\n\n- Like all containers on Kubernetes, Operators need not run as root unless absolutely necessary. Operators should come with their own ServiceAccount and not rely on the `default`.\n\n- Operators should not self-register their CRDs. These are global resources and careful consideration needs to be taken when setting those up. Also this requires the Operator to have global privileges which is potentially dangerous compared to that little extra convenience.\n\n- Operators use CRs as the primary interface to the cluster user. As such, at all times, meaningful status information should be written to those objects unless they are solely used to store data in a structured schema.\n\n- Operators should be updated frequently according to server versioning.\n\n- Operators need to support updating managed applications (Operands) that were set up by an older version of the Operator. There are multiple models for this:\n\n| Model | Description | \n| ------ | ----- |\n| **Operator fan-out** | where the Operator allows the user to specify the version in the custom resource |\n| **single version** | where the Operator is tied to the version of the operand. |\n| **hybrid approach** | where the Operator is tied to a range of versions, and the user can select some level of the version. |\n\n- An Operator should not deploy another Operator - an additional component on cluster should take care of this (OLM).\n\n- When Operators change their APIs, CRD conversion (webhooks) should be used to deal with potentially older instances of them using the previous API version.\n\n- Operators should make it easy for users to use their APIs - validating and rejecting malformed requests via extensive Open API validation schema on CRDs or via an admission webhook is good practice.\n\n- The Operator itself should be really modest in its requirements - it should always be able to deploy by deploying its controllers, no user input should be required to start up the Operator.\n\n- If user input is required to change the configuration of the Operator itself, a Configuration CRD should be used. Init-containers as part of the Operator deployments can be used to create a default instance of those CRs and then the Operator manages their lifecycle.\n\n### Summary:\n\nOn the cluster, an Operator...\n\n- Does not run as root\n- Does not self-register CRDs\n- Does not install other Operators\n- Does rely on dependencies via package manager (OLM)\n- Writes meaningful status information on Custom Resources objects unless pure data structure\n- Should be capable of updating from a previous version of the Operator\n- Should be capable of managing an Operand from an older Operator version\n- Uses CRD conversion (webhooks) if API/CRDs change\n- Uses OpenAPI validation / Admission Webhooks to reject invalid CRs\n- Should always be able to deploy and come up without user input\n- Offers (pre)configuration via a `“Configuration CR”` instantiated by InitContainers\n\n[Dependency Resolution]: https://olm.operatorframework.io/docs/concepts/olm-architecture/dependency-resolution/\n[advanced-topics]:/docs/building-operators/golang/advanced-topics#handle-cleanup-on-deletion\n"
  },
  {
    "path": "website/content/en/docs/best-practices/common-recommendation.md",
    "content": "---\ntitle: \"Common recommendations and suggestions\"\nlinkTitle: \"Common suggestions\"\nweight: 2\ndescription: Common recommendations and suggestions to built solutions with Operator SDK\n---\n\n## Overview\n\nAny recommendations or best practices suggested by the Kubernetes community, such as how to [develop Operator pattern solutions][operator-pattern] or how to [use controller-runtime][controller-runtime] are good recommendations for those who are looking to build operator projects with operator-sdk. Also, see [Operator Best Practices][operator-best-practices]. However, here are some common recommendations.\n\n## Common Recommendations\n\n### Develop idempotent reconciliation solutions\n\nWhen developing operators, it is essential for the controller’s reconciliation loop to be idempotent. By following the [Operator pattern][operator-pattern] you will create [Controllers](https://kubernetes.io/docs/concepts/architecture/controller/) which provide a reconcile function responsible for synchronizing resources until the desired state is reached on the cluster. Breaking this recommendation goes against  the design principles of [controller-runtime][controller-runtime] and may lead to unforeseen consequences such as resources becoming stuck and requiring manual intervention.\n\n### Understanding Kubernetes APIs\n\nBuilding your own operator commonly involves extending the Kubernetes API itself. It is helpful to understand exactly how [Custom Resource Definitions interact with the Kubernetes API][k8s-crd-doc]. Also, the Kubebuilder documentation on [Groups and Versions and Kinds][kb-gkv] may be helpful to better understand these concepts as they relate to operators.\n\n### Avoid a design solution where more than one Kind is reconciled by the same controller\n\nHaving many Kinds (such as CRDs) which are all managed by the same controller usually goes against the design proposed by [controller-runtime][controller-runtime]. Furthermore this might hurt concepts such as encapsulation, the Single Responsibility Principle, and Cohesion. Damaging these concepts may cause unexpected side effects, and increase the difficulty of extending, reusing, or maintaining the operator.\n\n### Ideally Operators does not manage other Operators\n\nFrom [best practices][best practices]: \n\n- _\"Operators should own a CRD and only one Operator should control a CRD on a cluster.\nTwo Operators managing the same CRD is not a recommended best practice. In the case where an API exists but \nwith multiple implementations, this is typically an example of a no-op Operator because it doesn't \nhave any deployment or reconciliation loop to define the shared API and other \nOperators depend on this Operator to provide one implementation of the \nAPI, e.g. similar to PVCs or Ingress.\"_\n\n- _\"An Operator shouldn't deploy or manage other operators (such patterns are known as meta or super operators \nor include CRDs in its Operands). It's the Operator Lifecycle Manager's job to manage the deployment and \nlifecycle of operators. For further information check [Dependency Resolution][Dependency Resolution].\"_\n\n#### What does it mainly mean:\n\n- If you want to define that your Operator depends on APIs which are owned by another Operator or on \nanother whole Operator itself you should use Operator Lifecycle Manager's [Dependency Resolution][Dependency Resolution]\n- If you want to reconcile core APIs (_defined by Kubernetes_) or External APIs (_defined from other operators_)\nyou should not re-define the API as owned by your project. Therefore, you can create the controller in this \ncases by using the flag `--resource=false`. (i.e. `$ operator-sdk create api --group ship --version v1beta1 --kind External --resource=false --controller=true`). \n**Attention:** If you are using Golang-based language Operator then, you will need to update the markers and imports \nmanually until it become officially supported by the tool. For further information check the issue [#1999](https://github.com/kubernetes-sigs/kubebuilder/issues/1999).\n\n**WARNING:** if you create CRD's via the reconciliations or via the Operands then, OLM cannot handle CRDs migration and update, validation.\n\n**NOTE:** By not following this guidance you might probably to be hurting concepts like as single responsibility principle\nand damaging these concepts could cause unexpected side effects, such as; difficulty extending, reuse, or maintenance, only to mention a few. \n\n### Other common suggestions\n\n- Provide the images and tags used by the operator solution via environment variables in the `config/manager/manager.yaml`: \n\n```yaml\n...\nspec:\n  ...\n    spec:\n      ...\n      containers:\n      - command:\n        - /manager\n        ...\n        env:\n        - name: MY_IMAGE\n          value: \"quay.io/example.com/image:0.0.1\"\n```\n\n- Manage your solutions using [Status Conditionals][status-conditionals] \n- Use [finalizers][finalizers] when/if required \n- Cover the project with tests/CI to ensure its quality:\n    - For any language-based operator, you can use [Scorecard][scorecard] to implement functional tests\n    - For Go-based operators, you can also use [envtest][envtest] to cover the controllers. For further information see [Testing with EnvTest][testing-with-envtest]. Also, see the `test` directory for the Memcached sample under the [testdata/go/v3/memcached-operator][sample] to know how can you build e2e tests.\n    - For Ansible-based operators, you can also use [Molecule][molecule], an Ansible testing framework. For further information see [Testing with Molecule][molecule-tests]\n    - For Helm-based operators, you can also use [Chart tests][helm-chart-tests]\n- Ensure that you checked the [Can I customize the projects initialized with operator-sdk?][faq] and understand the [Project Layout][project-layout] before starting to do your customizations as please you on top.\n- Optimize manager resource values in `config/manager/manager.yaml` according to project requirements. It is recommended to define resources limits in order to follow good practices and for security reasons. More info: [Managing Resources for Containers][k8s-manage-resources] and [Docker Security Cheat Sheet][docker-cheats].\n- Look for `TODO(user)` in the source code generated by the CLI to ensure that you follow all suggested customizations.\n- If you wish to integrate your project with OLM, you can also check its [Best Practices][olm-best-practices] section.\n \n[env-test]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/envtest\n[scorecard]: /docs/testing-operators/scorecard/\n[testing-with-envtest]: /docs/building-operators/golang/testing\n[olm-best-practices]: https://olm.operatorframework.io/docs/best-practices/\n[finalizers]: /docs/building-operators/golang/advanced-topics/#handle-cleanup-on-deletion\n[status-conditionals]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties\n[faq]: /docs/faqs/#can-i-customize-the-projects-initialized-with-operator-sdk\n[project-layout]: /docs/overview/project-layout\n[controller-runtime]: https://github.com/kubernetes-sigs/controller-runtime\n[k8s-crd-doc]: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/\n[operator-best-practices]: /docs/best-practices/best-practices\n[kb-gkv]: https://book.kubebuilder.io/cronjob-tutorial/gvks.html\n[operator-pattern]: https://kubernetes.io/docs/concepts/extend-kubernetes/operator/\n[molecule]: https://molecule.readthedocs.io/\n[molecule-tests]: /docs/building-operators/ansible/testing-guide\n[helm-chart-tests]: https://helm.sh/docs/topics/chart_tests/\n[envtest]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/envtest\n[docker-cheats]: https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html#rule-7-limit-resources-memory-cpu-file-descriptors-processes-restarts\n[k8s-manage-resources]: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/\n[best practices]: https://olm.operatorframework.io/docs/concepts/olm-architecture/dependency-resolution/\n[Dependency Resolution]:  /docs/best-practices/best-practices\n[sample]: https://github.com/operator-framework/operator-sdk/tree/master/testdata/go/v4/memcached-operator\n"
  },
  {
    "path": "website/content/en/docs/best-practices/designing-lean-operators.md",
    "content": "---\ntitle: \"Designing Lean Operators\"\nlinkTitle: \"Designing Lean Operators\"\nweight: 5\ndescription: This guide describes good practices concepts to designing lean Operators.\n---\n\n## Overview\n\nOne of the pitfalls that many operators are failing into is that they watch resources with high cardinality like secrets possibly in all namespaces. This has a massive impact on the memory used by the controller on big clusters. Such resources can be filtered by label or fields. The original doc design for `Filter cache ListWatch using selectors` can be accessed from [here][Filter cache ListWatch using selectors]\n\n**IMPORTANT NOTE**\nRequests to a client backed by a filtered cache for objects that do not match the filter will never return anything. In other words, filtered caches make the filtered-out objects invisible to the client. \n\n## How is this done ?\n\n- When creating the manager, you can add an Options struct to configure the Cache\n- Each client.Object can be filtered with labels and fields\n\n## Examples\n\nIn this scenario, the user will configure the Cache to filter the secret object by it's label. This will return a filtered cache for objects that match the filter.\n\n```yaml\nmgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{\n  Cache: cache.Options{\n    ByObject: map[client.Object]cache.ByObject{\n      &corev1.Secret{}: cache.ByObject{\n\tLabel: labels.SelectorFromSet(labels.Set{\"app\": \"app-name\"}),\n      },\n    },\n  },\n})\n```\n\nIn this scenario, the user will configure the Cache to filter the node object by it's field name. This will return a filtered cache for objects that match the filter.\n\n```yaml\nmgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{\n  Cache: cache.Options{\n    ByObject: map[client.Object]cache.ByObject{\n      &corev1.Node{}: cache.ByObject{\n\tFields: labels.SelectorFromSet(fields.Set{\"metadata.name\": \"node01\"}),\n      },\n    },\n  },\n})\n```\n\n[Filter cache ListWatch using selectors]: https://github.com/kubernetes-sigs/controller-runtime/blob/master/designs/use-selectors-at-cache.md\n"
  },
  {
    "path": "website/content/en/docs/best-practices/managing-resources.md",
    "content": "---\ntitle: \"Managing Resources\"\nlinkTitle: \"Managing Resources\"\nweight: 5\ndescription: This guide describes good practices concepts to Managing Resources.\n---\n\n## Managing Resources\n\nNote that pretty much all controllers consume:\n\n- `CPU`: largely based on the number of reconciliations they perform, which are generally related to event activity for resources they're watching.\n- `Memory`: largely based on the number of primary resources that exist (multiplied by some factor based on the number of operand resources they need to watch as a result) via informer caches.\n\nAnd then there is a concern that one Pod or Container could monopolize all available resources and Cluster admins must \nconsider the effects that one Pod or Container may have on other components. \n\nIn an effort to prevent a container from consuming all the resources on a cluster or affecting other workloads\nfrom being scheduled, many production clusters will define [ResourceQuota][k8s-resources-quotas] configurations.\n\nThe [ResourceQuota][k8s-resources-quotas] configuration also applies to tenant workloads that are managed by\nyour Operator. Cluster administrators will typically set a [ResourceQuota][k8s-resources-quotas] for each\ntenant's namespace as part of the onboarding. If a [LimitRange][k8s-limit-range] with default values\nhas **not** been created in each namespace and your Operator creates Containers inside the tenant\nnamespace without specifying at least resource requests for CPU and Memory of its Pods then,\nthe system or quota may reject Pod creation.\nCheck the following statements obtained from K8s docs:\n\n- > _\"If a LimitRange is activated in a namespace for computing resources like CPU and memory, users must specify requests or limits for those values. Otherwise, the system may reject Pod creation.\"_ ([Reference][k8s-limit-range]).\n- > _\"If quota is enabled in a namespace for compute resources like cpu and memory, users must specify requests or limits for those values; otherwise, the quota system may reject pod creation.\"_ ([Reference][k8s-resources-quotas]).\n\nIn an effort to support clusters with the above configuration, to ensure safe operations and avoid negatively\nimpacting other workloads: Operators should **always** include reasonable memory and CPU resource requests for their own deployment as well as for operands they deploy. \n\n**HINT** Cluster admins might also able to avoid the above scenario by setting default values when they are not specified for each Pod and/or Container in a namespace.  \n\nTherefore, your Operator should **always** apply at least resource requests for `CPU` and\nmemory for `Pods/Deployments` that it creates as part of the reconciliation logic. Ideally your\nOperator also applies memory limits to those `Pods/Deployments`. You may also consider CPU limits.\n\nResource requests and limits for the Operator Deployment can be defined by modifying the`config/manager/manager.yaml`\nas shown below:\n\n```yml\n  ...\n  # TODO(user): Configure the resources accordingly based on the project requirements.\n  # More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/\n  resources:\n    requests:\n      cpu: 10m\n      memory: 64Mi\n    ...\n```\n\n### How to compute default values\n\n**IMPORTANT:** A single configuration that fits all scenarios is not possible. \nIn this way, Operators authors **MUST** to ensure that Cluster Admins and its users can change the \nresource requests/limits of the Operator/manager, and of its Operands.\n\nHowever, you are able to benchmark your Operator by [Monitoring the resource usage][k8s-metrics] \nto ensure good and reasonable values for the general cases. Kubebuilder and SDK provide some \n[metrics][kb-metrics] which can help you with.\n\n**NOTE** Also, be aware that if the project was generated by Kubebuilder or SDK scaffold\nthen some values for the `Operator/manager`(See `config/manager/manager.yaml`)\nare populated by default to get you started, however, you ought to optimize them based \non your own tests and the specific needs of your operator.\n\n### How to change the Operator/manager resources values when under OLM management\n\nIf your operator is managed by OLM, administrators or users can configure your operator's resource requests and limits\nvia the [subscription][olm-subscriptions]. \n\n### General guidelines\n\nFollowing are some general recommendations to manage the resources:\n\n- **MUST** declare resource requests for both, CPU and Memory, for the `Operator/manager`  and any `Pod/Deployment` managed by it\n- **OPTIONALLY** setting the resources limit for CPU and Memory for the Operator Pod and any `Pod/Deployment` managed by it.\n- **SHOULD** provide the mechanisms for [Monitoring compute & memory resource usage][k8s-metrics] so that, \nCluster Admins can use these metrics to monitor and resize the Operator and its Operands._**CAVEAT:** If the Operator \nis integrated with OLM and the bundle has a `PodMonitor` or a `ServiceMonitor` the complete `InstallPlan` \nwill fail on a cluster, which does not have these CRD/the Prometheus operator installed. In this case, \nyou might want to ensure the dependency requirement with [OLM dependency][olm-dep] or make clear\nits requirement for the Operator consumers._\n- **SHOULD** allow admins to customize the `requests/limits` amounts defined for the `Pod/Deployment`\n  created by the Operator and not hardcode these values.\n- **SHOULD** document how your Operator consumer can customize/rightsize the resources requests and limits for the\nOperator and Operands `Pod/Deployments` or describe how the solution could be configured to automatically adjust these values based on the environment.\nthe Operator automatically adjust the values to the environment rather than asking its consumers to amend them.\nYou might also consider leveraging the [Vertical Pod Autoscaler][k8s-vertical-pod-scaling] to have the resources requested by the Operator\nautomatically adjusted to the cluster where it is deployed. You might also\nlook at allowing [horizontal pod autoscaling][k8s-autoscaling] for the other `Pod/Deployments` created by your Operator.\nIn this case, be aware that resource requests are also required for horizontal pod autoscaling to work._**CAVEAT:** If you are using OpenShift as your Kubernetes distribution you might want to check the\ndoc [Automatically adjust pod resource levels with the vertical pod autoscaler][ocp-pod-scaling]. Also, if the VPA CRD \nis not available in the cluster where the operator gets deployed the InstallPlan will fail. \nPlease, see how to work with [OLM dependency][olm-dep] if your project integrating with it._\n\n### Why should you set these?\n\n#### Resource Requests\n\n_What happens when the resource requests are not set?_\n\n- configurations made by the cluster administrators such as [ResourceQuota][k8s-resources-quotas] might not work without LimitRanges. The LimitRanger admission controller can provide default values for resource requests and limits when they have not been defined.\n- the Operators consumers might face resource shortages on a node when resource usage increases, for example, during a daily peak in request rate.\n- the Operator's consumers might be unable to successfully deploy the Operator because it does not have the minimal resources available.\n- the scheduler cannot make an informed placement choice when it picks the nodes the operator pods will be running on.\n- when there is memory contention on the node the pod is likely to get either evicted or OOM killed.\n- when there is CPU contention on the node the pod is likely to get starved of CPU cycles making the operator unresponsive.\n\n#### Resource Limits\n\n_What happens when the resource limits are not set?_\n\nWrong configurations or code implementations can consume all resources available, affecting other components on cluster.\nAlso, it might leave the containers more vulnerable such as to Dos Attacks. [More info][docker-security]. See that when there is memory\ncontention on a node, pods will start getting evicted and possibly killed according to their OOM score. The node will be flagged with a\nMemoryPressure condition and eventually made unschedulable. However, when there is CPU contention on the node, neighbour pods may\nget slowed down to the CPU cores they requested.\n\nHowever, a popular practice by cluster administrators is to leverage [ResourceQuota][k8s-resources-quotas] to limit\nthe total amount of resources that can be requested or allowed in a single namespace.\nThis may protect against over consumption of resources by operands of a faulty or wrongly configured operator.\nOn the other hand it also means that the operator may not be able to create additional pods,\nlimiting its functionality when the limit has been reached.\n\nAlso, see might want to check in the K8s docs the following sections:\n- [Motivation for CPU requests and limits][k8s-motivations] and [If you do not specify a CPU limit][k8s-missing-cpu-limits]\n- [Motivation for Memory requests and limits][k8s-motivations-memory] and [If you do not specify a memory limit][k8s-missing-memory-limits]\n\n### What happens when:\n\n#### Limits reached\n\n_What happens when the resource limits have been reached?_\n\n- `For Memory`: the container might be terminated with the reason `OOM Killed`. If it is restartable, the kubelet will\n  restart it, as with any other type of runtime failure.\n- `For CPU`: the container might or might not be allowed to exceed its CPU limit for extended periods of time. However, \nit will not be killed for excessive CPU usage. The `CPU` is considered a \"compressible\" resource,\nand if the `Pod` starts hitting the CPU limits, Kubernetes uses kernel to starts throttling the container.\nThat means the CPU will be artificially restricted, giving a potentially worse performance only.\n\nYou might want to check the [Troubleshooting][k8s-troubleshooting] section in the Kubernetes documents to better\nunderstand how to debug these scenarios.\n\n#### Limits are specified but not requests\n\n_What happens when the resource limits are defined but not the requests?_\n\nIf you specify a CPU or Memory limit for a Container but do not specify a request, \nKubernetes automatically assigns a CPU or Memory request that matches the limit. \nIn this way, you will be requesting **always** the limit and will be allocating \nmore resources than required. (**NOT RECOMMENDED**)\n\n#### Values are too big\n\nMemory and CPU requests and limits are associated with Containers, but be aware that the Memory and CPU \nrequests and limits of a Pod are the sum of its specific computing types for all the containers in the Pod. \n\nIf you define that your Pods should have Memory or CPU request too big then, you might not only be allocating and \nblocking the usage of more than you ought unnecessarily. Also, your Operator consumers might be able to install \nyour Operator via OLM, for example, but will be unable to check the Pods/Deployment running successfully \nwhen the amount defined exceeds the capacity available. In these scenarios, the Operator consumers \nwill check that Pod(s) failed to schedule with event errors like `Insufficient cpu` and/or `Insufficient memory`. \n\n[olm-docs]: /docs/olm-integration/\n[k8s-limit-range]: https://kubernetes.io/docs/concepts/policy/limit-range/\n[k8s-resources-quotas]: https://kubernetes.io/docs/concepts/policy/resource-quotas/\n[k8s-requests-limits]: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits\n[k8s-ingress-controllers]: https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/\n[olm]: https://github.com/operator-framework/operator-lifecycle-manager\n[k8s-metrics]: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#monitoring-compute-memory-resource-usage\n[k8s-autoscaling]: https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#support-for-resource-metrics\n[k8s-vertical-pod-scaling]: https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler\n[ocp-pod-scaling]: https://docs.openshift.com/container-platform/4.9/nodes/pods/nodes-pods-vertical-autoscaler.html\n[kb-metrics]: https://book.kubebuilder.io/reference/metrics.html\n[olm-subscriptions]: https://github.com/operator-framework/operator-lifecycle-manager/blob/master/doc/design/subscription-config.md#resources\n[docker-security]: https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html#rule-7-limit-resources-memory-cp[%E2%80%A6]le-descriptors-processes-restarts\n[k8s-troubleshooting]: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#troubleshooting\n[olm-dep]: https://olm.operatorframework.io/docs/concepts/olm-architecture/dependency-resolution/\n[k8s-motivations]: https://kubernetes.io/docs/tasks/configure-pod-container/assign-cpu-resource/#motivation-for-cpu-requests-and-limits\n[k8s-missing-cpu-limits]: https://kubernetes.io/docs/tasks/configure-pod-container/assign-cpu-resource/#if-you-do-not-specify-a-cpu-limit\n[k8s-missing-memory-limits]: https://kubernetes.io/docs/tasks/configure-pod-container/assign-memory-resource/#if-you-do-not-specify-a-memory-limit\n[k8s-motivations-memory]: https://kubernetes.io/docs/tasks/configure-pod-container/assign-memory-resource/#motivation-for-memory-requests-and-limits"
  },
  {
    "path": "website/content/en/docs/best-practices/multi-tenancy.md",
    "content": "---\ntitle: \"Multi-Tenancy\"\nlinkTitle: \"Multi-Tenancy\"\nweight: 4\ndescription: This guide describes the best practices concepts to write Operators for Multi-Tenancy solutions.\n---\n\n## NetworkPolicy \n\nIf your Operator creates or manages [NetworkPolicy][k8s-network-policy] configurations ensure that your solution:\n\n* applies fine-grained network policies to the extent that is required for your managed application to function properly\n* applies fine-grained network policies to enable your managed application internal components to communicate among each other\n* allows users to configure your operator so it does not create or manage [NetworkPolicy][k8s-network-policy] instances\n* does not create `allow traffic from everywhere in the cluster` type policies\n\n[NetworkPolicies][k8s-network-policy] are popular in multi-tenant cluster to provide an extra layer\nof segregation among tenants within SDN solutions. Users typically customize this extensively with goal of disallowing network traffic among unrelated\ntenants. Operators that deploy an `accept all traffic from anywhere in the cluster` style policy, are creating an obstacle in\npursuing this goal, especially in instances where these policies cannot be disabled. In security-conscious environments policies like these are not allowed\nin production. In such cases your operator should minimally **have the option to prevent [NetworkPolicy][k8s-network-policy] objects from being\ncreated** and leave this responsibility to the user. In more advanced cases, your operator should create [NetworkPolicy][k8s-network-policy] \nconfigurations that follow the least-privilege principle, i.e. denying access to everything and from everywhere by default and only allowing access to specific authorized resources from specific authorized components.\n\n## Traffic sharding\n\nThe goal is to split or to isolated ingress traffic from certain environments, e.g. production and development environments, ending up on\ndifferent routers and in this way, being managed by a different Ingress controller. This is a popular configuration \noption for heavily populated multi-tenant clusters, with several [IngressController][k8s-ingress-controllers] deployed. \n\nIf your Operator creates ingress resources the recommendation is to allow the users to customize them,\nthrough the use of a CRD. The required \n[IngressClass][ingress-class] needs then to be \npropagated to the ingress resources created so that they get picked up by the desired [IngressController][k8s-ingress-controllers].\nAnnotations are deprecated in favour of [IngressClass][ingress-class]. \n\n### Route resources\n\nTo run on the OpenShift distribution of Kubernetes you probably will use \nthe [Route][ocp-route] API. When sharding these routes may be configured with a label selector. \nBased on this label selector they will amend their configuration when a route (having the label) \nis created or not (if the route does not have the label). The label is applied at the `Route` level\nand there is no pre-defined convention here, so users set these custom labels in\naccordance to how they configured their [IngressController from operator.openshift.io/v1][k8s-ingress-controllers] instances. \n\nIn this way, **your operator should allow the user to specify custom labels for any\nRoute that it manages**. Check the [doc][ocp-ingress-doc] and this [blog][ocp-blog] for an end-to-end examples \nand further information.\n\n[olm-docs]: /docs/olm-integration/\n[ocp-route]: https://docs.openshift.com/container-platform/4.9/rest_api/network_apis/route-route-openshift-io-v1.html#route-route-openshift-io-v1\n[ocp-ingress-doc]: https://docs.openshift.com/container-platform/4.9/networking/ingress-operator.html#nw-ingress-sharding-route-labels_configuring-ingress\n[k8s-ingress-controllers]: https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/\n[ocp-blog]: https://rcarrata.com/openshift/ocp4_route_sharding/\n[k8s-network-policy]: https://kubernetes.io/docs/concepts/services-networking/network-policies/\n[ingress-class]: https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class"
  },
  {
    "path": "website/content/en/docs/best-practices/observability-best-practices.md",
    "content": "---\ntitle: \"Operator Observability Best Practices\"\nlinkTitle: \"Observability Best Practices\"\nweight: 6\ndescription: This guide describes the best practices concepts for adding Observability to operators.\n---\n\n## Operator Observability Best Practices\n\nIn this document, we provide best practices and examples for creating metrics, [recording rules](https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/#recording-rules) and alerts. It is based on the general guidelines in [Operator Capability Levels](https://sdk.operatorframework.io/docs/overview/operator-capabilities/).\n\n**Note:** For technical documentation of how to add metrics to your operator, please read the [Metrics](https://book.kubebuilder.io/reference/metrics.html) section of the Kubebuilder documentation.\n\n### Operator Observability Recommended Components\n\n1. **Health and Performance metrics** - for all of the operator components  \n    1.1. Metrics should be implemented based on the guidelines below.  \n    1.2. **Metrics Documentation** - All metrics should have documentation.  \n    1.3. **Metrics Tests** - Metrics should include tests that verify that they exist and that their value is correct.  \n2. **Alerts** for when things are not working as expected for each of the operator's components  \n    2.1  Alerts should be implemented based on the guidelines below.  \n    2.2. **Alerts Runbooks** - Each alert can include a `runbook_url` annotation and an alert runbook that describes it. See additional details below.  \n    2.3. **Alerts Tests** - Alerts should include E2E Testing and unit tests.  \n3. **Events** - Custom Resources should emit custom events for the operations taking place.\n\nAdditional components would be `Dashboards`, `Logs` and `Traces`, which are not addressed in this document at this point.  \n\n### Operators Observability General Guidelines\n**Important:** It is highly recommended to separate your monitoring code from your core operator code.  \nWe recommend to create a dedicated `/monitoring` subfolder that will include all the code of the [Operator Observability Recommended Components](#operator-observability-recommended-components), that are outlined above. For example, in the [memcached-operator](https://github.com/operator-framework/operator-sdk/tree/master/testdata/go/v4/monitoring/memcached-operator/monitoring).\n\nIn your core operator code only call the functions that will update the metrics value from your desired location. For example, in the [memcached-operator](https://github.com/operator-framework/operator-sdk/blob/367bd3597c30607099aa73637f5286f7120b847a/testdata/go/v3/monitoring/memcached-operator/controllers/memcached_controller.go#L242).\n\nAll operators start small. This separation will help you, as a developer, with easier maintenance of both your operator core code and the monitoring code and for other stakeholders to understand your monitoring code better.\n\n### Metrics Guidelines\n\n#### Metrics Naming\nKubernetes components emit metrics in [Prometheus format](https://prometheus.io/docs/instrumenting/exposition_formats/). This format is structured plain text, designed so that people and machines can both read it.\n\nYour operator users should get the same experience when searching for a metric across Kubernetes operators, resources and custom resources.\n1. Check if a similar Kubernetes metric, for node, container or pod, exists and try to align to it.\n2. The metrics search list, in the Prometheus, Grafana UI and even in the /metrics end point, is sorted in alphabetical order.\nWhen searching for a metric, it should be easy to identify metrics that are related to a specific operator.\nThat is why we recommend that your operator metrics name will follow this format:\n`operator name` prefix + the `sub-operator name` or `entity` + `metric name` based on the [Prometheus naming conventions](https://prometheus.io/docs/practices/naming/). For example, in the [memcached-operator](https://github.com/operator-framework/operator-sdk/blob/0d2fa86f0d3cc92c4672cb9e1d246efaefcf7ced/testdata/go/v4-alpha/monitoring/memcached-operator/monitoring/metrics.go#L14).\n\n**Note:** In [Prometheus Node Exporter](https://github.com/prometheus/node_exporter) metrics are separated like this:\n- node_network_**receive**_packets_total\n- node_network_**transmit**_packets_total  \n \nIn this example, based on `receive` and `transmit`.\n\nPlease follow the same principle and don't put similar metrics details as labels, so the user experience would be fluent.  \nExample for this in an operator:\n- kubevirt_vmi_network_**receive**_errors_total\n- kubevirt_vmi_network_**transmit**_bytes_total\n- kubevirt_migrate_vmi_**data_processed**_bytes\n- kubevirt_migrate_vmi_**data_remaining**_bytes\n\n3. Your metric suffix should indicate the metric unit. For better compatibility, [Prometheus base units](https://prometheus.io/docs/practices/naming/#base-units) should be used.\n4. Prometheus supports four [metric types](https://prometheus.io/docs/concepts/metric_types/#metric-types). `Gauge`,`Counter`,`Histogram` and `Summary`. You can read more about the different types here, [Understanding metrics types](https://prometheus.io/docs/tutorials/understanding_metric_types/#types-of-metrics).  \nThe most common types are:\n - `Counter` - Value can only increase or reset.\n - `Gauge` Value can be increased and decreased as needed.\n5. `_total` suffix should be used for accumulating count. If your metrics has labels with high cardinality, like `pod`/`container` it usually means that you can aggregate it more, thus it will not require `_total` suffix.\n\n### Prometheus Labels\n[Prometheus labels](https://prometheus.io/docs/practices/naming/#labels) are used to differentiate the characteristics of the thing that is being measured.\n\n1. **Important** - Be cautious when adding labels to metrics. Labels can dramatically increase the amount of data stored. Do not use labels to store dimensions with high cardinality (many different label values), such as user IDs, email addresses, or other unbounded sets of values. Note: There are still cases when we will still need to have a high cardinality label like the `pod name`, but try to keep this to the minimum.\n2. When creating a new metric, recording rule or alert, that reports a resource like a `pod` or a `container`, make sure that the `namespace` is included, in order to be able to uniquely identify it.\n\n#### Metrics `Help` message\n\nYour operator metrics `help` message should include the following details:\n- What does this metric measure?\n- What does the output mean?\n- What important labels does the metric use? (Optional. If applicable).\n\nThe `Help` message can be used to create auto-generated documentation, like it's done in [KubeVirt](https://github.com/kubevirt/kubevirt/blob/main/docs/observability/metrics.md) and generated by the [KubeVirt metrics doc generator](https://github.com/kubevirt/kubevirt/blob/main/tools/doc-generator/doc-generator.go).\n\nWe recommend to auto-generated metrics documentation and save it in your operator repository, to a location like `/docs/monitoring/`, so that the users can find the information about your operator metrics easily. \n\nSee [Alerts, Metrics and Recording Rules Tests](#alerts-metrics-and-recording-rules-tests) section for metrics testing recommendations. \n\n#### Prometheus Recording Rules Naming\nAs per [Prometheus](https://prometheus.io/docs/prometheus) documentation, [Recording rules](https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/#recording-rules) allow you to pre-compute frequently needed or computationally expensive expressions and save their result as a new set of time series.\n\n**Note:** The Prometheus recording rules appear in Prometheus UI as metrics.\nRecording rule names should follow the `level:metric:operations` format as specified in the [Prometheus recording rules best practices](https://prometheus.io/docs/practices/rules/). This naming convention makes it clear that the metric is a recording rule and helps consumers understand they need to examine the underlying query to fully understand what the metric provides.\n\n- **level:** represents the aggregation level and labels of the rule output\n- **metric:** is the metric name  \n- **operations:** is a list of operations that were applied to the metric, newest operation first\n\nFor example: `job:up:avg_over_time` or `instance:node_cpu_utilisation:rate5m`\n\nIn addition to this format, your operator recording rules should also follow the same naming guidelines as metrics for consistency within your operator's observability stack.\n\nSee [Alerts, Metrics and Recording Rules Tests](#alerts-metrics-and-recording-rules-tests) section for recording rules testing recommendations. \n\n### Prometheus Alerts Guidelines\nClear and actionable alerts are a key component of a smooth operational experience and will result in a better experience for the end users.\n\nThe following guidances aim to align alert naming, severities, labels, etc., in order to avoid alerts fatigue for administrators.\n\n#### Recommended Reading\n\nA list of references on good alerting practices:\n\n* [Google SRE Book - Monitoring Distributed Systems](https://sre.google/sre-book/monitoring-distributed-systems/)\n* [Prometheus Alerting Documentation](https://prometheus.io/docs/practices/alerting/)\n* [Alerting for Distributed Systems](https://www.usenix.org/sites/default/files/conference/protected-files/srecon16europe_slides_rabenstein.pdf)\n\n#### Alert Ownership\n\nIndividual operator authors are responsible for writing and maintaining alerting rules for\ntheir components, i.e. their operators and operands.\n\nOperator authors should also take into consideration how their components interact with\nexisting monitoring and alerting.\n\nAs an example, if your operator deploys a service which creates one or more `PersistentVolume` resources,\nand these volumes are expected to be mostly full as part of normal operation, it's likely\nthat this will cause unnecessary `KubePersistentVolumeFillingUp` alerts to fire.\n\nYou should work to find a solution to avoid triggering these alerts if they are not actionable.\n\n#### Alerts Style Guide\n\n* Alert names MUST be CamelCase, e.g.: `PrometheusRuleFailures`\n* Alert names SHOULD be prefixed with a component, e.g.: `AlertmanagerFailedReload`\n  * There may be exceptions for some broadly scoped alerts, e.g.: `TargetDown`\n* Alerts MUST include a `severity` label indicating the alert's urgency.\n  * Valid severities are: `critical`, `warning`, or `info` — see below for\n    guidelines on writing alerts of each severity.\n* Alerts MUST include `summary` and `description` annotations.\n  * Think of `summary` as the first line of a commit message, or an email\n    subject line.  It should be brief but informative.  The `description` is the\n    longer, more detailed explanation of the alert.\n* Alerts SHOULD include a `namespace` label indicating the source of the alert.\n  * Many alerts will include this by virtue of the fact that their PromQL\n    expressions result in a namespace label.  Others may require a static\n    namespace label — see for example, the [KubeCPUOvercommit](https://github.com/openshift/cluster-monitoring-operator/blob/79cdf68/assets/control-plane/prometheus-rule.yaml#L235-L247) alert.\n\n\n**Optional Alerts Labels and Annotations**\n* `priority` label indicating the alert's level of importance and the order in which it should be fixed.\n  * Valid priorities are: `high`, `medium`, or `low`.\n    Higher the priority the sooner the alert should be resolved.\n  * If the alert doesn't include a `priority` label, we can assume it is a `medium` priority alert.\nThis label will usually be used for alerts with `warning` severity, to indicate the order in which the alert should be addressed by, even though it doesn't require immediate action.\n* `runbook_url` annotation is a link to an alert runbook which is intended to guide a cluster owner and/or operator through the steps of fixing problems on clusters, which are surfaced by alerts.\n  * An example for [Runbook style documentation](https://github.com/openshift/runbooks/blob/master/example.md).\n  * Your operator alert runbooks can be saved at your operator repository, to `/docs/monitoring/runbooks/` for example,\n    at [OpenShift Runbooks](https://github.com/openshift/runbooks) if your operator is shipped with OpenShift\n    or another location that fits your operator.\n  * If you are using Github, you can use [Github Pages](https://pages.github.com/) for a better view of the runbooks.\n* `kubernetes_operator_part_of` label indicating the operator name. Label name is based on the  [Kubernetes Recommended Labels](https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/#labels).\n\n#### Alerts Severity\n##### Critical Alerts\n\nFor alerting current and impending disaster situations. These alerts\npage an SRE. The situation should warrant waking someone in the middle of the\nnight.\n\nTimeline:  ~5 minutes.\n\nReserve critical level alerts only for reporting conditions that may lead to loss of data or inability to deliver service for the cluster as a whole.  \nFailures of most individual components should not trigger critical level alerts, unless they would result in either of those conditions.  \nConfigure critical level alerts so they fire before the situation becomes irrecoverable.  \nExpect users to be notified of a critical alert within a short period of time after it fires so\nthey can respond with corrective action quickly.\n\nExample critical alert: [KubeAPIDown](https://github.com/openshift/cluster-monitoring-operator/blob/79cdf68/assets/control-plane/prometheus-rule.yaml#L412-L421)\n\n```yaml\n- alert: KubeAPIDown\n  annotations:\n    summary: Target disappeared from Prometheus target discovery.\n    description: KubeAPI has disappeared from Prometheus target discovery.\n    runbook_url: https://github.com/openshift/runbooks/blob/master/alerts/cluster-monitoring-operator/KubeAPIDown.md\n  expr: |\n    absent(up{job=\"apiserver\"} == 1)\n  for: 15m\n  labels:\n    severity: critical\n```\n\nThis alert fires if no Kubernetes API server instance has reported metrics successfully in the last 15 minutes.  \nThis is a clear example of a critical control-plane issue that represents a threat to the operability of the cluster as a whole, and likely warrants paging someone.  \nThe alert has clear summary and description annotations, and it links to a runbook with information on investigating and resolving the issue.\n\nThe group of critical alerts should be small, very well defined, highly documented, polished and with a high bar set for entry.\n\n##### Warning Alerts\n\nThe vast majority of alerts should use this severity.  \nIssues at the warning level should be addressed in a timely manner, but don't pose an immediate threat to the operation of the cluster as a whole.\n\nTimeline:  ~60 minutes\n\nIf your alert does not meet the criteria in \"Critical Alerts\" above, it belongs to the warning level or lower.\n\nUse warning level alerts for reporting conditions that may lead to inability to deliver individual features of the cluster, but not service for the cluster as a\nwhole. Most alerts are likely to be warnings.  \nConfigure warning level alerts so that they do not fire until components have sufficient time to try to recover from the interruption automatically.  \nExpect users to be notified of a warning, but for them not to respond with corrective action immediately.\n\nExample warning alert: [ClusterNotUpgradeable](https://github.com/openshift/cluster-version-operator/blob/513a2fc/install/0000_90_cluster-version-operator_02_servicemonitor.yaml#L68-L76)\n\n```yaml\n- alert: ClusterNotUpgradeable\n  annotations:\n    summary: One or more cluster operators have been blocking minor version cluster upgrades for at least an hour.\n    description: In most cases, you will still be able to apply patch releases.\n      Reason {{ \"{{ with $cluster_operator_conditions := \\\"cluster_operator_conditions\\\" | query}}{{range $value := .}}{{if and (eq (label \\\"name\\\" $value) \\\"version\\\") (eq (label \\\"condition\\\" $value) \\\"Upgradeable\\\") (eq (label \\\"endpoint\\\" $value) \\\"metrics\\\") (eq (value $value) 0.0) (ne (len (label \\\"reason\\\" $value)) 0) }}{{label \\\"reason\\\" $value}}.{{end}}{{end}}{{end}}\"}}\n      For more information refer to 'oc adm upgrade'{{ \"{{ with $console_url := \\\"console_url\\\" | query }}{{ if ne (len (label \\\"url\\\" (first $console_url ) ) ) 0}} or {{ label \\\"url\\\" (first $console_url ) }}/settings/cluster/{{ end }}{{ end }}\" }}.\n    expr: |\n      max by (name, condition, endpoint) (cluster_operator_conditions{name=\"version\", condition=\"Upgradeable\", endpoint=\"metrics\"} == 0)\n    for: 60m\n    labels:\n      severity: warning\n```\n\nThis alert fires if one or more operators have not reported their `Upgradeable` condition as true in more than an hour.  \nThe alert has a clear name and informative summary and description annotations.  \nThe timeline is appropriate for allowing the operator a chance to resolve the issue automatically, avoiding the need to alert an administrator.\n\n##### Info Alerts\n\nInfo level alerts represent situations an administrator should be aware of, but they don't necessarily require any action.  \nUse these sparingly, and consider instead reporting this information via Kubernetes events.\n\nExample info alert: [MultipleContainersOOMKilled](https://github.com/openshift/cluster-monitoring-operator/blob/79cdf68/assets/cluster-monitoring-operator/prometheus-rule.yaml#L326-L338)\n\n```yaml\n- alert: MultipleContainersOOMKilled\n  annotations:\n    description: Multiple containers were out of memory killed within the past\n      15 minutes. There are many potential causes of OOM errors, however issues\n      on a specific node or containers breaching their limits is common.\n      summary: Containers are being killed due to OOM\n  expr: sum(max by(namespace, container, pod) (increase(kube_pod_container_status_restarts_total[12m]))\n    and max by(namespace, container, pod) (kube_pod_container_status_last_terminated_reason{reason=\"OOMKilled\"}) == 1) > 5\n  for: 15m\n  labels:\n    namespace: kube-system\n    severity: info\n```\n\nThis alert fires if multiple containers have been terminated due to out of memory conditions in the last 15 minutes.  \nThis is something the administrator should be aware of, but may not require immediate action.\n\n### Alerts, Metrics and Recording Rules Tests\n\n1. Add tests for alerts that validate that:\n   - Each alert includes all mandatory fields.\n   - Each `runbook_url` link is valid.\n   - Each alert that includes a `pod` or a `container` also includes the `namespace`.\n2. Add e2e tests that inspect the alerts during upgrade and make sure that the alerts don’t fire when they shouldn’t (Zero noise).\n3. Add tests for metrics and recording rules that validate that:\n   - Metric / Recording rule exists.\n   - Metric / Recording rule value is as expected.\n   - Metric / Recording rule name follows the best practices guideline."
  },
  {
    "path": "website/content/en/docs/best-practices/pod-security-standards.md",
    "content": "---\ntitle: \"Pod Security Standards\"\nlinkTitle: \"Pod Security Standards\"\nweight: 5\ndescription: This guide describes best practices for security standards for Operators and Operands. This guide will also cover how to configure the Pods/Containers that will be created when your Operator is installed with OLM.\n---\n\n## Overview\n\nThe [PodSecurityPolicy][pod-security] API is deprecated and will be removed from Kubernetes in version 1.25. \nThis API is replaced by a new built-in admission controller ([KEP-2579: Pod Security Admission Control][2579-psp-replacement]) which allows cluster admins to [enforce \n Pod Security Standards Labels][enforce-standards-namespace-labels].\n\n### What does that mean?\n\nNamespace and Pod/Container can be defined with three different policies which are; **Privileged, Baseline and Restricted.** \n([More info][security-standards]). Therefore, Pod(s)/Container(s) that \nare **not** configured according to the enforced security standards defined globally or\non the namespace level will **not** be admitted and it will **not** be possible to run them.\n\n**As a best practice, you must ensure that workloads (Operators and Operands) are defined to run under \nrestricted permissions unless they need further privileges. For the cases where Pod/Container(s) requires \nescalating permissions, the recommendation is to use the label as described below**\n\n### How should I configure my Operators and Operands to comply with the criteria?\n\n- **For common cases that do not require escalating privileges:** configure all containers to comply with the [restricted][restricted] policy as shown in the following the examples:\n\n**IMPORTANT NOTE** The `seccompProfile` field to define that a container is [restricted][restricted] was introduced with K8s `1.19` and might **not** be supported on some vendors by default.\nPlease, do **not** use this field if you are looking to build Operators that work on K8s versions < `1.19` or on vendors that do **not** support this field. Having this field when it is not supported can result in your Pods/Containers **not** being allowed to run (i.e. On Openshift versions < `4.11` with its default configuration the deployments will fail with errors like `Forbidden: seccomp`.)\n\n**In Kubernetes manifests:**\n\n```yaml\n    spec:\n      securityContext:\n        # WARNING: Ensure that the image used defines an UserID in the Dockerfile\n        # otherwise the Pod will not run and will fail with `container has runAsNonRoot and image has non-numeric user`.\n        # If you want your workloads admitted in namespaces enforced with the restricted mode in OpenShift/OKD vendors\n        # then, you MUST ensure that the Dockerfile defines a User ID OR you MUST leave the `RunAsNonRoot` and\n        # RunAsUser fields empty.\n        runAsNonRoot: true\n        # Please ensure that you can use SeccompProfile and do not use\n        # if your project must work on old Kubernetes\n        # versions < 1.19 or on vendors versions which\n        # do NOT support this field by default (i.e. Openshift < 4.11 )\n        seccompProfile:\n          type: RuntimeDefault\n      ...\n      containers:\n      - name: controller-manager\n        securityContext:\n          allowPrivilegeEscalation: false\n          capabilities:\n            drop:\n            - ALL\n        ...\n```\n\n**On Reconciliations, such as code implementation in Go:**\n\n**Note:** *if you are setting the `RunAsNonRoot` value to `true` in the `SecurityContext` you will need to verify that the Pod or Container(s) are running with a numeric user that is not 0 (root). If the Pod or Container(s) do not use a non-zero numeric user, you can use the `RunAsUser` value to set the user to a non-zero numeric user. In this example, the memcached container does not use a non-zero numeric user and therefore the `RunAsUser` value is set to use a uid of `1000`.*\n```go\ndep:= &appsv1.Deployment{\n  ObjectMeta: metav1.ObjectMeta{\n  ….\n  },\n  Spec: appsv1.DeploymentSpec{\n    …\n     Template: corev1.PodTemplateSpec{\n       ….\n        Spec: corev1.PodSpec{\n           // Ensure restricted context for the Pod    \n           SecurityContext: &corev1.PodSecurityContext{\n              RunAsNonRoot: &[]bool{true}[0],\n\t\t\t  // Please ensure that you can use SeccompProfile and do NOT use\n\t\t\t  // this filed if your project must work on old Kubernetes\n\t\t\t  // versions < 1.19 or on vendors versions which \n\t\t\t  // do NOT support this field by default (i.e. Openshift < 4.11)\n              SeccompProfile: &corev1.SeccompProfile{\n                 Type: corev1.SeccompProfileTypeRuntimeDefault,\n              },\n           },\n           Containers: []corev1.Container{{\n              Image:   \"memcached:1.4.36-alpine\",\n              Name:    \"memcached\",\n              // Ensure restricted context for the container  \n              SecurityContext: &corev1.SecurityContext{\n\t\t\t\t // WARNING: Ensure that the image used defines an UserID in the Dockerfile\n\t\t\t\t // otherwise the Pod will not run and will fail with `container has runAsNonRoot and image has non-numeric user`.\n\t\t\t\t // If you want your workloads admitted in namespaces enforced with the restricted mode in OpenShift/OKD vendors \n\t\t\t\t // then, you MUST ensure that the Dockerfile defines a User ID OR you MUST leave the `RunAsNonRoot` and\n\t\t\t\t // RunAsUser fields empty. \n                 RunAsNonRoot:  &[]bool{true}[0],\n                 AllowPrivilegeEscalation:  &[]bool{false}[0],\n                 Capabilities: &corev1.Capabilities{\n                    Drop: []corev1.Capability{\n                       \"ALL\",\n                    },\n                 },\n              },\n           }},\n        },\n     },\n  },\n}\n```\n\n**For Ansible and Helm language based Operators:** Ansible playbooks or Helm charts MUST create manifests that comply \nwith the requirements in the same way. You can find some examples by looking at the samples under the \n[testdata](https://github.com/operator-framework/operator-sdk/tree/master/testdata) directory.\n\n- **For workloads that need elevated permissions:** it is recommended that you ensure the namespace containing your \nsolution is labeled accordingly. You can either update your operator to manage the namespace labels or include \nthe namespace labeling as part of the manual install instructions. \n\nIt is recommended that you provide a description to help cluster admins understand why elevated permissions are required.\nYou can add this information and the prerequisites to the description of your \nOperator Bundle (CSV).\n\nFollowing you will find a detailed description of how to configure and test your solutions. \nThe most straightforward way to ensure if your workloads will work in a restricted namespace is verifying if your solution can run in namespaces enforced as restricted. \n\n**NOTE**: It is recommended that you test the desired behavior as part of an e2e test suite. Examples of an e2e test for this will be shown in a later section.\n\n### How the Operator bundle (CSV) must be configured to apply the standards to the Pod/Containers which are installed by OLM (Operator itself)?\n\nFor Operators integrated with OLM, there is an Operator bundle with a CSV where the `spec.install.spec.deployments` has a Deployment \nwhich defines the Pod/Container(s) that will be installed by OLM to get your Operator running on the cluster. \nIn order for the security standards to be followed you will need to ensure the configurations are set correctly.\n\n**Note: Ensure the configuration is carried to the Pod/Containers on the bundle CSV after running make bundle**. See that \nthe Operator bundle generated with the target is built from the manifests under the `config` directory. To know more about\nthe layout of your operator built with Operator-SDK see [Project Layout][project-layout].\n\nTo check an example of a CSV which complies with the [restricted][restricted] policy, see the Golang sample\nunder the [testdata/go/v4/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml](https://github.com/operator-framework/operator-sdk/blob/master/testdata/go/v4/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml)\n\n### How can I verify my manifest? \n\n#### Using Kind\n\nTo verify the policy of your Pod/Container(s) you might to use a [Kind](https://kind.sigs.k8s.io/docs/user/quick-start/)\ncluster as described in the [K8s documentation](https://kubernetes.io/docs/tutorials/security/cluster-level-pss/).\n\n**Example**\n\n1. First lets create a namespace where we will test the files:\n\n```sh\nkubectl create ns mytest\n```\n\n2. Now, let's label the namespace so that we can check our manifest\n\n```sh\n kubectl label --overwrite ns mytest \\\n   pod-security.kubernetes.io/enforce=restricted \\\n   pod-security.kubernetes.io/enforce-version=v1.24 \\\n   pod-security.kubernetes.io/audit=restricted\n```\n\n3. Now, apply the following Pod which is **not** restricted on the namespace:\n\n```yaml\napiVersion: v1\nkind: Pod\nmetadata:\n name: example\n namespace: mytest\nspec:\n containers:\n  - name: test\n    securityContext:\n     # see that we are allowing privilege escalation  \n     allowPrivilegeEscalation: true \n    image: 'busybox:1.28'\n    ports:\n     - containerPort: 8080\n\n```\n\n4. Then, when we try to apply the Pod manifest above we should see an error:\n\n```sh\n$ kubectl apply -f mypodtest.yaml \nError from server (Forbidden): error when creating \"mypodtest.yaml\": pods \"example\" is forbidden: violates PodSecurity \"restricted:v1.24\": allowPrivilegeEscalation != false (container \"test\" must set securityContext.allowPrivilegeEscalation=false), unrestricted capabilities (container \"test\" must set securityContext.capabilities.drop=[\"ALL\"]), runAsNonRoot != true (pod or container \"test\" must set securityContext.runAsNonRoot=true), seccompProfile (pod or container \"test\" must set securityContext.seccompProfile.type to \"RuntimeDefault\" or \"Localhost\")\n```\n\n#### How do I check what policy (Privileged, Baseline and Restricted) is configured for my Operator and Operand(s)?\n\nAn easy way might be using the tool: [psachecker][psachecker]. This tool is only\nable to be used to check locally the `Deployments/Pods` manifests and not the CSV.\n\nAlternatively, you could test the policy enforcement by labeling the namespaces and running your operator or applying the manifests. [More info][enforce-standards-namespace-labels].\n\n##### How do I install psachecker?\n\nThe following steps will install [psachecker][psachecker] in a Golang environment.\n\n```sh\ngit clone git@github.com:stlaz/psachecker.git $GOPATH/src/github.com/stlaz/psachecker\ncd $GOPATH/src/github.com/stlaz/psachecker\nmake build\ncp kubectl-psachecker $GOPATH/bin/\n```\n\n#### How do I use psachecker to verify the policy of a manifests?\n\nThe following steps will demonstrate how we can use [psachecker][psachecker] to verify that our Operator and deployments are properly configured in the CSV.\n\n- Create a new `test.yaml` file\n- Add Deployment schema to the file:\n\n```yaml\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: test-manifest\n  namespace: test\nspec:\n...\n```\n\n- Now, add the CSV deployment to this test (`spec.install.spec.deployments`) \n- Then, you can run the tool and check if its result will be `restricted` as expected (i.e.):\n\n```sh\n$ kubectl-psachecker inspect-workloads -f test.yaml\nsystem: restricted\n```\n\n### Can I use the metrics to check if my Pod/Containers are violating the PodSecurity policies?\n\nYes, you can. You need to label the namespaces with `pod-security.kubernetes.io/audit: restricted` \n(i.e. `kubectl label --overwrite ns --all pod-security.kubernetes.io/enforce-version=v1.24 pod-security.kubernetes.io/audit=restricted`).\n It is important to note that the results may include metrics that do not come from your Operator and Operand(s). \nIf you are looking to use the metrics to do the checks, ensure that you check the\nresults before and after performing the tests, for example: \n\n```sh\nkubectl get --raw /metrics | prom2json | jq '[.[] | select(.name==\"pod_security_evaluations_total\") ]'\n```\n```json\n[\n  {\n    \"name\": \"pod_security_evaluations_total\",\n    \"help\": \"[ALPHA] Number of policy evaluations that occurred, not counting ignored or exempt requests.\",\n    \"type\": \"COUNTER\",\n    \"metrics\": [\n      {\n        \"labels\": {\n          \"decision\": \"allow\",\n          \"mode\": \"enforce\",\n          \"policy_level\": \"privileged\",\n          \"policy_version\": \"latest\",\n          \"request_operation\": \"create\",\n          \"resource\": \"pod\",\n          \"subresource\": \"\"\n        },\n        \"value\": \"29\"\n      },\n      {\n        \"labels\": {\n          \"decision\": \"allow\",\n          \"mode\": \"enforce\",\n          \"policy_level\": \"privileged\",\n          \"policy_version\": \"latest\",\n          \"request_operation\": \"update\",\n          \"resource\": \"pod\",\n          \"subresource\": \"\"\n        },\n        \"value\": \"0\"\n      },\n      {\n        \"labels\": {\n          \"decision\": \"deny\",\n          \"mode\": \"audit\",\n          \"policy_level\": \"restricted\",\n          \"policy_version\": \"latest\",\n          \"request_operation\": \"create\",\n          \"resource\": \"controller\",\n          \"subresource\": \"\"\n        },\n        \"value\": \"6\"\n      },\n      {\n        \"labels\": {\n          \"decision\": \"deny\",\n          \"mode\": \"audit\",\n          \"policy_level\": \"restricted\",\n          \"policy_version\": \"latest\",\n          \"request_operation\": \"create\",\n          \"resource\": \"pod\",\n          \"subresource\": \"\"\n        },\n        \"value\": \"7\"\n      },\n      {\n        \"labels\": {\n          \"decision\": \"deny\",\n          \"mode\": \"warn\",\n          \"policy_level\": \"restricted\",\n          \"policy_version\": \"latest\",\n          \"request_operation\": \"create\",\n          \"resource\": \"controller\",\n          \"subresource\": \"\"\n        },\n        \"value\": \"6\"\n      },\n      {\n        \"labels\": {\n          \"decision\": \"deny\",\n          \"mode\": \"warn\",\n          \"policy_level\": \"restricted\",\n          \"policy_version\": \"latest\",\n          \"request_operation\": \"create\",\n          \"resource\": \"pod\",\n          \"subresource\": \"\"\n        },\n        \"value\": \"7\"\n      }\n    ]\n  }\n]\n```\nAlso, you might be able to create Prometheus alerts such as:\n\n```sh\nsum (increase(pod_security_evaluations_total{decision=\"deny\",mode=\"audit\"}[1h])) by (policy_level)\n```\n\n### (Recommended) How can I automate this check using e2e testing to ensure that my solutions can run under the policies?\n\nIn the tests, you can create and label a namespace with the desired policy (i.e. restricted). This would allow you to verify\nif any warnings/errors occur and if the Pod(s)/Container(s) are in the `Running` state. It can be something like:\n\n**NOTE** See the `test` directory for the Memcached sample under the [testdata/go/v3/memcached-operator][sample] to see a full example.\n\n```go\n// namespace store the ns where the Operator and Operand(s) will be executed\nconst namespace = \"my-operator-system\"\n\nvar _ = Describe(\"my operator test\", func() {\n    BeforeEach(func() {\n        ...\n        \n        // Where we will create the namespace for to install the Operator and Operands\n        By(\"creating namespace\")\n        cmd := exec.Command(\"kubectl\", \"create\", \"ns\", namespace)\n        _, _ = utils.Run(cmd)\n        \n        // We will label as follows all namespaces so that we can check if warnings will be raised when \n\t\t// a manifest be applied. (Not that some namespaces might not acced the label, i.e. if it\n\t\t// has a container running with a less restrictive policy )\n        By(\"labeling all namespaces to warn against what can violate the restricted policy\")\n        cmd = exec.Command(\"kubectl\", \"label\", \"--overwrite\", \"ns\", \"--all\",\n            \"pod-security.kubernetes.io/audit=restricted\",\n            \"pod-security.kubernetes.io/enforce-version=v1.24\",\n            \"pod-security.kubernetes.io/warn=restricted\")\n        _, err := utils.Run(cmd)\n        ExpectWithOffset(1, err).NotTo(HaveOccurred())\n        \n\t\t// We will enforce the restricted policy so that if our Operator\n\t\t// or Operand be unable to run as restricted we will be able to check\n\t\t// it by validating their status\n        By(\"enforcing restricted to the ns where the Operator/Operand(s) will be checked\")\n        cmd = exec.Command(\"kubectl\", \"label\", \"--overwrite\", \"ns\", namespace,\n            \"pod-security.kubernetes.io/audit=restricted\",\n            \"pod-security.kubernetes.io/enforce-version=v1.24\",\n            \"pod-security.kubernetes.io/enforce=restricted\")\n        _, err = utils.Run(cmd)\n        Expect(err).To(Not(HaveOccurred()))\n        })\n    })\n    \n    AfterEach(func() {\n        ...\n    })\n\n    It(\"should successfully run the Operator and Operand(s)\", func() {\n        // Then, here we build the operator and deploy the\n        // manager as the operand in the namespaces were \n        // the policy restricted was enforced.\n\t\t\n        // Therefore, we can check the Operator and Operand\n        // status to ensure that all is Running.\n\t\t\n        // Note that we can also verify if warns like with\n        // the message Warning: would violate PodSecurity were \n        // returned when the manifest were applied on the cluster\n    })\n})\n```\n\n### After following the recommendations to be restricted my workload is not running (CreateContainerConfigError). What should I do?\n\nIf you are encountering errors similar to `Error: container has runAsNonRoot and image has non-numeric user` \nor `container has runAsNonRoot and image will run as root` that means that the image used does not have a non-zero numeric user defined, i.e.:\n\n```shell\nUSER 65532:65532 \nOR\nUSER 1001\n```\n\nDue to the `RunAsNonRoot` field being set to `true`, we need to force the user in the\ncontainer to a non-zero numeric user.\nIt is recommended that the images used by your operator have a non-zero numeric user set in the image itself (similar to the example above). For further information check the note [Consider an explicit UID/GID][docker-good-practices-doc] in the Dockerfile best practices guide.\nIf your Operator will be distributed and used in vanilla Kubernetes clusters you can also fix the issue by defining the user via the security context configuration). (i.e. `RunAsUser: &[]int64{1000}[0],`). \n\n**NOTE** If your Operator should work with specific vendors please ensure that you check if they have specific rules for Pod Security Admission.  For example, we know that if you use `RunAsUser` on OpenShift it will disqualify the Pod from their restricted-v2 SCC. \nTherefore, if you want your workloads running in namespaces labeled to enforce restricted you must leave `RunAsUser` and `RunAsNonRoot` fields empty or if you want set `RunAsNonRoot` then, you MUST ensure that the image itself properly defines the UserID.\n\n[project-layout]: /docs/overview/project-layout\n[pod-security]: https://kubernetes.io/blog/2021/04/06/podsecuritypolicy-deprecation-past-present-and-future/#what-is-podsecuritypolicy\n[2579-psp-replacement]: https://github.com/kubernetes/enhancements/tree/master/keps/sig-auth/2579-psp-replacement\n[enforce-standards-namespace-labels]: https://kubernetes.io/docs/tasks/configure-pod-container/enforce-standards-namespace-labels/\n[restricted]: https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted\n[security-standards]: https://kubernetes.io/docs/concepts/security/pod-security-standards/\n[psachecker]: https://github.com/stlaz/psachecker\n[sample]: https://github.com/operator-framework/operator-sdk/tree/master/testdata/go/v4/memcached-operator\n[docker-good-practices-doc]: https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#user\n"
  },
  {
    "path": "website/content/en/docs/best-practices/resource-pruning.md",
    "content": "---\ntitle: \"Resource pruning\"\nlinkTitle: \"Resource Pruning\"\nweight: 3\ndescription: Recommendations for pruning resources\n---\n\n## Overview\n\nOperators can create [Jobs][jobs] or Pods as part of their normal operation, and when those Jobs or Pods\ncomplete, they can remain on the Kubernetes cluster if not specifically removed. These resources\ncan consume valuable cluster resources like disk storage (e.g. etcd). These resources\nare not tied to a Custom Resource using an `ownerReference`.\n\nOperator authors have traditionally had two pruning options:\n\n * leave the resource cleanup to a system admin to perform\n * implement some form of pruning within their operator solution\n\nFor our purposes when we say, *prune*, we mean to remove a resource (e.g. kubectl delete) from\na Kubernetes cluster for a given namespace.\n\nThis documentation describes the pattern and library useful for implementing a solution within an operator.\n\n## operator-lib prune library\n\nA simple pruning implementation can be found in the [operator-lib prune package][operator-lib-prune]. This \npackage is written in Go and is meant to be used within Go-based operators. This package was \ndeveloped to include common pruning strategies as found in common operators. The package also allow \nfor customization of hooks and strategies.\n\n### Pruning Configuration\n\nUsers can configure the pruning library by creating code similar to this example:\n```golang\ncfg = Config{\n\tLog:           logf.Log.WithName(\"prune\"),\n\tDryRun:        false,\n\tClientset:     client,\n\tLabelSelector: \"app=churro\",\n\tResources: []schema.GroupVersionKind{\n\t\t{Group: \"\", Version: \"\", Kind: PodKind},\n\t},\n\tNamespaces: []string{\"default\"},\n\tStrategy: StrategyConfig{\n\t\tMode:            MaxCountStrategy,\n\t\tMaxCountSetting: 1,\n\t},\n\tPreDeleteHook: myhook,\n}\n```\n\n\n| Config Field | Description\n| ------------ | -----------\n| Log          | a logr.Logger. It is optional if a logger is provided through the context to the Execute method, which is the case with the context of the Reconcile function of operator-sdk and controller-runtime\n| DryRun       | a boolean determines whether to actually remove resources; `true` means to execute but not to remove resources\n| Clientset    | a client-go Kubernetes ClientSet that will be used for Kube API calls by the library\n| LabelSelector| Kubernetes label selector expression used to find resources to prune\n| Resources    | Kube resource Kinds, currently PodKind and JobKind are supported by the library\n| Namespaces   | a list of Kube Namespaces to search for resources\n| Strategy     | specifies the pruning strategy to execute\n| Strategy.Mode| currently MaxCountStrategy, MaxAgeStrategy, or CustomStrategy are supported\n| Strategy.MaxCountSetting| integer value for *maxcount* strategy, specifies how many resources should remain after pruning executes\n| Strategy.MaxAgeSetting| golang time.Duration string value (e.g. 48h), specifies age of resources to prune\n| Strategy.CustomSettings| a golang map of values that can be passed into a Custom strategy function\n| PreDeleteHook| optionally specifies a golang function to call before pruning a resource\n| CustomStrategy | optionally specifies a golang function that implements a custom pruning strategy\n\n\n### Pruning Execution\n\nUsers can invoke the pruning by running the *Execute* function on the pruning configuration\nas follows:\n```golang\nerr := cfg.Execute(ctx)\n```\n\nUsers might want to implement pruning execution by means of a cron package or simply call the prune\nlibrary based on some other triggering event.\n\nIf a logger has been configured in the Config structure it takes precedence on the one provided through ctx.\nAdding a logger.Logger to the context can be done with [logr.NewContext][logr-newcontext].\n\n## Pruning Strategies\n\n### maxcount Strategy\n\nA strategy of leaving a finite set of resources is implemented called *maxcount*. This strategy\nseeks to leave a specific number of resources, sorted by latest, on your cluster. For example, if\nyou have 10 resources that would be pruned, and you specified a *maxcount* value of 4, then 6 \nresources would be pruned (removed) from your cluster starting with the oldest resources.\n\n### maxage Strategy\n\nA strategy of removing resources greater than a specific time is called *maxage*.  This strategy\nseeks to remove resources older than a specified *maxage* duration.  For example, a library\nuser might specify a value of *48h* to indicate that any resource older than 48 hours would be\npruned.  Durations are specified using golang's [time.Duration formatting] (e.g. 48h).\n\n## Pruning Customization\n\n### preDelete Hook\n\nUsers can provide a *preDelete* hook when using the [operator-lib prune package][operator-lib-prune].  \nThis hook function will be called by the library before removing a resource.  This provides a means to examine\nthe resource logs for example, extracting any valued content, before the resource is removed\nfrom the cluster.\n\nHere is an example of a *preDelete* hook:\n```golang\nfunc myhook(ctx context.Context, cfg Config, res ResourceInfo) error {\n        log := prune.Logger(ctx, cfg)\n        log.V(4).Info(\"pre-deletion\", \"GVK\", res.GVK, \"namespace\", res.Namespace, \"name\", res.Name)\n       \tif res.GVK.Kind == PodKind {\n                req := cfg.Clientset.CoreV1().Pods(res.Namespace).GetLogs(res.Name, &v1.PodLogOptions{})\n                podLogs, err := req.Stream(context.Background())\n                if err != nil {\n                        return err\n                }\n                defer podLogs.Close()\n\n                buf := new(bytes.Buffer)\n                _, err = io.Copy(buf, podLogs)\n                if err != nil {\n                        return err\n                }\n\n                log.V(4).Info(\"pod log before removing is\", \"log\", buf.String())\n        }\n\treturn nil\n}\n```\n\n*Note* if your custom hook returns an error, then the resource will not be removed by the\nprune library.\n\n### Custom Strategy\n\nLibrary users can also write their own custom pruning strategy function to support advanced\ncases. Custom strategy functions are passed in the prune configuration and a list of resources selected by\nthe library.  The custom strategy builds up a list of resources to be removed, returning the list to the prune library which\nperforms the actual resource removal. Here is an example custom strategy:\n```golang\nfunc myStrategy(ctx context.Context, cfg Config, resources []ResourceInfo) (resourcesToRemove []ResourceInfo, err error) {\n        log := Logger(ctx, cfg)\n        log.V(4).Info(\"myStrategy called\", \"resources\", resources, \"config\", cfg)\n\tif len(resources) != 3 {\n\t\treturn resourcesToRemove, fmt.Errorf(\"count of resources did not equal our expectation\")\n\t}\n\treturn resourcesToRemove, nil\n}\n```\n\n\nTo have your custom strategy invoked, you will specify your function within the prune configuration\nas follows:\n```golang\ncfg.Strategy.Mode = CustomStrategy\ncfg.Strategy.CustomSettings = make(map[string]interface{})\ncfg.CustomStrategy = myStrategy\n```\n\nNotice that you can optionally pass in settings to your custom function as a map using the `cfg.Strategy.CustomSettings` field.\n\n\n[operator-lib]: https://github.com/operator-framework/operator-lib\n[operator-lib-prune]: https://github.com/operator-framework/operator-lib/tree/main/prune\n[jobs]: https://kubernetes.io/docs/concepts/workloads/controllers/job/\n[time.Duration formatting]: https://pkg.go.dev/time#Duration\n[logr-newcontext]: https://pkg.go.dev/github.com/go-logr/logr#NewContext\n"
  },
  {
    "path": "website/content/en/docs/building-operators/_index.md",
    "content": "---\ntitle: \"Building Operators\"\nlinkTitle: \"Building Operators\"\nweight: 3\ndate: 2020-07-09\ndescription: >\n  Building operators using Operator SDK.\n---"
  },
  {
    "path": "website/content/en/docs/building-operators/ansible/OWNERS",
    "content": "approvers:\n  - fabianvf\n  - jmrodri\n  - asmacdo\nreviewers:\n  - fabianvf\n  - jmrodri\n  - asmacdo\n"
  },
  {
    "path": "website/content/en/docs/building-operators/ansible/_index.md",
    "content": "---\ntitle: Ansible\nweight: 1\ndescription: Guide to building a Ansible Based Operator using Operator SDK\n---\n"
  },
  {
    "path": "website/content/en/docs/building-operators/ansible/development-tips.md",
    "content": "---\ntitle: Development Tips\nweight: 5\n---\n\nThis document provides some useful information and tips for a developer\ncreating an operator powered by Ansible.\n\n## Getting started with the Kubernetes Collection for Ansible\n\nSince we are interested in using Ansible for the lifecycle management of our\napplication on Kubernetes, it is beneficial for a developer to get a good\ngrasp of the [Kubernetes Collection for Ansible][kubernetes_collection].\nThis Ansible collection allows a developer to either leverage their existing\nKubernetes resource files (written in YAML) or express the lifecycle\nmanagement in native Ansible. One of the biggest benefits of using Ansible in\nconjunction with existing Kubernetes resource files is the ability to use\nJinja templating so that you can customize deployments with the simplicity of\na few variables in Ansible.\n\nThe easiest way to get started is to install the collection on your local\nmachine and test it using a playbook.\n\n### Installing the Kubernetes Collection for Ansible\n\nTo install the Kubernetes Collection, one must first install Ansible 2.9+.\nFor example, on Fedora/Centos:\n\n```sh\nsudo dnf install ansible\n```\n\nIn addition to Ansible, a user must install the\n[Python Kubernetes Client][python-kubernetes-client] package:\n\n```sh\npip3 install kubernetes\n```\n\nFinally, install the Kubernetes Collection from ansible-galaxy:\n\n```sh\nansible-galaxy collection install kubernetes.core\n```\n\nAlternatively, if you've already initialized your operator, you may have a\n`requirements.yml` file at the top level of your project. This file specifies\nAnsible dependencies that need to be installed for your operator to function.\nBy default it will install the `kubernetes.core` collection as well as\nthe `operator_sdk.util` collection, which provides modules and plugins for\noperator-specific operations.\n\nTo install the dependent modules from this file, run:\n\n```sh\nansible-galaxy collection install -r requirements.yml\n```\n\n### Testing the Kubernetes Collection locally\n\nSometimes it is beneficial for a developer to run the Ansible code from their\nlocal machine as opposed to running/rebuilding the operator each time. To do\nthis, initialize a new project:\n\n```sh\nmkdir memcached-operator && cd memcached-operator\noperator-sdk init --plugins=ansible --domain=example.com --group=cache --version=v1alpha1 --kind=Memcached --generate-role\nansible-galaxy collection install -r requirements.yml\n```\n\nModify `roles/memcached/tasks/main.yml` with desired Ansible logic. For this example\nwe will create and delete a ConfigMap based on the value of a variable named\n`state`:\n\n```yaml\n---\n- name: set ConfigMap example-config to {{ state }}\n  kubernetes.core.k8s:\n    api_version: v1\n    kind: ConfigMap\n    name: example-config\n    namespace: default\n    state: \"{{ state }}\"\n  ignore_errors: true\n```\n\n{{% alert title=\"Note\" color=\"primary\" %}}\nSetting `ignore_errors: true` is done so that deleting a nonexistent\nConfigMap doesn't error out.\n{{% /alert %}}\n\nModify `roles/memcached/defaults/main.yml` to set `state` to `present` as default.\n\n```yaml\n---\nstate: present\n```\n\nCreate an Ansible playbook `playbook.yml` in the top-level directory which\nincludes role `memcached`:\n\n```yaml\n---\n- hosts: localhost\n  roles:\n    - memcached\n```\n\nRun the playbook:\n\n```console\n$ ansible-playbook playbook.yml\n [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'\n\n\nPLAY [localhost] ***************************************************************************\n\nTASK [Gathering Facts] *********************************************************************\nok: [localhost]\n\nTask [memcached : set ConfigMap example-config to present]\nchanged: [localhost]\n\nPLAY RECAP *********************************************************************************\nlocalhost                  : ok=2    changed=1    unreachable=0    failed=0\n```\n\nCheck that the ConfigMap was created:\n\n```console\n$ kubectl get configmaps\nNAME                    STATUS    AGE\nexample-config          Active    3s\n```\n\nRerun the playbook setting `state` to `absent`:\n\n```console\n$ ansible-playbook playbook.yml --extra-vars state=absent\n [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'\n\n\nPLAY [localhost] ***************************************************************************\n\nTASK [Gathering Facts] *********************************************************************\nok: [localhost]\n\nTask [memcached : set ConfigMap example-config to absent]\nchanged: [localhost]\n\nPLAY RECAP *********************************************************************************\nlocalhost                  : ok=2    changed=1    unreachable=0    failed=0\n```\n\nCheck that the ConfigMap was deleted:\n\n```console\n$ kubectl get configmaps\nNo resources found in default namespace.\n```\n\n## Using Ansible inside an Operator\n\nNow that we have demonstrated using the Kubernetes Collection, we want to\ntrigger this Ansible logic when a custom resource changes. In the above\nexample, we want to map a role to a specific Kubernetes resource that the\noperator will watch. This mapping is done in a file called `watches.yaml`.\n\n### Custom Resource file\n\nThe Custom Resource (CR) file format is Kubernetes resource file. The object\nhas some mandatory fields:\n\n- `apiVersion`:  The version of the Custom Resource that will be created.\n- `kind`:  The kind of the Custom Resource that will be created\n- `metadata`:  Kubernetes specific metadata to be created\n- `spec`:  This is the key-value list of variables which are passed to Ansible.\n  This field is optional and empty by default.\n- `annotations`: Kubernetes specific annotations to be appended to the CR. See\n  the below section for Ansible Operator specific annotations. This field is optional.\n\n#### Annotations for Custom Resource\n\nThis is the list of CR annotations which will modify the behavior of the operator:\n\n- `ansible.operator-sdk/reconcile-period`: Specifies the maximum time before a\n  reconciliation is triggered. Note that at scale, this can reduce\n  performance, see [watches][watches] reference for more information. This value\n  is parsed using the standard Go package [time][time_pkg]. Specifically\n  [ParseDuration][time_parse_duration] is used which will apply the default\n  suffix of `s` giving the value in seconds.\n\n  Example:\n\n  ```yaml\n  apiVersion: cache.example.com/v1alpha1\n  kind: Memcached\n  metadata:\n    name: example\n    annotations:\n      ansible.operator-sdk/reconcile-period: \"30s\"\n  ```\n\nNote that a lower period will correct entropy more quickly, but reduce\nresponsiveness to change if there are many watched resources. Typically, this\noption should only be used in advanced use cases where\n`watchDependentResources` is set to `False`  and when is not possible to use\nthe watch feature. E.g To managing external resources that don’t raise\nKubernetes events.\n\n### Testing an Ansible Operator locally\n\nOnce a developer is comfortable working with the above workflow, it will be\nbeneficial to test the logic inside an operator.\n\n**Prerequisites**:\n- Read the [Ansible Operator tutorial][tutorial].\n- Install `ansible-operator` [dependencies][py-deps] using [`pipenv`][pipenv]\nand their OS prerequisite [packages][os-pkgs] (these will differ depending on OS) locally.\n\nThe `run` Makefile target runs the `ansible-operator` binary locally, which reads from\n`./watches.yaml` and uses `~/.kube/config` to communicate with a Kubernetes\ncluster just as the `k8s` modules do. The `install` target registers the operator's\n`Memcached` CustomResourceDefinition (CRD) with the apiserver.\n\n{{% alert title=\"Note\" color=\"primary\" %}}\nYou can customize the roles path by setting the environment variable\n`ANSIBLE_ROLES_PATH` or using the flag `ansible-roles-path`. Note that if the\nrole is not found in `ANSIBLE_ROLES_PATH`, then the operator will look for it\nin `{{current directory}}/roles`.   \n{{% /alert %}}\n\n```console\n$ make install run\n/home/user/memcached-operator/bin/kustomize build config/crd | kubectl apply -f -\ncustomresourcedefinition.apiextensions.k8s.io/memcacheds.cache.example.com created\n/home/user/go/bin/ansible-operator run\n{\"level\":\"info\",\"ts\":1595899073.9861593,\"logger\":\"cmd\",\"msg\":\"Version\",\"Go Version\":\"go1.13.12\",\"GOOS\":\"linux\",\"GOARCH\":\"amd64\",\"ansible-operator\":\"v0.19.0+git\"}\n{\"level\":\"info\",\"ts\":1595899073.987384,\"logger\":\"cmd\",\"msg\":\"WATCH_NAMESPACE environment variable not set. Watching all namespaces.\",\"Namespace\":\"\"}\n{\"level\":\"info\",\"ts\":1595899074.9504397,\"logger\":\"controller-runtime.metrics\",\"msg\":\"metrics server is starting to listen\",\"addr\":\":8080\"}\n{\"level\":\"info\",\"ts\":1595899074.9522583,\"logger\":\"watches\",\"msg\":\"Environment variable not set; using default value\",\"envVar\":\"ANSIBLE_VERBOSITY_MEMCACHED_CACHE_EXAMPLE_COM\",\"default\":2}\n{\"level\":\"info\",\"ts\":1595899074.9524004,\"logger\":\"cmd\",\"msg\":\"Environment variable not set; using default value\",\"Namespace\":\"\",\"envVar\":\"ANSIBLE_DEBUG_LOGS\",\"ANSIBLE_DEBUG_LOGS\":false}\n{\"level\":\"info\",\"ts\":1595899074.9524298,\"logger\":\"ansible-controller\",\"msg\":\"Watching resource\",\"Options.Group\":\"cache.example.com\",\"Options.Version\":\"v1\",\"Options.Kind\":\"Memcached\"}\n```\n\nNow that the operator is watching resource `Memcached` for events, the creation of a\nCustom Resource will trigger our Ansible Role to be executed. Take a look at\n`config/samples/cache_v1alpha1_memcached.yaml`:\n\n```yaml\napiVersion: cache.example.com/v1alpha1\nkind: Memcached\nmetadata:\n  name: \"memcached-sample\"\n```\n\nSince `spec` is not set, Ansible is invoked with no extra variables. The next\nsection covers how extra variables are passed from a Custom Resource to\nAnsible. This is why it is important to set sane defaults for the operator.\n\nCreate a Custom Resource instance of Memcached with variable `state` default to\n`present`:\n\n```sh\nkubectl create -f config/samples/cache_v1alpha1_memcached.yaml\n```\n\nCheck that ConfigMap `example-config` was created:\n\n```console\n$ kubectl get configmaps\nNAME                    STATUS    AGE\nexample-config          Active    3s\n```\n\nModify `config/samples/cache_v1alpha1_memcached.yaml` to set `state` to\n`absent`:\n\n```yaml\napiVersion: cache.example.com/v1alpha1\nkind: Memcached\nmetadata:\n  name: memcached-sample\nspec:\n  state: absent\n```\n\nApply the changes to Kubernetes and confirm that the ConfiMap is deleted:\n\n```sh\nkubectl apply -f config/samples/cache_v1alpha1_memcached.yaml\nkubectl get configmaps\n```\n\n### Testing an Ansible Operator on a cluster\n\nNow that a developer is confident in the operator logic, testing the operator\ninside of a pod on a Kubernetes cluster is desired. Running as a pod inside a\nKubernetes cluster is preferred for production use.\n\nTo build the `memcached-operator` image and push it to a registry:\n\n```sh\nmake docker-build docker-push IMG=example.com/memcached-operator:v0.0.1\n```\n\nDeploy the memcached-operator:\n\n```sh\nmake install\nmake deploy IMG=example.com/memcached-operator:v0.0.1\n```\n\nVerify that the memcached-operator is up and running:\n\n```console\n$ kubectl get deployment -n memcached-operator-system\nNAME                     DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE\nmemcached-operator       1         1         1            1           1m\n```\n\n### Viewing the Ansible logs\n\nIn order to see the logs from a particular operator you can run:\n\n```sh\nkubectl logs deployment/memcached-operator-controller-manager -n memcached-operator-system\n```\n\nThe logs contain the information about the Ansible run and are useful for\ndebugging your Ansible tasks. Note that the logs may contain much more\ndetailed information about the Ansible Operator's internals and its\ninteractions with Kubernetes as well.\n\nAlso, you can set the environment variable `ANSIBLE_DEBUG_LOGS` to `True` to\ncheck the full Ansible result in the logs in order to be able to debug it.\n\n**Example**\n\nIn `config/manager/manager.yaml` and `config/default/manager_metrics_patch.yaml`:\n\n```yaml\n...\n      containers:\n      - name: manager\n        env:\n        - name: ANSIBLE_DEBUG_LOGS\n          value: \"True\"\n...\n```\n\nOccasionally while developing additional debug in the Operator logs is nice to have.\nUsing the memcached operator as an example, we can simply add the\n`\"ansible.sdk.operatorframework.io/verbosity\"` annotation to the Custom\nResource with the desired verbosity.\n\n```yaml\napiVersion: \"cache.example.com/v1alpha1\"\nkind: \"Memcached\"\nmetadata:\n  name: \"example-memcached\"\n  annotations:\n    \"ansible.sdk.operatorframework.io/verbosity\": \"4\"\nspec:\n  size: 4\n```\n\n## Custom Resource Status Management\n\nBy default, an Ansible Operator will include the generic output from previous\nAnsible run as the `status` subresource of a CR. This includes the number of\nsuccessful and failed tasks and relevant error messages as shown below:\n\n```yaml\nstatus:\n  conditions:\n  - ansibleResult:\n      changed: 3\n      completion: 2018-12-03T13:45:57.13329\n      failures: 1\n      ok: 6\n      skipped: 0\n    lastTransitionTime: 2018-12-03T13:45:57Z\n    message: 'Status code was -1 and not [200]: Request failed: <urlopen error [Errno\n      113] No route to host>'\n    reason: Failed\n    status: \"True\"\n    type: Failure\n  - lastTransitionTime: 2018-12-03T13:46:13Z\n    message: Running reconciliation\n    reason: Running\n    status: \"True\"\n    type: Running\n```\n\nAn Ansible Operator also allows you to supply custom status values with the\n`k8s_status` Ansible module, which is included in\n[operator_sdk.util][operator_sdk_util] collection.\nYou can update the `status` from within Ansible with any key/value pairs as\ndesired. If you do not want the operator to update the status with Ansible\noutput, and you want to track the CR status manually from your application,\nyou can update the `watches.yaml` file with `manageStatus`, as shown below:\n\n```yaml\n- version: v1\n  group: api.example.com\n  kind: Memcached\n  role: memcached\n  manageStatus: false\n```\n\nThe simplest way to invoke the `k8s_status` module is to use its fully\nqualified collection name (fqcn), i.e. `operator_sdk.util.k8s_status`.  The\nfollowing example updates the `status` subresource with key `memcached` and value `bar`:\n\n```yaml\n- operator_sdk.util.k8s_status:\n    api_version: app.example.com/v1\n    kind: Memcached\n    name: \"{{ ansible_operator_meta.name }}\"\n    namespace: \"{{ ansible_operator_meta.namespace }}\"\n    status:\n      foo: bar\n```\n\nCollections can also be declared in the role's `meta/main.yml`, which is\nincluded for newly scaffolded Ansible operators.\n\n```yaml\ncollections:\n  - operator_sdk.util\n```\n\nDeclaring collections in the role meta allows you to invoke the\n`k8s_status` module directly.\n\n```yaml\n- k8s_status:\n    <snip>\n    status:\n      foo: bar\n```\n\n### Ansible Operator Conditions\n\nAn Ansible Operator has a set of conditions that are used during reconciliation.\nThere are only a few main conditions:\n\n* Running - the Ansible Operator is currently running the Ansible for\n  reconciliation.\n* Successful - if the run has finished and there were no errors, the Ansible\n  Operator will be marked as Successful. It will then wait for the next\n  reconciliation action, either the reconcile period, dependent watches triggers\n  or the resource is updated.\n* Failed - if there is any error during the reconciliation run, the Ansible\n  Operator will be marked as Failed with the error message from the error that\n  caused this condition. The error message is the raw output from the Ansible\n  run for reconciliation. If the Failure is intermittent, often times the\n  situation can be resolved when the Operator reruns the reconciliation loop.\n\n## Extra vars sent to Ansible\n\nThe extra vars that are sent to Ansible are managed by the operator. The `spec`\nsection will pass along the key-value pairs as extra vars.  This is equivalent\nto how above extra vars are passed in to `ansible-playbook`. The operator also\npasses along additional variables under the `ansible_operator_meta` field for\nthe name of the CR and the namespace of the CR.\n\nFor the CR example:\n\n```yaml\napiVersion: \"cache.example.com/v1alpha1\"\nkind: \"Memcached\"\nmetadata:\n  name: \"memcached-sample\"\nspec:\n  message: \"Hello world 2\"\n  newParameter: \"newParam\"\n```\n\nThe structure passed to Ansible as extra vars is:\n\n```json\n{ \"ansible_operator_meta\": {\n        \"name\": \"<cr-name>\",\n        \"namespace\": \"<cr-namespace>\",\n  },\n  \"message\": \"Hello world 2\",\n  \"new_parameter\": \"newParam\",\n  \"_app_example_com_database\": {\n     <Full CR>\n   },\n  \"_app_example_com_database_spec\": {\n     <Full CR .spec>\n   },\n}\n```\n\n`message` and `newParameter` are set in the top level as extra variables, and\n`ansible_operator_meta` provides the relevant metadata for the Custom Resource as defined in the\noperator. The `ansible_operator_meta` fields can be accessed via dot notation in Ansible as so:\n\n```yaml\n---\n- debug:\n    msg: \"name: {{ ansible_operator_meta.name }}, {{ ansible_operator_meta.namespace }}\"\n```\n\n[ansible-runner-http-plugin]:https://github.com/ansible/ansible-runner-http\n[ansible-runner-tool]: https://ansible-runner.readthedocs.io/en/latest/install.html\n[k8s_ansible_module]:https://docs.ansible.com/ansible/2.6/modules/k8s_module.html\n[tutorial]:../tutorial\n[kubernetes_collection]: https://galaxy.ansible.com/kubernetes/core\n[manage_status_proposal]:../../proposals/ansible-operator-status.md\n[operator_sdk_util]: https://galaxy.ansible.com/operator_sdk/util\n[passing_extra_vars]: https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#passing-variables-on-the-command-line\n[python-kubernetes-client]: https://github.com/kubernetes-client/python\n[time_pkg]:https://golang.org/pkg/time/\n[time_parse_duration]:https://golang.org/pkg/time/#ParseDuration\n[watches]:/docs/building-operators/ansible/reference/watches\n[py-deps]:https://github.com/operator-framework/operator-sdk/blob/c6796de/images/ansible-operator/Pipfile.lock\n[pipenv]:https://pypi.org/project/pipenv/\n[os-pkgs]:https://github.com/operator-framework/operator-sdk/blob/c6796de/images/ansible-operator/base.Dockerfile#L29\n"
  },
  {
    "path": "website/content/en/docs/building-operators/ansible/installation.md",
    "content": "---\ntitle: Installation Guide\nlinkTitle: Installation\nweight: 1\n---\n\n## Install `operator-sdk`\n\nFollow the steps in the [installation guide][install-guide] to learn how to install the `operator-sdk` CLI tool.\n\n## Additional Prerequisites\n\n- [docker][docker_tool] version 17.03+\n- [python][python] version 3.8.6+\n- [ansible][ansible] version v2.9.0+\n- [ansible-runner][ansible-runner] version 2.0.2+\n- [ansible-runner-http][ansible-runner-http-plugin] version v1.0.0+\n- [openshift][openshift-module] version v0.12.0+\n- [kubectl][kubectl_tool] and access to a Kubernetes cluster of a [compatible version][k8s-version-compat].\n\n[docker_tool]:https://docs.docker.com/install/\n[install-guide]:/docs/installation/\n[python]:https://www.python.org/downloads/\n[ansible]:https://docs.ansible.com/ansible/latest/index.html\n[ansible-runner]:https://ansible-runner.readthedocs.io/en/latest/install.html\n[ansible-runner-http-plugin]:https://github.com/ansible/ansible-runner-http\n[openshift-module]:https://pypi.org/project/openshift/\n[kubectl_tool]:https://kubernetes.io/docs/tasks/tools/install-kubectl/\n[k8s-version-compat]:/docs/overview#kubernetes-version-compatibility\n"
  },
  {
    "path": "website/content/en/docs/building-operators/ansible/migration.md",
    "content": "---\nlink: Migrating Projects from pre-v1.0.0 to the latest release\nlinkTitle: Migrating from pre-v1.0.0 to latest\nweight: 200\ndescription: Instructions for migrating an Ansible-based operator built prior to `v1.0.0` to use a Kubebuilder-style.\n---\n\n## Overview\n\nThe motivations for the new layout are related to bringing more flexibility to users and part of the process to Integrating Kubebuilder and Operator SDK. Because of this integration you may be referred to the Kubebuilder documentation [https://book.kubebuilder.io/](https://book.kubebuilder.io/) for more information about certain topics. When using this document just remember to replace `$ kubebuilder <command>` with `$ operator-sdk <command>`.\n\n**Note:** It is recommended that you have your project upgraded to the latest SDK v1.y release version before following the steps in this guide to migrate to the new layout. However, the steps might work from previous versions as well. In this case, if you find an issue which is not covered here then check the previous [Migration Guides][migration-doc] which might help out.\n\n### What was changed\n\n- The `deploy` directory was replaced with the `config` directory including a new layout of Kubernetes manifests files:\n    * CRD manifests in `deploy/crds/` are now in `config/crd/bases`\n    * CR manifests in `deploy/crds/` are now in `config/samples`\n    * Controller manifest `deploy/operator.yaml` is now in `config/manager/manager.yaml`\n    * RBAC manifests in `deploy` are now in `config/rbac/`\n\n- `build/Dockerfile` is moved to `Dockerfile` in the project root directory\n- The `molecule/` directory is now more aligned to Ansible and the new Layout\n\n### What is new\n\nScaffolded projects now use:\n\n- [kustomize][kustomize] to manage Kubernetes resources needed to deploy your operator\n- A `Makefile` with helpful targets for build, test, and deployment, and to give you flexibility to tailor things to your project's needs\n- Updated metrics configuration using [kube-auth-proxy][kube-auth-proxy], a `--metrics-bind-address` flag, and [kustomize][kustomize]-based deployment of a Kubernetes `Service` and prometheus operator `ServiceMonitor`\n- Preliminary support for CLI plugins. For more info see the [plugins design document][plugins-phase1-design-doc]\n- A `PROJECT` configuration file to store information about GVKs, plugins, and help the CLI make decisions.\n\nGenerated files with the default API versions:\n\n- `apiextensions/v1` for generated CRDs (`apiextensions/v1beta1` was deprecated in Kubernetes `1.16` and will be removed in `1.22`)\n- `admissionregistration.k8s.io/v1` for webhooks (`admissionregistration.k8s.io/v1beta1` was deprecated in Kubernetes `1.16` and will be removed in `1.22` )\n\n## How to migrate\n\nThe easy migration path is to initialize a new project, re-recreate APIs, then copy pre-v1.0.0 configuration files into the new project.\n\n### Prerequisites\n\n- Go through the [installation guide][install-guide].\n- Make sure your user is authorized with `cluster-admin` permissions.\n- An accessible image registry for various operator images (ex. [hub.docker.com](https://hub.docker.com/signup),\n[quay.io](https://quay.io/)) and be logged in to your command line environment.\n  - `example.com` is used as the registry Docker Hub namespace in these examples.\n  Replace it with another value if using a different registry or namespace.\n  - [Authentication and certificates][image-reg-config] if the registry is private or uses a custom CA.\n\n### Creating a new project\n\nIn Kubebuilder-style projects, CRD groups are defined using two different flags\n(`--group` and `--domain`).\n\nWhen we initialize a new project, we need to specify the domain that _all_ APIs in\nour project will share, so before creating the new project, we need to determine which\ndomain we're using for the APIs in our existing project.\n\nTo determine the domain, look at the `spec.group` field in your CRDs in the\n`deploy/crds` directory.\n\nThe domain is everything after the first DNS segment. Using `cache.example.com` as an\nexample, the `--domain` would be `example.com`.\n\nSo let's create a new project with the same domain (`example.com`):\n\n```sh\nmkdir memcached-operator\ncd memcached-operator\noperator-sdk init --plugins=ansible --domain=example.com\n```\n\nNow that we have our new project initialized, we need to recreate each of our APIs.\nUsing our API example from earlier (`cache.example.com`), we'll use `cache` for the\n`--group` flag.\n\nFor `--version` and `--kind`, we use `spec.versions[0].name` and `spec.names.kind`, respectively.\n\nFor each API in the existing project, run:\n\n```sh\noperator-sdk create api \\\n    --group=cache \\\n    --version=v1 \\\n    --kind=Memcached\n```\n\nRunning the above command creates an empty `roles/<kind>`. We can copy over the content of our old `roles/<kind>` to the new one.   \n\n### Migrating your Custom Resource samples\n\nUpdate the CR manifests in `config/samples` with the values of the CRs in your existing project which are in `deploy/crds/<group>_<version>_<kind>_cr.yaml` In our example\nthe `config/samples/cache_v1alpha1_memcached.yaml` will look like:\n\n```yaml\napiVersion: cache.example.com/v1alpha1\nkind: Memcached\nmetadata:\n  name: memcached-sample\nspec:\n  # TODO(user): Add fields here\n  size: 3\n```\n\n### Migrating `watches.yaml`\n\nUpdate the `watches.yaml` file with your `roles/playbooks` and check if you have custom options in the `watches.yaml` file of your existing project. If so, update the new `watches.yaml` file to match.\n\nIn our example, we will replace `# FIXME: Specify the role or playbook for this resource.` with our previous role and it will look like:\n\n```yaml\n---\n# Use the 'create api' subcommand to add watches to this file.\n- version: v1alpha1\n  group: cache.example.com\n  kind: Memcached\n  role: memcached\n#+kubebuilder:scaffold:watch\n```\n\n**NOTE**: Do not remove the `+kubebuilder:scaffold:watch` [marker][marker]. It allows the tool to update the watches file when new APIs are created.\n\nAdditionally pre-1.0 the `reconcilePeriod` parameter was an integer representing the maximum time in seconds before a reconcile would be triggered.\nWith 1.0, it was changed to a string representing the maximum duration before a reconcile will be triggered. Appending an `s` to your `reconcilePeriod`\nwill set the duration unit to seconds and match the old behavior.\n\nso for example a resource set to requeue every hour:\n\n```yaml\n---\n# Use the 'create api' subcommand to add watches to this file.\n- version: v1alpha1\n  group: cache.example.com\n  kind: Memcached\n  role: memcached\n  reconcilePeriod: 3600\n#+kubebuilder:scaffold:watch\n```\n\nwould become\n\n```yaml\n---\n# Use the 'create api' subcommand to add watches to this file.\n- version: v1alpha1\n  group: cache.example.com\n  kind: Memcached\n  role: memcached\n  reconcilePeriod: 3600s\n#+kubebuilder:scaffold:watch\n```\n\nand the values `60m` and `1h` would be equivalent to the `3600s` that is used.\n\n### Migrating your Molecule tests\n\nIf you are using [Molecule][molecule] in your project will be required to port the tests for the new layout.  \n\nSee that default structure changed from:\n\n```\n├── cluster\n│   ├── converge.yml\n│   ├── create.yml\n│   ├── destroy.yml\n│   ├── molecule.yml\n│   ├── prepare.yml\n│   └── verify.yml\n├── default\n│   ├── converge.yml\n│   ├── molecule.yml\n│   ├── prepare.yml\n│   └── verify.yml\n├── templates\n│   └── operator.yaml.j2\n└── test-local\n    ├── converge.yml\n    ├── molecule.yml\n    ├── prepare.yml\n    └── verify.yml\n```\n\nTo:\n\n```\n├── default\n│   ├── converge.yml\n│   ├── create.yml\n│   ├── destroy.yml\n│   ├── kustomize.yml\n│   ├── molecule.yml\n│   ├── prepare.yml\n│   ├── tasks\n│   │   └── foo_test.yml\n│   └── verify.yml\n└── kind\n    ├── converge.yml\n    ├── create.yml\n    ├── destroy.yml\n    └── molecule.yml\n```\n\nEnsure that the `provisioner.host_vars.localhost` has the following `host_vars`:\n\n```yaml\n....\n    host_vars:\n      localhost:\n        ansible_python_interpreter: '{{ ansible_playbook_python }}'\n        config_dir: ${MOLECULE_PROJECT_DIRECTORY}/config\n        samples_dir: ${MOLECULE_PROJECT_DIRECTORY}/config/samples\n        operator_image: ${OPERATOR_IMAGE:-\"\"}\n        operator_pull_policy: ${OPERATOR_PULL_POLICY:-\"Always\"}\n        kustomize: ${KUSTOMIZE_PATH:-kustomize}\n...\n```\n\nFor more information read the [Testing with Molecule][testing-guide].\n\n### Checking RBAC Permissions\n\nIn your new project, roles are automatically generated in `config/rbac/role.yaml`.\nIf you modified these permissions manually in `deploy/role.yaml` in your existing\nproject, you need to re-apply them in `config/rbac/role.yaml`.\n\n<!--\ntodo(camilamacedo86): Create an Ansible operator scope document.\nhttps://github.com/operator-framework/operator-sdk/issues/3447\n-->\n\nNew projects are configured to watch all namespaces by default, so they need a `ClusterRole` to have the necessary permissions. Ensure that `config/rbac/role.yaml` remains a `ClusterRole` if you want to retain the default behavior of the new project conventions.\n\nThe following rules were used in earlier versions of ansible-operator to automatically create and manage services and `servicemonitors` for metrics collection. If your operator's don't require these rules, they can safely be left out of the new `config/rbac/role.yaml` file:\n\n```yaml  \n  - apiGroups:\n    - monitoring.coreos.com\n    resources:\n    - servicemonitors\n    verbs:\n    - get\n    - create\n  - apiGroups:\n    - apps\n    resourceNames:\n    - memcached-operator\n    resources:\n    - deployments/finalizers\n    verbs:\n    - update\n```\n\n##### Updating your ServiceAccount\n\nNew Ansible projects come with a ServiceAccount `controller-manager` in `config/rbac/service_account.yaml`.\nYour project's RoleBinding and ClusterRoleBinding subjects, and Deployment's `spec.template.spec.serviceAccountName`\nthat reference a ServiceAccount already refer to this new name. When you run `make deploy`,\nyour project's name will be prepended to `controller-manager`, making it unique within a namespace,\nmuch like your old `deploy/service_account.yaml`. If you wish to use the old ServiceAccount,\nmake sure to update all RBAC bindings and your manager Deployment.\n\n### Configuring your Operator\n\nIf your existing project has customizations in `deploy/operator.yaml`, they need to be ported to\n`config/manager/manager.yaml`. If you are passing custom arguments in your deployment, make sure to also update `config/default/auth_proxy_patch.yaml`.\n\nNote that the following environment variables are no longer used.\n\n- `OPERATOR_NAME` is deprecated. It is used to define the name for a leader election config map. Operator authors should begin using `--leader-election-id` instead.\n- `POD_NAME` has been removed. It was used to enable a particular pod to hold the leader election lock when the Ansible operator used the leader for life mechanism. Ansible operator now uses controller-runtime's leader with lease mechanism.\n\n### Exporting metrics\n\nIf you are using metrics and would like to keep them exported you will need to configure\nit in the `config/default/kustomization.yaml`. Please see the [metrics][metrics] doc to know how you can perform this setup.\n\nThe default port used by the metric endpoint binds to was changed from `:8383` to `:8080`. To continue using port `8383`, specify `--metrics-bind-address=:8383` when you start the operator.\n\n### Verify the migration\n\nThe project can now be deployed on the cluster by running the command:\n\n```sh\nmake deploy IMG=example.com/memcached-operator:v0.0.1\n```\n\nYou can troubleshoot your deployment by checking the container logs:\n```sh\nkubectl logs deployment.apps/memcached-operator-controller-manager -n memcached-operator-system -c manager\n```\n\nFor further steps regarding the deployment of the operator, creation of custom resources, and cleaning up of resources, see the [tutorial][tutorial-deploy].\n\n[install-guide]: /docs/building-operators/ansible/installation\n[image-reg-config]:/docs/olm-integration/cli-overview#private-bundle-and-catalog-image-registries\n[kustomize]: https://github.com/kubernetes-sigs/kustomize\n[kube-auth-proxy]: https://github.com/brancz/kube-rbac-proxy\n[metrics]: https://book.kubebuilder.io/reference/metrics.html?highlight=metr#metrics\n[marker]: https://book.kubebuilder.io/reference/markers.html?highlight=markers#marker-syntax\n[molecule]: https://molecule.readthedocs.io/\n[testing-guide]: /docs/building-operators/ansible/testing-guide\n[migration-doc]: /docs/upgrading-sdk-version/\n[tutorial-deploy]: /docs/building-operators/ansible/tutorial/#run-the-operator\n"
  },
  {
    "path": "website/content/en/docs/building-operators/ansible/quickstart.md",
    "content": "---\ntitle: Quickstart for Ansible-based Operators\nlinkTitle: Quickstart\nweight: 2\ndescription: A simple set of instructions to set up and run an Ansible-based operator.\n---\n\nThis guide walks through an example of building a simple memcached-operator powered by [Ansible][ansible-link] using tools and libraries provided by the Operator SDK.\n\n## Prerequisites\n\n- Go through the [installation guide][install-guide].\n- Make sure your user is authorized with `cluster-admin` permissions.\n- Have an accessible image registry for various operator images (ex. [hub.docker.com](https://hub.docker.com/signup),\n[quay.io](https://quay.io/)) and be logged in to your command line environment.\n  - `example.com` is used as the registry Docker Hub namespace in these examples.\n  Replace it with another value if using a different registry or namespace.\n  - [Authentication and certificates][image-reg-config] if the registry is private or uses a custom CA.\n\n\n## Steps\n\n1. Create a project directory for your project and initialize the project:\n\n  ```sh\n  mkdir memcached-operator\n  cd memcached-operator\n  operator-sdk init --domain example.com --plugins ansible\n  ```\n\n1. Create a simple Memcached API:\n\n  ```sh\n  operator-sdk create api --group cache --version v1alpha1 --kind Memcached --generate-role\n  ```\n\n1. Build and push your operator's image:\n\n  ```sh\n  make docker-build docker-push IMG=\"example.com/memcached-operator:v0.0.1\"\n  ```\n\n### OLM deployment\n\n1. Install [OLM][doc-olm]:\n\n  ```sh\n  operator-sdk olm install\n  ```\n\n1. Bundle your operator, then build and push the bundle image (defaults to `example.com/memcached-operator-bundle:v0.0.1`):\n\n  ```sh\n  make bundle IMG=\"example.com/memcached-operator:v0.0.1\"\n  make bundle-build bundle-push\n  ```\n\n1. Run your bundle. If your bundle image is hosted in a registry that is private and/or\nhas a custom CA, these [configuration steps][image-reg-config] must be complete.\n\n  ```sh\n  operator-sdk run bundle example.com/memcached-operator-bundle:v0.0.1\n  ```\n\n1. Create a sample Memcached custom resource:\n\n  ```console\n  $ kubectl apply -f config/samples/cache_v1alpha1_memcached.yaml\n  memcached.cache.example.com/memcached-sample created\n  ```\n\n1. Uninstall the operator:\n\n  ```sh\n  operator-sdk cleanup memcached-operator\n  ```\n\n\n### Direct deployment\n\n1. Deploy your operator:\n\n  ```sh\n  make deploy IMG=\"example.com/memcached-operator:v0.0.1\"\n  ```\n\n1. Create a sample Memcached custom resource:\n\n  ```console\n  $ kubectl apply -f config/samples/cache_v1alpha1_memcached.yaml\n  memcached.cache.example.com/memcached-sample created\n  ```\n\n1. Uninstall the operator:\n\n  ```sh\n  make undeploy\n  ```\n\n\n## Next Steps\n\nRead the [full tutorial][tutorial] for an in-depth walkthrough of building an Ansible operator.\n\n\n[ansible-link]:https://www.ansible.com/\n[install-guide]:/docs/building-operators/ansible/installation\n[image-reg-config]:/docs/olm-integration/cli-overview#private-bundle-and-catalog-image-registries\n[doc-olm]:/docs/olm-integration/tutorial-bundle/#enabling-olm\n[tutorial]:/docs/building-operators/ansible/tutorial/\n"
  },
  {
    "path": "website/content/en/docs/building-operators/ansible/reference/_index.md",
    "content": "---\ntitle: Ansible Based Operator Reference\nlinkTitle: Reference\nweight: 200\n---\n"
  },
  {
    "path": "website/content/en/docs/building-operators/ansible/reference/advanced_options.md",
    "content": "---\ntitle: Ansible Operator Advanced Options\nlinkTitle: Advanced Options\nweight: 20\n---\n\nThis document shows the advanced options available to a developer of an ansible operator.\n\n### Runner Directory\n\nThe ansible runner will keep information about the ansible run in the container.  This is located `/tmp/ansible-operator/runner/<group>/<version>/<kind>/<namespace>/<name>`. To learn more  about the runner directory you can read the [ansible-runner docs](https://ansible-runner.readthedocs.io/en/latest/index.html).\n\n## Owner Reference Injection\n\nOwner references enable [Kubernetes Garbage Collection](https://kubernetes.io/docs/concepts/workloads/controllers/garbage-collection/) to clean up after a CR is deleted. Owner references are injected by ansible operators by default by the proxy.\n\nOwner references only apply to resources in the same namespace as the CR. Resources outside the namespace of the CR will automatically be annotated with `operator-sdk/primary-resource` and `operator-sdk/primary-resource-type` to track creation. These resources will not be automatically garbage collected. To handle deletion of these resources, use a [finalizer](../finalizers).\n\nYou may want to manage what your operator watches and the owner references. This means that your operator will need to understand how to clean up after itself when your CR is deleted. To disable these features you will need to edit your `Dockerfile` to include the line below.\n\n**NOTE**: That if you use this feature there will be a warning that dependent watches is turned off but there will be no error.\n**WARNING**: Once a CR is deployed without owner reference injection, there is no automatic way to add those references.\n\n```\nENTRYPOINT [\"/usr/local/bin/entrypoint\", \"--inject-owner-ref=false\"]\n```\n\nIf you have created resources without owner reference injection, it is\npossible to manually to update resources following [this\nguide.](../retroactively-owned-resources)\n\n## Max Concurrent Reconciles\n\nIncreasing the number of concurrent reconciles allows events to be processed\nconcurrently, which can improve reconciliation performance.\n\nThe maximum number of concurrent reconciles can be set in two ways. Operator **authors and admins**\ncan set the max concurrent reconciles default by including extra args to the operator\ncontainer in `config/manager/manager.yaml` and the patch in `config/default/auth_proxy_patch.yaml`.\n(Otherwise, the default is the maximum number of logical CPUs available for the process obtained\nusing `runtime.NumCPU()`.)\n\n**NOTE:** Admins using OLM should use the environment variable instead\nof the extra args.\n\n``` yaml\n- name: manager\n  image: \"quay.io/asmacdo/memcached-operator:v0.0.0\"\n  imagePullPolicy: \"Always\"\n  args:\n    - \"--max-concurrent-reconciles\"\n    - \"3\"\n```\nOperator **admins** can override the value by setting an environment\nvariable in the format `MAX_CONCURRENT_RECONCILES_<kind>_<group>`. This variable must be\nall uppercase, and periods (e.g. in the group name) are replaced with underscores.\n\nFor the memcached operator example, the component parts are retrieved\nwith a GET on the operator:\n\n```bash\n$ kubectl get memcacheds example-memcached -o yaml\n\napiVersion: cache.example.com/v1alpha1\nkind: Memcached\nmetadata:\n  name: example-memcached\n  namespace: default\n```\n\nFrom this data, we can see that the environment variable will be\n`MAX_CONCURRENT_RECONCILES_MEMCACHED_CACHE_EXAMPLE_COM`, which we can then add to\n`config/manager/manager.yaml` and `config/default/auth_proxy_patch.yaml`:\n\n``` yaml\n- name: manager\n  image: \"quay.io/asmacdo/memcached-operator:v0.0.0\"\n  imagePullPolicy: \"Always\"\n  args:\n    # This default is overridden.\n    - \"--max-concurrent-reconciles\"\n    - \"3\"\n  env:\n    # This value is used\n    - name: MAX_CONCURRENT_RECONCILES_MEMCACHED_CACHE_EXAMPLE_COM\n      value: \"6\"\n```\n\n## Ansible Verbosity\n\nSetting the verbosity at which `ansible-runner` is run controls how verbose the\noutput of `ansible-playbook` will be. The normal rules for verbosity apply\nhere, where higher values mean more output. Acceptable values range from 0\n(only the most severe messages are output) to 7 (all debugging messages are\noutput).\n\nThere are three ways to configure the verbosity argument to the `ansible-runner`\ncommand:\n\n1. Operator **authors and admins** can set the Ansible verbosity by including\n   extra args to the operator container in the operator deployment.\n1. Operator **admins** can set Ansible verbosity by setting an environment\n   variable in the format `ANSIBLE_VERBOSITY_<kind>_<group>`. This variable must\n   be all uppercase and all periods (e.g. in the group name) are replaced with\n   underscore.\n1. Operator **users, authors, and admins** can set the Ansible verbosity by\n   setting the `\"ansible.sdk.operatorframework.io/verbosity\"` annotation on the Custom\n   Resource.\n\n### Examples\n\nFor demonstration purposes, let us assume that we have a database operator that\nsupports two Kinds -- `MongoDB` and `PostgreSQL` -- in the `db.example.com`\nGroup. We have only recently implemented the support for the `MongoDB` Kind so\nwe want reconciles for this Kind to be more verbose. Our operator container's\nspec in our `config/manager/manager.yaml` and `config/default/auth_proxy_patch.yaml`\nfiles might contain something like:\n\n```yaml\n- name: manager\n  image: \"quay.io/example/database-operator:v1.0.0\"\n  imagePullPolicy: \"Always\"\n  args:\n    # This value applies to all GVKs specified in watches.yaml\n    # that are not overridden by environment variables.\n    - \"--ansible-verbosity\"\n    - \"1\"\n  env:\n    # Override the verbosity for the MongoDB kind\n    - name: ANSIBLE_VERBOSITY_MONGODB_DB_EXAMPLE_COM\n      value: \"4\"\n```\n\nOnce the Operator is deployed, the only way to change the verbosity is via the\n`\"ansible.sdk.operatorframework.io/verbosity\"` annotation. Continuing with our example, our\nCR may look like:\n\n```yaml\napiVersion: \"db.example.com/v1\"\nkind: \"PostgreSQL\"\nmetadata:\n  name: \"example-db\"\n  annotations:\n    \"ansible.sdk.operatorframework.io/verbosity\": \"5\"\nspec: {}\n```\n\n## Custom Resources with OpenAPI Validation\n\nCurrently, SDK tool does not support and will not generate automatically the CRD's using the [OpenAPI](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#validation) spec to perform validations. \n\nHowever, it can be done manually by adding its validations as you can check in the following example.\n\n**Example**\n\n```yaml\napiVersion: apiextensions.k8s.io/v1beta1\nkind: CustomResourceDefinition\nmetadata:\n  name: memcacheds.cache.example.com\nspec:\n  group: cache.example.com\n  names:\n    kind: Memcached\n    listKind: MemcachedList\n    plural: memcacheds\n    singular: memcached\n  scope: Namespaced\n  subresources:\n    status: {}\n  validation:\n    openAPIV3Schema:\n      description: Memcached is the Schema for the memcacheds API\n      properties:\n        apiVersion:\n          description: 'APIVersion defines the versioned schema of this representation\n            of an object. Servers should convert recognized schemas to the latest\n            internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'\n          type: string\n        kind:\n          description: 'Kind is a string value representing the REST resource this\n            object represents. Servers may infer this from the endpoint the client\n            submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'\n          type: string\n        metadata:\n          type: object\n        spec:\n          description: MemcachedSpec defines the desired state of Memcached\n          properties:\n            size:\n              description: Size is the size of the memcached deployment\n              format: int32\n              type: integer\n          required:\n          - size\n          type: object\n        status:\n          description: MemcachedStatus defines the observed state of Memcached\n          properties:\n            nodes:\n              description: Nodes are the names of the memcached pods\n              items:\n                type: string\n              type: array\n          required:\n          - nodes\n          type: object\n      type: object\n  versions:\n  - name: v1alpha1\n    served: true\n    storage: true\n```\n\n## Passing Arbitrary Arguments to Ansible\n\nYou are able to use the flag `--ansible-args` to pass an arbitrary argument to the Ansible-based Operator. With this option we can, for example, allow a playbook to run a specific part of the configuration without running the whole playbook:  \n\n```shell\nansible-operator run --ansible-args='--tags \"configuration,packages\"'\n```\n```\nansible-operator run --ansible-args='--skip-tags \"notification\"'\n```\nAnsible-runner will perform the task relevant to the command specified by the user in the ```---ansible-args``` flag.\n\n\n## Using Ansible-Vault\n\n[Ansible Vault][ansible-vault-doc] allows you to keep sensitive data such as passwords or keys in encrypted files, rather than as plaintext in playbooks or roles. You can specify Ansible-Vault file via an arbitrary argument by using the `--ansible-args` flag. For example, let's assume that a playbook reads in a file `vars.yml` which contains an encrypted text and stores it in a variable `secret`:\n\n```\n---\n- name: Playbook to print debug messages\n  hosts: localhost\n  tasks:\n    - name: Get the decrypted message variable\n      include_vars:\n        file: vars.yml\n        name: secret\n    - debug:\n        msg: The decrypted value is {{secret.the_secret}}\n```\n\nNow, let's also assume that we have a password file, `pwd.yml`, that contains the password to decrypt the encrypted text. Then, by running the command `ansible-operator run --ansible-args='--vault-password-file /absolute/path/to/pwd.yml'` the operator will read in the encrypted text from the file and perform decryption using the password stored in the `pwd.yml` file:\n\n```\n--------------------------- Ansible Task StdOut -------------------------------\n\n TASK [debug] ******************************** \nok: [localhost] => {\n    \"msg\": \"The decrypted value is DECRYPTED-TEST-VALUE\"\n}\n\n-------------------------------------------------------------------------------\n```\n\n## Using Ansible Log Events\n\nUsing the `--ansible-log-events` CLI flag, you can determine to what degree the Ansible task logs will be outputted. The flag can take any of the following values:\n\n1. `Nothing` - No tasks or task-related logs will be outputted.\n2. `Tasks` - Only Ansible Tasks will be outputted.\n3. `Everything` - All info logs and all tasks will be outputted.\n\nIf you want more control over the logs that are outputted, consider using the [Zap Logger][Zap-Logger] and [verbosity annotations][verbosity-annotations] in tandem with the `--ansible-log-events` CLI flag.\n\n## `ansible.sdk.operatorframework.io/reconcile-period` Custom Resource Annotation\n\nYou can specify the reconcile period for an Ansible Operator by adding the ansible.sdk.operatorframework.io/reconcile-period key to the custom resource annotations.\nThis feature specifies the maximum interval in which a cluster will get reconciled, and defaults to 10 hours if not manually set. If changes are detected in the desired state, the cluster may be reconciled sooner than the specified interval.\n\nThe reconcile period can be specified in the custom resource's annotations in the following manner: \n\n```yaml\n...\nmetadata:\n  name: memcached-sample\n  annotations:\n    ansible.sdk.operatorframework.io/reconcile-period: 5s\n...\n```\n\nThe key only accepts a value in the `h/m/s` format, such as `1h2m4s`, `3m0s`, or `4s`. Values such as `1x3m9s` are invalid.\n\n**NOTE**: Alternatively, you can specify the reconcile period for Ansible-based Operators in the following ways:\n- Using the `--reconcile-period` command-line flag \n- Using the 'reconcilePeriod' key in the `watches.yaml` file\nYou should not use all three methods to specify a single reconcile period. If all three methods are used simultaneously, the order of precedence is as follows: Custom resource annotations > `watches.yaml` file > command-line flag.\n\n\n[ansible-vault-doc]: https://docs.ansible.com/ansible/latest/user_guide/vault.html\n[Zap-Logger]: https://github.com/operator-framework/operator-sdk/blob/master/website/content/en/docs/building-operators/golang/references/logging.md#default-zap-logger\n[verbosity-annotations]: https://sdk.operatorframework.io/docs/building-operators/ansible/reference/advanced_options/#ansible-verbosity\n\n"
  },
  {
    "path": "website/content/en/docs/building-operators/ansible/reference/ansible-base-images.md",
    "content": "---\ntitle: Ansible Operator Base Images\nlinkTitle: Base Images\nweight: 20\n---\n\nAnsible-based operators are built on top of base images built for use\nwith the Operator-SDK.\n\n\n## Ansible Versions\n\nFor Operator-SDK versions > `v1.30.0` the `quay.io/operator-framework/ansible-operator`\nbase image has been updated to use Ansible 2.15. The Ansible 2.11 preview base image\nhas been removed and will no longer be built/supported past Operator-SDK `v1.30`.\n\nFor Operator-SDK versions <= `v1.30.0`, the below information applies:\n\nThere have been some major changes in the Ansible ecosystem, primarily\nthe addition of `collections` and the removal of these libraries from\nAnsible core. Ansible 2.9 is the last release of the \"old way\", with\nforward compatibility for collections. This is the version officially\nsupported by the Operator-SDK.\n\nAnsible 2.10 was a transition release, and it is NOT recommended for use\nwith operators.\n\nAnsible 2.11 is the future, and Operator-SDK will eventually provide only 2.11 images. Currently, 2.11 base images are in tech-preview.\nSee: [ansible-operator-2.11-preview](https://quay.io/repository/operator-framework/ansible-operator-2.11-preview).\n\n## Changing Ansible Operator Base Images\n\nFor Operator-SDK versions > `v1.30.0` - Operators are scaffolded with\nthe latest version of the base image (using Ansible 2.15). The base image\nname is the same as previous versions of the Operator-SDK.\n\nFor Operator-SDK versions <= `v1.30.0`, the below information applies:\n\nOperators are scaffolded with the latest version of the base image\n(using Ansible 2.9) in the first line of the operator Dockerfile.\n\n`FROM quay.io/operator-framework/ansible-operator:v1.16`\n\nOperator authors who want to try out 2.11 can simply replace their FROM with:\n`FROM quay.io/operator-framework/ansible-operator-2.11-preview:v1.16`\n"
  },
  {
    "path": "website/content/en/docs/building-operators/ansible/reference/dependent-watches.md",
    "content": "---\ntitle: Dependent Watches\nweight: 20\n---\n\nThis document describes the `watchDependentResources` option in [`watches.yaml`](#example) file. It delves into what dependent resources are, why the option is required, how it is achieved and finally gives an example.\n\n### What are dependent resources?\nIn most cases, an operator creates a bunch of Kubernetes resources in the cluster, that helps deploy and manage the application. For instance, the [etcd-operator](https://github.com/coreos/etcd-operator/blob/master/doc/gif/demo.gif) creates two services and a number of pods for a single `EtcdCluster` CR. In this case, all the Kubernetes resources created by the operator for a CR is defined as dependent resources.\n\n### Why the `watchDependentResources` option?\nOften, an operator needs to watch dependent resources. To achieve this, a developer would set the field, `watchDependentResources` to `True` in the `watches.yaml` file. If enabled, a change in a dependent resource will trigger the reconciliation loop causing Ansible code to run.\n\nFor example, since the _etcd-operator_ needs to ensure that all the pods are up and running, it needs to know when a pod changes. Enabling the dependent watches option would trigger the reconciliation loop to run. The Ansible logic needs to handle these cases and make sure that all the dependent resources are in the desired state as declared by the `CR spec`\n\n`Note: By default it is enabled when using ansible-operator`\n\n### How is this achieved?\nThe `ansible-operator` base image achieves this by leveraging the concept of [owner-references](https://kubernetes.io/docs/concepts/workloads/controllers/garbage-collection/). Whenever a Kubernetes resource is created by Ansible code, the `ansible-operator`'s `proxy` module injects `owner-references` into the resource being created. The `owner-references` means the resource is owned by the CR for which reconciliation is taking place.\n\nWhenever the `watchDependentResources` field is enabled, the `ansible-operator` will watch all the resources owned by the CR, registering callbacks to their change events. Upon a change, the callback will enqueue a `ReconcileRequest` for the CR. The enqueued reconciliation request will trigger the `Reconcile` function of the controller which will execute the ansible logic for reconciliation.\n\n### Example\n\nThis is an example of a watches file with the `watchDependentResources` field set to `True`\n```yaml\n\n- version: v1alpha1\n  group: app.example.com\n  kind: AppService\n  playbook: playbook.yml\n  maxRunnerArtifacts: 30\n  reconcilePeriod: 5s\n  manageStatus: False\n  watchDependentResources: True\n\n```\n"
  },
  {
    "path": "website/content/en/docs/building-operators/ansible/reference/finalizers.md",
    "content": "---\ntitle: Ansible Operator Finalizers\nlinkTitle: Finalizers\nweight: 20\n---\n\nThe default behavior of an Ansible Operator is to delete all resources the operator\ncreated during reconciliation when a managed resource is marked for deletion. This\nbehavior is usually sufficient for applications that exist only in Kubernetes, but\nsometimes it is necessary to perform more complex operations (for example, when\nyour action performed against a third party API needs to be undone). These more\ncomplex cases can still be handled by Ansible Operator, through the use of a [finalizer][doc-crd-finalizers].\n\nFinalizers allow controllers (such as an Ansible Operator) to implement asynchronous pre-delete hooks.\nThis allows custom logic to run after a resource has been marked for deletion, but\nbefore the resource has actually been deleted from the Kubernetes cluster.\nFor Ansible Operator, this hook takes the form of an Ansible playbook or role. You can\ndefine the mapping from your finalizer to a playbook or role by simply setting the\n`finalizer` field on the entry in your `watches.yaml`. You can also choose to re-run\nyour top-level playbook or role with different variables set. The `watches.yaml`\nfinalizer configuration accepts the following options:\n\nSee [Ansible watches documentation][ansible-watches] for more information.\n\n\n#### name\n\n`name` is required.\n\nThis is the name of the finalizer. This is basically an arbitrary string, the existence\nof any finalizer string on a resource will prevent that resource from being deleted until\nthe finalizer is removed. Ansible Operator will remove this string from the list of\nfinalizers on successful execution of the specified role or playbook. A typical finalizer\nwill be `<qualified-group>/finalizer`, where `<qualified-group>` is the fully qualified group\nof the resource being managed.\n\n#### playbook\n\nOne of `playbook`, `role`, or `vars` must be provided. If `playbook` is not provided, it\nwill default to the playbook specified at the top level of the `watches.yaml`\nentry.\n\nThis field is identical to the top-level `playbook` field. It requires an absolute\npath to a playbook on the operator’s file system.\n\n#### role\n\nOne of `playbook`, `role`, or `vars` must be provided. If `role` is not provided, it\nwill default to the role specified at the top level of the [`watches.yaml`][watches] entry.\n\nThis field is identical to the top-level `role` field.\n\n\n#### vars\n\nOne of `playbook`, `role`, or `vars` must be provided.\n\n`vars` is an arbitrary map of key-value pairs. The contents of `vars` will be passed as `extra_vars` to the\nplaybook or role specified in the finalizer block, or at the top-level if neither `playbook`\nor `role` was set for the finalizer.\n\n## Examples\n\nHere are a few examples of `watches.yaml` files that specify a finalizer:\n\n### Run top-level playbook or role with new variables\n\n```yaml\n---\n- version: v1alpha1\n  group: app.example.com\n  kind: Database\n  playbook: /opt/ansible/playbook.yml\n  finalizer:\n    name: app.example.com/finalizer\n    vars:\n      state: absent\n```\n\nThis example will run `playbook.yml` when the Custom Resource\nis deleted. Because `vars` is set, the playbook will be run with `state` set to `absent`. Inside the playbook,\nthe author can check this value and perform whatever cleanup is necessary.\n\n```yaml\n---\n- version: v1alpha1\n  group: app.example.com\n  kind: Database\n  role: database\n  finalizer:\n    name: app.example.com/finalizer\n    vars:\n      state: absent\n```\n\nThis example is nearly identical to the first, except it will run the `/opt/ansible/roles/database`\nrole, rather than a playbook, with the `state` variable set to `absent`.\n\n### Run a different playbook or role\n```yaml\n---\n- version: v1alpha1\n  group: app.example.com\n  kind: Database\n  playbook: playbook.yml\n  finalizer:\n    name: app.example.com/finalizer\n    role: teardown_database\n```\n\nThis example will run the `/opt/ansible/roles/teardown_database` role when the Custom Resource is deleted.\n\n```yaml\n---\n- version: v1alpha1\n  group: app.example.com\n  kind: Database\n  playbook: playbook.yml\n  finalizer:\n    name: app.example.com/finalizer\n    playbook: destroy.yml\n```\n\nThis example will run the `/opt/ansible/destroy.yml` playbook when the Custom Resource is deleted.\n\n```yaml\n---\n- version: v1alpha1\n  group: app.example.com\n  kind: Database\n  playbook: playbook.yml\n  finalizer:\n    name: app.example.com/finalizer\n    role: myNamespace.myCollection.myRole\n```\n\nThis example will run the `myRole` when the Custom Resource is deleted. (The collection must have been installed.)\n\n\n### Run a different playbook or role with vars\n\nYou can set `playbook` or `role` and `vars` at the same time. This can be useful if only a small\npart of your logic handles interacting with the component that requires cleanup. Rather than\nrun all the logic again, you can specify only to run the role or playbook that handled the\ninteraction, with a different variable set.\n\n```yaml\n---\n- version: v1alpha1\n  group: app.example.com\n  kind: Database\n  playbook: playbook.yml\n  finalizer:\n    name: app.example.com/finalizer\n    role: manage_credentials\n    vars:\n      state: revoked\n```\n\n\nFor this example, assume our application configures automated backups to a third party service.\nOn deletion, all we want to do is revoke the credentials used to backup the data. We run\njust the `/opt/ansible/roles/manage_credentials` role, which is imported by our playbook to\ncreate the credentials in the first place, but we pass the `state: revoked` option, which\ncauses the role to invalidate our credentials. For everything else in our application,\nautomatic deletion of dependent resources will be sufficient, so we can exit successfully and\nlet the operator remove our finalizer and allow the resource to be deleted.\n\n[doc-crd-finalizers]:https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#finalizers\n[ansible-watches]:/docs/building-operators/ansible/reference/watches/\n"
  },
  {
    "path": "website/content/en/docs/building-operators/ansible/reference/information-flow-ansible-operator.md",
    "content": "---\ntitle: Information Flow for Operator SDK Ansible-based Operators\nlinkTitle: Information Flow\nweight: 20\n---\n\n![Ansible Operator Flow](/ao-flow.png)\n\n### Controller/Reconciler\n * Gets the primary resource based on NamespacedName this uses the cache from controller runtime.\n * Determines if the resource is deleted based on the existence of a finalizer and a metadata.DeletionTimeStamp.\n   * If deleted and not one of our finalizers we exit with no error.\n   * If finalizer is needed, but is not on the object, and is not deleted then add it and continue.\n * Marks the status of the CR as running if it is managing the status and continues\n * Creates the proxy’s kubeconfig.\n * Calls out Runner using the runner package.\n * Watches for events to come back across the results channel.\n   * Logs the events\n   * Keeps track of failure messages as well as the StatusEvent, which is the ending event that the Ansible sends to mark the playbook/role is completed.\n * If a finalizer exists and the resource was deleted then remove the finalizer and update the object and continue.\n * Update the status of the resource to mark that the run has completed\n\n### Runner Package\n * Create the socket that ansible will communicate over\n * Translate object.Spec -> ansible vars (camelCase -> camel_case) and adds them as parameters for the ansible-runner directory.\n * Create the directory on disk for ansible runner. or update the files on disk if they already exist.\n * Run the ansible runner command in a go routine, when this exits close the channel for the socket.\n\n### The Proxy\n * Every request to the k8s api goes through the proxy.\n * The owner reference is injected into the object that is being created in the same namespace as the CR.\n * The operator-sdk annotations are injected into the object that is being created outside of namepsace of the CR.\n * The proxy then adds dependent watches for the correct controller if we have not started watching the type already.\n * On a GET, we attempt to use the informer cache to get the resource. This will also attempt to re-add dependent watches if we find a type with an owner reference.\n\n### Ansible Runner\n * Ansible is run and has its own process.\n * Ansible-runner-http package allows runner to set us ansible events as ansible is being run. ansible runner uses the socket and the controller is watching the events as they come through the channel.\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "website/content/en/docs/building-operators/ansible/reference/internal_metrics.md",
    "content": "---\ntitle: Internal Operator Metrics\nlinkTitle: Metrics\nweight: 20\n---\n\nThe Ansible Operator comes with three internal metrics that provide an insight to the frequency and time of operator reconciliations. These metrics can be\nscraped by a Prometheus instance or any other openmetrics system. To publish operator metrics and scrape them with an openmetrics system such as Prometheus, view \n[Kubebuilder documentation](https://book.kubebuilder.io/reference/metrics.html) on publishing metrics.\n\nThe default metrics recorded in Operator SDK are collected in a [histogram](https://prometheus.io/docs/practices/histograms/).\n\nThe following three metrics are derived from the histogram:\n1. `ansible_operator_reconciles_bucket` - Each bucket in the histogram counts the number of reconciliations that have a period (in seconds) less than or equal\nto the upper limit of the bucket.\n3. `ansible_operator_reconciles_count` - The total number of reconciliations that have occurred up to that instance of time while running an Ansible operator.\n4. `ansible_operator_reconciles_sum` - The cumulative amount of time (in seconds) of all reconciliations that have occurred up to that instance of time while \nrunning an Ansible operator.\n\nThese metrics can be queried in the Prometheus UI.\n\n![Screen Shot 2021-06-24 at 2 10 28 PM](https://user-images.githubusercontent.com/37827279/123332879-f0fb2900-d4f5-11eb-87ea-7afd04f35b1c.png)\n"
  },
  {
    "path": "website/content/en/docs/building-operators/ansible/reference/proxy-vars.md",
    "content": "---\ntitle: Proxy Friendly Operators\nlinkTitle: Proxy Vars\nweight: 20\n---\n\nProxy-friendly Operators should inspect their environment for the\nstandard proxy variables (`HTTPS_PROXY`, `HTTP_PROXY`, and `NO_PROXY`)\nand pass the values to Operands.\n\nExample:\n\n```yaml\n- name: start proxy-test job\n  kubernetes.core.k8s:\n    definition:\n      apiVersion: batch/v1\n      kind: Job\n      metadata:\n        name: env-job\n        namespace: \"{{ ansible_operator_meta.namespace }}\"\n      spec:\n        template:\n          spec:\n            containers:\n              - name: curl-example\n                image: registry.access.redhat.com/ubi8/ubi:8.8\n                command: [\"curl\"]\n                args: [\"http://example.com/job-request\"]\n                env:\n                  - name: HTTP_PROXY\n                    value: '{{ lookup(\"env\", \"HTTP_PROXY\") | default(\"\", True) }}'\n                  - name: http_proxy\n                    value: '{{ lookup(\"env\", \"HTTP_PROXY\") | default(\"\", True) }}'\n            restartPolicy: Never\n        backoffLimit: 4\n```\n\nYou can set the environment variable on the Operator deployment. Using the memcached tutorial, edit config/manager/manager.yaml:\n\n```yaml\ncontainers:\n - args:\n   - --leader-elect\n   - --leader-election-id=ansible-proxy-demo\n   image: controller:latest\n   name: manager\n   env:\n     - name: \"HTTP_PROXY\"\n       value: \"http_proxy_test\"\n```\n"
  },
  {
    "path": "website/content/en/docs/building-operators/ansible/reference/retroactively-owned-resources.md",
    "content": "---\ntitle: Adding Owner References for Existing Resources\nlinkTitle: Retroactively Owned Resources\nweight: 20\n---\n\nOwner references are automatically injected `only during creation of\nresources`. Enabling owner reference injection `will not update objects`\ncreated while [owner reference injection is\ndisabled](../advanced_options#owner-reference-injection)\n\nThis guide will demonstrate how to retroactively set owner references\nfor existing resources.\n\nA GET request to the owning resource will provide the necessary data to\nconstruct an `ownerReference` or an `annotation`.\n\n`$ kubectl get memcacheds.cache.example.com -o yaml`\n\n**Example Response (Abbreviated):**\n\n```yaml\napiVersion: cache.example.com/v1alpha1\nkind: Memcached\nmetadata:\n  name: example-memcached\n  namespace: default\n  uid: 2a94ff2b-84e0-40ce-8b5e-2b7e4d2bc0e2\n```\n\n`kubectl edit` can be used to update the resources by hand. See below\nfor example `ownerReference` and `annotations`.\n\n## For objects in the same namespace as the Owner (CR)\n\nDependent resources *within the same namespace as the owning CR* are\ntracked with the `ownerReference` field.\n\n`ownerReference` structure:\n  * apiVersion: {group}/{version}\n  * kind: {kind}\n  * name: {metadata.name}\n  * uid: {metadata.uid}\n\n**Example ownerReference:**\n\n```yaml\nmetadata:\n  ...(snip)\n  ownerReferences:\n    - apiVersion: cache.example.com/v1alpha1\n      kind: Memcached\n      name: example-memcached\n      uid: ad834522-d9a5-4841-beac-991ff3798c00\n```\n\n## For objects which are NOT in the same namespace as the Owner (CR)\n\nAn `annotation` is used instead of an `ownerReference` if the dependent\nresource is in a different namespace than the CR, or the dependent\nresource is a cluster level resource.\n\n`annotation` structure:\n  * operator-sdk/primary-resource: {metadata.namespace}/{metadata.name}\n  * operator-sdk/primary-resource-type: {kind}.{group}\n\n**NOTE**: The `{group}` can be found by splitting the `apiVersion`\nmetadata of the CR, into `group` and `version`. As an example, \n`apiVersion: cache.example.com/v1alpha1` in the `config/samples` directory\ngives us the group `cache.example.com`.\n\n**Example Annotation:**\n\n```yaml\nmetadata:\n  ...(snip)\n  annotations:\n    operator-sdk/primary-resource: default/example-memcached\n    operator-sdk/primary-resource-type: Memcached.cache.example.com\n```\n\n## Migration using Ansible assets \n\nIf you have many resources to update, it may be easier to use the\nfollowing Ansible assets, which **should be considered an example rather\nthan an officially supported workflow**.\n\nTo use these assets, create a `vars.yml` as specified below and copy\n`playbook.yml` and `each_resource.yml` into the same directory. Execute\nthe playbook with:\n\n``` bash\n$ ansible-playbook -i localhost playbook.yml\n```\n\n### vars.yml\n\nThis file should be created by the user to configure the playbook, and\nneeds to contain:\n\n  * owning_resource\n      * apiVersion\n      * kind\n      * name\n      * namespace\n  * resources_to_own (list): For each resource, specify:\n      * name\n      * namespace (if applicable)\n      * apiVersion\n      * kind\n\n```yaml\nowning_resource:\n  apiVersion: cache.example.com/v1alpha1\n  kind: Memcached\n  name: example-memcached\n  namespace: default\n\nresources_to_own:\n  - name: example-memcached-memcached\n    namespace: default\n    apiVersion: apps/v1\n    kind: Deployment\n  - name: example-memcached\n    apiVersion: v1\n    kind: Namespace\n```\n\n### playbook.yml\n\nThis file can be used as-is without user adjustments.\n\n```yaml\n- hosts: localhost\n\n  tasks:\n    - name: Import user variables\n      include_vars: vars.yml\n    - name: Retrieve owning resource\n      kubernetes.core.k8s_info:\n        api_version: \"{{ owning_resource.apiVersion }}\"\n        kind: \"{{ owning_resource.kind }}\"\n        name: \"{{ owning_resource.name }}\"\n        namespace: \"{{ owning_resource.namespace }}\"\n      register: extra_owner_data\n\n    - name: Ensure resources are owned\n      include_tasks: each_resource.yml\n      loop: \"{{ resources_to_own }}\"\n      vars:\n        to_be_owned: '{{ q(\"kubernetes.core.k8s\",\n          api_version=item.apiVersion,\n          kind=item.kind,\n          resource_name=item.name,\n          namespace=item.namespace\n        ).0 }}'\n        owner_reference:\n          apiVersion: \"{{ owning_resource.apiVersion }}\"\n          kind: \"{{ owning_resource.kind }}\"\n          name: \"{{ owning_resource.name }}\"\n          uid: \"{{ extra_owner_data.resources[0].metadata.uid }}\"\n```\n\n### `each_resource.yml`\n\nThis file can be used as-is without user adjustments.\n\n``` yaml\n- name: Patch resource with owner reference\n  when:\n    - to_be_owned.metadata.namespace is defined\n    - to_be_owned.metadata.namespace == owning_resource.namespace\n    - (to_be_owned.metadata.ownerReferences is not defined) or\n      (owner_reference not in to_be_owned.metadata.ownerReferences)\n  kubernetes.core.k8s:\n    state: present\n    resource_definition:\n      apiVersion: \"{{ to_be_owned.apiVersion }}\"\n      kind: \"{{ to_be_owned.kind }}\"\n      metadata:\n        name: \"{{ to_be_owned.metadata.name }}\"\n        namespace: \"{{ to_be_owned.metadata.namespace }}\"\n        ownerReferences: \"{{ (to_be_owned.metadata.ownerReferences | default([])) + [owner_reference] }}\"\n\n- name: Patch resource with owner annotation\n  when: to_be_owned.metadata.namespace is not defined or to_be_owned.metadata.namespace != owning_resource.namespace\n  kubernetes.core.k8s:\n    state: present\n    resource_definition:\n      apiVersion: \"{{ to_be_owned.apiVersion }}\"\n      kind: \"{{ to_be_owned.kind }}\"\n      metadata:\n        name: \"{{ to_be_owned.metadata.name }}\"\n        namespace: \"{{ to_be_owned.metadata.namespace | default(omit)}}\"\n        annotations:\n          operator-sdk/primary-resource: \"{{ owning_resource.namespace }}/{{ owning_resource.name }}\"\n          operator-sdk/primary-resource-type: \"{{ owning_resource.kind }}.{{ owning_resource.apiVersion.split('/')[0] }}\"\n```\n"
  },
  {
    "path": "website/content/en/docs/building-operators/ansible/reference/scaffolding.md",
    "content": "---\ntitle: Ansible Based Operator Scaffolding\nlinkTitle: Scaffolding\nweight: 20\n---\n\nA new Ansible operator project can be created using a command that looks like\nthe following:\n\n```\noperator-sdk init --plugins ansible \\\n  --domain=my.domain \\\n  --group=apps --version=v1alpha1 --kind=AppService \\\n  --generate-playbook \\\n  --generate-role\n```\n\nThe new project directory has many generated folders and files. For further information check the [Project Layout][project-layout] doc.\n\n## The Deployment\n\nThe default Deployment manifest generated for the operator can be found in the\n`config/manager/manager.yaml` file. By default, the Deployment is named as\n'controller-manager'. It contains a single container named 'manager', and it\nmay pick up a sidecar patch from the `config/default` directory. The\nDeployment will create a single Pod.\n\nFor the container in the Pod, there are a few things to note. The default\nDeployment contains a placeholder for the container image to use, so you\ncannot create a meaningful operator using the YAML file directly. To deploy\nthe operator, you will run `make deploy IMG=<IMG>`. The image name and tag\nare then patched using kustomize.\n\n### The Volume Mount Path\n\nThe default EmptyDir volume mounted at `/tmp/ansible-operator/runner` is used\nto serve the [input directory][runner_input_dir] in ansible-runner's terms.\nThe mount path can *NOT* be changed to other paths, or else the Operator will\nfail to communicate with ansible-runner.\n\n### The Environment Variables\n\nYou can customize the behavior of the Ansible operator by specifying the\nenvironment variables for the container. Please refer to the\n[Ansible Documentation][ansible_env] for a list of environment variables that\ncan be used to tune the behavior of the Ansible engine.\n\nIn addition to the Ansible environment variables, Operator SDK also support\nsome special environment variables:\n\n- `WATCH_NAMESPACE`: This is the namespace your operator will watch for resource\n  changes, i.e. resource create, update or delete operations. In the scaffolded\n  operator Deployment, this is set to the same namespace in which the\n  operator is deployed. This variable can be set to one of the following types\n  of values:\n\n  - '': An empty string means that the operator will watch all namespaces.\n    This is the default value if the `WATCH_NAMESPACE` environment variable is\n    not set. It is especially useful for watching cluster-scoped resources.\n\n  - `foo`: The operator will watch the namespace named `foo`.\n    This is the setting you will use if you are operating a namespaced resource\n    which is deployed into a specific namespace.\n\n  - `foo,bar`: The operator checks the value of the environment variable and\n    realizes that it is a comma-separated list. This means the operator will\n    watch for resources in each of the listed namespaces.\n\n\n- `ANSIBLE_DEBUG_LOGS`: A boolean value for toggling the Ansible output during\n  reconciliation. When set to True, the operator dumps the Ansible result into\n  its standard output. \n\n- `ANSIBLE_ROLES_PATH`: The parent path(s) for the Ansible roles. When there\n  are more than one path to set, you can use \":\" to separate them. Given a\n  path `/opt/foo` and a role name `bar`, the Ansible operator will check if\n  the Ansible role can be found in either `/opt/foo/bar` or\n  `/opt/foo/roles/bar`.\n\n  This value overrides the setting from the `ansible-roles-path` flag.\n\n- `ANSIBLE_COLLECTIONS_PATH`: The base path for the Ansible collections which\n  defaults to `~/.ansible/collections` or `/usr/share/ansible/collections`\n  when `ANSIBLE_COLLECTIONS_PATH` is not explicitly specified. When a fully\n  qualified collection name in the [watches][watches_doc] file, the Ansible\n  operator checks if the specified collection can found under the base path\n  that can be customized using this variable. Suppose you have\n  `ANSIBLE_COLLECTIONS_PATH` set to `/foo` and the fully qualified collection\n  name set to `example.com.bar`, the Ansible operator searches for the roles\n  under `/foo/ansible_collections/example/com/roles/bar`.\n\n  This value takes precedence over the `--ansible-collections-path` flag. \n\n- `MAX_CONCURRENT_RECONCILES_<kind>_<group>`: This specifies the maximum number\n  of concurrent reconciliations for the operator. It defaults to the number of\n  CPUs. You can adjust this based on the cluster resources.\n\n- `WORKER_<kind>_<group>`: **Deprecated**. Use\n  `MAX_CONCURRENT_RECONCILES_<kind>_<group>` instead.\n\n- `ANSIBLE_VERBOSITY_<kind>_<group>`: This is used to customize the verbosity\n  of the ansible-runner command. The default value is 2.\n  The value must be no less than  0 and no greater than 7. \n  This value takes precedence over the global `--ansible-verbosity` flag,\n  and it can be overridden by the per-resource annotation named\n  `ansible.operator-sdk/verbosity`.\n\n[ansible_env]: https://docs.ansible.com/ansible/latest/reference_appendices/config.html#environment-variables\n[runner_input_dir]: https://ansible-runner.readthedocs.io/en/latest/intro.html#runner-input-directory-hierarchy\n[watches_doc]: /docs/building-operators/ansible/reference/watches/\n[project-layout]: /docs/overview/project-layout"
  },
  {
    "path": "website/content/en/docs/building-operators/ansible/reference/watches.md",
    "content": "---\ntitle: Ansible Operator Watches\nlinkTitle: Watches\nweight: 20\n---\n\nThe Watches file contains a list of mappings from custom resources, identified\nby it's Group, Version, and Kind, to an Ansible Role or Playbook. The Operator\nexpects this mapping file in a predefined location: `/opt/ansible/watches.yaml`\nThese resources, as well as child resources (determined by owner references) will\nbe monitored for updates and cached.\n\n* **group**:  The group of the Custom Resource that you will be watching.\n* **version**:  The version of the Custom Resource that you will be watching.\n* **kind**:  The kind of the Custom Resource that you will be watching.\n* **role** (default): Specifies a role to be executed. This field is mutually exclusive with the\n  \"playbook\" field. This field can be:\n  * an absolute path to a role directory.\n  * a relative path within one of the directories specified by `ANSIBLE_ROLES_PATH` environment variable or `ansible-roles-path` flag.\n  * a relative path within the current working directory, which defaults to `/opt/ansible/roles`.\n  * a fully qualified collection name of an installed Ansible collection. Ansible collections are installed to\n    `~/.ansible/collections` or `/usr/share/ansible/collections` by default. If they are installed elsewhere,\n    use the `ANSIBLE_COLLECTIONS_PATH` environment variable or the `ansible-collections-path` flag\n* **playbook**: This is the playbook name that you have added to the\n  container. This playbook is expected to be simply a way to call roles. This\n  field is mutually exclusive with the \"role\" field. When running locally, the playbook is expected to be in the\n  current project directory.\n* **vars**: This is an arbitrary map of key-value pairs. The contents will be\n  passed as `extra_vars` to the playbook or role specified for this watch.\n* **reconcilePeriod** (optional): The maximum interval that the operator will wait before beginning another reconcile, even if no watched events are received. When an operator watches many resources, each reconcile can become expensive, and a low value here can actually reduce performance. Typically, this option should only be used in advanced use cases where `watchDependentResources` is set to `False`  and when is not possible to use the watch feature. E.g To manage external resources that don’t emit Kubernetes events. The format for the duration string is a sequence of decimal numbers, each with optional fraction and a unit suffix, such as \"300ms\", \"1.5h\" or \"2h45m\". Valid time units are \"ns\", \"us\" (or \"µs\"), \"ms\", \"s\", \"m\", \"h\". Defaults to 10 hours. \n* **manageStatus** (optional): When true (default), the operator will manage\n  the status of the CR generically. Set to false, the status of the CR is\n  managed elsewhere, by the specified role/playbook or in a separate controller.\n* **blacklist**: A list of child resources (by GVK) that will not be watched or cached.\n\nAn example Watches file:\n\n```yaml\n---\n# Simple example mapping Foo to the Foo role\n- version: v1alpha1\n  group: foo.example.com\n  kind: Foo\n  role: Foo\n\n# Simple example mapping Bar to a playbook\n- version: v1alpha1\n  group: bar.example.com\n  kind: Bar\n  playbook: playbook.yml\n\n# More complex example for our Baz kind\n# Here we will disable requeuing and be managing the CR status in the playbook,\n# and specify additional variables.\n- version: v1alpha1\n  group: baz.example.com\n  kind: Baz\n  playbook: baz.yml\n  manageStatus: False\n  vars:\n    foo: bar\n\n# ConfigMaps owned by a Memcached CR will not be watched or cached.\n- version: v1alpha1\n  group: cache.example.com\n  kind: Memcached\n  role: /opt/ansible/roles/memcached\n  blacklist:\n    - group: \"\"\n      version: v1\n      kind: ConfigMap\n\n# Example usage with a role from an installed Ansible collection\n- version: v1alpha1\n  group: bar.example.com\n  kind: Bar\n  role: myNamespace.myCollection.myRole\n\n# Example filtering of resources with specific labels\n- version: v1alpha1\n  group: bar.example.com\n  kind: Bar\n  playbook: playbook.yml\n  selector:\n    matchLabels:\n      foo: bar\n    matchExpressions:\n      - {key: foo, operator: In, values: [bar]}\n      - {key: baz, operator: Exists, values: []}\n```\n\n\nThe advanced features can be enabled by adding them to your watches file per GVK.\nThey can go below the `group`, `version`, `kind` and `playbook` or `role`.\n\nSome features can be overridden per resource via an annotation on that CR. The options that are overridable will have the annotation specified below.\n\n| Feature | Yaml Key | Description| Annotation for override | default | Documentation |\n|---------|----------|------------|-------------------------|---------|---------------|\n| Reconcile Period | `reconcilePeriod`  | time between reconcile runs for a particular CR  | ansible.sdk.operatorframework.io/reconcile-period  | 10h | |\n| Manage Status | `manageStatus` | Allows the ansible operator to manage the conditions section of each resource's status section. | | true | |\n| Watching Dependent Resources | `watchDependentResources` | Allows the ansible operator to dynamically watch resources that are created by ansible | | true | [dependent watches](../dependent-watches) |\n| Watching Cluster-Scoped Resources | `watchClusterScopedResources` | Allows the ansible operator to watch cluster-scoped resources that are created by ansible | | false | |\n| Max Runner Artifacts | `maxRunnerArtifacts` | Manages the number of [artifact directories](https://ansible-runner.readthedocs.io/en/latest/intro.html#runner-artifacts-directory-hierarchy) that ansible runner will keep in the operator container for each individual resource. | ansible.sdk.operatorframework.io/max-runner-artifacts | 20 | |\n| Finalizer | `finalizer`  | Sets a finalizer on the CR and maps a deletion event to a playbook or role | | | [finalizers](../finalizers)|\n| Selector | `selector`  | Identifies a set of objects based on their labels | | None Applied | [Labels and Selectors](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/)|\n| Automatic Case Conversion | `snakeCaseParameters`  | Determines whether to convert the CR spec from camelCase to snake_case before passing the contents to Ansible as extra_vars| | true | |\n| Watching Annotations Changes| `watchAnnotationsChanges` | Allows the ansible operator to trigger reconciliations on annotations changes on watched resources | | false | |\n\n\n#### Example\n```YaML\n---\n- version: v1alpha1\n  group: app.example.com\n  kind: AppService\n  playbook: playbook.yml\n  maxRunnerArtifacts: 30\n  reconcilePeriod: 5s\n  manageStatus: False\n  watchDependentResources: False\n  snakeCaseParameters: False\n  finalizer:\n    name: app.example.com/finalizer\n    vars:\n      state: absent\n```\n\n**Note:** By using the command `operator-sdk add api` you are able to add additional CRDs to the project API, which can aid in designing your solution using concepts such as encapsulation, single responsibility principle, and cohesion, which could make the project easier to read, debug, and maintain. With this approach, you are able to customize and optimize the configurations more specifically per GVK via the `watches.yaml` file.\n\n**Example:** \n\n```YaML\n---\n- version: v1alpha1\n  group: app.example.com\n  kind: AppService\n  playbook: playbook.yml\n  maxRunnerArtifacts: 30\n  reconcilePeriod: 5s\n  manageStatus: False\n  watchDependentResources: False\n  finalizer:\n    name: app.example.com/finalizer\n    vars:\n      state: absent\n\n- version: v1alpha1\n  group: app.example.com\n  kind: Database\n  playbook: playbook.yml\n  watchDependentResources: True\n  manageStatus: True\n```\n"
  },
  {
    "path": "website/content/en/docs/building-operators/ansible/reference/webhooks.md",
    "content": "---\ntitle: Adding Admission Webhooks to an Ansible-based Operator\nlinkTitle: Webhooks\nweight: 20\n---\n\nFor general background on what admission webhooks are, why to use them, and how to build them,\nplease refer to the official Kubernetes documentation on [Extensible Admission Controllers][admission-controllers]\n\nThis guide will assume that you understand the above content, and that you have an existing admission\nwebhook server. You will likely need to make a few modifications to the webhook server container.\n\nWhen integrating an admission webhook server into your Ansible-based Operator, we recommend that you\ndeploy it as a sidecar container alongside your operator. This allows you to make use of the proxy\nserver that the operator deploys, as well as the cache that backs it.\n\n## Ensuring the webhook server uses the caching proxy\n\nWhen an Ansible-based Operator runs, it creates a Kubernetes proxy server and serves it on\n`http://localhost:8888`. This proxy server does not require any authorization, so all you need to\ndo to make use of the proxy is ensure that your Kubernetes client is pointing at `http://localhost:8888`\nand that it does not attempt to verify SSL. If you use the default in-cluster configuration, you will\nbe hitting the real API server and will not get caching for free.\n\n## Deploying the webhook server\n\nCreate a new file called `config/default/manager_webhook_patch.yaml` with the following content\n(making sure to replace the image reference placeholder string):\n\n```yaml\n# This patch injects a sidecar container which is an admission webhook for the\n# controller manager.\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: controller-manager\n  namespace: system\nspec:\n  template:\n    spec:\n      containers:\n      - name: webhook\n        # Replace this with the built image name\n        image: \"REPLACE_WEBHOOK_IMAGE\"\n        volumeMounts:\n        - mountPath: /etc/tls/\n          name: webhook-cert\n      volumes:\n      # This assumes there is a secret called webhook-cert containing TLS certificates\n      # Projects like cert-manager can create these certificates\n      - name: webhook-cert\n        secret:\n          secretName: webhook-cert\n```\n\nThen, update `config/default/kustomization.yaml` to include this patch:\n\n```yaml\npatchesStrategicMerge:\n- manager_webhook_patch.yaml # Add this line\n```\n\nNow, when deploying the operator with `make deploy`, your webhook server will run alongside the\noperator, but Kubernetes will not yet call the webhooks before resources can be created. In order\nto let Kubernetes know about your webhooks, you must create specific API resources.\n\n\n<!--\n   TODO(fabianvf,asmacdo) update these sections to direct the user\n     to create files in the config directory and make use of kustomize.\n     The Go plugin's webhook scaffolding might be a good reference.\n-->\n## Making Kubernetes call your webhooks\n\nIn order to make your webhooks callable at all, first you must create a `Service` that points at your\nwebhook server. Below is a sample service that creates a `Service` named `my-operator-webhook`, that will\nsend traffic on port `443` to port `5000` in a `Pod` that matches the selector `name=my-operator`. Modify these\nvalues to match your environment.\n\n```yaml\napiVersion: v1\nkind: Service\nmetadata:\n  name: my-operator-webhook\nspec:\n  ports:\n  - name: webhook\n    port: 443\n    protocol: TCP\n    # Change targetPort to match the port your server is listening on\n    targetPort: 5000\n  selector:\n    # Change this selector to match the labels on your operator pod\n    name: my-operator\n  type: ClusterIP\n```\n\nNow that you have a `Service` directing traffic to your webhook server, you will need to create\n[`MutatingWebhookConfiguration`][mutating-webhook] or [`ValidatingWebhookConfiguration`][validating-webhook] objects (depending on what type of webhook you have deployed), which will tell Kubernetes\nto send certain API requests through your webhooks before writing to etcd.\n\nBelow are examples of both [`MutatingWebhookConfiguration`][mutating-webhook] and [`ValidatingWebhookConfiguration`][validating-webhook] objects,\nwhich will tell Kubernetes to call the `my-operator-webhook` service when `samples.example.com Example` resources\nare created. The mutating webhook is served on the `/mutating` path in my example webhook server, and the validating webhook is served on `/validating`. Update these values as needed to reflect your environment\nand desired behavior. These objects are thoroughly documented in the official Kubernetes documentation on [Extensible Admission Controllers][admission-controllers]\n\n```yaml\n---\napiVersion: admissionregistration.k8s.io/v1\nkind: MutatingWebhookConfiguration\nmetadata:\n  name: mutating.example.com\nwebhooks:\n- name: \"mutating.example.com\"\n  rules:\n  - apiGroups:   [\"samples.example.com\"]\n    apiVersions: [\"*\"]\n    operations:  [\"CREATE\"]\n    resources:   [\"examples\"]\n    scope:       \"Namespaced\"\n  clientConfig:\n    service:\n      # Replace this with the namespace your service is in\n      namespace: REPLACE_NAMESPACE\n      name: my-operator-webhook\n      path: /mutating\n  admissionReviewVersions: [\"v1\"]\n  sideEffects: None\n---\napiVersion: admissionregistration.k8s.io/v1\nkind: ValidatingWebhookConfiguration\nmetadata:\n  name: validating.example.com\nwebhooks:\n- name: validating.example.com\n  rules:\n  - apiGroups:   [\"samples.example.com\"]\n    apiVersions: [\"*\"]\n    operations:  [\"CREATE\"]\n    resources:   [\"examples\"]\n    scope:       \"Namespaced\"\n  clientConfig:\n    service:\n      # Replace this with the namespace your service is in\n      namespace: REPLACE_NAMESPACE\n      name: my-operator-webhook\n      path: /validating\n  admissionReviewVersions: [\"v1\"]\n  failurePolicy: Fail\n  sideEffects: None\n```\n\nIf these resources are configured properly you will now have an admissions webhook that can reject or mutate\nincoming resources before they are written to the Kubernetes database.\n\n## Summary\n\nTo deploy an existing admissions webhook to validate or mutate your Kubernetes resources alongside an\nAnsible-based Operator, you must\n1. Configure your admissions webhook to use the proxy server running on `http://localhost:8888` in the operator pod\n1. Add the webhook container to your operator deployment\n1. Create a `Service` pointing to your webhook\n1. Make sure your webhook is reachable via the `Service` over `https`\n1. Create [`MutatingWebhookConfiguration`][mutating-webhook] or [`ValidatingWebhookConfiguration`][validating-webhook] mapping the resource you want to mutate/validate to the `Service` you created\n\n\n[admission-controllers]:https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/\n[validating-webhook]:https://kubernetes.io/docs/reference/kubernetes-api/extend-resources/validating-webhook-configuration-v1/\n[mutating-webhook]:https://kubernetes.io/docs/reference/kubernetes-api/extend-resources/mutating-webhook-configuration-v1/\n"
  },
  {
    "path": "website/content/en/docs/building-operators/ansible/testing-guide.md",
    "content": "---\ntitle: Ansible Based Operator Testing with Molecule\nlinkTitle: Testing with Molecule\nweight: 4\n---\n\n## Getting started\n\n### Requirements\nTo begin, you should have:\n\n- The latest version of the [operator-sdk](https://github.com/operator-framework/operator-sdk) installed.\n- Docker installed and running\n- [Molecule](https://github.com/ansible/molecule) >= v3.0\n- [Ansible](https://github.com/ansible/ansible) >= v2.9\n- [The Python Kubernetes client](https://github.com/kubernetes-client/python)\n- An initialized Ansible Operator project, with the molecule directory present.\n\n**NOTE**  If you initialized a project with a previous version of operator-sdk, you can generate a new dummy project and copy in the `molecule` directory. Just be sure to generate the dummy project with the same `api-version` and `kind`, or some of the generated files will not work without modification. Your top-level project structure should look like this:\n\n    ```\n    .\n    ├── config\n    ├── Dockerfile\n    ├── Makefile\n    ├── molecule\n    ├── playbooks\n    ├── PROJECT\n    ├── requirements.yml\n    ├── roles\n    └── watches.yaml\n\n    ```\n\n- The Ansible content specified in `requirements.yml` will also need to be installed. You can install them with `ansible-galaxy collection install -r requirements.yml`\n\n<!-- TODO(fabianvf, asmacdo): update this section based on the new molecule scaffolding -->\n### Molecule scenarios\nIf you look into the `molecule` directory, you will see four directories (`default`, `test-local`,`cluster`, `templates`). The `default`, `test-local`, and `cluster` directories contain a set of files that together make up what is known as a molecule *scenario*. The `templates` directory contains Jinja templates that are used by multiple scenarios to configure the Kubernetes cluster.\n\nOur molecule scenarios have the following basic structure:\n\n```\n.\n├── molecule.yml\n├── prepare.yml\n├── converge.yml\n└── verify.yml\n```\n\n- `molecule.yml` is a configuration file for molecule. It defines what driver to use to stand up an environment and the associated configuration, linting rules, and a variety of other configuration options. For full documentation on the options available here, see the [molecule configuration documentation](https://molecule.readthedocs.io/configuration/)\n\n- `prepare.yml` is an Ansible playbook that is run once during the set up of a scenario. You can put any arbitrary Ansible in this playbook. It is used for one-time configuration of your test environment, for example, creating the cluster-wide `CustomResourceDefinition` that your Operator will watch.\n\n- `converge.yml` is an Ansible playbook that contains your core logic for the scenario. In a normal molecule scenario, this would import and run the associated role. For Ansible Operators, we mostly use this to create the Kubernetes resources necessary to deploy your operator into Kubernetes.\n\nBelow we will walk through the structure and function of each file for each scenario.\n\n#### default\nThe default scenario is intended for use during the development of your Ansible role or playbook, and will run it outside of the context of an operator. You can run this scenario with\n`molecule test` or `molecule converge`. There is no corresponding `operator-sdk` command for this scenario.\n\nThe scenario has the following structure:\n\n```\nmolecule/default\n├── molecule.yml\n├── prepare.yml\n├── converge.yml\n└── verify.yml\n```\n\n- `molecule.yml` for this scenario tells molecule to use the docker driver to bring up a Kubernetes-in-Docker container,\nand by default exposes the API on the host's port 9443. It also specifies a few inventory and environment\nvariables which are used in `prepare.yml` and `converge.yml`.\n\n- `prepare.yml` ensures that a kubeconfig properly configured to connect to the Kubernetes-in-Docker cluster exists and\nis mapped to the proper port, and also waits for the Kubernetes API to become available before allowing testing to begin.\n\n- `converge.yml` imports and runs your role or playbook.\n\n- `verify.yml` is an Ansible playbook where you can put tasks to verify that the state of your cluster matches what you expect.\n\n##### Configuration\n\nThere are a few parameters you can tweak at runtime to change the behavior of your molecule run.\nYou can change these parameters by setting the environment variable before invoking molecule.\n\nThe options supported by the default scenario are:\n\n| Environment variable | Default | Purpose |\n| :---                 | :---    | :---    |\n| KUBE_VERSION | 1.17 | The Kubernetes version to deploy |\n| TEST_CLUSTER_PORT | 9443 | The port on the host to expose the Kubernetes API |\n| TEST_OPERATOR_NAMESPACE | osdk-test | The namespace to run your role against |\n\n#### cluster\n\nThe cluster scenario runs an end-to-end test of your operator against an existing cluster.\nThe operator image needs to be available to the cluster for this scenario to succeed.\nThis scenario will deploy your CRDs, RBAC, and operator into the cluster,\nand then creates an instance of your CustomResource and runs your assertions to make sure the Operator responded properly.\n\nYou can run this scenario with `molecule test` or `molecule converge`. There is no corresponding `operator-sdk` command for this scenario.\n\nThe scenario has the following structure:\n\n```\nmolecule/default\n├── molecule.yml\n├── create.yml\n├── prepare.yml\n├── converge.yml\n├── verify.yml\n└── destroy.yml\n```\n\n- `molecule.yml` for this scenario uses the delegated driver, and does not spin up any additional infrastructure.\n\n- `create.yml` is a no-op, but must be present for the delegated driver to work.\n\n- `prepare.yml` ensures the CRD, namespace, and RBAC resources are present in the cluster.\n\n- `converge.yml` creates your operator deployment, based on the template in `molecule/templates/operator.yaml.j2`.\n\n- `verify.yml` is an Ansible playbook where you can put tasks to verify that the state of your cluster matches what you expect. By default, it creates a Custom Resource and waits for reconciliation to complete successfully. There is an example assertion present as well.\n\n- `destroy.yml` ensures that the namespace, RBAC resources, and CRD are deleted at the end of the run.\n\n##### Configuration\n\nThere are a few parameters you can tweak at runtime to change the behavior of your molecule run.\nYou can change these parameters by setting the environment variable before invoking molecule.\n\nThe options supported by the default scenario are:\n\n| Environment variable | Default | Purpose |\n| :---                 | :---    | :---    |\n| OPERATOR_IMAGE | None | *Required* The image to use when deploying the operator into the cluster |\n| OPERATOR_PULL_POLICY | Always | The pull policy to use when deploying the operator into the cluster |\n| KUBECONFIG | ~/.kube/config | The path to the Kubeconfig for the cluster to test against |\n| TEST_OPERATOR_NAMESPACE | osdk-test | The namespace to run your role against |\n\n#### test-local\nThe test-local scenario runs a full end-to-end test of your operator that does not require an existing\ncluster or external registry, and can run in CI environments that allow users to run privileged containers\n(such as Travis).\nIt brings up a Kubernetes-in-docker cluster, builds your Operator, deploys it into the cluster,\nand then creates an instance of your CustomResource and runs your assertions to make sure the Operator responded properly.\nYou can run this scenario with `molecule test -s local`, or with `molecule converge -s test-local` which will leave the environment up afterward.\n\nThe scenario has the following structure:\n\n```\nmolecule/test-local\n├── molecule.yml\n├── prepare.yml\n├── converge.yml\n└── verify.yml\n```\n\n- `molecule.yml` for this scenario tells molecule to use the docker driver to bring up a Kubernetes-in-Docker container with the project root mounted, and exposes the API on the host's port 10443. It also specifies a few inventory and environment variables which are used in `prepare.yml` and `converge.yml`. It is very similar to the default scenario's configuration.\n\n- `prepare.yml` first runs the `prepare.yml` from the default scenario to ensure the kubeconfig is present and the API is up.\nIt then runs the `prepare.yml` from the cluster scenario to configure your cluster's CRDs and RBAC.\n\n- `converge.yml` connects to your Kubernetes-in-Docker container, and uses your mounted project root to build your Operator. This makes your Operator available to the cluster without needing to push it to an external registry. Then, it will ensure that a fresh deployment of your Operator is present in the cluster, using the template `molecule/templates/operator.yaml.j2`.\n\n- `verify.yml` will run the `verify.yml` from the `cluster` scenario, as the main difference between the `test-local` and `cluster` scenarios is the method of deployment, but not the behavior of the operator.\n\n##### Configuration\n\nThere are a few parameters you can tweak at runtime to change the behavior of your molecule run.\nYou can change these parameters by setting the environment variable before invoking molecule.\n\nThe options supported by the default scenario are:\n\n| Environment variable | Default | Purpose |\n| :---                 | :---    | :---    |\n| KUBE_VERSION | 1.17 | The Kubernetes version to deploy |\n| TEST_CLUSTER_PORT | 10443 | The port on the host to expose the Kubernetes API |\n| TEST_OPERATOR_NAMESPACE | osdk-test | The namespace to deploy the operator and associated resources |\n\n#### converge vs test\nThe two most common molecule commands for testing during development are `molecule test` and `molecule converge`.\n`molecule test` performs a full loop, bringing a cluster up, preparing it, running your tasks, and tearing it down.\n`molecule converge` is more useful for iterative development, as it leaves your environment up between runs. This\ncan cause unexpected problems if you end up corrupting your environment during testing, but running `molecule destroy`\nwill reset it.\n\n- `molecule test` performs a full loop, bringing a cluster up, preparing it, running your tasks, and tearing it down.\n- `molecule converge` is more useful for iterative development, as it leaves your environment up between runs. This can cause unexpected problems if you end up corrupting your environment during testing, but running `molecule destroy` will reset it.\n\n## Writing tests\n\n### Adding a task\nThe default operator that is generated by `operator-sdk new` doesn't do anything, so first we will need to add an\nAnsible task so that the Operator does something we can verify. For this example, we will create a simple ConfigMap\nwith a single key.\nWe'll be adding the task to `roles/example/tasks/main.yml`, which should now look like this:\n\n```\n---\n# tasks file for exampleapp\n- name: create Example configmap\n  kubernetes.core.k8s:\n    definition:\n      apiVersion: v1\n      kind: ConfigMap\n      metadata:\n        name: 'test-data'\n        namespace: '{{ ansible_operator_meta.namespace }}'\n      data:\n        hello: world\n```\n\n\n\n### Adding a test\n\nNow that our Operator actually does some work, we can add a corresponding assert to `molecule/cluster/verify.yml`.\nWe'll also add a debug message so that we can see what the ConfigMap looks like.\nThe file should now look like this:\n\n```\n---\n\n- name: Verify\n  hosts: localhost\n  connection: local\n  tasks:\n    - debug: var=cm\n      vars:\n        cm: '{{ lookup(\"kubernetes.core.k8s\", api_version=\"v1\", kind=\"ConfigMap\", namespace=namespace, resource_name=\"test-data\") }}'\n    - assert:\n        that: cm.data.hello == 'world'\n      vars:\n        cm: '{{ lookup(\"kubernetes.core.k8s\", api_version=\"v1\", kind=\"ConfigMap\", namespace=namespace, resource_name=\"test-data\") }}'\n```\n\nNow that we have a functional Operator, and an assertion of its behavior, we can verify that everything is working\nby running `molecule test -s local`.\n\n#### The Ansible `assert` and `fail` modules\nThese modules are handy for adding assertions and failure conditions to your Ansible Operator tests:\n\n- [assert](https://docs.ansible.com/ansible/2.9/modules/assert_module.html)\n- [fail](https://docs.ansible.com/ansible/2.9/modules/fail_module.html)\n"
  },
  {
    "path": "website/content/en/docs/building-operators/ansible/tutorial.md",
    "content": "---\ntitle: Ansible Operator Tutorial\nlinkTitle: Tutorial\nweight: 3\ndescription: An in-depth walkthrough of building and running an Ansible-based operator.\n---\n\n**NOTE:** If your project was created with an `operator-sdk` version prior to `v1.0.0`\nplease [migrate][migration-guide], or consult the [legacy docs][legacy-quickstart-doc].\n\n## Prerequisites\n\n- Go through the [installation guide][install-guide].\n- Make sure your user is authorized with `cluster-admin` permissions.\n- An accessible image registry for various operator images (ex. [hub.docker.com](https://hub.docker.com/signup),\n[quay.io](https://quay.io/)) and be logged in to your command line environment.\n  - `example.com` is used as the registry Docker Hub namespace in these examples.\n  Replace it with another value if using a different registry or namespace.\n  - [Authentication and certificates][image-reg-config] if the registry is private or uses a custom CA.\n\n\n## Overview\n\nWe will create a sample project to let you know how it works and this sample will:\n\n- Create a Memcached Deployment if it doesn't exist\n- Ensure that the Deployment size is the same as specified by the Memcached CR spec\n- Update the Memcached CR status using the status writer with the names of the CR's pods\n\n## Create a new project\n\nUse the CLI to create a new memcached-operator project:\n\n```sh\nmkdir memcached-operator\ncd memcached-operator\noperator-sdk init --plugins=ansible --domain example.com\n```\n\nAmong the files generated by this command is a Kubebuilder `PROJECT`\nfile. Subsequent `operator-sdk` commands (and help text) run from the\nproject root read this file and are aware that the project type is\nAnsible.\n\nNext, we will create a `Memcached` API.\n\n```sh\noperator-sdk create api --group cache --version v1alpha1 --kind Memcached --generate-role\n```\n\nThe scaffolded operator has the following structure:\n- `Memcached` Custom Resource Definition, and a sample `Memcached` resource.\n- A \"Manager\" that reconciles the state of the cluster to the desired state\n  - A reconciler, which is an Ansible Role or Playbook.\n  - A `watches.yaml` file, which connects the `Memcached` resource to the `memcached` Ansible Role.\n\nSee [scaffolded files reference][layout-doc] and [watches reference][ansible-watches] for more detailed information.\n\n### Modify the Manager\n\nNow we need to provide the reconcile logic, in the form of an Ansible\nRole, which will run every time a `Memcached` resource is created,\nupdated, or deleted.\n\nUpdate `roles/memcached/tasks/main.yml`:\n\n\n```yaml\n---\n- name: start memcached\n  kubernetes.core.k8s:\n    definition:\n      kind: Deployment\n      apiVersion: apps/v1\n      metadata:\n        name: '{{ ansible_operator_meta.name }}-memcached'\n        namespace: '{{ ansible_operator_meta.namespace }}'\n      spec:\n        replicas: \"{{size}}\"\n        selector:\n          matchLabels:\n            app: memcached\n        template:\n          metadata:\n            labels:\n              app: memcached\n          spec:\n            containers:\n            - name: memcached\n              command:\n              - memcached\n              - -m=64\n              - -o\n              - modern\n              - -v\n              image: \"docker.io/memcached:1.4.36-alpine\"\n              ports:\n                - containerPort: 11211\n```\n\nThis memcached role will:\n- Ensure a memcached Deployment exists\n- Set the Deployment size\n\nNote that the tasks in this Ansible role file are what actually defines the behavior of the spec and status of the memcached custom resource.\nAs Kubernetes allows entry of arbitrary fields when creating resources, we don't need to actually create specific fields in the CRD.\nWhile we won't be doing this in this tutorial, it is recommended to also define these fields in the CRD, so that Kubernetes users\ncan see the fields that will be used when using the custom resource.\nIt is also good practice to set default values for variables used in Ansible\nRoles, so edit `roles/memcached/defaults/main.yml`:\n\n```yaml\n---\n# defaults file for Memcached\nsize: 1\n```\n\nFinally, update the `Memcached` sample, `config/samples/cache_v1alpha1_memcached.yaml`:\n\n```yaml\napiVersion: cache.example.com/v1alpha1\nkind: Memcached\nmetadata:\n  name: memcached-sample\nspec:\n  size: 3\n```\n\nThe key-value pairs in the Custom Resource spec are passed\nto Ansible as extra variables.\n\n**Note:** The names of all variables in the spec field are converted to\nsnake_case by the operator before running Ansible. For example,\nserviceAccount in the spec becomes service_account in Ansible. You can\ndisable this case conversion by setting the `snakeCaseParameters` option\nto `false` in your `watches.yaml`. It is recommended that you perform some\ntype validation in Ansible on the variables to ensure that your\napplication is receiving the expected input.\n\n## Configure the operator's image registry\n\nAll that remains is to build and push the operator image to the desired image registry.\nYour Makefile composes image tags either from values written at project initialization or from the CLI.\nIn particular, `IMAGE_TAG_BASE` lets you define a common image registry, namespace, and partial name\nfor all your image tags. Update this to another registry and/or namespace if the current value is incorrect.\nAfterwards you can update the `IMG` variable definition like so:\n\n```diff\n-IMG ?= controller:latest\n+IMG ?= $(IMAGE_TAG_BASE):$(VERSION)\n```\n\nOnce done, you do not have to set `IMG` or any other image variable in the CLI. The following command will\nbuild and push an operator image tagged as `example.com/memcached-operator:v0.0.1` to Docker Hub:\n\n```console\nmake docker-build docker-push\n```\n\n\n## Run the Operator\n\nThere are three ways to run the operator:\n\n- As a Go program outside a cluster\n- As a Deployment inside a Kubernetes cluster\n- Managed by the [Operator Lifecycle Manager (OLM)][doc-olm] in [bundle][tutorial-bundle] format\n\n### 1. Run locally outside the cluster\n\nExecute the following command, which installs your CRDs and runs the manager locally:\n\n```sh\nmake install run\n```\n\n### 2. Run as a Deployment inside the cluster\n\nBy default, a new namespace is created with name `<project-name>-system`, ex. `memcached-operator-system`, and will be used for the deployment.\n\nCommonly, Operator authors may need to modify `config/rbac` in order to\ngive their Operator the necessary permissions to reconcile.\n\nRun the following to customize the manifests and deploy the operator.\n\n```sh\nmake deploy\n```\n\nThe scaffolded `Makefile` uses [`kustomize`][kustomize-docs] to apply custom\nconfigurations and generate manifests from the `config/` directory, which are\npiped to `kubectl`. Run the following command to see the manifests that were\napplied to the cluster.\n\n```sh\nkustomize build config/default\n```\n\nVerify that the memcached-operator is up and running:\n\n```console\n$ kubectl get deployment -n memcached-operator-system\nNAME                                    READY   UP-TO-DATE   AVAILABLE   AGE\nmemcached-operator-controller-manager   1/1     1            1           8m\n```\n\n### 3. Deploy your Operator with OLM\n\nFirst, install [OLM][doc-olm]:\n\n```sh\noperator-sdk olm install\n```\n\nBundle your operator, then build and push the bundle image. The `bundle` target generates a [bundle][doc-bundle]\nin the `bundle` directory containing manifests and metadata defining your operator.\n`bundle-build` and `bundle-push` build and push a bundle image defined by `bundle.Dockerfile`.\n\n```sh\nmake bundle bundle-build bundle-push\n```\n\nFinally, run your bundle. If your bundle image is hosted in a registry that is private and/or\nhas a custom CA, these [configuration steps][image-reg-config] must be complete.\n\n```sh\noperator-sdk run bundle example.com/memcached-operator-bundle:v0.0.1\n```\n\nCheck out the [docs][tutorial-bundle] for a deep dive into `operator-sdk`'s OLM integration.\n\n\n## Create a Memcached CR\n\nUpdate the sample Memcached CR manifest at `config/samples/cache_v1alpha1_memcached.yaml` and define the `spec` as the following:\n\n```YAML\napiVersion: cache.example.com/v1alpha1\nkind: Memcached\nmetadata:\n  name: memcached-sample\nspec:\n  size: 3\n```\n\nCreate the CR:\n\n```sh\nkubectl apply -f config/samples/cache_v1alpha1_memcached.yaml\n```\n\nEnsure that the memcached operator creates the deployment for the sample CR with the correct size:\n\n```console\n$ kubectl get deployment\nNAME                                    READY   UP-TO-DATE   AVAILABLE   AGE\nmemcached-sample                        3/3     3            3           1m\n```\n\nCheck the pods and CR status to confirm the status is updated with the memcached pod names:\n\n```console\n$ kubectl get pods\nNAME                                  READY     STATUS    RESTARTS   AGE\nmemcached-sample-6fd7c98d8-7dqdr      1/1       Running   0          1m\nmemcached-sample-6fd7c98d8-g5k7v      1/1       Running   0          1m\nmemcached-sample-6fd7c98d8-m7vn7      1/1       Running   0          1m\n```\n\n```console\n$ kubectl get memcached/memcached-sample -o yaml\napiVersion: cache.example.com/v1alpha1\nkind: Memcached\nmetadata:\n  creationTimestamp: \"2021-03-17T19:54:42Z\"\n  generation: 1\n  managedFields:\n  - apiVersion: cache.example.com/v1alpha1\n    fieldsType: FieldsV1\n    fieldsV1:\n      f:status:\n        .: {}\n        f:conditions: {}\n    manager: ansible-operator\n    operation: Update\n    time: \"2021-03-17T19:54:42Z\"\n  - apiVersion: cache.example.com/v1alpha1\n    fieldsType: FieldsV1\n    fieldsV1:\n      f:spec:\n        .: {}\n        f:size: {}\n    manager: kubectl\n    operation: Update\n    time: \"2021-03-17T19:54:42Z\"\n  name: memcached-sample\n  namespace: default\n  resourceVersion: \"1008\"\n  uid: 4b023125-132a-44e3-80de-20801c7a9268\nspec:\n  size: 3\nstatus:\n  conditions:\n  - ansibleResult:\n      changed: 0\n      completion: 2021-03-17T19:54:54.890394\n      failures: 0\n      ok: 1\n      skipped: 0\n    lastTransitionTime: \"2021-03-17T19:54:42Z\"\n    message: Awaiting next reconciliation\n    reason: Successful\n    status: \"True\"\n    type: Running\n```\n\n### Update the size\n\nUpdate `config/samples/cache_v1alpha1_memcached.yaml` to change the `spec.size` field in the Memcached CR from 3 to 5:\n\n```sh\nkubectl patch memcached memcached-sample -p '{\"spec\":{\"size\": 5}}' --type=merge\n```\n\nConfirm that the operator changes the deployment size:\n\n```console\n$ kubectl get deployment\nNAME                                    READY   UP-TO-DATE   AVAILABLE   AGE\nmemcached-sample                        5/5     5            5           3m\n```\n\n### Cleanup\n\nRun the following to delete all deployed resources:\n\n```sh\nkubectl delete -f config/samples/cache_v1alpha1_memcached.yaml\nmake undeploy\n```\n\n## Next Steps\n\nWe recommend reading through the [Ansible development section][ansible-developer-tips]\nfor tips and tricks, including how to run the operator locally.\n\nIn this tutorial, the scaffolded `watches.yaml` could be used as-is, but\nhas additional optional features. See the [watches reference][ansible-watches].\n\nFor brevity, some of the scaffolded files were left out of this guide.\nSee [Scaffolding Reference][layout-doc].\n\nThis example built a namespaced scope operator, but Ansible operators\ncan also be used with cluster-wide scope.\n\n<!--\ntodo(camilamacedo86): Create an Ansible operator scope document.\nhttps://github.com/operator-framework/operator-sdk/issues/3447\n-->\n\nOLM will manage creation of most if not all resources required to run your operator, using a bit of setup from other operator-sdk commands. Check out the [OLM integration guide][tutorial-bundle].\n\n[ansible-developer-tips]:/docs/building-operators/ansible/development-tips/\n[ansible-watches]:/docs/building-operators/ansible/reference/watches\n[custom-resources]:https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/\n[doc-bundle]:https://github.com/operator-framework/operator-registry/blob/v1.16.1/docs/design/operator-bundle.md#operator-bundle\n[doc-olm]:/docs/olm-integration/tutorial-bundle/#enabling-olm\n[image-reg-config]:/docs/olm-integration/cli-overview#private-bundle-and-catalog-image-registries\n[install-guide]:/docs/building-operators/ansible/installation\n[layout-doc]:/docs/building-operators/ansible/reference/scaffolding\n[legacy-quickstart-doc]:https://github.com/operator-framework/operator-sdk/blob/v0.19.x/website/content/en/docs/ansible/quickstart.md\n[kustomize-docs]:https://kustomize.io/\n[migration-guide]:/docs/building-operators/ansible/migration\n[tutorial-bundle]:/docs/olm-integration/tutorial-bundle\n"
  },
  {
    "path": "website/content/en/docs/building-operators/golang/_index.md",
    "content": "---\ntitle: Go\nweight: 2\ndescription: Guide to building a Go-based Operator using Operator SDK\n---\n"
  },
  {
    "path": "website/content/en/docs/building-operators/golang/advanced-topics.md",
    "content": "---\ntitle: Advanced Topics\nlinkTitle: Advanced Topics\nweight: 80\n---\n\n### Manage CR status conditions\n\nAn often-used pattern is to include `Conditions` in the status of custom resources. A [`Condition`][apimachinery_condition] represents the latest available observations of an object's state (see the [Kubernetes API conventions documentation][typical-status-properties] for more information).\n\nThe `Conditions` field added to the `MemcachedStatus` struct simplifies the management of your CR's conditions. It:\n- Enables callers to add and remove conditions.\n- Ensures that there are no duplicates.\n- Sorts the conditions deterministically to avoid unnecessary repeated reconciliations.\n- Automatically handles the each condition's `LastTransitionTime`.\n- Provides helper methods to make it easy to determine the state of a condition.\n\nTo use conditions in your custom resource, add a Conditions field to the Status struct in `_types.go`:\n\n```Go\nimport (\n    metav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n)\n\ntype MyAppStatus struct {\n    // Conditions represent the latest available observations of an object's state\n    Conditions []metav1.Condition `json:\"conditions\"`\n}\n```\n\nThen, in your controller, you can use [`Conditions`][helpers-conditions] methods to make it easier to set and remove conditions or check their current values.\n\n### Adding 3rd Party Resources To Your Operator\n\n\nThe operator's Manager supports the core Kubernetes resource types as found in the client-go [scheme][scheme_package] package and will also register the schemes of all custom resource types defined in your project.\n\n```Go\nimport (\n    cachev1alpha1 \"github.com/example/memcached-operator/api/v1alpha1\n    ...\n)\n\nfunc init() {\n\n    // Setup Scheme for all resources\n    utilruntime.Must(cachev1alpha1.AddToScheme(scheme))\n    //+kubebuilder:scaffold:scheme\n}\n```\n\nTo add a 3rd party resource to an operator, you must add it to the Manager's scheme. By creating an `AddToScheme()` method or reusing one you can easily add a resource to your scheme. An [example][deployments_register] shows that you define a function and then use the [runtime][runtime_package] package to create a `SchemeBuilder`.\n\n#### Register with the Manager's scheme\n\nCall the `AddToScheme()` function for your 3rd party resource and pass it the Manager's scheme via `mgr.GetScheme()` or `scheme` in `main.go`.\nExample:\n```go\nimport (\n    routev1 \"github.com/openshift/api/route/v1\"\n)\n\nfunc init() {\n    ...\n\n    // Adding the routev1\n    utilruntime.Must(clientgoscheme.AddToScheme(scheme))\n\n    utilruntime.Must(routev1.AddToScheme(scheme))\n    //+kubebuilder:scaffold:scheme\n\n    ...\n}\n```\n\n##### If 3rd party resource does not have `AddToScheme()` function\n\nUse the [SchemeBuilder][scheme_builder] package from controller-runtime to initialize a new scheme builder that can be used to register the 3rd party resource with the manager's scheme.\n\nExample of registering `DNSEndpoints` 3rd party resource from `external-dns`:\n\n```go\nimport (\n    ...\n    \"k8s.io/apimachinery/pkg/runtime/schema\"\n    \"sigs.k8s.io/controller-runtime/pkg/scheme\"\n    ...\n    // DNSEndpoints\n    externaldns \"github.com/kubernetes-incubator/external-dns/endpoint\"\n    metav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n )\n\nfunc init() {\n    ...\n\n    log.Info(\"Registering Components.\")\n\n    schemeBuilder := &scheme.Builder{GroupVersion: schema.GroupVersion{Group: \"externaldns.k8s.io\", Version: \"v1alpha1\"}}\n    schemeBuilder.Register(&externaldns.DNSEndpoint{}, &externaldns.DNSEndpointList{})\n    if err := schemeBuilder.AddToScheme(mgr.GetScheme()); err != nil {\n        log.Error(err, \"\")\n        os.Exit(1)\n    }\n\n    ...\n}\n```\n\n\n\n**NOTES:**\n\n* After adding new import paths to your operator project, run `go mod vendor` if a `vendor/` directory is present in the root of your project directory to fulfill these dependencies.\n* Your 3rd party resource needs to be added before add the controller in `\"Setup all Controllers\"`.\n\n### Monitoring and Observability\nThis section covers how to create custom metrics, [alerts] and [recording rules] for your operator. It focuses on the technical aspects, and demonstrates the implementation by updating the sample [memcached-operator].\n\nFor more information regarding monitoring best practices, take a look at our docs on [observability-best-practices].  \n\n#### Prerequisites\nThe following steps are required in order to inspect the operator's custom metrics, alerts and recording rules:\n- Install Prometheus and Prometheus Operator. We recommend using [kube-prometheus] in production if you don’t have your own monitoring system. If you are just experimenting, you can only install Prometheus and Prometheus Operator.\n- Make sure Prometheus has access to the operator's namespace, by setting the corresponding RBAC rules.\n  \n  Example: [prometheus_role.yaml] and [prometheus_role_binding.yaml]\n\n#### Publishing Custom Metrics\nIf you wish to publish custom metrics for your operator, this can be easily achieved by using the global registry from `controller-runtime/pkg/metrics`.\nOne way to achieve this is to declare your collectors as global variables, register them using `RegisterMetrics()` and call it in the controller's `init()` function.\n\nExample custom metric: [MemcachedDeploymentSizeUndesiredCountTotal]\n\n```go\npackage monitoring\n\nimport (\n\t\"github.com/prometheus/client_golang/prometheus\"\n\t\"sigs.k8s.io/controller-runtime/pkg/metrics\"\n)\n\nvar (\n\tMemcachedDeploymentSizeUndesiredCountTotal = prometheus.NewCounter(\n\t\tprometheus.CounterOpts{\n\t\t\tName: \"memcached_deployment_size_undesired_count_total\",\n\t\t\tHelp: \"Total number of times the deployment size was not as desired.\",\n\t\t},\n\t)\n)\n\n// RegisterMetrics will register metrics with the global prometheus registry\nfunc RegisterMetrics() {\n\tmetrics.Registry.MustRegister(MemcachedDeploymentSizeUndesiredCountTotal)\n}\n```\n\n- The above example creates a new `Counter` metric. For other metrics' types, see [Prometheus Documentation].\n- For more information regarding operators metrics best-practices, please follow [observability-best-practices].\n\n[init() function example]:\n\n```go\npackage main\n\n\nimport (\n   ...\n   \"github.com/example/memcached-operator/monitoring\"\n)\n\nfunc init() {\n   ...\n   monitoring.RegisterMetrics()\n   ...\n}\n```\n\nThe next step would be to set the controller's logic according to which we update the metric's value. In this case, the new metric type is `Counter`, thus a valid update operation would be to increment its value. \n\n[Metric update example]:\n\n```go\n...\nsize := memcached.Spec.Size\nif *found.Spec.Replicas != size {\n    // Increment MemcachedDeploymentSizeUndesiredCountTotal metric by 1\n    monitoring.MemcachedDeploymentSizeUndesiredCountTotal.Inc()\n}\n...\n```\nDifferent metrics types have different valid operations. For more information, please follow [Prometheus Golang client].\n\n#### Publishing Alerts and Recording Rules\nIn order to add alerts and recording rules, which are unique to the operator's needs, we'll create a dedicated PrometheusRule object, by using [prometheus-operator API].\n\n[PrometheusRule example]:\n\n```go\npackage monitoring\n\nimport (\n\tmonitoringv1 \"github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/util/intstr\"\n)\n\n// NewPrometheusRule creates new PrometheusRule(CR) for the operator to have alerts and recording rules\nfunc NewPrometheusRule(namespace string) *monitoringv1.PrometheusRule {\n\treturn &monitoringv1.PrometheusRule{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tAPIVersion: monitoringv1.SchemeGroupVersion.String(),\n\t\t\tKind:       \"PrometheusRule\",\n\t\t},\n\t\tObjectMeta: metav1.ObjectMeta{\n\t\t\tName:      \"memcached-operator-rules\",\n\t\t\tNamespace: \"memcached-operator-system\",\n\t\t},\n\t\tSpec: *NewPrometheusRuleSpec(),\n\t}\n}\n\n// NewPrometheusRuleSpec creates PrometheusRuleSpec for alerts and recording rules\nfunc NewPrometheusRuleSpec() *monitoringv1.PrometheusRuleSpec {\n\treturn &monitoringv1.PrometheusRuleSpec{\n\t\tGroups: []monitoringv1.RuleGroup{{\n\t\t\tName: \"memcached.rules\",\n\t\t\tRules: []monitoringv1.Rule{\n\t\t\t\tcreateOperatorUpTotalRecordingRule(), \n\t\t\t\tcreateOperatorDownAlertRule()\n\t\t\t},\n\t\t}},\n\t}\n}\n\n// createOperatorUpTotalRecordingRule creates memcached_operator_up_total recording rule\nfunc createOperatorUpTotalRecordingRule() monitoringv1.Rule {\n   return monitoringv1.Rule{\n      Record: \"memcached_operator_up_total\",\n      Expr:   intstr.FromString(\"sum(up{pod=~'memcached-operator-controller-manager-.*'} or vector(0))\"),\n   }\n}\n\n// createOperatorDownAlertRule creates MemcachedOperatorDown alert rule\nfunc createOperatorDownAlertRule() monitoringv1.Rule {\n\treturn monitoringv1.Rule{\n\t\tAlert: \"MemcachedOperatorDown\",\n\t\tExpr:  intstr.FromString(\"memcached_operator_up_total == 0\"),\n\t\tAnnotations: map[string]string{\n\t\t\t\"description\": \"No running memcached-operator pods were detected in the last 5 min.\",\n\t\t},\n\t\tFor: \"5m\",\n\t\tLabels: map[string]string{\n\t\t\t\"severity\":    \"critical\",\n\t\t},\n\t}\n}\n```\n\nThen, we may want to ensure that the new PrometheusRule is being created and reconciled. One way to achieve this is by expanding the existing `Reconcile()` function logic.\n\n[PrometheusRule reconciliation example]:\n\n```go\nfunc (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {\n    ...\n    ...\n    // Check if prometheus rule already exists, if not create a new one\n    foundRule := &monitoringv1.PrometheusRule{}\n    err := r.Get(ctx, types.NamespacedName{Name: ruleName, Namespace: namespace}, foundRule)\n    if err != nil && apierrors.IsNotFound(err) {\n        // Define a new prometheus rule\n        prometheusRule := monitoring.NewPrometheusRule(namespace)\n        if err := r.Create(ctx, prometheusRule); err != nil {\n            log.Error(err, \"Failed to create prometheus rule\")\n            return ctrl.Result{}, nil\n        }\n    }\n    \n    if err == nil {\n    // Check if prometheus rule spec was changed, if so set as desired\n    desiredRuleSpec := monitoring.NewPrometheusRuleSpec()\n    if !reflect.DeepEqual(foundRule.Spec.DeepCopy(), desiredRuleSpec) {\n        desiredRuleSpec.DeepCopyInto(&foundRule.Spec)\n        if r.Update(ctx, foundRule); err != nil {\n            log.Error(err, \"Failed to update prometheus rule\")\n            return ctrl.Result{}, nil\n        }\n    }\n    ...\n    ...\n}\n```\n\n- Please review the [observability-best-practices] for additional important information regarding alerts and recording rules.\n\n\n#### Alerts Unit Testing\nIt is highly recommended implementing unit tests for prometheus rules. For more information, please follow the Prometheus [unit testing documentation]. For examples of unit testing in a Golang operator, see the sample memcached-operator [alerts unit tests].\n\n#### Inspecting the metrics, alerts and recording rules with Prometheus UI\nFinally, in order to inspect the exposed metrics and alerts, we need to forward the corresponding port where metrics are published by Prometheus (usually `9090`, which is the default value). This can be done with the following command:\n```bash\n$ kubectl -n monitoring port-forward svc/prometheus-k8s 9090\n```\n\n\nwhere we assume that the prometheus service is available in the `monitoring` namespace.\n\nNow you can access Prometheus UI using `http://localhost:9090`. For more details on exposing prometheus metrics, please refer [kube-prometheus docs].\n\n### Handle Cleanup on Deletion\n\nOperators may create objects as part of their operational duty. Object accumulation can consume unnecessary resources, slow down the API and clutter the user interface. As such it is important for operators to keep good hygiene and to clean up resources when they are not needed. Here are a few common scenarios.\n \n#### Internal Resources\n\nA typical example of correct resource cleanup is the [Jobs][jobs] implementation. When a Job is created, one or multiple Pods are created as child resources. When a Job is deleted, the associated Pods are deleted as well. This is a very common pattern easily achieved by setting an owner reference from the parent (Job) to the child (Pod) object. Here is a code snippet for doing so, where \"r\" is the reconcilier and \"ctrl\" the controller-runtime library:\n\n```go\nctrl.SetControllerReference(job, pod, r.Scheme)\n```\n\nNote that the default behavior for cascading deletion is background propagation, meaning deletion requests for child objects occur after the request to delete the parent object. [This Kubernetes doc][garbage_collection] provides alternative deletion types.\n\n#### External Resources\n\nSometimes external resources or resources that are not owned by a custom resource, those across namespaces for example, need to be cleaned up when the parent resource is deleted. In that case [Finalizers][finalizers] can be leveraged. A deletion request for an object with a finalizer becomes an update during which a deletion timestamp is set; the object is not deleted while the finalizer is present. The reconciliation loop of the custom resource's controller will then need to check whether a the deletion timestamp is set, perform the external cleanup operation(s), then remove the finalizer to allow garbage collection of the object. Multiple finalizers may be present on an object, each with a key that should indicate what external resources require deletion by the controller.\n\nThe following is a snippet from a theoretical controller file `controllers/memcached_controller.go` that implements a finalizer handler:\n\n\n```go\nimport (\n    ...\n    \"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil\"\n)\n\nconst memcachedFinalizer = \"cache.example.com/finalizer\"\n\nfunc (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {\n    reqLogger := r.log.WithValues(\"memcached\", req.NamespacedName)\n    reqLogger.Info(\"Reconciling Memcached\")\n\n    // Fetch the Memcached instance\n    memcached := &cachev1alpha1.Memcached{}\n    err := r.Get(ctx, req.NamespacedName, memcached)\n    if err != nil {\n        if errors.IsNotFound(err) {\n            // Request object not found, could have been deleted after reconcile request.\n            // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers.\n            // Return and don't requeue\n            reqLogger.Info(\"Memcached resource not found. Ignoring since object must be deleted.\")\n            return ctrl.Result{}, nil\n        }\n        // Error reading the object - requeue the request.\n        reqLogger.Error(err, \"Failed to get Memcached.\")\n        return ctrl.Result{}, err\n    }\n\n    ...\n\n    // Check if the Memcached instance is marked to be deleted, which is\n    // indicated by the deletion timestamp being set.\n    isMemcachedMarkedToBeDeleted := memcached.GetDeletionTimestamp() != nil\n    if isMemcachedMarkedToBeDeleted {\n        if controllerutil.ContainsFinalizer(memcached, memcachedFinalizer) {\n            // Run finalization logic for memcachedFinalizer. If the\n            // finalization logic fails, don't remove the finalizer so\n            // that we can retry during the next reconciliation.\n            if err := r.finalizeMemcached(reqLogger, memcached); err != nil {\n                return ctrl.Result{}, err\n            }\n\n            // Remove memcachedFinalizer. Once all finalizers have been\n            // removed, the object will be deleted.\n            controllerutil.RemoveFinalizer(memcached, memcachedFinalizer)\n            err := r.Update(ctx, memcached)\n            if err != nil {\n                return ctrl.Result{}, err\n            }\n        }\n        return ctrl.Result{}, nil\n    }\n\n    // Add finalizer for this CR\n    if !controllerutil.ContainsFinalizer(memcached, memcachedFinalizer) {\n        controllerutil.AddFinalizer(memcached, memcachedFinalizer)\n        err = r.Update(ctx, memcached)\n        if err != nil {\n            return ctrl.Result{}, err\n        }\n    }\n\n    ...\n\n    return ctrl.Result{}, nil\n}\n\nfunc (r *MemcachedReconciler) finalizeMemcached(reqLogger logr.Logger, m *cachev1alpha1.Memcached) error {\n    // TODO(user): Add the cleanup steps that the operator\n    // needs to do before the CR can be deleted. Examples\n    // of finalizers include performing backups and deleting\n    // resources that are not owned by this CR, like a PVC.\n    reqLogger.Info(\"Successfully finalized memcached\")\n    return nil\n}\n```\n\n#### Complex cleanup logic\n\nSimilar to the previous scenario, finalizers can be used for implementing complex cleanup logic. Take [CronJobs][cronjobs] as an example: the controller maintains limited-size lists of jobs that have been created by the CronJob controller to check for deletion. These list sizes are configured by the CronJob fields [`.spec.successfulJobsHistoryLimit` and `.spec.failedJobsHistoryLimit`][cronjob_fields], which specify how many completed and failed jobs should be kept. Check out the [Kubebuilder CronJob tutorial][cronjob_tutorial] for full implementation details.\n\n#### Sensitive resources\n\nSensitive resources need to be protected against unintended deletion. An intuitive example of protecting resources is the [PersistentVolume (PV) / PersistentVolumeClaim (PVC)][pv] relationship. A PV is first created, after which users can request access to that PV's storage by creating a PVC, which gets bound to the PV. If a user tries to delete a PV currently bound by a PVC, the PV is not removed immediately. Instead, PV removal is postponed until the PV is not bound to any PVC. Finalizers again can be leveraged to achieve a similar behaviour for your own PV-like custom resources: by setting a finalizer on an object, your controller can make sure there are no remaining objects bound to it before removing the finalizer and deleting the object.\nAdditionally, the user who created the PVC can specify what happens to the underlying storage allocated in a PV when the PVC is deleted through the [reclaim policy][reclaiming]. There are several options available, each of which defines a behavior that is achieved again through the use of finalizers. The key concept to take away is that your operator can give a user the power to decide how their resources are cleaned up via finalizers, which may be dangerous yet useful depending on your workloads.\n\n### Leader election\n\nDuring the lifecycle of an operator it's possible that there may be more than 1 instance running at any given time e.g when rolling out an upgrade for the operator.\nIn such a scenario it is necessary to avoid contention between multiple operator instances via leader election so that only one leader instance handles the reconciliation while the other instances are inactive but ready to take over when the leader steps down.\n\nThere are two different leader election implementations to choose from, each with its own tradeoff.\n\n- [Leader-with-lease][leader_with_lease]: The leader pod periodically renews the leader lease and gives up leadership when it can't renew the lease. This implementation allows for a faster transition to a new leader when the existing leader is isolated, but there is a possibility of split brain in [certain situations][lease_split_brain].\n- [Leader-for-life][leader_for_life]: The leader pod only gives up leadership (via garbage collection) when it is deleted. This implementation precludes the possibility of 2 instances mistakenly running as leaders (split brain). However, this method can be subject to a delay in electing a new leader. For instance when the leader pod is on an unresponsive or partitioned node, the [`pod-eviction-timeout`][pod_eviction_timeout] dictates how long it takes for the leader pod to be deleted from the node and step down (default 5m).\n\nBy default the SDK enables the leader-with-lease implementation. However you should consult the docs above for both approaches to consider the tradeoffs that make sense for your use case.\n\nThe following examples illustrate how to use the two options:\n\n#### Leader for life\n\nA call to `leader.Become()` will block the operator as it retries until it can become the leader by creating the configmap named `memcached-operator-lock`.\n\n```Go\nimport (\n    ...\n    \"github.com/operator-framework/operator-lib/leader\"\n)\n\nfunc main() {\n    ...\n    err = leader.Become(context.TODO(), \"memcached-operator-lock\")\n    if err != nil {\n        log.Error(err, \"Failed to retry for leader lock\")\n        os.Exit(1)\n    }\n    ...\n}\n```\nIf the operator is not running inside a cluster `leader.Become()` will simply return without error to skip the leader election since it can't detect the operator's namespace.\n\n#### Leader with lease\n\nThe leader-with-lease approach can be enabled via the [Manager Options][manager_options] for leader election.\n\n```Go\nimport (\n    ...\n    \"sigs.k8s.io/controller-runtime/pkg/manager\"\n)\n\nfunc main() {\n    ...\n    opts := manager.Options{\n        ...\n        LeaderElection: true,\n        LeaderElectionID: \"memcached-operator-lock\"\n    }\n    mgr, err := manager.New(cfg, opts)\n    ...\n}\n```\n\nWhen the operator is not running in a cluster, the Manager will return an error on starting since it can't detect the operator's namespace in order to create the configmap for leader election. You can override this namespace by setting the Manager's `LeaderElectionNamespace` option.\n\n### Multiple architectures\n\nAuthors may decide to distribute their bundles for various architectures: x86_64, aarch64, ppc64le, s390x, etc, to accommodate the diversity of Kubernetes clusters and reach a larger number of potential users. Each architecture requires however compatible binaries. Considerations on the topic are available in the [Multiple Architectures page][multi_arch].\n\n[typical-status-properties]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties\n[scheme_package]:https://github.com/kubernetes/client-go/blob/master/kubernetes/scheme/register.go\n[deployments_register]: https://github.com/kubernetes/api/blob/master/apps/v1/register.go#L41\n[runtime_package]: https://pkg.go.dev/k8s.io/apimachinery/pkg/runtime\n[scheme_builder]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/scheme#Builder\n[metrics_doc]: https://book.kubebuilder.io/reference/metrics.html\n[jobs]: https://kubernetes.io/docs/concepts/workloads/controllers/job/\n[garbage_collection]: https://kubernetes.io/docs/concepts/workloads/controllers/garbage-collection/\n[finalizers]: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#finalizers\n[cronjobs]: https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/\n[cronjob_fields]: https://kubernetes.io/docs/tasks/job/automated-tasks-with-cron-jobs/#jobs-history-limits\n[cronjob_tutorial]: https://book.kubebuilder.io/cronjob-tutorial/controller-implementation.html#3-clean-up-old-jobs-according-to-the-history-limit\n[pv]: https://kubernetes.io/docs/concepts/storage/persistent-volumes/\n[reclaiming]: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#reclaiming\n[lease_split_brain]: https://github.com/kubernetes/client-go/blob/30b06a83d67458700a5378239df6b96948cb9160/tools/leaderelection/leaderelection.go#L21-L24\n[leader_for_life]: https://pkg.go.dev/github.com/operator-framework/operator-lib/leader\n[leader_with_lease]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/leaderelection\n[pod_eviction_timeout]: https://kubernetes.io/docs/reference/command-line-tools-reference/kube-controller-manager/#options\n[manager_options]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Options\n[apimachinery_condition]: https://github.com/kubernetes/apimachinery/blob/d4f471b82f0a17cda946aeba446770563f92114d/pkg/apis/meta/v1/types.go#L1368\n[helpers-conditions]: https://github.com/kubernetes/apimachinery/blob/master/pkg/api/meta/conditions.go\n[multi_arch]:/docs/advanced-topics/multi-arch\n[observability-best-practices]:https://sdk.operatorframework.io/docs/best-practices/observability-best-practices/\n[alerts]:https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/\n[recording rules]:https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/\n[prometheus_role.yaml]:https://github.com/operator-framework/operator-sdk/blob/master/testdata/go/v4/monitoring/memcached-operator/config/rbac/prometheus_role.yaml\n[prometheus_role_binding.yaml]:https://github.com/operator-framework/operator-sdk/blob/master/testdata/go/v4/monitoring/memcached-operator/config/rbac/prometheus_role_binding.yaml\n[MemcachedDeploymentSizeUndesiredCountTotal]:https://github.com/operator-framework/operator-sdk/blob/master/testdata/go/v4/monitoring/memcached-operator/monitoring/metrics.go\n[init() function example]:https://github.com/operator-framework/operator-sdk/blob/master/testdata/go/v4/monitoring/memcached-operator/cmd/main.go\n[Metric update example]:https://github.com/operator-framework/operator-sdk/blob/master/testdata/go/v4/monitoring/memcached-operator/internal/controller/memcached_controller.go\n[Prometheus Documentation]:https://prometheus.io/docs/concepts/metric_types/\n[Prometheus Golang client]:https://pkg.go.dev/github.com/prometheus/client_golang/prometheus\n[kube-prometheus]:https://github.com/prometheus-operator/kube-prometheus\n[memcached-operator]:https://github.com/operator-framework/operator-sdk/tree/master/testdata/go/v4/monitoring/memcached-operator\n[prometheus-operator API]:https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api-reference/api.md\n[PrometheusRule example]:https://github.com/operator-framework/operator-sdk/blob/master/testdata/go/v4/monitoring/memcached-operator/monitoring/alerts.go\n[PrometheusRule reconciliation example]:https://github.com/operator-framework/operator-sdk/blob/master/testdata/go/v4/monitoring/memcached-operator/internal/controller/memcached_controller.go\n[unit testing documentation]:https://prometheus.io/docs/prometheus/latest/configuration/unit_testing_rules/\n[alerts unit tests]:https://github.com/operator-framework/operator-sdk/tree/master/testdata/go/v4/monitoring/memcached-operator/monitoring/prom-rule-ci\n[kube-prometheus docs]:https://github.com/prometheus-operator/kube-prometheus/blob/main/docs/access-ui.md#prometheus\n"
  },
  {
    "path": "website/content/en/docs/building-operators/golang/crds-scope.md",
    "content": "---\ntitle: CRD Scope\nlinkTitle: CRD Scope\nweight: 60\n---\n\n## Overview\n\nThis page details the various methods to control the scope of a CRD. See the [operator scope doc](/docs/building-operators/golang/operator-scope/) for information on configuring operator scope, such as which namespaces to watch.\n\nCustom Resource Definitions (CRDs) contain a scope field that determines whether the resulting Custom Resource (CR)\nis cluster or namespace scoped. An operator author might use a namespaced-scoped CRD\nto restrict access to a CR to certain namespaces, or to have different versions of CRs accessible in different namespaces.\nAlternatively, an operator author might want a cluster-scoped CRD so all namespaces have visibility and access to CRs.\n\nThe CRD manifests are generated by the `operator-sdk create api` command in `config/crd/bases`. A CRD's `spec.scope` field controls API scope; valid values are [`Cluster` and `Namespaced`](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#create-a-customresourcedefinition).\nFor an Operator-sdk Go project, this value is determined by the `operator-sdk create api --namespaced` boolean flag, which edits the\n`types.go` file for the resource. For other operator types, the command edits `spec.scope` in the CRD's YAML manifest directly.\n\n## Set `create api` --namespaced flag\n\nWhen creating a new API, the `--namespaced` flag controls whether the resulting CRD will be cluster or namespace scoped.\nBy default, `--namespaced` is set to `true` which sets the scope to `Namespaced`. An example command to create a cluster-scoped API would be:\n\n```console\n$ operator-sdk create api --group cache --version v1alpha1 --kind Memcached --resource=true --controller=true --namespaced=false\n```\n\n## Set Scope Marker in types.go\n\nYou can also manually set the scope in the Go `types.go` file by adding or changing the [kubebuilder scope marker][kubebuilder_crd_markers]\nto your resource. This file is usually located in `api/<version>/<kind>_types.go` or `apis/<group>/<version>/<kind>_types.go` if\nyou are using the [multigroup][kubebuilder_multigroup] layout. Once this marker is set, the CRD files will be generated with the approriate scope.\nHere is an example API type with the marker set to cluster scope:\n\n```golang\n//+kubebuilder:object:root=true\n//+kubebuilder:subresource:status\n//+kubebuilder:resource:scope=Cluster\n\n// Memcached is the Schema for the memcacheds API\ntype Memcached struct {\n\tmetav1.TypeMeta   `json:\",inline\"`\n\tmetav1.ObjectMeta `json:\"metadata,omitempty\"`\n\n\tSpec   MemcachedSpec   `json:\"spec,omitempty\"`\n\tStatus MemcachedStatus `json:\"status,omitempty\"`\n}\n```\nTo set the scope to namespaced, the marker would be set to `//+kubebuilder:resource:scope=Namespaced` instead.\n\n\n## Set scope in CRD YAML file\n\nThe scope can be manually set directly in the CRD's Kind YAML file, normally located in  `config/crd/bases/<group>.<domain>_<kind>.yaml`.\nAn example YAML file for a namespace-scoped CRD is shown below:\n\n```YAML\napiVersion: apiextensions.k8s.io/v1beta1\nkind: CustomResourceDefinition\nmetadata:\n  annotations:\n    controller-gen.kubebuilder.io/version: v0.2.5\n  creationTimestamp: null\n  name: memcacheds.cache.example.com\nspec:\n  group: cache.example.com\n  names:\n    kind: Memcached\n    listKind: MemcachedList\n    plural: memcacheds\n    singular: memcached\n  scope: Namespaced\n  subresources:\n    status: {}\n...   \n``` \n\n\n\n[manager_options]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Options\n[manager_user_guide]:/docs/building-operators/golang/tutorial/#manager\n[k8s_crd_scope]: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#create-a-customresourcedefinition \n[kubebuilder_crd_markers]: https://book.kubebuilder.io/reference/markers/crd.html\n[kubebuilder_multigroup]: https://book.kubebuilder.io/migration/multi-group.html\n[RBAC]: https://kubernetes.io/docs/reference/access-authn-authz/rbac/\n"
  },
  {
    "path": "website/content/en/docs/building-operators/golang/installation.md",
    "content": "---\ntitle: Installation Guide\nlinkTitle: Installation\nweight: 1\n---\n\n## Install `operator-sdk`\n\nFollow the steps in the [installation guide][install-guide] to learn how to install the `operator-sdk` CLI tool.\n\n## Additional Prerequisites\n\n- [git][git_tool]\n- [go][go_tool] version 1.22\n- [docker][docker_tool] version 17.03+.\n- [kubectl][kubectl_tool] and access to a Kubernetes cluster of a [compatible version][k8s-version-compat].\n\n\n[install-guide]:/docs/installation/\n[git_tool]:https://git-scm.com/downloads\n[go_tool]:https://golang.org/dl/\n[docker_tool]:https://docs.docker.com/install/\n[kubectl_tool]:https://kubernetes.io/docs/tasks/tools/install-kubectl/\n[k8s-version-compat]:/docs/overview#kubernetes-version-compatibility\n"
  },
  {
    "path": "website/content/en/docs/building-operators/golang/migration.md",
    "content": "---\nlink: Migrating Projects from pre-v1.0.0 to the latest release\nlinkTitle: Migrating from pre-v1.0.0 to latest\nweight: 200\ndescription: Instructions for migrating a Go-based project built prior to `v1.0.0` (`0.19.x+`) to use the Kubebuilder-style layout which is the default layout adopted by SDK since the `1.0.0` release.\n---\n\n## Overview\n\nThe motivations for the new layout are related to bringing more flexibility to users and part of the process to Integrating Kubebuilder and Operator SDK. Because of this integration you may be referred to the Kubebuilder documentation [https://book.kubebuilder.io/](https://book.kubebuilder.io/) for more information about certain topics. When using this document just remember to replace `$ kubebuilder <command>` with `$ operator-sdk <command>`.\n\n**Note:** It is recommended that you have your project upgraded to the latest SDK v1.y release version before following the steps in this guide to migrate to the new layout. However, the steps might work from previous versions as well. In this case, if you find an issue which is not covered here then check the previous [Migration Guides][migration-doc] which might help out.\n\n### What was changed\n\n- The `deploy` directory was replaced with the `config` directory including a new layout of Kubernetes manifests files:\n    * CRD manifests in `deploy/crds/` are now in `config/crd/bases`\n    * CR manifests in `deploy/crds/` are now in `config/samples`\n    * Controller manifest `deploy/operator.yaml` is now in `config/manager/manager.yaml`\n    * RBAC manifests in `deploy` are now in `config/rbac/`\n\n- `build/Dockerfile` is moved to `Dockerfile` in the project root directory\n- `pkg/apis` and `pkg/controllers` are now in the root directory.\n- `cmd/manager/main.go` is now in the root directory.\n\n### What is new\n\nScaffolded projects now use:\n\n- [kustomize][kustomize] to manage Kubernetes resources needed to deploy your operator\n- A `Makefile` with helpful targets to build, test, deploy and tailor things based on your project needs\n- Helpers and options to work with webhooks. For further information see [What is a Webhook?][webhook-doc]\n- Updated metrics configuration using [kube-auth-proxy][kube-auth-proxy], a `--metrics-addr` flag, and [kustomize][kustomize]-based deployment of a Kubernetes `Service` and prometheus operator `ServiceMonitor`\n- Scaffolded tests that use the [`envtest`][envtest] test framework\n- Preliminary support for CLI plugins. For more info see the [plugins design document][plugins-phase1-design-doc]\n- A `PROJECT` configuration file to store information about GVKs, plugins, and help the CLI make decisions\n- A new option to create projects using ComponentConfig. For more info, see the [enhancement proposal][component-proposal] and the [Component config tutorial][component-config-tutorial]\n- Go version `1.15` (previously it was `1.13`)\n\nGenerated files with the default API versions:\n\n- `apiextensions/v1` for generated CRDs (`apiextensions/v1beta1` was deprecated in Kubernetes `1.16` and will be removed in `1.22`)\n- `admissionregistration.k8s.io/v1` for webhooks (`admissionregistration.k8s.io/v1beta1` was deprecated in Kubernetes `1.16` and will be removed in `1.22` )\n- `cert-manager.io/v1` for the certificate manager when webhooks are used (`cert-manager.io/v1alpha2` was deprecated in `Cert-Manager 0.14`. More info: [CertManager v1.0 docs][cert-manager-docs])\n\n**Note:** You can still use the deprecated APIs which are only needed to support Kubernetes `1.15` and earlier.\n\n## How to migrate\n\nThe easy migration path is to initialize a new project, re-recreate APIs, then copy pre-v1.0.0 configuration files into the new project.\n\n### Prerequisites\n\n- Go through the [installation guide][install-guide].\n- Make sure your user is authorized with `cluster-admin` permissions.\n- An accessible image registry for various operator images (ex. [hub.docker.com](https://hub.docker.com/signup),\n[quay.io](https://quay.io/)) and be logged in to your command line environment.\n  - `example.com` is used as the registry Docker Hub namespace in these examples.\n  Replace it with another value if using a different registry or namespace.\n  - [Authentication and certificates][image-reg-config] if the registry is private or uses a custom CA.\n\n### Create a new project\n\nIn Kubebuilder-style projects, CRD groups are defined using two different flags\n(`--group` and `--domain`).\n\nWhen we initialize a new project, we need to specify the domain that _all_ APIs in\nour project will share, so before creating the new project, we need to determine which\ndomain we're using for the APIs in our existing project.\n\nTo determine the domain, look at the `spec.group` field in your CRDs in the\n`deploy/crds` directory.\n\nThe domain is everything after the first DNS segment. Using `cache.example.com` as an\nexample, the `--domain` would be `example.com`.\n\nSo let's create a new project with the same domain (`example.com`):\n\n```sh\nmkdir memcached-operator\ncd memcached-operator\noperator-sdk init --domain example.com --repo github.com/example/memcached-operator\n```\n\n**Note:**: `operator-sdk` attempts to automatically discover the Go module path of your project by looking for a `go.mod` file, or if in `$GOPATH`, by using the directory path. Use the `--repo` flag to explicitly set the module path.\n\n### Check if your project is multi-group\n\nBefore we start creating the APIs, check if your project has more than one group such as: `foo.example.com/v1` and `crew.example.com/v1`. If you intend to work with multiple groups in your project, then run the command `operator-sdk edit --multigroup=true` to change the project's layout to support multi-group.\n\n**Note:** In multi-group projects, APIs are defined in `apis/<group>/<version>` and controllers are defined in `controllers/<group>`.\nFor further information see [Single Group to Multi-Group][multigroup-kubebuilder-doc].\n\n### Migrate APIs and Controllers\n\nNow that we have our new project initialized, we need to re-create each of our APIs.\nUsing our API example from earlier (`cache.example.com`), we'll use `cache` for the\n`--group`, `v1alpha1` for the `--version` and `Memcached` for `--kind` flag.\n\nFor each API in the existing project, run:\n\n```sh\noperator-sdk create api \\\n    --group=cache \\\n    --version=<version> \\\n    --kind=<Kind> \\\n    --resource \\\n    --controller\n```\n\n#### How to keep `apiextensions.k8s.io/v1beta1` for CRDs?\n\nFrom now on, the CRDs that will be created by controller-gen will be using Kubernetes API version `apiextensions.k8s.io/v1` by default, instead of `apiextensions.k8s.io/v1beta1`.\n\nThe `apiextensions.k8s.io/v1beta1` was deprecated in Kubernetes `1.16` and will be removed in Kubernetes `1.22`.\n\nIf you would like to keep using the previous version, use the flag `--crd-version=v1beta1` in the above command. This is only needed if you want your operator to support Kubernetes `1.15` and earlier.\n\n### APIs\n\nNow let’s copy the API definition from `pkg/apis/<group>/<version>/<kind>_types.go` to `api/<version>/<kind>_types.go`. For our example, it is only required to copy the code from the `Spec` and `Status` fields.\n\nThis file is quite similar to the old one. Once you copy over your API definitions and generate manifests, you should end up with an identical API for your custom resource type. However, pay close attention to these kubebuilder [Markers][markers]:\n\n- The `+k8s:deepcopy-gen:interfaces=...` marker was replaced with `+kubebuilder:object:root=true`.\n- If you are not using [openapi-gen][openapi-gen] to generate OpenAPI Go code, then `// +k8s:openapi-gen=true` and other related openapi markers can be removed.\n\n**Note::** The `operator-sdk generate openapi` command was deprecated in `0.13.0` and was removed in `0.17` SDK release. Hence, it is recommended to use [openapi-gen][openapi-gen] directly for OpenAPI code generation.\n\nOur Memcached API types will look like:\n\n```go\n// MemcachedSpec defines the desired state of Memcached\ntype MemcachedSpec struct {\n\t// Size is the size of the memcached deployment\n\tSize int32 `json:\"size\"`\n}\n\n// MemcachedStatus defines the observed state of Memcached\ntype MemcachedStatus struct {\n\t// Nodes are the names of the memcached pods\n\tNodes []string `json:\"nodes\"`\n}\n\n//+kubebuilder:object:root=true\n//+kubebuilder:subresource:status\n\n// Memcached is the Schema for the memcacheds API\ntype Memcached struct {...}\n\n//+kubebuilder:object:root=true\n\n// MemcachedList contains a list of Memcached\ntype MemcachedList struct {...}\n```\n\n### Webhooks\n\nSDK version `1.0.0` and later has support for webhooks by the CLI. If your project doesn't require any webhooks, you can skip this section. However, if you have been using it via customizations in your project, you should use the tool to re-scaffold the webhooks.\n\nA webhook can only be scaffolded for a pre-existent API in your project. Then, for each case you will run the command `operator-sdk create webhook` providing the `--group`, `--kind` and `version` of the API based on the flags that need to be used.\n\nThe valid flags for its types are: `--defaulting`, `--programmatic-validation` and `--conversion`. Use the same type that was used for scaffolding. To create `defaulting` and `validating` webhook:\n\n```sh\noperator-sdk create webhook \\\n    --group=cache \\\n    --version=<version> \\\n    --kind=<Kind> \\\n    --defaulting \\\n    --programmatic-validation\n```\n\nTo create `conversion` webhook:\n\n```sh\noperator-sdk create webhook \\\n    --group=cache \\\n    --version=<version> \\\n    --kind=<Kind> \\\n    --conversion\n```\n\nAfter the webhook is generated, you will need to copy the webhook definition and content from your old project to the new one. You can find the respective file in `api/v1/<kind>_webhook.go`.\n\n#### How to keep using `apiextensions.k8s.io/v1beta1` for Webhooks?\n\nHereafter, the webhooks that are created by SDK will use Kubernetes API version `admissionregistration.k8s.io/v1` by default instead of `admissionregistration.k8s.io/v1beta1` and `cert-manager.io/v1` instead of `cert-manager.io/v1alpha2`.\n\nNote that `apiextensions/v1beta1` and `admissionregistration.k8s.io/v1beta1` were deprecated in Kubernetes `1.16` and will be removed in Kubernetes `1.22`. If you use `apiextensions/v1` and `admissionregistration.k8s.io/v1`, then you need to use `cert-manager.io/v1` which will be the default API adopted by the SDK CLI.\n\n**Note:** If you are using the API `cert-manager.io/v1alpha2`, it is not compatible with the latest Kubernetes API version. (`cert-manager.io/v1alpha2` was deprecated in `Cert-Manager 0.14`. For more info, refer to [CertManager v1.0 docs][cert-manager-docs])\n\nIf you would like to use the previous version, use the flag `--webhook-version=v1beta1` in the above command which is only required if you want your operator to support Kubernetes `1.15` and earlier.\n\n### Controllers\n\nNow let’s migrate the controller code from `pkg/controller/<kind>/<kind>_controller.go` to `controllers/<kind>_controller.go` following these steps:\n\n1. Copy over any struct fields from the existing project into the new `<Kind>Reconciler` struct.\n**Note:** The `Reconciler` struct has been renamed from `Reconcile<Kind>` to `<Kind>Reconciler`. In our example, we would see `ReconcileMemcached` instead of `MemcachedReconciler`.\n2. Replace the `// your logic here` in the new layout with your reconcile logic.\n3. Copy the code under `func add(mgr manager.Manager, r reconcile.Reconciler)` to `func SetupWithManager`:\n```go\nfunc (r *MemcachedReconciler) SetupWithManager(mgr ctrl.Manager) error {\n\treturn ctrl.NewControllerManagedBy(mgr).\n\t\tFor(&cachev1alpha1.Memcached{}).\n\t\tOwns(&appsv1.Deployment{}).\n\t\tComplete(r)\n}\n```\n\nIn our example, the `Watch` implemented for the Deployment will be replaced with `Owns(&appsv1.Deployment{})`. Setting up controller `Watches` is simplified in more recent versions of controller-runtime, which has controller [Builder][builder] helpers to handle more of the details.\n\n#### Set RBAC permissions\n\nThe RBAC permissions are now configured via [RBAC markers][rbac_markers], which are used to generate and update the manifest files present in `config/rbac/`. These markers can be found (and should be defined) on the `Reconcile()` method of each controller.\n\nIn the Memcached example, they look like the following:\n\n```go\n//+kubebuilder:rbac:groups=cache.example.com,resources=memcacheds,verbs=get;list;watch;create;update;patch;delete\n//+kubebuilder:rbac:groups=cache.example.com,resources=memcacheds/status,verbs=get;update;patch\n//+kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete\n//+kubebuilder:rbac:groups=core,resources=pods,verbs=get;list\n```\n\nTo update `config/rbac/role.yaml` after changing the markers, run `make manifests`.\n\nBy default, new projects are cluster-scoped (i.e. they have cluster-scoped permissions and watch all namespaces). Read the [operator scope documentation][operator-scope] for more information about changing the scope of your operator.\n\nSee the complete migrated `memcached_controller.go` code [here][memcached_controller].\n\n**Note:** The version of [controller-runtime][controller-runtime] used in the projects scaffolded by SDK `0.19.x+` was `v0.6.0`. Please check [sigs.k8s.io/controller-runtime release docs from 0.7.0+ version][controller-runtime] for breaking changes.\n\n##### Updating your ServiceAccount\n\nNew Go projects come with a ServiceAccount `controller-manager` in `config/rbac/service_account.yaml`.\nYour project's RoleBinding and ClusterRoleBinding subjects, and Deployments `spec.template.spec.serviceAccountName`\nthat reference a ServiceAccount already refer to this new name. When you run `make deploy`,\nyour project's name will be prepended to `controller-manager`, making it unique within a namespace,\nmuch like your old `deploy/service_account.yaml`. If you wish to use the old ServiceAccount,\nmake sure to update all RBAC bindings and your manager Deployment.\n\n### Migrate `main.go`\n\nBy checking our new `main.go` we will find that:\n\n- The SDK [leader.Become][leader-lib-doc] was replaced by the [controller-runtime's leader][controller-runtime-leader] with lease mechanism. However, you can still use [leader.Become][leader-lib-doc] if you wish:\n\n```go\nfunc main() {\n...\n\tctx := context.TODO()\n\t// Become the leader before proceeding\n\terr = leader.Become(ctx, \"memcached-operator-lock\")\n\tif err != nil {\n    \tlog.Error(err, \"\")\n    \tos.Exit(1)\n\t}\n...\n}\n```\n\nIn order to use the previous one ensure that you have the [operator-lib][operator-lib] as a dependency of your project.\n\n- The default port used by the metric endpoint binds to `:8080` from the previous `:8383`. To continue using port `8383`, specify `--metrics-bind-address=:8383` when you start the operator.\n\n- `OPERATOR_NAME` and `POD_NAME` environment variables are no longer used. `OPERATOR_NAME` was used to define the name for a leader election config map. Operator authors should use the `LeaderElectionID` attribute from the [Manager Options][ctrl-options] which is hardcoded in `main.go`:\n\n```go\nfunc main() {\n...\n\tmgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{\n\t\tScheme:                 scheme,\n\t\tMetricsBindAddress:     metricsAddr,\n\t\tPort:                   9443,\n\t\tHealthProbeBindAddress: probeAddr,\n\t\tLeaderElection:         enableLeaderElection,\n\t\tLeaderElectionID:       \"86f835c3.example.com\",\n\t})\n...\n}\n```\n\n- Ensure that you copy all customizations made in `cmd/manager/main.go` to `main.go`. You’ll also need to ensure that all needed schemes have been registered, if you have been using third-party APIs (i.e Route Api from OpenShift).\n\n### Migrate your tests\n\nFor the new layout, you will see that `controllers/suite_test.go` is created when a controller is scaffolded by the tool. This file contains boilerplate for executing integration tests using [envtest][envtest] with [ginkgo](https://onsi.github.io/ginkgo/) and [gomega][gomega].\n\nOperator SDK 1.0.0+ removes support for the legacy test framework and no longer supports the `operator-sdk test` subcommand. All affected tests should be migrated to use `envtest`.\n\nThe Operator SDK project recommends controller-runtime's [envtest][envtest] because it has a more active contributor community, it is more mature than Operator SDK's test framework, and it does not require an actual cluster to run tests, which can be a huge benefit in CI scenarios.\n\nTo learn more about how you can test your controllers, see the documentation about [writing controller tests][writing-controller-tests].\n\n### Migrate your Custom Resources\n\nCustom resource samples are stored in `./config/samples` using the new project structure. Copy the examples from your existing project into this directory. In existing projects, CR files have the format `./deploy/crds/<group>.<domain>_<version>_<kind>_cr.yaml`.\n\nIn our example, we'll copy the specs from `deploy/crds/cache.example.com_v1alpha1_memcached_cr.yaml`\nto `config/samples/cache_v1alpha1_memcached.yaml`\n\n### Configure your Operator\n\nIn case your project has customizations in the `deploy/operator.yaml`, it needs to be added to\n`config/manager/manager.yaml`. Note that `OPERATOR_NAME` and `POD_NAME` env vars are no longer used. For further information, check out the section [Migrate `main.go` ][migration-guide-main-section].\n\n### Export Metrics\n\nIf you are using metrics and would like to keep them exported, see that the `func addMetrics()` is no longer generated in the `main.go` and it is now configurable via [kustomize][kustomize].\n\n#### Configure Prometheus metrics\n\n- Ensure that you have Prometheus installed in the cluster:\nTo check if you have the required API resource to create the `ServiceMonitor` run:\n```sh\nkubectl api-resources | grep servicemonitors\n```\nIf not, you can install Prometheus via [kube-prometheus](https://github.com/coreos/kube-prometheus#installing):\n```sh\nkubectl apply -f https://raw.githubusercontent.com/coreos/prometheus-operator/release-0.33/bundle.yaml\n```\n- Now uncomment the line `- ../prometheus` in the `config/default/kustomization.yaml` file. It creates the `ServiceMonitor` resource which enables exporting the metrics:\n```yaml\n# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'.\n- ../prometheus\n```\n\n#### Use Handler from `operator-lib`\n\nBy using the [InstrumentedEnqueueRequestForObject](https://pkg.go.dev/github.com/operator-framework/operator-lib@v0.1.0/handler?tab=doc#InstrumentedEnqueueRequestForObject) you will be able to export metrics from your Custom Resources. In our example, it would look like:\n\n```go\nimport (\n    ...\n\t\"github.com/operator-framework/operator-lib/handler\"\n    ...\n)\n\nfunc (r *MemcachedReconciler) SetupWithManager(mgr ctrl.Manager) error {\n\t// Create a new controller\n\tc, err := controller.New(\"memcached-controller\", mgr, controller.Options{Reconciler: r})\n\tif err != nil {\n\t\treturn err\n\t}\n    ...\n\terr = c.Watch(&source.Kind{Type: &cachev1alpha1.Memcached{}}, &handler.InstrumentedEnqueueRequestForObject{})\n\tif err != nil {\n\t\treturn err\n\t}\n\t...\n\treturn nil\n}\n```\n\n**Note:** Ensure that you have the [operator-lib][operator-lib] added to your `go.mod`.\n\nIn this way, the following metric with the resource info will be exported:\n\n```\nresource_created_at_seconds{\"name\", \"namespace\", \"group\", \"version\", \"kind\"}\n```\n\n**Note:** To check it you can create a pod to curl the `metrics/` endpoint but note that it is now protected by the [kube-auth-proxy][kube-auth-proxy] which means that you will need to create a `ClusterRoleBinding` and obtain the token from the ServiceAccount's secret which will be used in the requests. Otherwise, to test you can disable the [kube-auth-proxy][kube-auth-proxy] as well.\n\nFor more info see the [metrics][metrics].\n\n### Operator image\n\nThe Dockerfile image also changes and now it is `multi-stage`, `distroless` and still `rootless`. However, users can change it to work as they want.\n\nYou might need to port some customizations made in your old Dockerfile as well. Also, if you wish to still use the previous UBI image replace:\n\n```docker\n# Use distroless as minimal base image to package the manager binary\n# Refer to https://github.com/GoogleContainerTools/distroless for more details\nFROM gcr.io/distroless/static:nonroot\n```\n\nWith:\n\n```docker\nFROM registry.access.redhat.com/ubi8/ubi-minimal:latest\n```\n\n### Generate Manifests and Build the operator\n\nNote that:\n\n- `operator-sdk generate crds` is replaced with `make manifests`, which generates CRDs and RBAC rules.\n- `operator-sdk build` is replaced with `make docker-build IMG=<some-registry>/<project-name>:<tag>`.\n\nIn this way, run:\n\n```sh\nmake manifests docker-build docker-push IMG=example.com/memcached-operator:v0.0.1\n```\n\n\n### Verify the migration\n\nThe project can now be deployed on cluster by running the command:\n\n```sh\nmake deploy IMG=example.com/memcached-operator:v0.0.1\n```\n\nYou can troubleshoot your deployment by checking container logs:\n```sh\nkubectl logs deployment.apps/memcached-operator-controller-manager -n memcached-operator-system -c manager\n```\n\nFor further steps regarding the deployment of the operator, creation of custom resources, and cleaning up of resources, see the [tutorial][tutorial-deploy].\n\n\n[install-guide]: /docs/building-operators/ansible/installation\n[image-reg-config]:/docs/olm-integration/cli-overview#private-bundle-and-catalog-image-registries\n[metrics]: https://book.kubebuilder.io/reference/metrics.html?highlight=metr#metrics\n[memcached_controller]: https://github.com/operator-framework/operator-sdk/tree/master/testdata/go/v4/memcached-operator\n[rbac_markers]: https://book.kubebuilder.io/reference/markers/rbac.html\n[kube-auth-proxy]: https://github.com/brancz/kube-rbac-proxy\n[markers]: https://book.kubebuilder.io/reference/markers.html?highlight=markers#marker-syntax\n[operator-scope]: /docs/building-operators/golang/operator-scope\n[leaderElection]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/leaderelection?tab=doc\n[ginkgo]: https://onsi.github.io/ginkgo/\n[gomega]: https://onsi.github.io/gomega/\n[builder]: https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.6.1/pkg/builder?tab=doc\n[writing-controller-tests]: https://book.kubebuilder.io/cronjob-tutorial/writing-tests.html\n[openapi-gen]: https://github.com/kubernetes/kube-openapi/tree/master/cmd/openapi-gen\n[controller-runtime-leader]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#LeaderElectionRunnable\n[operator-lib]: https://github.com/operator-framework/operator-lib/\n[leader-lib-doc]: https://pkg.go.dev/github.com/operator-framework/operator-lib@v0.1.0/leader?tab=doc\n[migration-guide-main-section]: /docs/building-operators/golang/migration/#migrate-maingo\n[kustomize]: https://github.com/kubernetes-sigs/kustomize\n[ctrl-options]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Options\n[envtest]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/envtest\n[gomega]: https://onsi.github.io/gomega/\n[multigroup-kubebuilder-doc]: https://book.kubebuilder.io/migration/multi-group.html\n[what-are-the-the-differences-between-kubebuilder-and-operator-sdk]: /docs/faqs/#what-are-the-the-differences-between-kubebuilder-and-operator-sdk\n[controller-runtime]: https://github.com/kubernetes-sigs/controller-runtime/releases\n[cert-manager-docs]: https://cert-manager.io/docs/installation/upgrade/\n[webhook-doc]: https://book.kubebuilder.io/reference/webhook-overview.html\n[healthz-ping]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/healthz#CheckHandler\n[controller-runtime]: https://github.com/kubernetes-sigs/controller-runtime/releases\n[component-proposal]: https://github.com/kubernetes-sigs/controller-runtime/blob/master/designs/component-config.md\n[plugins-phase1-design-doc]: https://github.com/kubernetes-sigs/kubebuilder/blob/master/designs/extensible-cli-and-scaffolding-plugins-phase-1.md\n[migration-doc]: /docs/upgrading-sdk-version/\n[tutorial-deploy]: /docs/building-operators/golang/tutorial/#run-the-operator\n\n"
  },
  {
    "path": "website/content/en/docs/building-operators/golang/operator-scope.md",
    "content": "---\ntitle: Operators Scope\nlinkTitle: Operator Scope\nweight: 50\n---\n\n## Overview\n\nA namespace-scoped operator watches and manages resources in a single Namespace, whereas a cluster-scoped operator\n watches and manages resources cluster-wide.\n\nAn operator should be cluster-scoped if it watches resources that can be created in any Namespace. An operator should\nbe namespace-scoped if it is intended to be flexibly deployed. This scope permits\ndecoupled upgrades, namespace isolation for failures and monitoring, and differing API definitions.\n\nBy default, `operator-sdk init` scaffolds a cluster-scoped operator. This document details conversion of default\noperator projects to namespaced-scoped operators. Before proceeding, be aware that your operator may be better suited\nas cluster-scoped. For example, the [cert-manager][cert-manager] operator is often deployed with cluster-scoped\npermissions and watches so that it can manage and issue certificates for an entire cluster.\n\n**IMPORTANT**: When a [Manager][ctrl-manager] instance is created in the `main.go` file, the\nNamespaces are set via [Cache Config][cache-config] as described below. These Namespaces should be watched and\ncached for the Client which is provided by the Manager. Only clients provided by cluster-scoped Managers are able\nto manage cluster-scoped CRD's. For further information see: [CRD scope doc][crd-scope-doc].\n\n## Manager watching options\n\n### Watching resources in all Namespaces (default)\n\nA [Manager][ctrl-manager] is initialized with no Cache option specified, or with a Cache.DefaultNamespaces of `Namespace: \"\"` will\nwatch all Namespaces:\n\n```go\n...\nmgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{\n    Scheme:             scheme,\n    MetricsBindAddress: metricsAddr,\n    Port:               9443,\n    LeaderElection:     enableLeaderElection,\n    LeaderElectionID:   \"f1c5ece8.example.com\",\n})\n...\n```\n\n### Watching resources in specific Namespaces\n\nTo restrict the scope of the [Manager's][ctrl-manager] cache to a specific Namespace, set `Cache.DefaultNamespaces`\nfield in [Options][ctrl-options]:\n\n```go\n...\nmgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{\n    Scheme:             scheme,\n    MetricsBindAddress: metricsAddr,\n    Port:               9443,\n    LeaderElection:     enableLeaderElection,\n    LeaderElectionID:   \"f1c5ece8.example.com\",\n    Cache: cache.Options{\n      DefaultNamespaces: map[string]cache.Config{\"operator-namespace\": cache.Config{}},\n    },\n})\n...\n```\n\n### Watching resources in a set of Namespaces\n\nIt is also possible to use `DefaultNamespaces` to watch and manage resources in a set of Namespaces:\n\n```go\n...\nmgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{\n    Scheme:             scheme,\n    MetricsBindAddress: metricsAddr,\n    Port:               9443,\n    LeaderElection:     enableLeaderElection,\n    LeaderElectionID:   \"f1c5ece8.example.com\",\n    Cache: cache.Options{\n      DefaultNamespaces: map[string]cache.Config{\n        \"operator-namespace1\": cache.Config{},\n        \"operator-namespace2\": cache.Config{},\n      },\n    },\n})\n...\n```\n\nIn the above example, a CR created in a Namespace not in the set passed to `Cache.DefaultNamespaces` will not be reconciled by\nits controller because the [Manager][ctrl-manager] does not manage that Namespace. Further restrictions and qualifications\ncan created on a per-namespace basis by setting fields in the cache.Config object, for further information see the\n[controller runtime docs][cache-config]\n\n**IMPORTANT:** Note that this is not intended to be used for excluding Namespaces, this is better done via a Predicate.\n\n## Restricting Roles and permissions\n\nAn operator's scope defines its [Manager's][ctrl-manager] cache's scope but not the permissions to access the resources.\nAfter updating the Manager's scope to be Namespaced, [Role-Based Access Control (RBAC)][k8s-rbac] permissions\napplied to the operator's service account should be restricted accordingly.\n\nThese permissions are found in the directory `config/rbac/`. The `ClusterRole` in `role.yaml` and `ClusterRoleBinding`\nin `role_binding.yaml` are used to grant the operator permissions to access and manage its resources.\n\n**NOTE** For changing the operator's scope only the `role.yaml` and `role_binding.yaml` manifests need to be updated.\nFor the purposes of this doc, the other RBAC manifests `<kind>_editor_role.yaml`, `<kind>_viewer_role.yaml`,\nand `auth_proxy_*.yaml` are not relevant to changing the operator's resource permissions.\n\n### Changing the permissions to Namespaced\n\nTo change the scope of the RBAC permissions from cluster-wide to a specific namespace, you will need to:\n\n- Use `Role`s instead of `ClusterRole`s.\n\n[`RBAC markers`][rbac-markers] defined in the controller (e.g `controllers/memcached_controller.go`)\nare used to generate the operator's [RBAC ClusterRole][rbac-clusterrole] (e.g `config/rbac/role.yaml`). The default\nmarkers don't specify a `namespace` property and will result in a `ClusterRole`.\n\nUpdate the [`RBAC markers`][rbac-markers] in `<kind>_controller.go` with `namespace=<namespace>` where the `Role` is to be applied, such as:\n\n```go\n//+kubebuilder:rbac:groups=cache.example.com,namespace=memcached-operator-system,resources=memcacheds,verbs=get;list;watch;create;update;patch;delete\n//+kubebuilder:rbac:groups=cache.example.com,namespace=memcached-operator-system,resources=memcacheds/status,verbs=get;update;patch\n```\n\nThen run `make manifests` to update `config/rbac/role.yaml`. In our example it would look like:\n\n```yaml\napiVersion: rbac.authorization.k8s.io/v1\nkind: Role\nmetadata:\n  creationTimestamp: null\n  name: manager-role\n  namespace: memcached-operator-system\n```\n\n- Use `RoleBinding`s instead of `ClusterRoleBinding`s. The `config/rbac/role_binding.yaml` needs to be manually updated:\n\n```yaml\napiVersion: rbac.authorization.k8s.io/v1\nkind: RoleBinding\nmetadata:\n  name: manager-rolebinding\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: Role\n  name: manager-role\nsubjects:\n- kind: ServiceAccount\n  name: controller-manager\n  namespace: system\n```\n\n<!-- todo(camilamacedo86): The need for the RoleBinding show an issue tracked\nin https://github.com/kubernetes-sigs/kubebuilder/issues/1496. -->\n\n## Configuring watch namespaces dynamically\n\nInstead of having any Namespaces hard-coded in the `main.go` file a good practice is to use an environment\nvariable to allow the restrictive configurations. The one suggested here is `WATCH_NAMESPACE`, a\ncomma-separated list of namespaces passed to the manager at deploy time.\n\n### Configuring Namespace scoped operators\n\n- Add a helper function in the `main.go` file:\n\n```go\n// getWatchNamespace returns the Namespace the operator should be watching for changes\nfunc getWatchNamespace() (string, error) {\n    // WatchNamespaceEnvVar is the constant for env variable WATCH_NAMESPACE\n    // which specifies the Namespace to watch.\n    // An empty value means the operator is running with cluster scope.\n    var watchNamespaceEnvVar = \"WATCH_NAMESPACE\"\n\n    ns, found := os.LookupEnv(watchNamespaceEnvVar)\n    if !found {\n        return \"\", fmt.Errorf(\"%s must be set\", watchNamespaceEnvVar)\n    }\n    return ns, nil\n}\n```\n\n- Use the environment variable value:\n\n```go\n...\nwatchNamespace, err := getWatchNamespace()\nif err != nil {\n    setupLog.Error(err, \"unable to get WatchNamespace, \" +\n       \"the manager will watch and manage resources in all namespaces\")\n}\n\nmgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{\n    Scheme:             scheme,\n    MetricsBindAddress: metricsAddr,\n    Port:               9443,\n    LeaderElection:     enableLeaderElection,\n    LeaderElectionID:   \"f1c5ece8.example.com\",\n    Cache: cache.Options{\n      DefaultNamespaces: map[string]cache.Config{watchNamespace: cache.Config{}},\n    },\n})\n...\n```\n\n- Define the environment variable in the `config/manager/manager.yaml`:\n\n```yaml\nspec:\n  containers:\n  - command:\n    - /manager\n    args:\n    - --leader-elect\n    image: controller:latest\n    name: manager\n    resources:\n      limits:\n        cpu: 100m\n        memory: 30Mi\n      requests:\n        cpu: 100m\n        memory: 20Mi\n    env:\n      - name: WATCH_NAMESPACE\n        valueFrom:\n          fieldRef:\n            fieldPath: metadata.namespace\n  terminationGracePeriodSeconds: 10\n```\n\n**NOTE** `WATCH_NAMESPACE` here will always be set as the namespace where the operator is deployed.\n\n### Configuring cluster-scoped operators with MultiNamespacedCacheBuilder\n\n- Add a helper function to get the environment variable value in the `main.go` file as done in the previous example (e.g `getWatchNamespace()`)\n- Use the environment variable value and check if it is a multi-namespace scenario:\n\n```go\n    ...\nwatchNamespace, err := getWatchNamespace()\nif err != nil {\n    setupLog.Error(err, \"unable to get WatchNamespace, \" +\n        \"the manager will watch and manage resources in all Namespaces\")\n}\n\noptions := ctrl.Options{\n    Scheme:             scheme,\n    MetricsBindAddress: metricsAddr,\n    Port:               9443,\n    LeaderElection:     enableLeaderElection,\n    LeaderElectionID:   \"f1c5ece8.example.com\",\n    Cache: cache.Options{\n      DefaultNamespaces: map[string]cache.Config{watchNamespace: cache.Config{}},\n    },\n}\n\n// Add support for MultiNamespace set in WATCH_NAMESPACE (e.g ns1,ns2)\nif strings.Contains(watchNamespace, \",\") {\n    setupLog.Info(\"manager set up with multiple namespaces\", \"namespaces\", watchNamespace)\n    // configure cluster-scoped with MultiNamespacedCacheBuilder\n    options.Namespace = \"\"\n    options.NewCache = cache.MultiNamespacedCacheBuilder(strings.Split(watchNamespace, \",\"))\n}\n...\n```\n\n- Define the environment variable in the `config/manager/manager.yaml`:\n\n```yaml\n...\n    env:\n      - name: WATCH_NAMESPACE\n        value: \"ns1,ns2\"\n  terminationGracePeriodSeconds: 10\n...\n```\n\n## Updating your CSV's installModes\n\nIf your operator is [integrated with OLM][olm-integration], you will want to update your [CSV base's][csv-base]\n`spec.installModes` list to support the desired namespacing requirements. Support for multiple types of namespacing\nis allowed, so supporting multiple install modes in a CSV is permitted. After doing so, update your\n[bundle][bundle-quickstart] or [package manifests][packagemanifests-tutorial] by following the linked guides.\n\n### Watching resources in all Namespaces (default)\n\nOnly the `AllNamespaces` install mode is `supported: true` by default, so no changes are required.\n\n### Watching resources in a single Namespace\n\nIf the operator can watch its own namespace, set the following in your `spec.installModes` list:\n\n```yaml\n  - type: OwnNamespace\n    supported: true\n```\n\nIf the operator can watch a single namespace that is not its own, set the following in your `spec.installModes` list:\n\n```yaml\n  - type: SingleNamespace\n    supported: true\n```\n\n### Watching resources in multiple Namespaces\n\nIf the operator can watch multiple namespaces, set the following in your `spec.installModes` list:\n\n```yaml\n  - type: MultiNamespace\n    supported: true\n```\n\n[cache-config]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/cache#Config\n[cert-manager]: https://github.com/jetstack/cert-manager\n[ctrl-manager]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Manager\n[ctrl-options]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Options\n[k8s-rbac]: https://kubernetes.io/docs/reference/access-authn-authz/rbac/\n[rbac-clusterrole]: https://kubernetes.io/docs/reference/access-authn-authz/rbac/#role-and-clusterrole\n[crd-scope-doc]: /docs/building-operators/golang/crds-scope/\n[rbac-markers]: https://book.kubebuilder.io/reference/markers/rbac.html\n[olm-integration]: /docs/olm-integration\n[csv-base]: /docs/olm-integration/generation/#kustomize-files\n[bundle-quickstart]: /docs/olm-integration/quickstart-bundle\n[packagemanifests-tutorial]: /docs/olm-integration/tutorial-package-manifests\n"
  },
  {
    "path": "website/content/en/docs/building-operators/golang/quickstart.md",
    "content": "---\ntitle: Quickstart for Go-based Operators\nlinkTitle: Quickstart\nweight: 20\ndescription: A simple set of instructions to set up and run a Go-based operator.\n---\n\nThis guide walks through an example of building a simple memcached-operator using tools and libraries provided by the Operator SDK.\n\n## Prerequisites\n\n- Go through the [installation guide][install-guide].\n- Make sure your user is authorized with `cluster-admin` permissions.\n- An accessible image registry for various operator images (ex. [hub.docker.com](https://hub.docker.com/signup),\n[quay.io](https://quay.io/)) and be logged in to your command line environment.\n  - `example.com` is used as the registry Docker Hub namespace in these examples.\n  Replace it with another value if using a different registry or namespace.\n  - [Authentication and certificates][image-reg-config] if the registry is private or uses a custom CA.\n\n\n## Steps\n\n1. Create a project directory for your project and initialize the project:\n\n  ```sh\n  mkdir memcached-operator\n  cd memcached-operator\n  operator-sdk init --domain example.com --repo github.com/example/memcached-operator\n  ```\n\n**Note** If your local environment is Apple Silicon (`darwin/arm64`) use the `go/v4`\nplugin which provides support for this platform by adding to the init subCommand the flag `--plugins=go/v4`\n\n1. Create a simple Memcached API:\n\n  ```sh\n  operator-sdk create api --group cache --version v1alpha1 --kind Memcached --resource --controller\n  ```\n\n1. Build and push your operator's image:\n\n  ```sh\n  make docker-build docker-push IMG=\"example.com/memcached-operator:v0.0.1\"\n  ```\n\n### OLM deployment\n\n1. Install [OLM][doc-olm]:\n\n  ```sh\n  operator-sdk olm install\n  ```\n\n1. Bundle your operator, then build and push the bundle image (defaults to `example.com/memcached-operator-bundle:v0.0.1`):\n\n  ```sh\n  make bundle IMG=\"example.com/memcached-operator:v0.0.1\"\n  make bundle-build bundle-push BUNDLE_IMG=\"example.com/memcached-operator-bundle:v0.0.1\"\n  ```\n\n1. Run your bundle. If your bundle image is hosted in a registry that is private and/or\nhas a custom CA, these [configuration steps][image-reg-config] must be complete.\n\n  ```sh\n  operator-sdk run bundle <some-registry>/memcached-operator-bundle:v0.0.1\n  ```\n\n1. Create a sample Memcached custom resource:\n\n  ```console\n  $ kubectl apply -f config/samples/cache_v1alpha1_memcached.yaml\n  memcached.cache.example.com/memcached-sample created\n  ```\n\n1. Uninstall the operator:\n\n  ```sh\n  operator-sdk cleanup memcached-operator\n  ```\n\n\n### Direct deployment\n\n1. Deploy your operator:\n\n  ```sh\n  make deploy IMG=\"example.com/memcached-operator:v0.0.1\"\n  ```\n\n1. Create a sample Memcached custom resource:\n\n  ```console\n  $ kubectl apply -f config/samples/cache_v1alpha1_memcached.yaml\n  memcached.cache.example.com/memcached-sample created\n  ```\n\n1. Uninstall the operator:\n\n  ```sh\n  make undeploy\n  ```\n\n### Run locally (outside the cluster)\n\nThis is recommended ONLY for development purposes\n\n1. Run the operator:\n\n  ```sh\n  make install run\n  ```\n\n1. In a new terminal tab/window, create a sample Memcached custom resource:\n  \n  ```console\n  $ kubectl apply -f config/samples/cache_v1alpha1_memcached.yaml\n  memcached.cache.example.com/memcached-sample created\n  ```\n\n1. Stop the operator by pressing `ctrl+c` in the terminal tab or window the operator is running in\n\n## Next Steps\n\nRead the [full tutorial][tutorial] for an in-depth walkthrough of building a Go operator.\n\n\n[install-guide]:/docs/building-operators/golang/installation\n[image-reg-config]:/docs/olm-integration/cli-overview#private-bundle-and-catalog-image-registries\n[doc-olm]:/docs/olm-integration/tutorial-bundle/#enabling-olm\n[tutorial]:/docs/building-operators/golang/tutorial/\n"
  },
  {
    "path": "website/content/en/docs/building-operators/golang/references/_index.md",
    "content": "---\ntitle: Go-based Operator Reference\nlinkTitle: Reference\nweight: 100\n---"
  },
  {
    "path": "website/content/en/docs/building-operators/golang/references/client.md",
    "content": "---\ntitle: Controller Runtime Client API\nlinkTitle: Controller Runtime Client API\nweight: 10\n---\n\n## Overview\n\nThe [`controller-runtime`][repo-controller-runtime] library provides various abstractions to watch and reconcile resources in a Kubernetes cluster via CRUD (Create, Update, Delete, as well as Get and List in this case) operations. Operators use at least one controller to perform a coherent set of tasks within a cluster, usually through a combination of CRUD operations. The Operator SDK uses controller-runtime's [Client][doc-client] interface, which provides the interface for these operations.\n\ncontroller-runtime defines several interfaces used for cluster interaction:\n- `client.Client`: implementers perform CRUD operations on a Kubernetes cluster.\n- `manager.Manager`: manages shared dependencies, such as Caches and Clients.\n- `reconcile.Reconciler`: compares provided state with actual cluster state and updates the cluster on finding state differences using a Client.\n\nClients are the focus of this document. A separate document will discuss Managers.\n\n**Note:** this document uses parts of the sample [`memcached-operator`][memcached-testdata] for example code.\nImport paths may be different for brevity.\n\n## Client Usage\n\n### Default Client\n\nThe SDK relies on a `manager.Manager` to create a `client.Client` interface that performs Create, Update, Delete, Get, and List operations within a `reconcile.Reconciler`'s Reconcile function. The SDK will generate code to create a Manager, which holds a Cache and a Client to be used in CRUD operations and communicate with the API server. By default a Controller's Reconciler will be populated with the Manager's Client which is a [split-client][doc-split-client].\n\nThe following code, found in `controllers/memcached_controller.go`, demonstrates how the Manager's client is passed to a reconciler.\n\n```Go\nimport (\n\tappsv1 \"k8s.io/api/apps/v1\"\n\tctrl \"sigs.k8s.io/controller-runtime\"\n\n\tcachev1alpha1 \"github.com/example/memcached-operator/api/v1alpha1\"\n)\n\nfunc (r *MemcachedReconciler) SetupWithManager(mgr ctrl.Manager) error {\n\treturn ctrl.NewControllerManagedBy(mgr). // mgr's Client is passed to r.\n\t\tFor(&cachev1alpha1.Memcached{}).\n\t\tOwns(&appsv1.Deployment{}).\n\t\tComplete(r)\n}\n\ntype MemcachedReconciler struct {\n    client.Client // Populated above from a manager.Manager.\n\n    Log    logr.Logger\n    Scheme *runtime.Scheme\n}\n```\n\nA split client reads (Get and List) from the Cache and writes (Create, Update, Delete) to the API server. Reading from the Cache significantly reduces request load on the API server; as long as the Cache is updated by the API server, read operations are eventually consistent.\n\n### Non-default Client\n\nAn operator developer may wish to create their own Client that serves read requests(Get List) from the API server instead of the cache, for example. controller-runtime provides a [constructor][doc-client-constr] for Clients:\n\n```Go\n// New returns a new Client using the provided config and Options.\nfunc New(config *rest.Config, options client.Options) (client.Client, error)\n```\n\n`client.Options` allow the caller to specify how the new Client should communicate with the API server.\n\n```Go\n// Options are creation options for a Client\ntype Options struct {\n    // Scheme, if provided, will be used to map go structs to GroupVersionKinds\n    Scheme *runtime.Scheme\n\n    // Mapper, if provided, will be used to map GroupVersionKinds to Resources\n    Mapper meta.RESTMapper\n}\n```\n\nExample:\n\n```Go\nimport (\n    \"sigs.k8s.io/controller-runtime/pkg/client/config\"\n    \"sigs.k8s.io/controller-runtime/pkg/client\"\n)\n\ncfg, err := config.GetConfig()\n...\nc, err := client.New(cfg, client.Options{})\n...\n```\n\n**Note**: defaults are set by `client.New` when Options are empty. The default [scheme][code-scheme-default] will have the [core][doc-k8s-core] Kubernetes resource types registered. The caller *must* set a scheme that has custom operator types registered for the new Client to recognize these types.\n\nCreating a new Client is not usually necessary nor advised, as the default Client is sufficient for most use cases.\n\n### Reconcile and the Client API\n\nA Reconciler implements the [`reconcile.Reconciler`][doc-reconcile-reconciler] interface, which exposes the Reconcile method. Reconcilers are added to a corresponding Controller for a Kind; Reconcile is called in response to cluster or external Events, with a `reconcile.Request` object argument, to read and write cluster state by the Controller, and returns a `ctrl.Result`. SDK Reconcilers have access to a Client in order to make Kubernetes API calls.\n\n```Go\n// MemcachedReconciler reconciles a Memcached object\ntype MemcachedReconciler struct {\n    // client, initialized using mgr.Client() above, is a split client\n    // that reads objects from the cache and writes to the apiserver\n    client.Client\n\n    Log    logr.Logger\n\n    // scheme defines methods for serializing and deserializing API objects,\n    // a type registry for converting group, version, and kind information\n    // to and from Go schemas, and mappings between Go schemas of different\n    // versions. A scheme is the foundation for a versioned API and versioned\n    // configuration over time.\n    Scheme *runtime.Scheme\n}\n\n// Reconcile watches for Events and reconciles cluster state with desired\n// state defined in the method body.\n// The Controller will requeue the Request to be processed again if an error\n// is non-nil or Result.Requeue is true, otherwise upon completion it will\n// remove the work from the queue.\nfunc (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error)\n```\n\nReconcile is where Controller business logic lives, i.e. where Client API calls are made via `MemcachedReconciler.client`. A `client.Client` implementer performs the following operations:\n\n#### Get\n\n```Go\n// Get retrieves an API object for a given object key from the Kubernetes cluster\n// and stores it in obj.\nfunc (c Client) Get(ctx context.Context, key client.ObjectKey, obj client.Object) error\n```\n\n**Note**: A `client.ObjectKey` is simply an alias for [`types.NamespacedName`][doc-types-nsname].\n\nExample:\n\n```Go\nimport (\n    \"context\"\n\n    ctrl \"sigs.k8s.io/controller-runtime\"\n\n    cachev1alpha1 \"github.com/example/memcached-operator/api/v1alpha1\"\n)\n\nfunc (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {\n    ...\n\n    memcached := &cachev1alpha1.Memcached{}\n    err := r.Get(ctx, request.NamespacedName, memcached)\n\n    ...\n}\n```\n\n#### List\n\n```Go\n// List retrieves a list of objects for a given namespace and list options\n// and stores the list in obj.\nfunc (c Client) List(ctx context.Context, list client.Object, opts ...client.ListOption) error\n```\n\nA `client.ListOption` is an interface that sets [`client.ListOptions`][list-options] fields. A `client.ListOption` is created by using one of the provided implementations: [`MatchingLabels`][matching-labels], [`MatchingFields`][matching-fields], [`InNamespace`][in-namespace].\n\nExample:\n\n```Go\nimport (\n    \"context\"\n    \"fmt\"\n\n    \"k8s.io/api/core/v1\"\n    ctrl \"sigs.k8s.io/controller-runtime\"\n    \"sigs.k8s.io/controller-runtime/pkg/client\"\n)\n\nfunc (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {\n    ...\n\n    // Return all pods in the request namespace with a label of `instance=<name>`\n    // and phase `Running`.\n    podList := &v1.PodList{}\n    opts := []client.ListOption{\n        client.InNamespace(request.NamespacedName.Namespace),\n        client.MatchingLabels{\"instance\": request.NamespacedName.Name},\n        client.MatchingFields{\"status.phase\": \"Running\"},\n    }\n    err := r.List(ctx, podList, opts...)\n\n    ...\n}\n```\n\n[list-options]:https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/client#ListOptions\n[matching-labels]:https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/client#MatchingLabels\n[matching-fields]:https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/client#MatchingFields\n[in-namespace]:https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/client#InNamespace\n\n#### Create\n\n```Go\n// Create saves the object obj in the Kubernetes cluster.\n// Returns an error\nfunc (c Client) Create(ctx context.Context, obj client.Object, opts ...client.CreateOption) error\n```\n\nA `client.CreateOption` is an interface that sets [`client.CreateOptions`][create-options] fields. A `client.CreateOption` is created by using one of the provided implementations: [`DryRunAll`][dry-run-all], [`ForceOwnership`][force-ownership]. Generally these options are not needed.\n\nExample:\n\n```Go\nimport (\n    \"context\"\n\n    \"k8s.io/api/apps/v1\"\n    ctrl \"sigs.k8s.io/controller-runtime\"\n)\n\nfunc (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {\n    ...\n\n    dep := &v1.Deployment{ // Any cluster object you want to create.\n        ...\n    }\n    err := r.Create(ctx, dep)\n\n    ...\n}\n```\n\n[create-options]:https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/client#CreateOptions\n\n#### Update\n\n```Go\n// Update updates the given obj in the Kubernetes cluster. obj must be a\n// struct pointer so that obj can be updated with the content returned\n// by the API server. Update does *not* update the resource's status\n// subresource\nfunc (c Client) Update(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error\n```\n\nA `client.UpdateOption` is an interface that sets [`client.UpdateOptions`][update-options] fields. A `client.UpdateOption` is created by using one of the provided implementations: [`DryRunAll`][dry-run-all], [`ForceOwnership`][force-ownership]. Generally these options are not needed.\n\nExample:\n\n```Go\nimport (\n    \"context\"\n\n    \"k8s.io/api/apps/v1\"\n    ctrl \"sigs.k8s.io/controller-runtime\"\n)\n\nfunc (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {\n    ...\n\n    dep := &v1.Deployment{}\n    err := r.Get(ctx, request.NamespacedName, dep)\n\n    ...\n\n    dep.Spec.Selector.MatchLabels[\"is_running\"] = \"true\"\n    err := r.Update(ctx, dep)\n\n    ...\n}\n```\n\n[update-options]:https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/client#UpdateOptions\n\n#### Patch\n\n```Go\n// Patch patches the given obj in the Kubernetes cluster. obj must be a\n// struct pointer so that obj can be updated with the content returned by the Server.\nfunc (c Client) Patch(ctx context.Context, obj client.Object, patch client.Patch, opts ...client.PatchOption) error\n```\n\nA `client.PatchOption` is an interface that sets [`client.PatchOptions`][patch-options] fields. A `client.PatchOption` is created by using one of the provided implementations: [`DryRunAll`][dry-run-all], [`ForceOwnership`][force-ownership]. Generally these options are not needed.\n\nExample:\n\n```Go\nimport (\n    \"context\"\n\n    \"k8s.io/api/apps/v1\"\n    ctrl \"sigs.k8s.io/controller-runtime\"\n    \"sigs.k8s.io/controller-runtime/pkg/client\"\n)\n\nfunc (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {\n    ...\n\n    dep := &v1.Deployment{}\n    err := r.Get(ctx, request.NamespacedName, dep)\n\n    ...\n\n    // A merge patch will preserve other fields modified at runtime.\n    patch := client.MergeFrom(dep.DeepCopy())\n    dep.Spec.Selector.MatchLabels[\"is_running\"] = \"true\"\n    err := r.Patch(ctx, dep, patch)\n\n    ...\n}\n```\n\n[patch-options]:https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/client#PatchOption\n[dry-run-all]:https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/client#DryRunAll\n[force-ownership]:https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/client#ForceOwnership\n\n##### Updating Status Subresource\n\nWhen updating the [status subresource][cr-status-subresource] from the client, the [`StatusWriter`][status-writer] must be used. The status subresource is retrieved with `Status()` and updated with `Update()` or patched with `Patch()`.\n\n`Update()` takes variadic `client.UpdateOption`'s, and `Patch()` takes variadic `client.PatchOption`'s. See [`Client.Update()`](#update) and [`Client.Patch()`](#patch) for more details. Generally these options are not needed.\n\n##### Status\n\n```Go\n// Status() returns a StatusWriter object that can be used to update the\n// object's status subresource\nfunc (c Client) Status() (client.StatusWriter, error)\n```\n\nExample:\n```Go\nimport (\n    \"context\"\n\n    ctrl \"sigs.k8s.io/controller-runtime\"\n\n    cachev1alpha1 \"github.com/example/memcached-operator/api/v1alpha1\"\n)\n\nfunc (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {\n    ...\n\n    mem := &cachev1alpha1.Memcached{}\n    err := r.Get(ctx, request.NamespacedName, mem)\n\n    ...\n\n    // Update\n    mem.Status.Nodes = []string{\"pod1\", \"pod2\"}\n    err := r.Status().Update(ctx, mem)\n\n    ...\n\n    // Patch\n    patch := client.MergeFrom(mem.DeepCopy())\n    mem.Status.Nodes = []string{\"pod1\", \"pod2\", \"pod3\"}\n    err := r.Status().Patch(ctx, mem, patch)\n\n    ...\n}\n```\n\n[status-writer]:https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/client#StatusWriter\n\n#### Delete\n\n```Go\n// Delete deletes the given obj from Kubernetes cluster.\nfunc (c Client) Delete(ctx context.Context, obj client.Object, opts ...client.DeleteOption) error\n```\n\nA `client.DeleteOption` is an interface that sets [`client.DeleteOptions`][delete-opts] fields. A `client.DeleteOption` is created by using one of the provided implementations: [`GracePeriodSeconds`][grace-period-seconds], [`Preconditions`][preconditions], [`PropagationPolicy`][propagation-policy].\n\nExample:\n\n```Go\nimport (\n    \"context\"\n\n    \"k8s.io/api/core/v1\"\n    ctrl \"sigs.k8s.io/controller-runtime\"\n    \"sigs.k8s.io/controller-runtime/pkg/client\"\n)\n\nfunc (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {\n    ...\n\n    pod := &v1.Pod{}\n    err := r.Get(ctx, request.NamespacedName, pod)\n\n    ...\n\n    if pod.Status.Phase == v1.PodUnknown {\n        // Delete the pod after 5 seconds.\n        err := r.Delete(ctx, pod, client.GracePeriodSeconds(5))\n        ...\n    }\n\n    ...\n}\n```\n\n[delete-opts]:https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/client#DeleteOptions\n[grace-period-seconds]:https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/client#GracePeriodSeconds\n[preconditions]:https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/client#Preconditions\n[propagation-policy]:https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/client#PropagationPolicy\n\n#### DeleteAllOf\n\n```Go\n// DeleteAllOf deletes all objects of the given type matching the given options.\nfunc (c Client) DeleteAllOf(ctx context.Context, obj client.Object, opts ...client.DeleteAllOfOption) error\n```\n\nA `client.DeleteAllOfOption` is an interface that sets [`client.DeleteAllOfOptions`][deleteallof-opts] fields. A `client.DeleteAllOfOption` wraps a [`client.ListOption`](#list) and [`client.DeleteOption`](#delete).\n\nExample:\n\n```Go\nimport (\n    \"context\"\n    \"fmt\"\n\n    \"k8s.io/api/core/v1\"\n    ctrl \"sigs.k8s.io/controller-runtime\"\n    \"sigs.k8s.io/controller-runtime/pkg/client\"\n)\n\nfunc (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {\n    ...\n\n    // Delete all pods in the request namespace with a label of `instance=<name>`\n    // and phase `Failed`.\n    pod := &v1.Pod{}\n    opts := []client.DeleteAllOfOption{\n        client.InNamespace(request.NamespacedName.Namespace),\n        client.MatchingLabels{\"instance\", request.NamespacedName.Name},\n        client.MatchingFields{\"status.phase\": \"Failed\"},\n        client.GracePeriodSeconds(5),\n    }\n    err := r.DeleteAllOf(ctx, pod, opts...)\n\n    ...\n}\n```\n\n[deleteallof-opts]:https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/client#DeleteAllOfOptions\n\n### Example usage\n\n```Go\nimport (\n    \"context\"\n    \"reflect\"\n\n    appsv1 \"k8s.io/api/apps/v1\"\n    corev1 \"k8s.io/api/core/v1\"\n    \"k8s.io/apimachinery/pkg/api/errors\"\n    metav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n    \"k8s.io/apimachinery/pkg/labels\"\n    \"k8s.io/apimachinery/pkg/runtime\"\n    \"k8s.io/apimachinery/pkg/types\"\n    ctrl \"sigs.k8s.io/controller-runtime\"\n    \"sigs.k8s.io/controller-runtime/pkg/client\"\n    \"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil\"\n\n    cachev1alpha1 \"github.com/example/memcached-operator/api/v1alpha1\"\n)\n\ntype MemcachedReconciler struct {\n    client.Client\n    Log    logr.Logger\n    Scheme *runtime.Scheme\n}\n\nfunc (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {\n\n    // Fetch the Memcached instance.\n    memcached := &cachev1alpha1.Memcached{}\n    err := r.Get(ctx, request.NamespacedName, memcached)\n    if err != nil {\n        if errors.IsNotFound(err) {\n            return ctrl.Result{}, nil\n        }\n        return ctrl.Result{}, err\n    }\n\n    // Check if the deployment already exists, if not create a new deployment.\n    found := &appsv1.Deployment{}\n    err = r.Get(ctx, types.NamespacedName{Name: memcached.Name, Namespace: memcached.Namespace}, found)\n    if err != nil {\n         if errors.IsNotFound(err) {\n            // Define and create a new deployment.\n            dep := r.deploymentForMemcached(memcached)\n            if err = r.Create(ctx, dep); err != nil {\n                return ctrl.Result{}, err\n            }\n            return ctrl.Result{Requeue: true}, nil\n        } else {\n            return ctrl.Result{}, err\n        }\n    }\n\n    // Ensure the deployment size is the same as the spec.\n    size := memcached.Spec.Size\n    if *found.Spec.Replicas != size {\n        found.Spec.Replicas = &size\n        if err = r.Update(ctx, found); err != nil {\n            return ctrl.Result{}, err\n        }\n        return ctrl.Result{Requeue: true}, nil\n    }\n\n    // Update the Memcached status with the pod names.\n    // List the pods for this CR's deployment.\n    podList := &corev1.PodList{}\n    listOpts := []client.ListOption{\n        client.InNamespace(memcached.Namespace),\n        client.MatchingLabels(labelsForApp(memcached.Name)),\n    }\n    if err = r.List(ctx, podList, listOpts...); err != nil {\n        return ctrl.Result{}, err\n    }\n\n    // Update status.Nodes if needed.\n    podNames := getPodNames(podList.Items)\n    if !reflect.DeepEqual(podNames, memcached.Status.Nodes) {\n        memcached.Status.Nodes = podNames\n        if err := r.Status().Update(ctx, memcached); err != nil {\n            return ctrl.Result{}, err\n        }\n    }\n\n    return ctrl.Request{}, nil\n}\n\n// deploymentForMemcached returns a Deployment object for data from m.\nfunc (r *MemcachedReconciler) deploymentForMemcached(m *cachev1alpha1.Memcached) *appsv1.Deployment {\n    lbls := labelsForApp(m.Name)\n    replicas := m.Spec.Size\n\n    dep := &appsv1.Deployment{\n        ObjectMeta: metav1.ObjectMeta{\n            Name:      m.Name,\n            Namespace: m.Namespace,\n        },\n        Spec: appsv1.DeploymentSpec{\n            Replicas: &replicas,\n            Selector: &metav1.LabelSelector{\n                MatchLabels: lbls,\n            },\n            Template: corev1.PodTemplateSpec{\n                ObjectMeta: metav1.ObjectMeta{\n                    Labels: lbls,\n                },\n                Spec: corev1.PodSpec{\n                    Containers: []corev1.Container{{\n                        Image:   \"memcached:alpine\",\n                        Name:    \"memcached\",\n                        Command: []string{\"memcached\", \"-a=64\", \"-b\"},\n                        Ports: []corev1.ContainerPort{{\n                            ContainerPort: 10000,\n                            Name:          \"memcached\",\n                        }},\n                    }},\n                },\n            },\n        },\n    }\n\n    // Set Memcached instance as the owner and controller.memcac\n    // NOTE: calling SetControllerReference, and setting owner references in\n    // general, is important as it allows deleted objects to be garbage collected.\n    controllerutil.SetControllerReference(m, dep, r.Scheme)\n    return dep\n}\n\n// labelsForApp creates a simple set of labels for Memcached.\nfunc labelsForApp(name string) map[string]string {\n    return map[string]string{\"cr_name\": name}\n}\n```\n\n[memcached-testdata]:https://github.com/operator-framework/operator-sdk/tree/master/testdata/go/v4/memcached-operator\n[repo-controller-runtime]:https://github.com/kubernetes-sigs/controller-runtime\n[doc-client]:https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/client#Client\n[doc-split-client]:https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/client#DelegatingClient\n[doc-client-constr]:https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/client#New\n[code-scheme-default]:https://github.com/kubernetes-sigs/controller-runtime/blob/master/pkg/client/client.go#L51\n[doc-k8s-core]:https://pkg.go.dev/k8s.io/api/core/v1\n[doc-reconcile-reconciler]:https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/reconcile#Reconciler\n[doc-osdk-handle]:https://github.com/operator-framework/operator-sdk/blob/master/design/milestone-0.0.2/action-api.md#handler\n[doc-types-nsname]:https://pkg.go.dev/k8s.io/apimachinery/pkg/types#NamespacedName\n[cr-status-subresource]:https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#status-subresource\n"
  },
  {
    "path": "website/content/en/docs/building-operators/golang/references/event-filtering.md",
    "content": "---\ntitle: Using Predicates for Event Filtering with Operator SDK\nlinkTitle: Using Predicates for Event Filtering\nweight: 30\n---\n\n[Events][doc_event] are produced by [Sources][doc_source] assigned to resources a controller is watching. These events are transformed into Requests by [EventHandlers][doc_eventhandler] and passed to `Reconcile()`. [Predicates][doc_predicate] allow controllers to filter events before they are provided to EventHandlers. Filtering is useful because your controller may only want to handle specific types of events. Filtering also helps reduce chattiness with the API server, as `Reconcile()` is only called for events transformed by EventHandlers.\n\n## Predicate types\n\nA Predicate implements the following methods that take an event of a particular type and return true if the event should be processed by `Reconcile()`:\n\n```Go\n// Predicate filters events before enqueuing the keys.\ntype Predicate interface {\n  Create(event.CreateEvent) bool\n  Delete(event.DeleteEvent) bool\n  Update(event.UpdateEvent) bool\n  Generic(event.GenericEvent) bool\n}\n\n// Funcs implements Predicate.\ntype Funcs struct {\n  CreateFunc func(event.CreateEvent) bool\n  DeleteFunc func(event.DeleteEvent) bool\n  UpdateFunc func(event.UpdateEvent) bool\n  GenericFunc func(event.GenericEvent) bool\n}\n```\n\nFor example, all Create events for any watched resource will be passed to `Funcs.Create()` and filtered out if the method evaluates to `false`. If you do not register a Predicate method for a particular type, events of that type will not be filtered.\n\nAll event types contain Kubernetes [metadata][doc_object_metadata] about the object that triggered the event, and the object itself. Predicate logic uses these data to make decisions about what should be filtered. Some event types include other fields pertaining to the semantics of that event. For example, `event.UpdateEvent` includes both old and new metadata and objects:\n\n```Go\ntype UpdateEvent struct {\n  // ObjectOld is the object from the event.\n  ObjectOld runtime.Object\n\n  // ObjectNew is the object from the event.\n  ObjectNew runtime.Object\n}\n```\n\nYou can find all type definitions in the `event` package [documentation][doc_event].\n\n## Using Predicates\n\nAny number of Predicates can be set for a controller via the builder method `WithEventFilter()`, which will filter an event if any of those Predicates evaluates to `false`. This first example is an implementation of a `memcached-operator` controller that simply filters Delete events on Pods that have been confirmed deleted; the controller receives all Delete events that occur, and we may only care about resources that have not been completely deleted:\n\n```Go\nimport (\n\t\"context\"\n\n\t\"github.com/go-logr/logr\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\tctrl \"sigs.k8s.io/controller-runtime\"\n\t\"sigs.k8s.io/controller-runtime/pkg/client\"\n\t\"sigs.k8s.io/controller-runtime/pkg/event\"\n\t\"sigs.k8s.io/controller-runtime/pkg/predicate\"\n\n\tcachev1alpha1 \"github.com/example/app-operator/api/v1alpha1\"\n)\n\n...\n\nfunc ignoreDeletionPredicate() predicate.Predicate {\n\treturn predicate.Funcs{\n\t\tUpdateFunc: func(e event.UpdateEvent) bool {\n\t\t\t// Ignore updates to CR status in which case metadata.Generation does not change\n\t\t\treturn e.ObjectOld.GetGeneration() != e.ObjectNew.GetGeneration()\n\t\t},\n\t\tDeleteFunc: func(e event.DeleteEvent) bool {\n\t\t\t// Evaluates to false if the object has been confirmed deleted.\n\t\t\treturn !e.DeleteStateUnknown\n\t\t},\n\t}\n}\n\nfunc (r *MemcachedReconciler) SetupWithManager(mgr ctrl.Manager) error {\n\treturn ctrl.NewControllerManagedBy(mgr).\n\t\tFor(&cachev1alpha1.Memcached{}).\n\t\tOwns(&corev1.Pod{}).\n\t\tWithEventFilter(ignoreDeletionPredicate()).\n\t\tComplete(r)\n}\n  ...\n}\n```\n\n## Use cases\n\nPredicates are not necessary for many operators, although filtering reduces the amount of chatter to the API server from `Reconcile()`. They are particularly useful for controllers that watch resources cluster-wide, i.e. without a namespace.\n\n[doc_event]:https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/event\n[doc_source]:https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/source#Source\n[doc_eventhandler]:https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/handler#EventHandler\n[doc_predicate]:https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/predicate\n[doc_object_metadata]:https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1#Object\n"
  },
  {
    "path": "website/content/en/docs/building-operators/golang/references/logging.md",
    "content": "---\ntitle: Logging\nlinkTitle: Logging\nweight: 20\n---\n\n# Overview\n\nOperator SDK-generated operators use the [`logr`][godoc_logr] interface to log. This log interface has several backends such as [`zap`][repo_zapr], which the SDK uses in generated code by default. [`logr.Logger`][godoc_logr_logger] exposes structured logging methods that help create machine-readable logs and adding a wealth of information to log records.\n\n## Default zap logger\n\nOperator SDK uses a `zap`-based `logr` backend when scaffolding new projects. To assist with configuring and using this logger, the SDK includes several helper functions.\n\nIn the simple example below, we add the zap flagset to the operator's command line flags with `BindFlags()`, and then set the controller-runtime logger with `zap.Options{}`.\n\nBy default, `zap.Options{}` will return a logger that is ready for production use. It uses a JSON encoder, logs starting at the `info` level. To customize the default behavior, users can use the zap flagset and specify flags on the command line. The zap flagset includes the following flags that can be used to configure the logger:\n\n* `--zap-devel`: Development Mode defaults(encoder=consoleEncoder,logLevel=Debug,stackTraceLevel=Warn)\n\t\t\t  Production Mode defaults(encoder=jsonEncoder,logLevel=Info,stackTraceLevel=Error)\n* `--zap-encoder`: Zap log encoding ('json' or 'console')\n* `--zap-log-level`: Zap Level to configure the verbosity of logging. Can be one of 'debug', 'info', 'error',\n\t\t\t       or any integer value > 0 which corresponds to custom debug levels of increasing verbosity\")\n* `--zap-stacktrace-level`: Zap Level at and above which stacktraces are captured (one of 'info' or 'error')\n\nConsult the controller-runtime [godocs][logging_godocs] for more detailed flag information.\n\n### A simple example\n\nOperators set the logger for all operator logging in `main.go`. To illustrate how this works, try out this simple example:\n\n```Go\npackage main\n\nimport (\n\t\"sigs.k8s.io/controller-runtime/pkg/log/zap\"\n\tlogf \"sigs.k8s.io/controller-runtime/pkg/log\"\n)\n\nvar globalLog = logf.Log.WithName(\"global\")\nfunc main() {\n\t// Add the zap logger flag set to the CLI. The flag set must\n\t// be added before calling flag.Parse().\n\topts := zap.Options{}\n\topts.BindFlags(flag.CommandLine)\n\tflag.Parse()\n\n\tlogger := zap.New(zap.UseFlagOptions(&opts))\n\tlogf.SetLogger(logger)\n\n\tscopedLog := logf.Log.WithName(\"scoped\")\n\n\tglobalLog.Info(\"Printing at INFO level\")\n\tglobalLog.V(1).Info(\"Printing at DEBUG level\")\n\tscopedLog.Info(\"Printing at INFO level\")\n\tscopedLog.V(1).Info(\"Printing at DEBUG level\")\n}\n```\n\n#### Output using the defaults\n```console\n$ go run main.go\nINFO[0000] Running the operator locally in namespace default.\n{\"level\":\"info\",\"ts\":1587741740.407766,\"logger\":\"global\",\"msg\":\"Printing at INFO level\"}\n{\"level\":\"info\",\"ts\":1587741740.407855,\"logger\":\"scoped\",\"msg\":\"Printing at INFO level\"}\n```\n\n#### Output overriding the log level to 1 (debug)\n```console\n$ go run main.go --zap-log-level=debug\nINFO[0000] Running the operator locally in namespace default.\n{\"level\":\"info\",\"ts\":1587741837.602911,\"logger\":\"global\",\"msg\":\"Printing at INFO level\"}\n{\"level\":\"debug\",\"ts\":1587741837.602964,\"logger\":\"global\",\"msg\":\"Printing at DEBUG level\"}\n{\"level\":\"info\",\"ts\":1587741837.6029708,\"logger\":\"scoped\",\"msg\":\"Printing at INFO level\"}\n{\"level\":\"debug\",\"ts\":1587741837.602973,\"logger\":\"scoped\",\"msg\":\"Printing at DEBUG level\"}\n```\n## Custom zap logger\n\nIn order to use a custom zap logger, [`zap`][controller_runtime_zap] from controller-runtime can be utilized to wrap it in a `logr` implementation.\n\nBelow is an example illustrating the use of [`zap-logfmt`][logfmt_repo] in logging.\n\n### Example\n\nIn your `main.go` file, replace the current implementation for logs inside the `main` function:\n\n```Go\n...\n// Add the zap logger flag set to the CLI. The flag set must\n// be added before calling flag.Parse().\n\topts := zap.Options{}\n\topts.BindFlags(flag.CommandLine)\n\tflag.Parse()\n\n\tlogger := zap.New(zap.UseFlagOptions(&opts))\n\tlogf.SetLogger(logger)\n...\n```\n\nWith:\n\n```Go\n\timport(\n\t...\n\tzaplogfmt \"github.com/sykesm/zap-logfmt\"\n\tuzap \"go.uber.org/zap\"\n\t\"go.uber.org/zap/zapcore\"\n\tlogf \"sigs.k8s.io/controller-runtime/pkg/log\"\n\t\"sigs.k8s.io/controller-runtime/pkg/log/zap\"\n\t...\n)\n\tconfigLog := uzap.NewProductionEncoderConfig()\n\tconfigLog.EncodeTime = func(ts time.Time, encoder zapcore.PrimitiveArrayEncoder) {\n\t\tencoder.AppendString(ts.UTC().Format(time.RFC3339Nano))\n\t}\n\tlogfmtEncoder := zaplogfmt.NewEncoder(configLog)\n\n\t// Construct a new logr.logger.\n\tlogger := zap.New(zap.UseDevMode(true), zap.WriteTo(os.Stdout), zap.Encoder(logfmtEncoder))\n\tlogf.SetLogger(logger)\n```\n\n**NOTE**: For this example, you will need to add the module `\"github.com/sykesm/zap-logfmt\"` to your project. Run `go get -u github.com/sykesm/zap-logfmt`.\n\n#### Output using custom zap logger\n\n```console\n$ go run main.go\nts=2020-04-30T20:35:59.551268Z level=info logger=global msg=\"Printing at INFO level\"\nts=2020-04-30T20:35:59.551314Z level=debug logger=global msg=\"Printing at DEBUG level\"\nts=2020-04-30T20:35:59.551318Z level=info logger=scoped msg=\"Printing at INFO level\"\nts=2020-04-30T20:35:59.55132Z level=debug logger=scoped msg=\"Printing at DEBUG level\"\n```\n\nBy using `sigs.k8s.io/controller-runtime/pkg/log`, your logger is propagated through `controller-runtime`. Any logs produced by `controller-runtime` code will be through your logger, and therefore have the same formatting and destination.\n\n### Setting flags when running locally\n\nWhen running locally with `make run ENABLE_WEBHOOKS=false`, you can use the `ARGS` var to pass additional flags to your operator, including the zap flags. For example:\n\n```console\n$ make run ARGS=\"--zap-encoder=console\" ENABLE_WEBHOOKS=false\n```\nMake sure to have your `run` target to take `ARGS` as shown below in `Makefile`.\n\n```makefile\n# Run against the configured Kubernetes cluster in ~/.kube/config\nrun: manifests generate fmt vet\n\tgo run ./main.go $(ARGS)\n```\n\n### Setting flags when deploying to a cluster\n\nWhen deploying your operator to a cluster you can set additional flags using an `args` array in your operator's `container` spec in the file `config/default/manager_metrics_patch.yaml` For example:\n\n```yaml\n- op: add\n  path: /spec/template/spec/containers/0/args/0\n  value: --zap-log-level=debug \n- op: add\n  path: /spec/template/spec/containers/0/args/0\n  value: --zap-encoder=console\n```\n\n## Creating a structured log statement\n\nThere are two ways to create structured logs with `logr`. You can create new loggers using `log.WithValues(keyValues)` that include `keyValues`, a list of key-value pair `interface{}`'s, in each log record. Alternatively you can include `keyValues` directly in a log statement, as all `logr` log statements take some message and `keyValues`. The signature of `logr.Error()` has an `error`-type parameter, which can be `nil`.\n\nAn example from [`memcached_controller.go`][code_memcached_controller]:\n\n```Go\npackage memcached\n\nimport (\n  ctrllog \"sigs.k8s.io/controller-runtime/pkg/log\"\n)\n\n\n// MemcachedReconciler reconciles a Memcached object\ntype MemcachedReconciler struct {\n\tclient.Client\n\tLog    logr.Logger\n\tScheme *runtime.Scheme\n}\n\nfunc (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {\n\tlog := ctrllog.FromContext(ctx)\n\n\t// Fetch the Memcached instance\n\tmemcached := &cachev1alpha1.Memcached{}\n\terr := r.Get(ctx, req.NamespacedName, memcached)\n\tif err != nil {\n\t\tif errors.IsNotFound(err) {\n\t\t\t// Request object not found, could have been deleted after reconcile request.\n\t\t\t// Owned objects are automatically garbage collected. For additional cleanup logic use finalizers.\n\t\t\t// Return and don't requeue\n\t\t\tlog.Info(\"Memcached resource not found. Ignoring since object must be deleted\")\n\t\t\treturn ctrl.Result{}, nil\n\t\t}\n\t\t// Error reading the object - requeue the request.\n\t\tlog.Error(err, \"Failed to get Memcached\")\n\t\treturn ctrl.Result{}, err\n\t}\n\n\t// Check if the deployment already exists, if not create a new one\n\tfound := &appsv1.Deployment{}\n\terr = r.Get(ctx, types.NamespacedName{Name: memcached.Name, Namespace: memcached.Namespace}, found)\n\tif err != nil && errors.IsNotFound(err) {\n\t\t// Define a new deployment\n\t\tdep := r.deploymentForMemcached(memcached)\n\t\tlog.Info(\"Creating a new Deployment\", \"Deployment.Namespace\", dep.Namespace, \"Deployment.Name\", dep.Name)\n\t\terr = r.Create(ctx, dep)\n\t\tif err != nil {\n\t\t\tlog.Error(err, \"Failed to create new Deployment\", \"Deployment.Namespace\", dep.Namespace, \"Deployment.Name\", dep.Name)\n\t\t\treturn ctrl.Result{}, err\n\t\t}\n\t\t// Deployment created successfully - return and requeue\n\t\treturn ctrl.Result{Requeue: true}, nil\n\t} else if err != nil {\n\t\tlog.Error(err, \"Failed to get Deployment\")\n\t\treturn ctrl.Result{}, err\n\t}\n\n\t...\n}\n```\n\nLog records will look like the following (from `log.Error()` above):\n\n```\n2020-04-27T09:14:15.939-0400\tERROR\tcontrollers.Memcached\tFailed to create new Deployment\t{\"memcached\": \"default/memcached-sample\", \"Deployment.Namespace\": \"default\", \"Deployment.Name\": \"memcached-sample\"}\n```\n\n## Non-default logging\n\nIf you do not want to use `logr` as your logging tool, you can remove `logr`-specific statements without issue from your operator's code, including the `logr` setup code in `main.go`, and add your own. Note that removing `logr` setup code will prevent `controller-runtime` from logging.\n\n\n[godoc_logr]:https://pkg.go.dev/github.com/go-logr/logr\n[repo_zapr]:https://pkg.go.dev/github.com/go-logr/zapr\n[godoc_logr_logger]:https://pkg.go.dev/github.com/go-logr/logr#Logger\n[code_memcached_controller]: https://github.com/operator-framework/operator-sdk/blob/v1.2.0/testdata/go/memcached-operator/controllers/memcached_controller.go\n[logfmt_repo]:https://github.com/jsternberg/zap-logfmt\n[controller_runtime_zap]:https://github.com/kubernetes-sigs/controller-runtime/tree/master/pkg/log/zap\n[logging_godocs]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/log/zap#Options.BindFlags\n"
  },
  {
    "path": "website/content/en/docs/building-operators/golang/references/markers.md",
    "content": "---\ntitle: API Markers\nlinkTitle: API Markers\nweight: 40\n---\n\nThis document describes [code markers][markers] supported by the SDK.\n\n## ClusterServiceVersion markers\n\nThis section details ClusterServiceVersion (CSV) code markers and lists available markers.\n\n**Note:** CSV markers can only be used in Go Operator projects. Annotations for Ansible and Helm Operator projects will be added in the future.\n\n### Usage\n\nAll CSV markers have the prefix `+operator-sdk:csv`.\n\n#### `+operator-sdk:csv:customresourcedefinitions`\n\nThese markers populate [owned `customresourcedefinitions`][csv-crds] in your CSV.\n\nPossible type-level markers:\n- `+operator-sdk:csv:customresourcedefinitions:displayName=\"some display name\"`\n\t- Configures the kind's display name.\n- `+operator-sdk:csv:customresourcedefinitions:resources={{Kind1,v1alpha1,dns-name-1},{Kind2,v1,\"dns-name-2\"},...}`\n\t- Configures the kind's resources.\n- `+operator-sdk:csv:customresourcedefinitions:order=1`\n\t- Configures the order of this type in the list. Markers with order omitted have the highest order, i.e. are at the end of the list. If more than one marker has the same order, the corresponding descriptions will be sorted alphabetically and placed above others with higher orders. Pre-existing list elements in the CSV will be appended to the set of other elements in the order corresponding to its index.\n\nPossible field-level markers, all of which must contain the `type=[spec,status]` key-value pair:\n- `+operator-sdk:csv:customresourcedefinitions:type=[spec,status],displayName=\"some field display name\"`\n\t- Configures the field's display name.\n- `+operator-sdk:csv:customresourcedefinitions:type=[spec,status],xDescriptors={\"urn:alm:descriptor:com.tectonic.ui:podCount\",\"urn:alm:descriptor:io.kubernetes:custom\"}`\n\t- Configures the field's x-descriptors.\n- `+operator-sdk:csv:customresourcedefinitions:type=[spec,status],order=1`\n\t- Configures the order of this type in the list. Markers with order omitted have the highest order, i.e. are at the end of the list. If more than one marker has the same order, the corresponding descriptions will be sorted alphabetically and placed above others with higher orders.\n\nTop-level `kind`, `name`, and `version` fields are parsed from API code.\nAll `description` fields are parsed from type declaration and `struct` type field comments.\nAll `path` fields are parsed from a field's JSON tag and merged with parent\nfield path's in dot-hierarchy notation.\n\n##### x-descriptors\n\nCheck out the [descriptor reference][csv-x-desc] for available `x-descriptors` paths.\n\n#### Examples\n\nThese examples assume `Memcached`, `MemcachedSpec`, and `MemcachedStatus` are the example projects' kind, spec, and status.\n\n1. Set a `displayName` and `resources` for a `customresourcedefinitions` kind entry:\n\n\t```go\n\t//+operator-sdk:csv:customresourcedefinitions:displayName=\"Memcached App\",resources={{Pod,v1,memcached-runner},{Deployment,v1,memcached-deployment}}\n\ttype Memcached struct {\n\t\tmetav1.TypeMeta   `json:\",inline\"`\n\t\tmetav1.ObjectMeta `json:\"metadata,omitempty\"`\n\n\t\tSpec   MemcachedSpec   `json:\"spec,omitempty\"`\n\t\tStatus MemcachedStatus `json:\"status,omitempty\"`\n\t}\n\t```\n\n2. Set `displayName`, `path`, `xDescriptors`, and `description` on a field for a `customresourcedefinitions.specDescriptors` entry:\n\n\t```go\n\ttype MemcachedSpec struct {\n\t\t// Size is the size of the memcached deployment. <-- This will become Size's specDescriptors.description.\n\t\t//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName=\"Number of pods\",xDescriptors={\"urn:alm:descriptor:com.tectonic.ui:podCount\",\"urn:alm:descriptor:io.kubernetes:custom\"}\n\t\tSize int32 `json:\"size\"` // <-- Size's specDescriptors.path is inferred from this JSON tag.\n\t}\n\t```\n\n3. Let the SDK infer all unmarked paths on a field for a `customresourcedefinitions.specDescriptors` entry:\n\n\t```go\n\ttype MemcachedSpec struct {\n\t\t// Size is the size of the memcached deployment.\n\t\t//+operator-sdk:csv:customresourcedefinitions:type=spec\n\t\tSize int32 `json:\"size\"`\n\t}\n\t```\n\n\tThe SDK uses the `Size` fields' `json` tag name as `path`, `Size` as `displayName`, and field comments as `description`.\n\n4. A comprehensive example:\n\t- Infer `path`, `description`, `displayName`, and `x-descriptors` for `specDescriptors` and `statusDescriptors` entries.\n\t- Create three `resources` entries each with `kind`, `version`, and `name` values.\n\n\t```go\n\t// Represents a cluster of Memcached apps\n\t//+operator-sdk:csv:customresourcedefinitions:displayName=\"Memcached App\",resources={{Pod,v1,memcached-runner},{Deployment,v1,memcached-deployment}}\n\ttype Memcached struct {\n\t\tmetav1.TypeMeta   `json:\",inline\"`\n\t\tmetav1.ObjectMeta `json:\"metadata,omitempty\"`\n\n\t\tSpec   MemcachedSpec   `json:\"spec,omitempty\"`\n\t\tStatus MemcachedStatus `json:\"status,omitempty\"`\n\t}\n\n\ttype MemcachedSpec struct {\n\t\tPods MemcachedPods `json:\"pods\"`\n\t}\n\n\ttype MemcachedStatus struct {\n\t\tPods \t\t MemcachedPods `json:\"podStatuses\"`\n\t\t//+operator-sdk:csv:customresourcedefinitions:type=status,displayName=\"Pod Count\",xDescriptors=\"urn:alm:descriptor:com.tectonic.ui:podCount\"\n\t\tPodCount int \t\t\t\t\t `json:\"podCount\"`\n\t}\n\n\ttype MemcachedPods struct {\n\t\t// Size is the size of the memcached deployment.\n\t\t//+operator-sdk:csv:customresourcedefinitions:type=spec\n\t\t//+operator-sdk:csv:customresourcedefinitions:type=status\n\t\tSize int32 `json:\"size\"`\n\t}\n\t```\n\n\tThe generated `customresourcedefinitions` will look like:\n\n\t```yaml\n\tcustomresourcedefinitions:\n\t  owned:\n\t  - description: Represents a cluster of Memcached apps\n\t    displayName: Memcached App\n\t    kind: Memcached\n\t    name: memcacheds.cache.example.com\n\t    version: v1alpha1\n\t    resources:\n\t    - kind: Deployment\n\t      name: memcached-deployment\n\t      version: v1\n\t    - kind: Pod\n\t      name: memcached-runner\n\t      version: v1\n\t    specDescriptors:\n\t    - description: The desired number of member Pods for the deployment.\n\t      displayName: Size\n\t      path: pods.size\n\t    statusDescriptors:\n\t    - description: The desired number of member Pods for the deployment.\n\t      displayName: Size\n\t      path: podStatuses.size\n\t    - displayName: Size\n\t      path: podCount\n\t      x-descriptors:\n\t      - 'urn:alm:descriptor:com.tectonic.ui:podCount'\n\t```\n\n\n## Deprecated markers\n\nMarkers supported by `operator-sdk` prior to v1.0.0 are deprecated.\nYou can migrate to the new marker system by running the following script:\n\n```console\n$ curl -sSLo migrate-markers.sh https://raw.githubusercontent.com/operator-framework/operator-sdk/master/hack/generate/migrate-markers.sh\n$ chmod +x ./migrate-markers.sh\n$ ./migrate-markers.sh path/to/*_types.go\n```\n\n\n[markers]:https://pkg.go.dev/sigs.k8s.io/controller-tools/pkg/markers\n[cli-gen-kustomize-manifests]:/docs/cli/operator-sdk_generate_kustomize_manifests\n[csv-x-desc]:https://github.com/openshift/console/blob/master/frontend/packages/operator-lifecycle-manager/src/components/descriptors/reference/reference.md\n[csv-spec]:https://github.com/operator-framework/operator-lifecycle-manager/blob/e0eea22/doc/design/building-your-csv.md\n[csv-crds]:https://github.com/operator-framework/operator-lifecycle-manager/blob/master/doc/design/building-your-csv.md#your-custom-resource-definitions\n"
  },
  {
    "path": "website/content/en/docs/building-operators/golang/references/openapi-validation.md",
    "content": "---\ntitle: OpenAPI validation\nlinkTitle: OpenAPI validation\nweight: 70\n---\n\nOpenAPIv3 schemas are added to CRD manifests in the `spec.validation` block when the manifests are generated. This validation block allows Kubernetes to validate the properties in a Memcached Custom Resource when it is created or updated.\n\n[Markers][markers] (annotations) are available to configure validations for your API. These markers will always have a `+kubebuilder:validation` prefix.\n\nUsage of markers in API code is discussed in the kubebuilder [CRD generation][generating-crd] and [marker][markers] documentation. A full list of OpenAPIv3 validation markers can be found [here][crd-markers].\n\nTo learn more about OpenAPI v3.0 validation schemas in CRDs, refer to the [Kubernetes Documentation][doc-validation-schema].\n\n[markers]: https://book.kubebuilder.io/reference/markers.html\n[crd-markers]: https://book.kubebuilder.io/reference/markers/crd-validation.html\n[generating-crd]: https://book.kubebuilder.io/reference/generating-crd.html\n[doc-validation-schema]: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#specifying-a-structural-schema\n"
  },
  {
    "path": "website/content/en/docs/building-operators/golang/references/proxy-vars.md",
    "content": "---\ntitle: Proxy Friendly Operators\nlinkTitle: Proxy Vars\nweight: 20\n---\n\nProxy-friendly Operators should inspect their environment for the\nstandard proxy variables (`HTTPS_PROXY`, `HTTP_PROXY`, and `NO_PROXY`)\nand pass the values to Operands.\n\nOperator-lib provides a helper function `proxy.ReadProxyVarsFromEnv`\nthat does this inspection, all you need to do is append the\nresults to the Operand environments.\n\nUsing the memcached tutorial as an example, add the following to the\nReconcile loop in `controllers/memcached_controller.go`:\n\n\n```go\nimport (\n  ...\n   \"github.com/operator-framework/operator-lib/proxy\"\n)\n\n\nfor i, container := range dep.Spec.Template.Spec.Containers {\n\t\tdep.Spec.Template.Spec.Containers[i].Env = append(container.Env, proxy.ReadProxyVarsFromEnv()...)\n}\n```\n\nYou can set the environment variable on the Operator deployment. Using the memcached tutorial, edit config/manager/manager.yaml:\n\n```yaml\ncontainers:\n - args:\n   - --leader-elect\n   - --leader-election-id=go-proxy-demo\n   image: controller:latest\n   name: manager\n   env:\n     - name: \"HTTP_PROXY\"\n       value: \"http_proxy_test\"\n```\n"
  },
  {
    "path": "website/content/en/docs/building-operators/golang/testing.md",
    "content": "---\ntitle: Testing your Operator project\nlinkTitle: Testing with EnvTest\ndescription: Learn how to ensure the quality of your Operator project\nweight: 70\n---\n\n## Overview\n\nThe Operator SDK project recommends using controller-runtime's [envtest][envtest] to write tests for your Operators projects. Envtest has a more active contributor community, it is more mature than Operator SDK's test framework, and it does not require an actual cluster to run tests which can be a huge benefit in CI scenarios.\n\n## Using EnvTest\n\nYou will see that `controllers/suite_test.go` is created when a controller is scaffolded by the tool. This file contains boilerplate for executing integration tests using [envtest][envtest] with [ginkgo](https://onsi.github.io/ginkgo/) and [gomega][gomega].\nSetup instructions, including those for disconnected environments, are found [here][envtest-setup].\n\nThese tests are runnable as native Go tests:\n\n```shell\ngo test controllers/ -v -ginkgo.v\n```\n\nThe projects generated by using the SDK tool have a Makefile which contains the target tests which executes when you run `make test`. Note that this target will also execute when you run `make docker-build IMG=<some-registry>/<project-name>:<tag>`.\n\nOperator SDK adopted this stack to write tests for its operators. It might be useful to check [writing controller tests][writing-controller-tests] documentation and examples to learn how to better write tests for your operator. See, for example, that [controller-runtime](https://github.com/kubernetes-sigs/controller-runtime) is covered by tests using the same stack as well.\n\n## e2e Integration tests\n\n- **For Golang-based operators**: you can create the e2e tests using Go. See the `test` directory for the Memcached sample\nunder the [testdata/go/v3/memcached-operator][sample] to see an example of e2e tests.\n- **For Ansible-based operators**: you can use [Molecule][molecule], an Ansible testing framework. For further information see [Testing with Molecule][molecule-tests].\n- **For Helm-based operators**: you can also use [Chart tests][helm-chart-tests].\n\nAlternatively, you can achieve the same goal using shell scripts. The following are a few examples of shell scripts\nused for testing projects built with SDK `1.0.0`:\n\n- [Legacy test to check Golang-based Operators][go-legacy-shell]\n- [Legacy test to check Helm-based Operators][helm-legacy-shell]\n- [Legacy test to check Ansible-based Operators][ansible-legacy-shell]\n\n## Other Options\n\nAlso, you can write tests for your operator in a declarative format using [kuttl][kuttl]. Via kuttl, you can define YAML manifests that specify the expected before and after states of a cluster when your operator is used. For more info see [Writing Kuttl Scorecard Tests][writing-kuttl-scorecard-tests].\n\nAn alternative and more modern solution to kuttl is [chainsaw][chainsaw]. Chainsaw offers more flexibility, a rich assertion model, and is actively maintained. Tests from kuttl can be automatically converted to chainsaw, see [Migration from KUTTL][from-kuttl-to-chainsaw].\n\nTo implement application-specific tests, the SDK's test harness, [scorecard][scorecard], provides the ability to ship custom code in container images as well, which can be referenced in the test suite. Because this test suite definition metadata travels with the Operator Bundle, it allows for functional testing of the Operator without the source code or the project layout being available. See [Writing Custom Scorecard Tests][writing-custom-scorecard-tests].\n\n[envtest]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/envtest\n[envtest-setup]:https://book.kubebuilder.io/reference/envtest.html\n[writing-controller-tests]: https://book.kubebuilder.io/cronjob-tutorial/writing-tests.html\n[writing-kuttl-scorecard-tests]: /docs/testing-operators/scorecard/kuttl-tests\n[writing-custom-scorecard-tests]: /docs/testing-operators/scorecard/custom-tests\n[scorecard]: /docs/testing-operators/scorecard/\n[gomega]: https://onsi.github.io/gomega/\n[kuttl]: https://github.com/kudobuilder/kuttl/\n[sample]: https://github.com/operator-framework/operator-sdk/tree/master/testdata/go/v4/memcached-operator\n[molecule]: https://molecule.readthedocs.io/\n[molecule-tests]: /docs/building-operators/ansible/testing-guide\n[helm-chart-tests]: https://helm.sh/docs/topics/chart_tests/\n[go-legacy-shell]: https://github.com/operator-framework/operator-sdk/blob/v1.0.0/hack/tests/e2e-go.sh\n[helm-legacy-shell]: https://github.com/operator-framework/operator-sdk/blob/v1.0.0/hack/tests/e2e-helm.sh\n[ansible-legacy-shell]: https://github.com/operator-framework/operator-sdk/blob/v1.0.0/hack/tests/e2e-ansible.sh\n[chainsaw]: https://kyverno.github.io/chainsaw/latest/\n[from-kuttl-to-chainsaw]: https://kyverno.github.io/chainsaw/latest/guides/kuttl-migration\n"
  },
  {
    "path": "website/content/en/docs/building-operators/golang/tutorial.md",
    "content": "---\ntitle: Go Operator Tutorial\nlinkTitle: Tutorial\nweight: 30\ndescription: An in-depth walkthrough of building and running a Go-based operator.\n---\n\n**NOTE:** If your project was created with an `operator-sdk` version prior to `v1.0.0`\nplease [migrate][migration-guide], or consult the [legacy docs][legacy-quickstart-doc].\n\n## Prerequisites\n\n- Go through the [installation guide][install-guide].\n- Make sure your user is authorized with `cluster-admin` permissions.\n- An accessible image registry for various operator images (ex. [hub.docker.com](https://hub.docker.com/signup),\n[quay.io](https://quay.io/)) and be logged in to your command line environment.\n  - `example.com` is used as the registry Docker Hub namespace in these examples.\n  Replace it with another value if using a different registry or namespace.\n  - [Authentication and certificates][image-reg-config] if the registry is private or uses a custom CA.\n\n## Overview\n\nWe will create a sample project to let you know how it works and this sample will:\n\n- Create a Memcached Deployment if it doesn't exist\n- Ensure that the Deployment size is the same as specified by the Memcached CR spec\n- Update the Memcached CR status using the status writer with the names of the CR's pods\n\n## Create a new project\n\nUse the CLI to create a new memcached-operator project:\n\n```sh\nmkdir -p $HOME/projects/memcached-operator\ncd $HOME/projects/memcached-operator\n# we'll use a domain of example.com\n# so all API groups will be <group>.example.com\noperator-sdk init --domain example.com --repo github.com/example/memcached-operator\n```\n`--domain` will be used as the prefix of the API group your custom resources will be created in.\nAPI groups are a mechanism to group portions of the Kubernetes API. You're probably already familiar with\nsome of the core Kubernetes API groups, such as `apps` or `rbac.authorization.k8s.io`. API groups are used\ninternally to version your Kubernetes resources and are thus used for many things. Importantly, you should \nname your domain to group your resource types in meaningful group(s) for ease of understanding and because these\ngroups determine how access can be controlled to your resource types using RBAC. For more information, see [the core Kubernetes docs](https://kubernetes.io/docs/reference/using-api/#api-groups) and [the Kubebuilder docs](https://book.kubebuilder.io/cronjob-tutorial/gvks.html).\n\n**Note** If your local environment is Apple Silicon (`darwin/arm64`) use the `go/v4`\nplugin which provides support for this platform by adding to the init subCommand the flag `--plugins=go/v4`\n\nTo learn about the project directory structure, see [Kubebuilder project layout][kubebuilder_layout_doc] doc.\n\n#### A note on dependency management\n\n`operator-sdk init` generates a `go.mod` file to be used with [Go modules][go_mod_wiki]. The `--repo=<path>` flag is required when creating a project outside of `$GOPATH/src`, as scaffolded files require a valid module path. Ensure you [activate module support][activate_modules] by running `export GO111MODULE=on` before using the SDK.\n\n### Manager\n\nThe main program for the operator `main.go` initializes and runs the [Manager][manager_go_doc].\n\nSee the [Kubebuilder entrypoint doc][kubebuilder_entrypoint_doc] for more details on how the manager registers the Scheme for the custom resource API definitions, and sets up and runs controllers and webhooks.\n\n\nThe Manager can restrict the namespace that all controllers will watch for resources:\n\n```Go\nmgr, err := ctrl.NewManager(cfg, manager.Options{Namespace: namespace})\n```\n\nBy default this will be empty string which means watch all namespaces:\n\n```Go\nmgr, err := ctrl.NewManager(cfg, manager.Options{Namespace: \"\"})\n```\n\nRead the [operator scope][operator_scope] documentation on how to run your operator as namespace-scoped vs cluster-scoped.\n\n## Create a new API and Controller\n\nCreate a new Custom Resource Definition (CRD) API with group `cache` version `v1alpha1` and Kind Memcached.\nWhen prompted, enter yes `y` for creating both the resource and controller.\n\n```console\n$ operator-sdk create api --group cache --version v1alpha1 --kind Memcached --resource --controller\nWriting scaffold for you to edit...\napi/v1alpha1/memcached_types.go\ncontrollers/memcached_controller.go\n...\n```\n\nThis will scaffold the Memcached resource API at `api/v1alpha1/memcached_types.go` and the controller at `controllers/memcached_controller.go`.\n\n**Note:** In this tutorial we will be providing all the steps to show you how to implement an operator project. However, as a follow up you might want to check the [Deploy Image plugin][deploy-image-plugin-doc] with which it is possible to have the whole code generated to deploy and manage an Operand(image). To do so, you can use the command `$ operator-sdk create api --group cache --version v1alpha1 --kind Memcached --plugins=\"deploy-image/v1-alpha\" --image=memcached:1.4.36-alpine --image-container-command=\"memcached,-m=64,modern,-v\" --run-as-user=\"1001\"`\n\n**Note:** This guide will cover the default case of a single group API. If you would like to support Multi-Group APIs see the [Single Group to Multi-Group][multigroup-kubebuilder-doc] doc.\n\n#### Understanding Kubernetes APIs\n\nFor an in-depth explanation of Kubernetes APIs and the group-version-kind model, check out these [kubebuilder docs][kb-doc-gkvs].\n\nIn general, it's recommended to have one controller responsible for managing each API created for the project to\nproperly follow the design goals set by [controller-runtime][controller-runtime].\n\n### Define the API\n\nTo begin, we will represent our API by defining the `Memcached` type, which will have a `MemcachedSpec.Size` field to set the quantity of memcached instances (CRs) to be deployed, and a `MemcachedStatus.Conditions` field to store a CR's [Conditions][conditionals].\n\nDefine the API for the Memcached Custom Resource(CR) by modifying the Go type definitions at `api/v1alpha1/memcached_types.go` to have the following spec and status:\n\n```Go\n// MemcachedSpec defines the desired state of Memcached\ntype MemcachedSpec struct {\n\t// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster\n\t// Important: Run \"make\" to regenerate code after modifying this file\n\n\t// The following markers will use OpenAPI v3 schema to validate the value\n\t// More info: https://book.kubebuilder.io/reference/markers/crd-validation.html\n\t// +kubebuilder:validation:Minimum=1\n\t// +kubebuilder:validation:Maximum=5\n\t// +kubebuilder:validation:ExclusiveMaximum=false\n\n\t// Size defines the number of Memcached instances\n\t// +operator-sdk:csv:customresourcedefinitions:type=spec\n\tSize int32 `json:\"size,omitempty\"`\n\n\t// Port defines the port that will be used to init the container with the image\n\t// +operator-sdk:csv:customresourcedefinitions:type=spec\n\tContainerPort int32 `json:\"containerPort,omitempty\"`\n}\n\n// MemcachedStatus defines the observed state of Memcached\ntype MemcachedStatus struct {\n\t// Represents the observations of a Memcached's current state.\n\t// Memcached.status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\"\n\t// Memcached.status.conditions.status are one of True, False, Unknown.\n\t// Memcached.status.conditions.reason the value should be a CamelCase string and producers of specific\n\t// condition types may define expected values and meanings for this field, and whether the values\n\t// are considered a guaranteed API.\n\t// Memcached.status.conditions.Message is a human readable message indicating details about the transition.\n\t// For further information see: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties\n\n\t// Conditions store the status conditions of the Memcached instances\n\t// +operator-sdk:csv:customresourcedefinitions:type=status\n\tConditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n}\n```\n\nAdd the `+kubebuilder:subresource:status` [marker][status_marker] to add a [status subresource][status_subresource] to the CRD manifest so that the controller can update the CR status without changing the rest of the CR object:\n\n```Go\n// Memcached is the Schema for the memcacheds API\n//+kubebuilder:subresource:status\ntype Memcached struct {\n\tmetav1.TypeMeta   `json:\",inline\"`\n\tmetav1.ObjectMeta `json:\"metadata,omitempty\"`\n\n\tSpec   MemcachedSpec   `json:\"spec,omitempty\"`\n\tStatus MemcachedStatus `json:\"status,omitempty\"`\n}\n```\n\nAfter modifying the `*_types.go` file always run the following command to update the generated code for that resource type:\n\n```sh\nmake generate\n```\n\nThe above makefile target will invoke the [controller-gen][controller_tools] utility to update the `api/v1alpha1/zz_generated.deepcopy.go` file to ensure our API's Go type definitions implement the `runtime.Object` interface that all Kind types must implement.\n\n### Generating CRD manifests\n\nOnce the API is defined with spec/status fields and CRD validation markers, the CRD manifests can be generated and updated with the following command:\n\n```sh\nmake manifests\n```\n\nThis makefile target will invoke [controller-gen][controller_tools] to generate the CRD manifests at `config/crd/bases/cache.example.com_memcacheds.yaml`.\n\n### OpenAPI validation\n\nOpenAPI validation defined in a CRD ensures CRs are validated based on a set of declarative rules. All CRDs should have validation.\nSee the [OpenAPI validation][openapi-validation] doc for details.\n\n## Implement the Controller\n\nFor this example replace the generated controller file `controllers/memcached_controller.go` with the example [`memcached_controller.go`][memcached_controller] implementation. \n\n**Note**: If you used a value other than `github.com/example/memcached-operator` for repository (`--repo` flag) when running the `operator-sdk init` command, modify accordingly in the `import` block of the file.\n\n**Note**: The next two subsections explain how the controller watches resources and how the reconcile loop is triggered.\nIf you'd like to skip this section, head to the [deploy](#run-the-operator) section to see how to run the operator.\n\n### Setup a Recorder\n\nFirst, add a recorder when you initialize the Memcached reconciler in `main.go`. \n\n```Go\nif err = (&controllers.MemcachedReconciler{\n\tClient:   mgr.GetClient(),\n\tScheme:   mgr.GetScheme(),\n\tRecorder: mgr.GetEventRecorderFor(\"memcached-controller\"),\n}).SetupWithManager(mgr); err != nil {\n\tsetupLog.Error(err, \"unable to create controller\", \"controller\", \"Memcached\")\n\tos.Exit(1)\n}\n```\n\nThis recorder will be used within the reconcile method of the controller to emit events.\n\n### Resources watched by the Controller\n\nThe `SetupWithManager()` function in `controllers/memcached_controller.go` specifies how the controller is built to watch a CR and other resources that are owned and managed by that controller.\n\n```Go\nimport (\n\t...\n\tappsv1 \"k8s.io/api/apps/v1\"\n\t...\n)\n\nfunc (r *MemcachedReconciler) SetupWithManager(mgr ctrl.Manager) error {\n\treturn ctrl.NewControllerManagedBy(mgr).\n\t\tFor(&cachev1alpha1.Memcached{}).\n\t\tOwns(&appsv1.Deployment{}).\n\t\tComplete(r)\n}\n```\n\nThe `NewControllerManagedBy()` provides a controller builder that allows various controller configurations.\n\n`For(&cachev1alpha1.Memcached{})` specifies the Memcached type as the primary resource to watch. For each Memcached type Add/Update/Delete event the reconcile loop will be sent a reconcile `Request` (a namespace/name key) for that Memcached object.\n\n`Owns(&appsv1.Deployment{})` specifies the Deployments type as the secondary resource to watch. For each Deployment type Add/Update/Delete event, the event handler will map each event to a reconcile `Request` for the owner of the Deployment. Which in this case is the Memcached object for which the Deployment was created.\n\nThe dependent objects, in this case the Deployments, need to have an [Owner References](https://kubernetes.io/docs/concepts/overview/working-with-objects/owners-dependents/#owner-references-in-object-specifications) field that references their owner object. This will be added by using the method `ctrl.SetControllerReference`. [More info][k8s-doc-owner-ref]\n\nNote: The K8s api will manage the resources according to the`ownerRef` which will be properly set by using this method. Therefore, the K8s API will know that these resources, such as the Deployment to run the Memcached Operand image, depend on the custom resource for the Memcached Kind.  This allows the K8s API to delete all dependent resources when/if the custom resource is deleted. [More info][k8s-doc-deleting-cascade]\n\n### Controller Configurations\n\nThere are a number of other useful configurations that can be made when initializing a controller. For more details on these configurations consult the upstream [builder][builder_godocs] and [controller][controller_godocs] godocs.\n\n- Set the max number of concurrent Reconciles for the controller via the [`MaxConcurrentReconciles`][controller_options]  option. Defaults to 1.\n  ```Go\n  func (r *MemcachedReconciler) SetupWithManager(mgr ctrl.Manager) error {\n    return ctrl.NewControllerManagedBy(mgr).\n      For(&cachev1alpha1.Memcached{}).\n      Owns(&appsv1.Deployment{}).\n      WithOptions(controller.Options{MaxConcurrentReconciles: 2}).\n      Complete(r)\n  }\n  ```\n- Filter watch events using [predicates][event_filtering]\n- Choose the type of [EventHandler][event_handler_godocs] to change how a watch event will translate to reconcile requests for the reconcile loop. For operator relationships that are more complex than primary and secondary resources, the [`EnqueueRequestsFromMapFunc`][enqueue_requests_from_map_func] handler can be used to transform a watch event into an arbitrary set of reconcile requests.\n\n### Reconcile loop\n\nThe reconcile function is responsible for enforcing the desired CR state on the actual state of the system. It runs each time an event occurs on a watched CR or resource, and will return some value depending on whether those states match or not.\n\nIn this way, every Controller has a Reconciler object with a `Reconcile()` method that implements the reconcile loop. The reconcile loop is passed the [`Request`][request-go-doc] argument which is a Namespace/Name key used to lookup the primary resource object, Memcached, from the cache:\n\n```Go\nimport (\n\tctrl \"sigs.k8s.io/controller-runtime\"\n\n\tcachev1alpha1 \"github.com/example/memcached-operator/api/v1alpha1\"\n\t...\n)\n\nfunc (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {\n  // Lookup the Memcached instance for this reconcile request\n  memcached := &cachev1alpha1.Memcached{}\n  err := r.Get(ctx, req.NamespacedName, memcached)\n  ...\n}\n```\n\nFor a guide on Reconcilers, Clients, and interacting with resource Events, see the [Client API doc][doc_client_api].\n\nThe following are a few possible return options for a Reconciler:\n\n- With the error:\n  ```go\n  return ctrl.Result{}, err\n  ```\n- Without an error:\n  ```go\n  return ctrl.Result{Requeue: true}, nil\n  ```\n- Therefore, to stop the Reconcile, use:\n  ```go\n  return ctrl.Result{}, nil\n  ```\n- Reconcile again after X time:\n  ```go\n   return ctrl.Result{RequeueAfter: 5 * time.Minute}, nil\n   ```\n\nFor more details, check the Reconcile and its [Reconcile godoc][reconcile-godoc].\n\n### Specify permissions and generate RBAC manifests\n\nThe controller needs certain [RBAC][rbac-k8s-doc] permissions to interact with the resources it manages. These are specified via [RBAC markers][rbac_markers] like the following:\n\n```Go\n//+kubebuilder:rbac:groups=cache.example.com,resources=memcacheds,verbs=get;list;watch;create;update;patch;delete\n//+kubebuilder:rbac:groups=cache.example.com,resources=memcacheds/status,verbs=get;update;patch\n//+kubebuilder:rbac:groups=cache.example.com,resources=memcacheds/finalizers,verbs=update\n//+kubebuilder:rbac:groups=core,resources=events,verbs=create;patch\n//+kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete\n//+kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;watch\n\nfunc (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {\n  ...\n}\n```\n\nThe `ClusterRole` manifest at `config/rbac/role.yaml` is generated from the above markers via controller-gen with the following command:\n\n```sh\nmake manifests\n```\n\nNOTE: If you receive an error, please run the specified command in the error and re-run `make manifests`. \n\n## Configure the operator's image registry\n\nAll that remains is to build and push the operator image to the desired image registry.\n\nBefore building the operator image, ensure the generated Dockerfile references\nthe base image you want. You can change the default \"runner\" image `gcr.io/distroless/static:nonroot`\nby replacing its tag with another, for example `alpine:latest`, and removing\nthe `USER 65532:65532` directive.\n\nYour Makefile composes image tags either from values written at project initialization or from the CLI.\nIn particular, `IMAGE_TAG_BASE` lets you define a common image registry, namespace, and partial name\nfor all your image tags. Update this to another registry and/or namespace if the current value is incorrect.\nAfterwards you can update the `IMG` variable definition like so:\n\n```diff\n-IMG ?= controller:latest\n+IMG ?= $(IMAGE_TAG_BASE):$(VERSION)\n```\n\nOnce done, you do not have to set `IMG` or any other image variable in the CLI. The following command will\nbuild and push an operator image tagged as `example.com/memcached-operator:v0.0.1` to Docker Hub:\n\n```console\nmake docker-build docker-push\n```\n\n\n## Run the Operator\n\nThere are three ways to run the operator:\n\n- As a Go program outside a cluster\n- As a Deployment inside a Kubernetes cluster\n- Managed by the [Operator Lifecycle Manager (OLM)][doc-olm] in [bundle][quickstart-bundle] format\n\n### 1. Run locally outside the cluster\n\nThe following steps will show how to deploy the operator on the cluster. However, to run locally for development purposes and outside of a cluster use the target `make install run`.\n\nNote that by using this plugin the Operand image informed will be stored via an environment variable in the `config/manager/manager.yaml` manifest.\n\nTherefore, before running `make install run` you need to export any environment variable that you might have. Example:\n\n```sh\nexport MEMCACHED_IMAGE=\"memcached:1.4.36-alpine\"\n```\n\n### 2. Run as a Deployment inside the cluster\n\nBy default, a new namespace is created with name `<project-name>-system`, ex. `memcached-operator-system`, and will be used for the deployment.\n\nRun the following to deploy the operator. This will also install the RBAC manifests from `config/rbac`.\n\n```sh\nmake deploy\n```\n\nVerify that the memcached-operator is up and running:\n\n```console\n$ kubectl get deployment -n memcached-operator-system\nNAME                                    READY   UP-TO-DATE   AVAILABLE   AGE\nmemcached-operator-controller-manager   1/1     1            1           8m\n```\n\n### 3. Deploy your Operator with OLM\n\nFirst, install [OLM][doc-olm]:\n\n```sh\noperator-sdk olm install\n```\n\nBundle your operator, then build and push the bundle image. The `bundle` target generates a [bundle][doc-bundle]\nin the `bundle` directory containing manifests and metadata defining your operator.\n`bundle-build` and `bundle-push` build and push a bundle image defined by `bundle.Dockerfile`.\n\n```sh\nmake bundle bundle-build bundle-push\n```\n\nFinally, run your bundle. If your bundle image is hosted in a registry that is private and/or\nhas a custom CA, these [configuration steps][image-reg-config] must be complete.\n\n```sh\noperator-sdk run bundle <some-registry>/memcached-operator-bundle:v0.0.1\n```\n\nCheck out the [docs][tutorial-bundle] for a deep dive into `operator-sdk`'s OLM integration.\n\n\n## Create a Memcached CR\n\nUpdate the sample Memcached CR manifest at `config/samples/cache_v1alpha1_memcached.yaml` and define the `spec` as the following:\n\n```YAML\napiVersion: cache.example.com/v1alpha1\nkind: Memcached\nmetadata:\n  name: memcached-sample\nspec:\n  size: 3\n  containerPort: 11211\n```\n\nCreate the CR:\n\n```sh\nkubectl apply -f config/samples/cache_v1alpha1_memcached.yaml\n```\n\nEnsure that the memcached operator creates the deployment for the sample CR with the correct size:\n\n```console\n$ kubectl get deployment\nNAME                                    READY   UP-TO-DATE   AVAILABLE   AGE\nmemcached-sample                        3/3     3            3           1m\n```\n\nCheck the pods and CR status to confirm the status is updated with the memcached pod names:\n\n```console\n$ kubectl get pods\nNAME                                  READY     STATUS    RESTARTS   AGE\nmemcached-sample-6fd7c98d8-7dqdr      1/1       Running   0          1m\nmemcached-sample-6fd7c98d8-g5k7v      1/1       Running   0          1m\nmemcached-sample-6fd7c98d8-m7vn7      1/1       Running   0          1m\n```\n\n```console\n$ kubectl get memcached/memcached-sample -o yaml\napiVersion: cache.example.com/v1alpha1\nkind: Memcached\nmetadata:\n  clusterName: \"\"\n  creationTimestamp: 2018-03-31T22:51:08Z\n  generation: 0\n  name: memcached-sample\n  namespace: default\n  resourceVersion: \"245453\"\n  selfLink: /apis/cache.example.com/v1alpha1/namespaces/default/memcacheds/memcached-sample\n  uid: 0026cc97-3536-11e8-bd83-0800274106a1\nspec:\n  size: 3\nstatus:\n  nodes:\n  - memcached-sample-6fd7c98d8-7dqdr\n  - memcached-sample-6fd7c98d8-g5k7v\n  - memcached-sample-6fd7c98d8-m7vn7\n```\n\n### Update the size\n\nUpdate `config/samples/cache_v1alpha1_memcached.yaml` to change the `spec.size` field in the Memcached CR from 3 to 5:\n\n```sh\nkubectl patch memcached memcached-sample -p '{\"spec\":{\"size\": 5}}' --type=merge\n```\n\nConfirm that the operator changes the deployment size:\n\n```console\n$ kubectl get deployment\nNAME                                    READY   UP-TO-DATE   AVAILABLE   AGE\nmemcached-sample                        5/5     5            5           3m\n```\n\n### Cleanup\n\nRun the following to delete all deployed resources:\n\n```sh\nkubectl delete -f config/samples/cache_v1alpha1_memcached.yaml\nmake undeploy\n```\n\n## Next steps\n\nNext, check out the following:\n1. Validating and mutating [admission webhooks][create_a_webhook].\n1. Operator packaging and distribution with [OLM][olm-integration].\n1. The [advanced topics][advanced-topics] doc for more use cases and under-the-hood details.\n\n\n[API-groups]:https://kubernetes.io/docs/concepts/overview/kubernetes-api/#api-groups\n[activate_modules]: https://github.com/golang/go/wiki/Modules#how-to-install-and-activate-module-support\n[advanced-topics]: /docs/building-operators/golang/advanced-topics/\n[api_terms_doc]: https://book.kubebuilder.io/cronjob-tutorial/gvks.html\n[builder_godocs]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/builder#example-Builder\n[conditionals]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties\n[controller-runtime]: https://github.com/kubernetes-sigs/controller-runtime\n[controller_godocs]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/controller\n[controller_options]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/controller#Options\n[controller_tools]: https://sigs.k8s.io/controller-tools\n[crd-markers]: https://book.kubebuilder.io/reference/markers/crd-validation.html\n[create_a_webhook]: /docs/building-operators/golang/webhook\n[deploy-image-plugin-doc]: https://book.kubebuilder.io/plugins/available/deploy-image-plugin-v1-alpha\n[doc-bundle]:https://github.com/operator-framework/operator-registry/blob/v1.16.1/docs/design/operator-bundle.md#operator-bundle\n[doc-olm]:/docs/olm-integration/tutorial-bundle/#enabling-olm\n[doc-validation-schema]: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#specifying-a-structural-schema\n[doc_client_api]:/docs/building-operators/golang/references/client/\n[enqueue_requests_from_map_func]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/handler#EnqueueRequestsFromMapFunc\n[event_filtering]:/docs/building-operators/golang/references/event-filtering/\n[event_handler_godocs]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/handler#hdr-EventHandlers\n[generating-crd]: https://book.kubebuilder.io/reference/generating-crd.html\n[go_mod_wiki]: https://github.com/golang/go/wiki/Modules\n[image-reg-config]:/docs/olm-integration/cli-overview#private-bundle-and-catalog-image-registries\n[install-guide]:/docs/building-operators/golang/installation\n[k8s-doc-deleting-cascade]: https://kubernetes.io/docs/concepts/architecture/garbage-collection/#cascading-deletion\n[k8s-doc-owner-ref]: https://kubernetes.io/docs/concepts/overview/working-with-objects/owners-dependents/\n[kb-doc-gkvs]: https://book.kubebuilder.io/cronjob-tutorial/gvks.html\n[kb_api_doc]: https://book.kubebuilder.io/cronjob-tutorial/new-api.html\n[kb_controller_doc]: https://book.kubebuilder.io/cronjob-tutorial/controller-overview.html\n[kubebuilder_entrypoint_doc]: https://book.kubebuilder.io/cronjob-tutorial/empty-main.html\n[kubebuilder_layout_doc]:https://book.kubebuilder.io/cronjob-tutorial/basic-project.html\n[kubernetes-extend-api]: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/\n[legacy-quickstart-doc]:https://github.com/operator-framework/operator-sdk/blob/v0.19.x/website/content/en/docs/golang/legacy/quickstart.md\n[legacy_CLI]:https://github.com/operator-framework/operator-sdk/tree/v0.19.x/website/content/en/docs/cli\n[manager_go_doc]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Manager\n[markers]: https://book.kubebuilder.io/reference/markers.html\n[memcached_controller]: https://github.com/operator-framework/operator-sdk/blob/latest/testdata/go/v4/memcached-operator/internal/controller/memcached_controller.go\n[migration-guide]:/docs/building-operators/golang/migration\n[multigroup-kubebuilder-doc]: https://book.kubebuilder.io/migration/multi-group.html\n[olm-integration]: /docs/olm-integration\n[openapi-validation]: /docs/building-operators/golang/references/openapi-validation\n[operator_scope]:/docs/building-operators/golang/operator-scope/\n[quickstart-bundle]:/docs/olm-integration/quickstart-bundle\n[rbac-k8s-doc]: https://kubernetes.io/docs/reference/access-authn-authz/rbac/\n[rbac_markers]: https://book.kubebuilder.io/reference/markers/rbac.html\n[reconcile-godoc]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/reconcile\n[request-go-doc]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/reconcile#Request\n[result_go_doc]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/reconcile#Result\n[role-based-access-control]: https://cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control#iam-rolebinding-bootstrap\n[status_marker]: https://book.kubebuilder.io/reference/generating-crd.html#status\n[status_subresource]: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#status-subresource\n[tutorial-bundle]:/docs/olm-integration/tutorial-bundle\n"
  },
  {
    "path": "website/content/en/docs/building-operators/golang/webhook.md",
    "content": "---\ntitle: Admission Webhooks\nlinkTitle: Webhook\nweight: 30\ndescription: An in-depth walkthrough of admission webhooks.\n---\n\n## Create a validating or mutating Admission Webhook \n\nAdmission webhooks are HTTP callbacks that receive admission requests and do something with them. It is registered with Kubernetes, and\nwill be called by Kubernetes to validate or mutate a resource before being stored. There are two types of admission webhooks.\n\n#### 1. Validating admission webhook\n\nValidating webhooks can be used to perform validations that go beyond the capabilities of OpenAPI schema validation, \nsuch as ensuring a field is immutable after creation or higher level permissions checks based on the user that is making \nthe request to the API server. It can reject the request, but it cannot modify the object that they are receiving in the request.\n\n#### 2. Mutating admission webhook\n\nMutating webhooks are most frequently used for defaulting, by adding default values for unset fields in the resource on creation. \nThey can modify objects by creating a patch that will be sent back in the admission response.\n\nFor more background on Admission webhooks, refer to the [Kubebuilder documentation](https://book.kubebuilder.io/reference/admission-webhook.html) or the [official Kubernetes documentation](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/). \nYou can also refer to the [Kubebuilder webhook walkthrough](https://book.kubebuilder.io/cronjob-tutorial/webhook-implementation.html), which is similar in content to this guide. \n\n### Create Validation Webhook\n\nAs an example, let's walk through the scaffolding of a validation webhook for the sample memcached operator.\n\n```sh\n$ operator-sdk create webhook --group cache --version v1alpha1 --kind Memcached --defaulting --programmatic-validation\n```\n\nAfter, `create webhook` command, the following message will appear on the terminal. It scaffolds out `api/<version>/<kind>_webhook.go` file. In this example, it would be `api/v1alpha1/memcached_webhook.go`.\n\n```sh\nWriting kustomize manifests for you to edit...\nWriting scaffold for you to edit...\napi/v1alpha1/memcached_webhook.go\n```\n\nThe `--defaulting` flag will scaffold the resources required for a mutating webhook, and the `--programmatic-validation` flag will scaffold the resources required for a validating webhook. \nIn this case we have scaffolded both.\n\nAfter running the `create webhook` command the file structure would be:\n\n```sh\n├── Dockerfile\n├── Makefile\n├── PROJECT\n├── api\n│   └── v1alpha1\n│       ├── memcached_webhook.go\n│       ├── webhook_suite_test.go\n├── config\n│   ├── certmanager\n│   │   ├── certificate.yaml\n│   │   ├── kustomization.yaml\n│   │   └── kustomizeconfig.yaml\n│   ├── default\n│   │   ├── manager_webhook_patch.yaml\n│   │   └── webhookcainjection_patch.yaml\n│   └── webhook\n│       ├── kustomization.yaml\n│       ├── kustomizeconfig.yaml\n│       └── service.yaml\n├── go.mod\n├── go.sum\n└── main.go\n```\n\nThe scaffolded file `api/v1alpha1/memcached_webhook.go` has method signatures which need to be implemented for the validation webhook.\n\nFollowing this, there are a few steps which need to be done in your operator project to enable webhooks. This will involve:\n\n1. Implementing the required methods for Validating or Mutating webhook in `<kind>_webhook.go`. An example of such implementation is provided [here](https://book.kubebuilder.io/cronjob-tutorial/webhook-implementation.html).\n\n2. Uncommenting sections in `config/default/kustomization.yaml` to enable webhook and cert-manager configuration through kustomize. Cert-manager (or any third party solution) can be used to provision certificates for webhook server. This is explained in detail [here](https://book.kubebuilder.io/cronjob-tutorial/running-webhook.html#deploy-webhooks).\n\n**Note**\nIf OLM is being used to deploy the operator, then the section prefixed with `[CERT-MANAGER]` need not be uncommented. This is because, OLM currently handles the cert generation and rotation for webhook deployment using self-signed certs. It also does not allow users to specify the name or mount location for the certs. More documentation on this issue can be found [here](https://olm.operatorframework.io/docs/advanced-tasks/adding-admission-and-conversion-webhooks/#deploying-an-operator-with-webhooks-using-olm).\n\n### Generate webhook manifests and enable webhook deployment \n\nOnce your webhooks are implemented, all that’s left is to create the `WebhookConfiguration` manifests required to register your webhooks with Kubernetes:\n\n```sh\n$ make manifests\n```\n\n## Run your operator and webhooks \n\nThere are two ways to test your operator project with webhooks.\n\n#### Run locally\n\nTechnically, the webhooks can be run locally, but for it to work you need to generate certificates for the webhook server and store them at `/tmp/k8s-webhook-server/serving-certs/tls.{crt,key}`. For more details about running webhook locally, refer [here](https://book.kubebuilder.io/cronjob-tutorial/running.html#running-webhooks-locally).\n\n#### Run as a Deployment inside the cluster\n\nAdding webhooks does not alter deploying your operator. For instructions on deploying your operator into a cluster, refer to the [tutorial](https://sdk.operatorframework.io/docs/building-operators/golang/tutorial/#2-run-as-a-deployment-inside-the-cluster).\n"
  },
  {
    "path": "website/content/en/docs/building-operators/helm/_index.md",
    "content": "---\ntitle: Helm\nweight: 3\ndescription: Guide to building a Helm Based Operator using Operator SDK\n---\n"
  },
  {
    "path": "website/content/en/docs/building-operators/helm/installation.md",
    "content": "---\ntitle: Installation Guide\nlinkTitle: Installation\nweight: 1\n---\n\n## Install `operator-sdk`\n\nFollow the steps in the [installation guide][install-guide] to learn how to install the `operator-sdk` CLI tool.\n\n### Additional Prerequisites\n\n- [docker][docker_tool] version 17.03+.\n- [kubectl][kubectl_tool] and access to a Kubernetes cluster of a [compatible version][k8s-version-compat].\n\n\n[install-guide]:/docs/installation/\n[docker_tool]:https://docs.docker.com/install/\n[kubectl_tool]:https://kubernetes.io/docs/tasks/tools/install-kubectl/\n[k8s-version-compat]:/docs/overview#kubernetes-version-compatibility\n"
  },
  {
    "path": "website/content/en/docs/building-operators/helm/migration.md",
    "content": "---\nlink: Migrating Projects from pre-v1.0.0 to the latest release\nlinkTitle: Migrating from pre-v1.0.0 to latest\nweight: 200\ndescription: Instructions for migrating an Helm-based operator built prior to `v1.0.0` to use a Kubebuilder-style.\n---\n\n## Overview\n\nThe motivations for the new layout are related to bringing more flexibility to users and part of the process to Integrating Kubebuilder and Operator SDK. Because of this integration you may be referred to the Kubebuilder documentation [https://book.kubebuilder.io/](https://book.kubebuilder.io/) for more information about certain topics. When using this document just remember to replace `$ kubebuilder <command>` with `$ operator-sdk <command>`.\n\n**Note:** It is recommended that you have your project upgraded to the latest SDK v1.y release version before following the steps in this guide to migrate to the new layout. However, the steps might work from previous versions as well. In this case, if you find an issue which is not covered here then check the previous [Migration Guides][migration-doc] which might help out.\n\n### What was changed\n\n- The `deploy` directory was replaced with the `config` directory including a new layout of Kubernetes manifests files:\n    * CRD manifests in `deploy/crds/` are now in `config/crd/bases`\n    * CR manifests in `deploy/crds/` are now in `config/samples`\n    * Controller manifest `deploy/operator.yaml` is now in `config/manager/manager.yaml`\n    * RBAC manifests in `deploy` are now in `config/rbac/`\n\n- `build/Dockerfile` is moved to `Dockerfile` in the project root directory\n\n### What is new\n\nScaffolded projects now use:\n\n- [kustomize][kustomize] to manage Kubernetes resources needed to deploy your operator\n- A `Makefile` with helpful targets for build, test, and deployment, and to give you flexibility to tailor things to your project's needs\n- Updated metrics configuration using [kube-auth-proxy][kube-auth-proxy], a `--metrics-bind-address` flag, and [kustomize][kustomize]-based deployment of a Kubernetes `Service` and prometheus operator `ServiceMonitor`\n- Preliminary support for CLI plugins. For more info see the [plugins design document][plugins-phase1-design-doc]\n- A `PROJECT` configuration file to store information about GVKs, plugins, and help the CLI make decisions\n\nGenerated files with the default API versions:\n\n- `apiextensions/v1` for generated CRDs (`apiextensions/v1beta1` was deprecated in Kubernetes `1.16` and will be removed in `1.22`)\n- `admissionregistration.k8s.io/v1` for webhooks (`admissionregistration.k8s.io/v1beta1` was deprecated in Kubernetes `1.16` and will be removed in `1.22` )\n\n## How to migrate\n\nThe easy migration path is to initialize a new project, re-recreate APIs, then copy pre-v1.0.0 configuration files into the new project.\n\n### Prerequisites\n\n- Go through the [installation guide][install-guide].\n- Make sure your user is authorized with `cluster-admin` permissions.\n- An accessible image registry for various operator images (ex. [hub.docker.com](https://hub.docker.com/signup),\n[quay.io](https://quay.io/)) and be logged in to your command line environment.\n  - `example.com` is used as the registry Docker Hub namespace in these examples.\n  Replace it with another value if using a different registry or namespace.\n  - [Authentication and certificates][image-reg-config] if the registry is private or uses a custom CA.\n\n### Creating a new project\n\nIn Kubebuilder-style projects, CRD groups are defined using two different flags\n(`--group` and `--domain`).\n\nWhen we initialize a new project, we need to specify the domain that _all_ APIs in\nour project will share, so before creating the new project, we need to determine which\ndomain we're using for the APIs in our existing project.\n\nTo determine the domain, look at the `spec.group` field in your CRDs in the\n`deploy/crds` directory.\n\nThe domain is everything after the first DNS segment. Using `demo.example.com` as an\nexample, the `--domain` would be `example.com`.\n\nSo let's create a new project with the same domain (`example.com`):\n\n```sh\nmkdir nginx-operator\ncd nginx-operator\noperator-sdk init --plugins=helm --domain=example.com\n```\n\nNow that we have our new project initialized, we need to re-create each of our APIs.\nUsing our API example from earlier (`demo.example.com`), we'll use `demo` for the\n`--group` flag.\n\nFor `--version` and `--kind`, we use `spec.versions[0].name` and `spec.names.kind`, respectively.\n\nFor each API in the existing project, run:\n```sh\noperator-sdk create api \\\n    --group=demo \\\n    --version=<version> \\\n    --kind=<Kind> \\\n    --helm-chart=<path_to_existing_project>/helm-charts/<chart>\n```\n\n### Migrating your Custom Resource samples\n\nUpdate the CR manifests in `config/samples` with the values of the CRs in your existing project which are in `deploy/crds/<group>_<version>_<kind>_cr.yaml`\n\n### Migrating `watches.yaml`\n\nCheck if you have custom options in the `watches.yaml` file of your existing project. If so, update the new `watches.yaml` file to match. In our example, it will look like:\n\n```yaml\n# Use the 'create api' subcommand to add watches to this file.\n- group: example.com\n  version: v1alpha1\n  kind: Nginx\n  chart: helm-charts/nginx\n#+kubebuilder:scaffold:watch\n```\n\n**NOTE**: Do not remove the `+kubebuilder:scaffold:watch` [marker][marker]. It allows the tool to update the watches file when new APIs are created.\n\n### Checking RBAC Permissions\n\nIn your new project, roles are automatically generated in `config/rbac/role.yaml`.\nIf you modified these permissions manually in `deploy/role.yaml` in your existing\nproject, you need to re-apply them in `config/rbac/role.yaml`.\n\nNew projects are configured to watch all namespaces by default, so they need a `ClusterRole` to have the necessary permissions. Ensure that `config/rbac/role.yaml` remains a `ClusterRole` if you want to retain the default behavior of the new project conventions.\n\n<!--\ntodo(camilamacedo86): Create an Ansible operator scope document.\nhttps://github.com/operator-framework/operator-sdk/issues/3447\n-->\n\nThe following rules were used in earlier versions of helm-operator to automatically create and manage services and servicemonitors for metrics collection. If your operator's charts don't require these rules, they can safely be left out of the new `config/rbac/role.yaml` file:\n\n```yaml  \n  - apiGroups:\n    - monitoring.coreos.com\n    resources:\n    - servicemonitors\n    verbs:\n    - get\n    - create\n  - apiGroups:\n    - apps\n    resourceNames:\n    - nginx-operator\n    resources:\n    - deployments/finalizers\n    verbs:\n    - update\n```\n\n##### Updating your ServiceAccount\n\nNew Helm projects come with a ServiceAccount `controller-manager` in `config/rbac/service_account.yaml`.\nYour project's RoleBinding and ClusterRoleBinding subjects, and Deployments `spec.template.spec.serviceAccountName`\nthat reference a ServiceAccount already refer to this new name. When you run `make deploy`,\nyour project's name will be prepended to `controller-manager`, making it unique within a namespace,\nmuch like your old `deploy/service_account.yaml`. If you wish to use the old ServiceAccount,\nmake sure to update all RBAC bindings and your manager Deployment.\n\n### Configuring your Operator\n\nIf your existing project has customizations in `deploy/operator.yaml`, they need to be ported to\n`config/manager/manager.yaml`. If you are passing custom arguments in your deployment, make sure to also update `config/default/auth_proxy_patch.yaml`.\n\nNote that the following environment variables are no longer used.\n\n- `OPERATOR_NAME` is deprecated. It is used to define the name for a leader election config map. Operator authors should begin using `--leader-election-id` instead.\n- `POD_NAME` was used to enable a particular pod to hold the leader election lock when the Helm operator used the leader for life mechanism. Helm operator now uses controller-runtime's leader with lease mechanism, and `POD_NAME` is no longer necessary.\n\n### Exporting metrics\n\nIf you are using metrics and would like to keep them exported you will need to configure\nit in the `config/default/kustomization.yaml`. Please see the [metrics][metrics] doc to know how you can perform this setup.\n\nThe default port used by the metric endpoint binds to was changed from `:8383` to `:8080`. To continue using port `8383`, specify `--metrics-bind-address=:8383` when you start the operator.\n\n### Verify the migration\n\nThe project can now be deployed on cluster by running the command:\n\n```sh\nmake deploy IMG=example.com/nginx-operator:v0.0.1\n```\n\nYou can troubleshoot your deployment by checking container logs:\n```sh\nkubectl logs deployment.apps/nginx-operator-controller-manager -n nginx-operator-system -c manager\n```\n\nFor further steps regarding the deployment of the operator, creation of custom resources, and cleaning up of resources, see the [tutorial][tutorial-deploy].\n\n[install-guide]: /docs/building-operators/helm/installation\n[image-reg-config]:/docs/olm-integration/cli-overview#private-bundle-and-catalog-image-registries\n[kustomize]: https://github.com/kubernetes-sigs/kustomize\n[kube-auth-proxy]: https://github.com/brancz/kube-rbac-proxy\n[metrics]: https://book.kubebuilder.io/reference/metrics.html?highlight=metr#metrics\n[marker]: https://book.kubebuilder.io/reference/markers.html?highlight=markers#marker-syntax\n[migration-doc]: /docs/upgrading-sdk-version/\n[tutorial-deploy]: /docs/building-operators/helm/tutorial/#run-the-operator\n\n"
  },
  {
    "path": "website/content/en/docs/building-operators/helm/quickstart.md",
    "content": "---\ntitle: Quickstart for Helm-based Operators\nlinkTitle: Quickstart\nweight: 100\ndescription: A simple set of instructions to set up and run a Helm-based operator.\n---\n\nThis guide walks through an example of building a simple nginx-operator powered by [Helm][helm-official] using tools and libraries provided by the Operator SDK.\n\n## Prerequisites\n\n- Go through the [installation guide][install-guide].\n- Make sure your user is authorized with `cluster-admin` permissions.\n- An accessible image registry for various operator images (ex. [hub.docker.com](https://hub.docker.com/signup),\n[quay.io](https://quay.io/)) and be logged in to your command line environment.\n  - `example.com` is used as the registry Docker Hub namespace in these examples.\n  Replace it with another value if using a different registry or namespace.\n  - [Authentication and certificates][image-reg-config] if the registry is private or uses a custom CA.\n\n\n## Steps\n\n1. Create a project directory for your project and initialize the project:\n\n  ```sh\n  mkdir nginx-operator\n  cd nginx-operator\n  operator-sdk init --domain example.com --plugins helm\n  ```\n\n1. Create a simple nginx API using Helm's built-in chart boilerplate (from `helm create`):\n\n  ```sh\n  operator-sdk create api --group demo --version v1alpha1 --kind Nginx\n  ```\n\n1. Build and push your operator's image:\n\n  ```sh\n  make docker-build docker-push IMG=\"example.com/nginx-operator:v0.0.1\"\n  ```\n\n\n### OLM deployment\n\n1. Install [OLM][doc-olm]:\n\n  ```sh\n  operator-sdk olm install\n  ```\n\n1. Bundle your operator, then build and push the bundle image (defaults to `example.com/nginx-operator-bundle:v0.0.1`):\n\n  ```sh\n  make bundle IMG=\"example.com/nginx-operator:v0.0.1\"\n  make bundle-build bundle-push IMG=\"example.com/nginx-operator:v0.0.1\"\n  ```\n\n1. Run your bundle. If your bundle image is hosted in a registry that is private and/or\nhas a custom CA, these [configuration steps][image-reg-config] must be complete.\n\n  ```sh\n  operator-sdk run bundle example.com/nginx-operator-bundle:v0.0.1\n  ```\n\n1. Create a sample Nginx custom resource:\n\n  ```console\n  $ kubectl apply -f config/samples/demo_v1alpha1_nginx.yaml\n  nginx.demo.example.com/nginx-sample created\n  ```\n\n1. Uninstall the operator:\n\n  ```sh\n  operator-sdk cleanup nginx-operator\n  ```\n\n\n### Direct deployment\n\n1. Deploy your operator:\n\n  ```sh\n  make deploy IMG=\"example.com/nginx-operator:v0.0.1\"\n  ```\n\n1. Create a sample Nginx custom resource:\n\n  ```console\n  $ kubectl apply -f config/samples/demo_v1alpha1_nginx.yaml\n  nginx.demo.example.com/nginx-sample created\n  ```\n\n1. Uninstall the operator:\n\n  ```sh\n  make undeploy\n  ```\n\n## Next Steps\n\nRead the [full tutorial][tutorial] for an in-depth walkthrough of building a Helm operator.\n\n\n[helm-official]:https://helm.sh/docs/\n[install-guide]:/docs/building-operators/helm/installation\n[image-reg-config]:/docs/olm-integration/cli-overview#private-bundle-and-catalog-image-registries\n[doc-olm]:/docs/olm-integration/tutorial-bundle/#enabling-olm\n[tutorial]:/docs/building-operators/helm/tutorial/\n"
  },
  {
    "path": "website/content/en/docs/building-operators/helm/reference/_index.md",
    "content": "---\ntitle: Reference for Helm-based Operators\nlinkTitle: Reference\nweight: 400\ndescription: Detailed information about Helm-based operators\n---\n"
  },
  {
    "path": "website/content/en/docs/building-operators/helm/reference/advanced_features/_index.md",
    "content": "---\ntitle: Advanced Features of Helm-based Operators\nlinkTitle: Advanced Features\nweight: 300\ndescription: Descriptions of the advanced features of Helm-based operators\n---\n"
  },
  {
    "path": "website/content/en/docs/building-operators/helm/reference/advanced_features/annotations.md",
    "content": "---\ntitle: Custom Resource Annotations in Helm-based Operators\nlinkTitle: Custom Resource Annotations\nweight: 300\ndescription: Use custom resource annotations to configure how reconciliation works.\n---\n\n## `helm.sdk.operatorframework.io/upgrade-force`\n\nThis annotation can be set to `\"true\"` on custom resources to enable the chart to be upgraded with the\n`helm upgrade --force` option. For more info see the [Helm Upgrade documentation](https://helm.sh/docs/helm/helm_upgrade/)\nand this [explanation](https://github.com/helm/helm/issues/7082#issuecomment-559558318) of `--force` behavior.\n\n**Example**\n\n```yaml\napiVersion: example.com/v1alpha1\nkind: Nginx\nmetadata:\n  name: nginx-sample\n  annotations:\n    helm.sdk.operatorframework.io/upgrade-force: \"true\"\nspec:\n  replicaCount: 2\n  service:\n    port: 8080\n```\n\nSetting this annotation to `true` and making a change to trigger an upgrade (e.g. setting `spec.replicaCount: 3`)\nwill cause the custom resource to be reconciled and upgraded with the `force` option. This can be verified in the\nlog message when an upgrade succeeds:\n\n```\n{\"level\":\"info\",\"ts\":1591198931.1703992,\"logger\":\"helm.controller\",\"msg\":\"Upgraded release\",\"namespace\":\"helm-nginx\",\"name\":\"example-nginx\",\"apiVersion\":\"cache.example.com/v1alpha1\",\"kind\":\"Nginx\",\"release\":\"example-nginx\",\"force\":true}\n```\n\n## `helm.sdk.operatorframework.io/uninstall-wait`\n\nThis annotation can be set to `\"true\"` on custom resources to enable the deletion to wait until all the resources in the\n`status.deployedRelease.manifest` are deleted. \n\n**Example**\n\n```yaml\napiVersion: example.com/v1alpha1\nkind: Nginx\nmetadata:\n  name: nginx-sample\n  annotations:\n    helm.sdk.operatorframework.io/uninstall-wait: \"true\"\nspec:\n...\nstatus:\n  ...\n  deployedRelease:\n    manifest: |\n      ---\n      # Source: nginx/templates/serviceaccount.yaml\n      apiVersion: v1\n      kind: ServiceAccount\n      metadata:\n        name: nginx-sample\n        labels:\n          helm.sh/chart: nginx-0.1.0\n          app.kubernetes.io/name: nginx\n          app.kubernetes.io/instance: nginx-sample\n          app.kubernetes.io/version: \"1.16.0\"\n          app.kubernetes.io/managed-by: Helm\n      ---\n      # Source: nginx/templates/service.yaml\n      apiVersion: v1\n      kind: Service\n      metadata:\n        name: nginx-sample\n        labels:\n          helm.sh/chart: nginx-0.1.0\n          app.kubernetes.io/name: nginx\n          app.kubernetes.io/instance: nginx-sample\n          app.kubernetes.io/version: \"1.16.0\"\n          app.kubernetes.io/managed-by: Helm\n      spec:\n        type: ClusterIP\n        ports:\n          - port: 80\n            targetPort: http\n            protocol: TCP\n            name: http\n        selector:\n          app.kubernetes.io/name: nginx\n          app.kubernetes.io/instance: nginx-sample\n      ---\n      # Source: nginx/templates/deployment.yaml\n      apiVersion: apps/v1\n      kind: Deployment\n      metadata:\n        name: nginx-sample\n        labels:\n          helm.sh/chart: nginx-0.1.0\n          app.kubernetes.io/name: nginx\n          app.kubernetes.io/instance: nginx-sample\n          app.kubernetes.io/version: \"1.16.0\"\n          app.kubernetes.io/managed-by: Helm\n      spec:\n        replicas: 1\n        selector:\n          matchLabels:\n            app.kubernetes.io/name: nginx\n            app.kubernetes.io/instance: nginx-sample\n        template:\n          metadata:\n            labels:\n              app.kubernetes.io/name: nginx\n              app.kubernetes.io/instance: nginx-sample\n          spec:\n            serviceAccountName: nginx-sample\n            securityContext:\n              {}\n            containers:\n              - name: nginx\n                securityContext:\n                  {}\n                image: \"nginx:1.16.0\"\n                imagePullPolicy: IfNotPresent\n                ports:\n                  - name: http\n                    containerPort: 80\n                    protocol: TCP\n                livenessProbe:\n                  httpGet:\n                    path: /\n                    port: http\n                readinessProbe:\n                  httpGet:\n                    path: /\n                    port: http\n                resources:\n                  {}\n```\n\nSetting this annotation to `true` and deleting the custom resource will cause the custom resource to be reconciled\ncontinuously until all the resources in `status.deployedRelease.manifest` are deleted. This can be verified in the\nlog message when a delete has been triggered:\n\n```\n{\"level\":\"info\",\"ts\":1612294054.5845876,\"logger\":\"helm.controller\",\"msg\":\"Uninstall wait\",\"namespace\":\"default\",\"name\":\"nginx-sample\",\"apiVersion\":\"example.com/v1alpha1\",\"kind\":\"Nginx\",\"release\":\"nginx-sample\"}\n\n```\n\n## `helm.sdk.operatorframework.io/reconcile-period`\n\nWhile running a Helm-based operator, the reconcile-period can be specified through the custom resource's annotations under the `helm.sdk.operatorframework.io/reconcile-period` key. \nThis feature guarantees that an operator will get reconciled, at minimum, in the specified interval of time. In other words, it ensures that the cluster will not go longer\nthan the specified reconcile-period without being reconciled. However, the cluster may be reconciled at any moment if there are changes detected in the desired state.\n\nThe reconcile period can be specified in the custom resource's annotations in the following manner: \n\n```sh\n...\nmetadata:\n  name: nginx-sample\n  annotations:\n    helm.sdk.operatorframework.io/reconcile-period: 5s\n...\n```\n\nThe value that is present under this key must be in the h/m/s format. For example, 1h2m4s, 3m0s, 4s are all valid values, but 1x3m9s is invalid. \n\n**NOTE**: This is just one way of specifying the reconcile period for Helm-based operators. There are two other ways: using the `--reconcile-period` command-line flag and under the 'reconcilePeriod' key in the watches.yaml file. If these three methods are used simultaneously to specify reconcile period (which they should not be), the order of precedence is as follows: \nCustom Resource Annotations > watches.yaml > command-line flag.\n\n## `helm.sdk.operatorframework.io/rollback-force`\n\nWhenever a helm-based operator encounters an error during reconcilliation, by default, it would attempt to perform a rollback with the `--force` option. While this works as expected in most scenarios, there are a few edge cases where performing a rollback with `--force` could have undesired side effects.\n\n```sh\n...\nmetadata:\n  name: nginx-sample\n  annotations:\n    helm.sdk.operatorframework.io/rollback-force: false\n...\n```\n\nAdding annotation to the custom resource, `helm.sdk.operatorframework.io/rollback-force: false` therefore allows a user, to change the default behavior of the helm-based operator whereby, rollbacks will be performed without the `--force` option whenever an error is encountered."
  },
  {
    "path": "website/content/en/docs/building-operators/helm/reference/advanced_features/max_concurrent_reconciles.md",
    "content": "---\ntitle: Maximum Concurrent Reconciles in Helm-based Operators\nlinkTitle: Maximum Concurrent Reconciles\nweight: 200\ndescription: Increase concurrency of custom reconciliation to scale your operator to large clusters.\n---\n\nDepending on the number of CRs your operator is managing, it might be necessary to tune the maximum number of concurrent reconciles to ensure timely reconciliations. The `--max-concurrent-reconciles` flag can be used to override the default max concurrent reconciles, which by default is the number of CPUs on the node on which the operator is running. For example:\n\n```sh\n$ cat config/manager/manager.yaml\n...\n    spec:\n      containers:\n      - args:\n        - manager\n        - --max-concurrent-reconciles=10\n...\n```\n\nWhile running locally, this flag can also be added to the helm binary. For example, running `helm-operator` binary with the above mentioned flag would give us a similar result:\n```\nhelm-operator --max-concurrent-reconciles=10\n```\n\n**NOTE**: If you're using the default scaffolding, it is necessary to also apply this change to the `config/default/manager_metrics_patch.yaml` file. \nThis file is a `kustomize` patch to the operator deployment that configures metrics to require authorization for accessing \nyour operator metrics. When `kustomize` applies this patch, it overrides the args defined in `config/manager/manager.yaml`\n"
  },
  {
    "path": "website/content/en/docs/building-operators/helm/reference/advanced_features/override_values.md",
    "content": "---\ntitle: Setting Override Values in Helm-based Operators\nlinkTitle: Override Values\nweight: 100\ndescription: Learn how to set override values and pass environment variables to your Helm chart.\n---\n\nSometimes it is useful to pass down environment variables from the Operators `Deployment`\nall the way to the helm charts templates. This allows the Operator to be configured at a global\nlevel at runtime. This is new compared to dealing with the helm CLI\nas they usually don't have access to any environment variables in the context of Tiller (helm v2)\nor the helm binary (helm v3) for security reasons.\n\nWith the helm Operator this becomes possible by override values. This enforces that certain\ntemplate values provided by the chart's default `values.yaml` or by a CR spec are always set\nwhen rendering the chart. If the value is set by a CR it gets overridden by the global override value.\nThe override value can be static but can also refer to an environment variable and use go templates.\nUsing override values is currently the only way to pass down environment variables to the chart.\n\nAn example use case of this is when your helm chart references container images by chart variables,\nwhich is a good practice.\nIf your Operator is deployed in a disconnected environment (no network access to the default images\nlocation) you can use this mechanism to set them globally at the Operator level using environment variables\nversus individually per CR / chart release.\n\n> Note that it is strongly recommended to reference container images in your chart by helm variables\n> and then also associate these with an environment variable of your Operator like shown below.\n> This allows your Operator to be mirrored for offline usage when packaged for OLM.\n\n## Basic usage\n\nTo configure your operator with override values, add an `overrideValues` map to your\n`watches.yaml` file for the GVK and chart you need to override. For example, to change\nthe repository used by the nginx chart, you would update your `watches.yaml` to the\nfollowing:\n\n```yaml\n# Use the 'create api' subcommand to add watches to this file.\n- group: example.com\n  version: v1alpha1\n  kind: Nginx\n  chart: helm-charts/nginx\n  overrideValues:\n    image.repository: quay.io/mycustomrepo/myimage\n```\n\nBy setting `image.repository` to `quay.io/mycustomrepo/myimage` you are ensuring that\n`quay.io/mycustomrepo/myimage` will always be used instead of the chart's default repository\n(`nginx`). If the CR attempts to set this value, it will be ignored.\n\n## Using environment variables\n\nIt is also possible to reference environment variables in the `overrideValues` section:\n\n```yaml\n  overrideValues:\n    image.repository: $IMAGE_REPOSITORY # or ${IMAGE_REPOSITORY}\n```\n\nBy using an environment variable reference in `overrideValues` you enable these override\nvalues to be set at runtime by configuring the environment variable on the\noperator deployment. For example, in `config/manager/manager.yaml` you could add the\nfollowing snippet to the container spec:\n\n```yaml\nenv:\n  - name: IMAGE_REPOSITORY\n    value: quay.io/mycustomrepo/myimage\n```\n\nIf an environment variable reference is listed in `overrideValues`, but is not present\nin the environment when the operator runs, it will resolve to an empty string and\noverride all other values. Therefore, these environment variables should _always_ be\nset. It is suggested to update the Dockerfile to set these environment variables to\nthe same defaults that are defined by the chart.\n\n## Using Go templates\n\nLastly, you can use Go `text/template` strings along with\n[slim-sprig](https://go-task.github.io/slim-sprig/) functions to provide even more\nflexibility when building override values.\n\nFor example, consider a situation where your operator has an environment variable,\n`$IMAGE`, set to `quay.io/mycustomrepo/myimage:latest`. You can use sprig template\nfunctions to split that environment variable into its repo and tag:\n\n```yaml\n  overrideValues:\n    image.repository: '{{ (\"$IMAGE\" | split \":\")._0 }}'\n    image.tag: '{{ (\"$IMAGE\" | split \":\")._1 }}'\n```\n\nThe resulting override values sent to the helm installation would look like:\n\n```yaml\n  overrideValues:\n    image.repository: quay.io/mycustomrepo/myimage\n    image.tag: latest\n```\n\n## Event generation\n\nTo warn users that their CR settings may be ignored, the Helm operator creates events on\nthe CR that include the name and value of each overridden value. For example:\n\n```\n$ kubectl describe nginxes.example.com\n...\nEvents:\n  Type     Reason               Age   From              Message\n  ----     ------               ----  ----              -------\n  Warning  OverrideValuesInUse  1m    nginx-controller  Chart value \"image.repository\" overridden to \"quay.io/mycustomrepo\" by operator's watches.yaml\n```\n"
  },
  {
    "path": "website/content/en/docs/building-operators/helm/reference/proxy-vars.md",
    "content": "---\ntitle: Proxy Friendly Operators\nlinkTitle: Proxy Vars\nweight: 20\n---\n\nProxy-friendly Operators should inspect their environment for the\nstandard proxy variables (`HTTPS_PROXY`, `HTTP_PROXY`, and `NO_PROXY`)\nand pass the values to Operands.\n\nThis can be accomplished by modifying the `watches.yaml` to include the\noverrides based on an environment variable:\n\n```yaml\n- group: demo.example.com\n  version: v1alpha1\n  kind: Nginx\n  chart: helm-charts/nginx\n  overrideValues:\n    proxy.http: $HTTP_PROXY\n#+kubebuilder:scaffold:watch\n```\n\nNote: This example assumes that `proxy.http` is included in your chart's\n`Values.yaml`. The nginx tutorial does not have this value, but you can\nadd to the `helmcharts/nginx/Values.yaml`:\n\n```yaml\nproxy:\n  http: \"\"\n  https: \"\"\n  no_proxy: \"\"\n```\n\nYou will also need to make sure the chart template supports the usage of\nthese values. Using the nginx tutorial, edit\n`helm-charts/nginx/templates/deployment.yaml`\n\n```yaml\ncontainers:                                                                                                                                                                                                                             \n  - name: {{ .Chart.Name }}                                                                                                                                                                                                             \n    securityContext:                                                                                                                                                                                                                    \n      {{- toYaml .Values.securityContext | nindent 12 }}                                                                                                                                                                                \n    image: \"{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}\"                                                                                                                                         \n    imagePullPolicy: {{ .Values.image.pullPolicy }}                                                                                                                                                                                     \n    env:                                                                                                                                                                                                                                \n      - name: http_proxy                                                                                                                                                                                                                \n        value: \"{{ .Values.proxy.http }}\"  \n```\n\n\n\nYou can set the environment variable on the Operator deployment. Using\nthe nginx tutorial, edit `config/manager/manager.yaml`:\n\n```yaml\ncontainers:\n - args:\n   - --leader-elect\n   - --leader-election-id=helm-proxy-demo\n   image: controller:latest\n   name: manager\n   env:\n     - name: \"HTTP_PROXY\"\n       value: \"http_proxy_test\"\n```\n"
  },
  {
    "path": "website/content/en/docs/building-operators/helm/reference/watches.md",
    "content": "---\ntitle: Define Watches in Helm-based operators\nlinkTitle: Define Watches\nweight: 200\ndescription: Specification for the `watches.yaml` file in Helm-based operators.\n---\n\nThe Watches file contains a list of mappings from custom resources, identified\nby it's Group, Version, and Kind, to a Helm chart. The Operator\nexpects this mapping file in a predefined location: `/opt/helm/watches.yaml`\n\nThe follow tables describes the fields in an entry in `watches.yaml`:\n\n| Field                   | Description |\n| :---------------------- | :---------- |\n| group                   | The group of the Custom Resource that you will be watching. |\n| version                 | The version of the Custom Resource that you will be watching. |\n| kind                    | The kind of the Custom Resource that you will be watching. |\n| chart                   | The path to the helm chart to use when reconciling this GVK.  |\n| watchDependentResources | Enable watching resources that are created by helm (default: `true`). |\n| overrideValues          | Values to be used for overriding Helm chart's defaults. For additional information see the [reference doc][override-values]. |\n| selector                | The conditions that a resource's labels must satisfy in order to get reconciled. For additional information see [labels and selectors documentation][label-selector-doc]. |\n| dryRunOption            | The helm dry-run method to use when comparing manifests. Set to `server` to ensure `lookup()` functions are evaluated (default: `client/none`) |\n\n\nFor reference, here is an example of a simple `watches.yaml` file:\n\n```yaml\n# Use the 'create api' subcommand to add watches to this file.\n- group: foo.example.com\n  version: v1alpha1\n  kind: Foo\n  chart: helm-charts/foo\n  overrideValues:\n    image.repository: quay.io/mycustomrepo\n  watchDependentResources: false\n  selector:\n    matchExpressions:\n     - {key: testLabel, operator: Exists, values: []}\n  dryRunOption: server\n```\n\n[override-values]: /docs/building-operators/helm/reference/advanced_features/override_values/\n[label-selector-doc]: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/\n"
  },
  {
    "path": "website/content/en/docs/building-operators/helm/tutorial.md",
    "content": "---\ntitle: Helm Operator Tutorial\nlinkTitle: Tutorial\nweight: 200\ndescription: An in-depth walkthrough of building and running a Helm-based operator.\n---\n\n**NOTE:** If your project was created with an `operator-sdk` version prior to `v1.0.0`\nplease [migrate][migration-guide], or consult the [legacy docs][legacy-quickstart-doc].\n\n## Prerequisites\n\n- Go through the [installation guide][install-guide].\n- Make sure your user is authorized with `cluster-admin` permissions.\n- An accessible image registry for various operator images (ex. [hub.docker.com](https://hub.docker.com/signup),\n[quay.io](https://quay.io/)) and be logged in to your command line environment.\n  - `example.com` is used as the registry Docker Hub namespace in these examples.\n  Replace it with another value if using a different registry or namespace.\n  - [Authentication and certificates][image-reg-config] if the registry is private or uses a custom CA.\n\n## Overview\n\nWe will create a sample project to let you know how it works and this sample will:\n\n- Create an Nginx Deployment if it doesn't exist\n- Ensure that the Deployment size is the same as specified by the Nginx CR spec\n\n## Create a new project\n\nUse the CLI to create a new Helm-based nginx-operator project:\n\n```sh\nmkdir nginx-operator\ncd nginx-operator\noperator-sdk init --plugins helm --domain example.com --group demo --version v1alpha1 --kind Nginx\n```\n\nThis creates the nginx-operator project specifically for watching the\nNginx resource with APIVersion `demo.example.com/v1alpha1` and Kind\n`Nginx`.\n\nFor Helm-based projects, `operator-sdk init` also generates the RBAC rules\nin `config/rbac/role.yaml` based on the resources that would be deployed by the\nchart's default manifest. Be sure to double check that the rules generated\nin `config/rbac/role.yaml` meet the operator's permission requirements.\n\nTo learn more about the project directory structure, see the\n[project layout][layout-doc] doc.\n\n### Use an existing chart\n\nInstead of creating your project with a boilerplate Helm chart, you can also use `--helm-chart`, `--helm-chart-repo`, and `--helm-chart-version` to use an existing chart, either from your local filesystem or a remote chart repository.\n\nIf `--helm-chart` is specified, the `--group`, `--version`, and `--kind` flags become optional. If left unset, the default will be:\n\n| Flag | Value |\n| :--- | :---    |\n| domain | my.domain |\n| group | charts |\n| kind |  deduce from the specified chart |\n| version | v1alpha1 |\n\nIf `--helm-chart` is a local chart archive (e.g `example-chart-1.2.0.tgz`) or directory,\nit will be validated and unpacked or copied into the project.\n\nOtherwise, the SDK will attempt to fetch the specified helm chart from a remote repository.\n\nIf a custom repository URL is not specified by `--helm-chart-repo`, the following chart reference formats are supported:\n\n- `<repoName>/<chartName>`: Fetch the helm chart named `chartName` from the helm\n                            chart repository named `repoName`, as specified in the\n                           `$HELM_HOME/repositories/repositories.yaml` file.\n                            Use [`helm repo add`](https://helm.sh/docs/helm/helm_repo_add) to configure this file.\n\n- `<url>`: Fetch the helm chart archive at the specified URL.\n\nIf a custom repository URL is specified by `--helm-chart-repo`, the only supported format for `--helm-chart` is:\n\n- `<chartName>`: Fetch the helm chart named `chartName` in the helm chart repository\n                 specified by the `--helm-chart-repo` URL.\n\nIf `--helm-chart-version` is not set, the SDK will fetch the latest available version of the helm chart. Otherwise, it will fetch the specified version. The option `--helm-chart-version` is not used when `--helm-chart` itself refers to a specific version, for example when it is a local path or a URL.\n\n**Note:** For more details and examples run `operator-sdk init --plugins helm --help`.\n\n<!--\ntodo(camilamacedo86): Create an Ansible operator scope document.\nhttps://github.com/operator-framework/operator-sdk/issues/3447\n-->\n\n\n## Customize the operator logic\n\nFor this example the nginx-operator will execute the following\nreconciliation logic for each `Nginx` Custom Resource (CR):\n\n- Create an nginx Deployment if it doesn't exist\n- Create an nginx Service if it doesn't exist\n- Create an nginx Ingress if it is enabled and doesn't exist\n- Ensure that the Deployment, Service, and optional Ingress match the desired configuration (e.g. replica count, image, service type, etc) as specified by the `Nginx` CR\n\n### Watch the Nginx CR\n\nBy default, the nginx-operator watches `Nginx` resource events as shown\nin `watches.yaml` and executes Helm releases using the specified chart:\n\n```yaml\n# Use the 'create api' subcommand to add watches to this file.\n- group: demo\n  version: v1alpha1\n  kind: Nginx\n  chart: helm-charts/nginx\n#+kubebuilder:scaffold:watch\n```\n\n### Reviewing the Nginx Helm Chart\n\nWhen a Helm operator project is created, the SDK creates an example Helm chart\nthat contains a set of templates for a simple Nginx release.\n\nFor this example, we have templates for deployment, service, and ingress\nresources, along with a `NOTES.txt` template, which Helm chart developers use\nto convey helpful information about a release.\n\nIf you aren't already familiar with Helm Charts, take a moment to review\nthe [Helm Chart developer documentation][helm-charts].\n\n### Understanding the Nginx CR spec\n\nHelm uses a concept called [values][helm-values] to provide customizations\nto a Helm chart's defaults, which are defined in the Helm chart's `values.yaml`\nfile.\n\nOverriding these defaults is as simple as setting the desired values in the CR\nspec. Let's use the number of replicas as an example.\n\nFirst, inspecting `helm-charts/nginx/values.yaml`, we see that the chart has a\nvalue called `replicaCount` and it is set to `1` by default. If we want to have\n2 nginx instances in our deployment, we would need to make sure our CR spec\ncontained `replicaCount: 2`.\n\nUpdate `config/samples/demo_v1alpha1_nginx.yaml` to look like the following:\n\n```yaml\napiVersion: demo.example.com/v1alpha1\nkind: Nginx\nmetadata:\n  name: nginx-sample\nspec:\n  replicaCount: 2\n```\n\nSimilarly, we see that the default service port is set to `80`, but we would\nlike to use `8080`, so we'll again update `config/samples/demo_v1alpha1_nginx.yaml`\nby adding the service port override:\n\n```yaml\napiVersion: demo.example.com/v1alpha1\nkind: Nginx\nmetadata:\n  name: nginx-sample\nspec:\n  replicaCount: 2\n  service:\n    port: 8080\n```\n\nAs you may have noticed, the Helm operator simply applies the entire spec as if\nit was the contents of a values file, just like `helm install -f ./overrides.yaml`\nworks.\n\n## Configure the operator's image registry\n\nAll that remains is to build and push the operator image to the desired image registry.\nYour Makefile composes image tags either from values written at project initialization or from the CLI.\nIn particular, `IMAGE_TAG_BASE` lets you define a common image registry, namespace, and partial name\nfor all your image tags. Update this to another registry and/or namespace if the current value is incorrect.\nAfterwards you can update the `IMG` variable definition like so:\n\n```diff\n-IMG ?= controller:latest\n+IMG ?= $(IMAGE_TAG_BASE):$(VERSION)\n```\n\nOnce done, you do not have to set `IMG` or any other image variable in the CLI. The following command will\nbuild and push an operator image tagged as `example.com/nginx-operator:v0.0.1` to Docker Hub:\n\n```console\nmake docker-build docker-push\n```\n\n\n## Run the operator\n\nThere are three ways to run the operator:\n\n- As a Go program outside a cluster\n- As a Deployment inside a Kubernetes cluster\n- Managed by the [Operator Lifecycle Manager (OLM)][doc-olm] in [bundle][tutorial-bundle] format\n\n### 1. Run locally outside the cluster\n\nExecute the following command, which installs your CRDs and runs the manager locally:\n\n```sh\nmake install run\n```\n\n### 2. Run as a Deployment inside the cluster\n\nBy default, a new namespace is created with the name `<project-name>-system`, ex. `nginx-operator-system`, and will be used for the deployment.\n\nRun the following to deploy the operator. This will also install the RBAC manifests from `config/rbac`.\n\n```sh\nmake deploy\n```\n\nVerify that the nginx-operator is up and running:\n\n```console\n$ kubectl get deployment -n nginx-operator-system\nNAME                                    READY   UP-TO-DATE   AVAILABLE   AGE\nnginx-operator-controller-manager   1/1     1            1           8m\n```\n\n### 3. Deploy your Operator with OLM\n\nFirst, install [OLM][doc-olm]:\n\n```sh\noperator-sdk olm install\n```\n\nBundle your operator, then build and push the bundle image. The `bundle` target generates a [bundle][doc-bundle]\nin the `bundle` directory containing manifests and metadata defining your operator.\n`bundle-build` and `bundle-push` build and push a bundle image defined by `bundle.Dockerfile`.\n\n```sh\nmake bundle bundle-build bundle-push\n```\n\nFinally, run your bundle. If your bundle image is hosted in a registry that is private and/or\nhas a custom CA, these [configuration steps][image-reg-config] must be completed.\n\n```sh\noperator-sdk run bundle example.com/nginx-operator-bundle:v0.0.1\n```\n\nCheck out the [docs][tutorial-bundle] for a deep dive into the `operator-sdk`'s OLM integration.\n\n\n## Create a Nginx CR\n\nCreate the nginx CR that we modified earlier:\n\n```sh\nkubectl apply -f config/samples/demo_v1alpha1_nginx.yaml\n```\n\nEnsure that the nginx-operator creates the deployment for the CR:\n\n```console\n$ kubectl get deployment\nNAME           READY   UP-TO-DATE   AVAILABLE   AGE\nnginx-sample   2/2     2            2           2m13s\n```\n\nCheck the pods to confirm 2 replicas were created:\n\n```console\n$ kubectl get pods\nNAME                                                   READY   STATUS    RESTARTS   AGE\nnginx-sample-c786bfdcf-4g6md                           1/1     Running   0          81s\nnginx-sample-c786bfdcf-6bhmx                           1/1     Running   0          81s\n```\n\nCheck that the service port is set to `8080`:\n\n```console\n$ kubectl get service\nNAME                                      TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE\nnginx-sample                              ClusterIP   10.96.26.3   <none>        8080/TCP   1m\n```\n\n### Update the replicaCount and remove the port\n\nChange the `spec.replicaCount` field from 2 to 3, remove the `spec.service`\nfield:\n\n```console\n$ cat config/samples/demo_v1alpha1_nginx.yaml\napiVersion: demo.example.com/v1alpha1\nkind: Nginx\nmetadata:\n  name: nginx-sample\nspec:\n  replicaCount: 3\n```\n\nAnd apply the change:\n\n```sh\nkubectl apply -f config/samples/demo_v1alpha1_nginx.yaml\n```\n\nConfirm that the operator changes the deployment size:\n\n```console\n$ kubectl get deployment\nNAME                                           DESIRED   CURRENT   UP-TO-DATE     AGE\nnginx-sample                                   3/3       3            3           7m29s\n```\n\nCheck that the service port is set to the default (`80`):\n\n```console\n$ kubectl get service\nNAME                                      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)  AGE\nnginx-sample                              ClusterIP   10.96.152.76    <none>        80/TCP   7m54s\n```\n\n### Troubleshooting\n\nUse the following command to check the operator logs.\n\n```sh\nkubectl logs deployment.apps/nginx-operator-controller-manager  -n nginx-operator-system -c manager\n```\n\nUse the following command to check the CR status and events.\n\n```sh\nkubectl describe nginxes.demo.example.com\n```\n\n### Cleanup\n\nClean up the resources:\n\n```sh\nkubectl delete -f config/samples/demo_v1alpha1_nginx.yaml\n```\n\n**Note:** Make sure the above custom resource has been deleted before proceeding to\nrun `make undeploy`, as helm-operator's controller adds finalizers to the custom resources.\nOtherwise your cluster may have dangling custom resource objects that cannot be deleted.\n\n```sh\nmake undeploy\n```\n\n## Next steps\n\nNext, check out the following:\n1. Operator packaging and distribution with [OLM][olm-integration].\n1. The [advanced features][advanced-features] doc for more use cases and under-the-hood details.\n\n\n[legacy-quickstart-doc]:https://github.com/operator-framework/operator-sdk/tree/v0.19.x/website/content/en/docs/helm/quickstart.md\n[migration-guide]:/docs/building-operators/helm/migration\n[install-guide]:/docs/building-operators/helm/installation\n[image-reg-config]:/docs/olm-integration/cli-overview#private-bundle-and-catalog-image-registries\n[layout-doc]: /docs/overview/project-layout\n[helm-charts]:https://helm.sh/docs/topics/charts/\n[helm-values]:https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing\n[helm-official]:https://helm.sh/docs/\n[tutorial-bundle]:/docs/olm-integration/tutorial-bundle\n[doc-olm]:/docs/olm-integration/tutorial-bundle/#enabling-olm\n[olm-integration]:/docs/olm-integration\n[advanced-features]:/docs/building-operators/helm/reference/advanced_features\n"
  },
  {
    "path": "website/content/en/docs/cli/_index.md",
    "content": "---\ntitle: Command Line Interface\nlinkTitle: Commands\nweight: 7\ndescription: Working with the operator-sdk CLI\n---\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk.md",
    "content": "---\ntitle: \"operator-sdk\"\n---\n## operator-sdk\n\n\n\n### Synopsis\n\nCLI tool for building Kubernetes extensions and tools.\n\n\n```\noperator-sdk [flags]\n```\n\n### Examples\n\n```\nThe first step is to initialize your project:\n    operator-sdk init [--plugins=<PLUGIN KEYS> [--project-version=<PROJECT VERSION>]]\n\n<PLUGIN KEYS> is a comma-separated list of plugin keys from the following table\nand <PROJECT VERSION> a supported project version for these plugins.\n\n                             Plugin keys | Supported project versions\n-----------------------------------------+----------------------------\n     ansible.sdk.operatorframework.io/v1 |                          3\n deploy-image.go.kubebuilder.io/v1-alpha |                          3\n                    go.kubebuilder.io/v4 |                          3\n         grafana.kubebuilder.io/v1-alpha |                          3\n        helm.sdk.operatorframework.io/v1 |                          3\n\nFor more specific help for the init command of a certain plugins and project version\nconfiguration please run:\n    operator-sdk init --help --plugins=<PLUGIN KEYS> [--project-version=<PROJECT VERSION>]\n\nDefault plugin keys: \"go.kubebuilder.io/v4\"\nDefault project version: \"3\"\n\n```\n\n### Options\n\n```\n  -h, --help                     help for operator-sdk\n      --plugins strings          plugin keys to be used for this subcommand execution\n      --project-version string   project version (default \"3\")\n      --verbose                  Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk alpha](../operator-sdk_alpha)\t - Alpha-stage subcommands\n* [operator-sdk bundle](../operator-sdk_bundle)\t - Manage operator bundle metadata\n* [operator-sdk cleanup](../operator-sdk_cleanup)\t - Clean up an Operator deployed with the 'run' subcommand\n* [operator-sdk completion](../operator-sdk_completion)\t - Load completions for the specified shell\n* [operator-sdk create](../operator-sdk_create)\t - Scaffold a Kubernetes API or webhook\n* [operator-sdk edit](../operator-sdk_edit)\t - Update the project configuration\n* [operator-sdk generate](../operator-sdk_generate)\t - Invokes a specific generator\n* [operator-sdk init](../operator-sdk_init)\t - Initialize a new project\n* [operator-sdk olm](../operator-sdk_olm)\t - Manage the Operator Lifecycle Manager installation in your cluster\n* [operator-sdk pkgman-to-bundle](../operator-sdk_pkgman-to-bundle)\t - Migrates packagemanifests to bundles\n* [operator-sdk run](../operator-sdk_run)\t - Run an Operator in a variety of environments\n* [operator-sdk scorecard](../operator-sdk_scorecard)\t - Runs scorecard\n* [operator-sdk version](../operator-sdk_version)\t - Print the operator-sdk version\n\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk_alpha.md",
    "content": "---\ntitle: \"operator-sdk alpha\"\n---\n## operator-sdk alpha\n\nAlpha-stage subcommands\n\n### Synopsis\n\nAlpha subcommands are for unstable features.\n\n- Alpha subcommands are exploratory and may be removed without warning.\n- No backwards compatibility is provided for any alpha subcommands.\n\n### Options\n\n```\n  -h, --help   help for alpha\n```\n\n### Options inherited from parent commands\n\n```\n      --plugins strings   plugin keys to be used for this subcommand execution\n      --verbose           Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk](../operator-sdk)\t - \n* [operator-sdk alpha config-3alpha-to-3](../operator-sdk_alpha_config-3alpha-to-3)\t - Convert your PROJECT config file from version 3-alpha to 3\n* [operator-sdk alpha generate](../operator-sdk_alpha_generate)\t - Re-scaffold an existing Kuberbuilder project\n\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk_alpha_config-3alpha-to-3.md",
    "content": "---\ntitle: \"operator-sdk alpha config-3alpha-to-3\"\n---\n## operator-sdk alpha config-3alpha-to-3\n\nConvert your PROJECT config file from version 3-alpha to 3\n\n### Synopsis\n\nYour PROJECT file contains config data specified by some version.\nThis version is not a kubernetes-style version. In general, alpha and beta config versions\nare unstable and support for them is dropped once a stable version is released.\nThe 3-alpha version has recently become stable (3), and therefore is no longer\nsupported by operator-sdk v1.5+. This command is intended to migrate 3-alpha PROJECT files\nto 3 with as few manual modifications required as possible.\n\n\n```\noperator-sdk alpha config-3alpha-to-3 [flags]\n```\n\n### Options\n\n```\n  -h, --help   help for config-3alpha-to-3\n```\n\n### Options inherited from parent commands\n\n```\n      --plugins strings   plugin keys to be used for this subcommand execution\n      --verbose           Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk alpha](../operator-sdk_alpha)\t - Alpha-stage subcommands\n\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk_alpha_generate.md",
    "content": "---\ntitle: \"operator-sdk alpha generate\"\n---\n## operator-sdk alpha generate\n\nRe-scaffold an existing Kuberbuilder project\n\n### Synopsis\n\nIt's an experimental feature that has the purpose of re-scaffolding the whole project from the scratch \nusing the current version of KubeBuilder binary available.\n# make sure the PROJECT file is in the 'input-dir' argument, the default is the current directory.\n$ kubebuilder alpha generate --input-dir=\"./test\" --output-dir=\"./my-output\"\nThen we will re-scaffold the project by Kubebuilder in the directory specified by 'output-dir'.\n\t\t\n\n```\noperator-sdk alpha generate [flags]\n```\n\n### Options\n\n```\n  -h, --help                help for generate\n      --input-dir string    Specifies the full path to a Kubebuilder project file. If not provided, the current working directory is used.\n      --output-dir string   Specifies the full path where the scaffolded files will be output. Defaults to a directory within the current working directory.\n```\n\n### Options inherited from parent commands\n\n```\n      --plugins strings   plugin keys to be used for this subcommand execution\n      --verbose           Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk alpha](../operator-sdk_alpha)\t - Alpha-stage subcommands\n\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk_bundle.md",
    "content": "---\ntitle: \"operator-sdk bundle\"\n---\n## operator-sdk bundle\n\nManage operator bundle metadata\n\n### Synopsis\n\nManage bundle builds, bundle metadata generation, and bundle validation.\nAn operator bundle is a portable operator packaging format understood by Kubernetes\nnative software, like the Operator Lifecycle Manager.\n\nMore information about operator bundles and metadata:\nhttps://github.com/operator-framework/operator-registry/blob/master/docs/design/operator-bundle.md\n\nMore information about the integration with OLM via SDK:\nhttps://sdk.operatorframework.io/docs/olm-integration\n\n\n### Options\n\n```\n  -h, --help   help for bundle\n```\n\n### Options inherited from parent commands\n\n```\n      --plugins strings   plugin keys to be used for this subcommand execution\n      --verbose           Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk](../operator-sdk)\t - \n* [operator-sdk bundle validate](../operator-sdk_bundle_validate)\t - Validate an operator bundle\n\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk_bundle_validate.md",
    "content": "---\ntitle: \"operator-sdk bundle validate\"\n---\n## operator-sdk bundle validate\n\nValidate an operator bundle\n\n### Synopsis\n\nThe 'operator-sdk bundle validate' command can validate both content and format of an operator bundle\nimage or an operator bundle directory on-disk containing operator metadata and manifests. This command will exit\nwith an exit code of 1 if any validation errors arise, and 0 if only warnings arise or all validators pass.\n\nA valid bundle is defined by the bundle spec (linked below), therefore the default validator ensures a bundle conforms to\nthat spec. If you want to ensure that your bundle is valid for an optional superset of requirements such as to those\nrequired to publish your operator on operatorhub.io, then you will need to run one or more supported optional validators.\nSet '--list-optional' to list which optional validators are supported, and how they are grouped by label.\n\nMore information about operator bundles and metadata:\nhttps://github.com/operator-framework/operator-registry/blob/master/docs/design/operator-bundle.md\n\nNOTE: if validating an image, the image must exist in a remote registry, not just locally.\n\n\n```\noperator-sdk bundle validate [flags]\n```\n\n### Examples\n\n```\nThis example assumes you either have a *pullable* bundle image,\nor something similar to the following operator bundle layout present locally:\n\n  $ tree ./bundle\n  ./bundle\n  ├── manifests\n  │   ├── cache.my.domain_memcacheds.yaml\n  │   └── memcached-operator.clusterserviceversion.yaml\n  └── metadata\n      └── annotations.yaml\n\nTo validate a local bundle:\n\n  $ operator-sdk bundle validate ./bundle\n\nTo build and validate a *pullable* bundle image:\n\n  $ operator-sdk bundle validate <some-registry>/<operator-bundle-name>:<tag>\n\nTo list and run optional validators, which are specified by a label selector:\n\n  $ operator-sdk bundle validate --list-optional\n  NAME           LABELS                     DESCRIPTION\n  operatorhub    name=operatorhub           OperatorHub.io metadata validation.\n                 suite=operatorframework\n\nTo validate a bundle against the entire suite of validators for Operator Framework, in addition to required bundle validators:\n\n  $ operator-sdk bundle validate ./bundle --select-optional suite=operatorframework\n\nThe OperatorHub.io validator in the operatorframework optional suite allows you to validate that your manifests can work with a Kubernetes cluster of a particular version using the k8s-version optional key value:\n\n  $ operator-sdk bundle validate ./bundle --select-optional suite=operatorframework --optional-values=k8s-version=1.22\n\nTo validate a bundle against the validator for operatorhub.io specifically, in addition to required bundle validators:\n\n  $ operator-sdk bundle validate ./bundle --select-optional name=operatorhub\n\nThis validator allows check the bundle against an specific Kubernetes cluster version using the k8s-version optional key value:\n\n  $ operator-sdk bundle validate ./bundle --select-optional name=operatorhub --optional-values=k8s-version=1.22\n\n[Deprecated] To validate a bundle against the (alpha) validator for Community Operators specifically, in addition to required bundle validators:\n\n  $ operator-sdk bundle validate ./bundle --select-optional name=community --optional-values=index-path=bundle.Dockerfile\n\nTo validate a bundle against the validator for Good Practices specifically, in addition to required bundle validators:\n\n  $ operator-sdk bundle validate ./bundle --select-optional name=good-practices\n\nTo validate a bundle against the (alpha) validator for Deprecated APIs specifically, in addition to required bundle validators:\n\n  $ operator-sdk bundle validate ./bundle --select-optional name=alpha-deprecated-apis --optional-values=k8s-version=1.22\n\nTo validate a bundle against an external validator, in addition to required bundle validators:\n\n  $ operator-sdk bundle validate ./bundle --alpha-select-external /path/to/external-validator[:/path/to/optional-second-validator]\n\nTo validate a bundle against the (alpha) validator for Multiple Architectures bundle validation, in addition to required bundle validators:\n\nIMPORTANT: To use this option it is required to have access to pull the images defined on the CSV.\n\n  $ operator-sdk bundle validate ./bundle --select-optional name=multiarch \n\nNOTE: The --optional-values can be used to inform the container-tools that should be used i.e. \"--optional-values=container-tools=docker\".\nThe valid values for the container-tools optional value are [docker, podman, none]. If no value is supplied then the command will default to using docker to inspect the images.\nMore info: https://github.com/operator-framework/api/blob/master/pkg/validation/internal/multiarch.go\n\n```\n\n### Options\n\n```\n      --alpha-select-external string                         Selector to select external validators to run. It should be set to a Unix path list (\"/path/to/e1.sh:/path/to/e2\")\n  -h, --help                                                 help for validate\n  -b, --image-builder string                                 Tool to pull and unpack bundle images. Only used when validating a bundle image. One of: [docker, podman, none] (default \"docker\")\n      --list-optional                                        List all optional validators available. When set, no validators will be run\n      --optional-values --optional-values=k8s-version=1.22   Inform a []string map of key=values which can be used by the validator. e.g. to check the operator bundle against an Kubernetes version that it is intended to be distributed use --optional-values=k8s-version=1.22 (default [])\n  -o, --output string                                        Result format for results. One of: [text, json-alpha1]. Note: output format types containing \"alphaX\" are subject to change and not covered by guarantees of stable APIs. (default \"text\")\n      --select-optional string                               Label selector to select optional validators to run. Run this command with '--list-optional' to list available optional validators\n```\n\n### Options inherited from parent commands\n\n```\n      --plugins strings   plugin keys to be used for this subcommand execution\n      --verbose           Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk bundle](../operator-sdk_bundle)\t - Manage operator bundle metadata\n\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk_cleanup.md",
    "content": "---\ntitle: \"operator-sdk cleanup\"\n---\n## operator-sdk cleanup\n\nClean up an Operator deployed with the 'run' subcommand\n\n### Synopsis\n\nThis command has subcommands that will destroy an Operator deployed with OLM.\n\n```\noperator-sdk cleanup <operatorPackageName> [flags]\n```\n\n### Options\n\n```\n      --delete-all               If set to true, all other delete options will be enabled (default true)\n      --delete-crds              If set to true, owned CRDs and CRs will be deleted\n      --delete-operator-groups   If set to true, operator groups will be deleted\n  -h, --help                     help for cleanup\n      --kubeconfig string        Path to the kubeconfig file to use for CLI requests.\n  -n, --namespace string         If present, namespace scope for this CLI request\n      --timeout duration         Duration to wait for the command to complete before failing (default 2m0s)\n```\n\n### Options inherited from parent commands\n\n```\n      --plugins strings   plugin keys to be used for this subcommand execution\n      --verbose           Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk](../operator-sdk)\t - \n\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk_completion.md",
    "content": "---\ntitle: \"operator-sdk completion\"\n---\n## operator-sdk completion\n\nLoad completions for the specified shell\n\n### Synopsis\n\nOutput shell completion code for the specified shell.\nThe shell code must be evaluated to provide interactive completion of operator-sdk commands.\nDetailed instructions on how to do this for each shell are provided in their own commands.\n\n\n### Options\n\n```\n  -h, --help   help for completion\n```\n\n### Options inherited from parent commands\n\n```\n      --plugins strings   plugin keys to be used for this subcommand execution\n      --verbose           Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk](../operator-sdk)\t - \n* [operator-sdk completion bash](../operator-sdk_completion_bash)\t - Load bash completions\n* [operator-sdk completion fish](../operator-sdk_completion_fish)\t - Load fish completions\n* [operator-sdk completion powershell](../operator-sdk_completion_powershell)\t - Load powershell completions\n* [operator-sdk completion zsh](../operator-sdk_completion_zsh)\t - Load zsh completions\n\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk_completion_bash.md",
    "content": "---\ntitle: \"operator-sdk completion bash\"\n---\n## operator-sdk completion bash\n\nLoad bash completions\n\n```\noperator-sdk completion bash [flags]\n```\n\n### Examples\n\n```\n# To load completion for this session, execute:\n$ source <(operator-sdk completion bash)\n\n# To load completions for each session, execute once:\nLinux:\n  $ operator-sdk completion bash > /etc/bash_completion.d/operator-sdk\nMacOS:\n  $ operator-sdk completion bash > /usr/local/etc/bash_completion.d/operator-sdk\n\n```\n\n### Options\n\n```\n  -h, --help   help for bash\n```\n\n### Options inherited from parent commands\n\n```\n      --plugins strings   plugin keys to be used for this subcommand execution\n      --verbose           Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk completion](../operator-sdk_completion)\t - Load completions for the specified shell\n\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk_completion_fish.md",
    "content": "---\ntitle: \"operator-sdk completion fish\"\n---\n## operator-sdk completion fish\n\nLoad fish completions\n\n```\noperator-sdk completion fish [flags]\n```\n\n### Examples\n\n```\n# To load completion for this session, execute:\n$ operator-sdk completion fish | source\n\n# To load completions for each session, execute once:\n$ operator-sdk completion fish > ~/.config/fish/completions/operator-sdk.fish\n\n```\n\n### Options\n\n```\n  -h, --help   help for fish\n```\n\n### Options inherited from parent commands\n\n```\n      --plugins strings   plugin keys to be used for this subcommand execution\n      --verbose           Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk completion](../operator-sdk_completion)\t - Load completions for the specified shell\n\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk_completion_powershell.md",
    "content": "---\ntitle: \"operator-sdk completion powershell\"\n---\n## operator-sdk completion powershell\n\nLoad powershell completions\n\n```\noperator-sdk completion powershell [flags]\n```\n\n### Options\n\n```\n  -h, --help   help for powershell\n```\n\n### Options inherited from parent commands\n\n```\n      --plugins strings   plugin keys to be used for this subcommand execution\n      --verbose           Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk completion](../operator-sdk_completion)\t - Load completions for the specified shell\n\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk_completion_zsh.md",
    "content": "---\ntitle: \"operator-sdk completion zsh\"\n---\n## operator-sdk completion zsh\n\nLoad zsh completions\n\n```\noperator-sdk completion zsh [flags]\n```\n\n### Examples\n\n```\n# If shell completion is not already enabled in your environment you will need\n# to enable it. You can execute the following once:\n$ echo \"autoload -U compinit; compinit\" >> ~/.zshrc\n\n# To load completions for each session, execute once:\n$ operator-sdk completion zsh > \"${fpath[1]}/_operator-sdk\"\n\n# You will need to start a new shell for this setup to take effect.\n\n```\n\n### Options\n\n```\n  -h, --help   help for zsh\n```\n\n### Options inherited from parent commands\n\n```\n      --plugins strings   plugin keys to be used for this subcommand execution\n      --verbose           Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk completion](../operator-sdk_completion)\t - Load completions for the specified shell\n\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk_create.md",
    "content": "---\ntitle: \"operator-sdk create\"\n---\n## operator-sdk create\n\nScaffold a Kubernetes API or webhook\n\n### Synopsis\n\nScaffold a Kubernetes API or webhook.\n\n### Options\n\n```\n  -h, --help   help for create\n```\n\n### Options inherited from parent commands\n\n```\n      --plugins strings   plugin keys to be used for this subcommand execution\n      --verbose           Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk](../operator-sdk)\t - \n* [operator-sdk create api](../operator-sdk_create_api)\t - Scaffold a Kubernetes API\n* [operator-sdk create webhook](../operator-sdk_create_webhook)\t - Scaffold a webhook for an API resource\n\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk_create_api.md",
    "content": "---\ntitle: \"operator-sdk create api\"\n---\n## operator-sdk create api\n\nScaffold a Kubernetes API\n\n### Synopsis\n\nScaffold a Kubernetes API by writing a Resource definition and/or a Controller.\n\nIf information about whether the resource and controller should be scaffolded\nwas not explicitly provided, it will prompt the user if they should be.\n\nAfter the scaffold is written, the dependencies will be updated and\nmake generate will be run.\n\n\n```\noperator-sdk create api [flags]\n```\n\n### Examples\n\n```\n  # Create a frigates API with Group: ship, Version: v1beta1 and Kind: Frigate\n  operator-sdk create api --group ship --version v1beta1 --kind Frigate\n\n  # Edit the API Scheme\n\n  nano api/v1beta1/frigate_types.go\n\n  # Edit the Controller\n  nano internal/controller/frigate/frigate_controller.go\n\n  # Edit the Controller Test\n  nano internal/controller/frigate/frigate_controller_test.go\n\n  # Generate the manifests\n  make manifests\n\n  # Install CRDs into the Kubernetes cluster using kubectl apply\n  make install\n\n  # Regenerate code and run against the Kubernetes cluster configured by ~/.kube/config\n  make run\n\n```\n\n### Options\n\n```\n      --controller                   if set, generate the controller without prompting the user (default true)\n      --external-api-domain string   Specify the domain name for the external API. This domain is used to generate accurate RBAC markers and permissions for the external resources (e.g., cert-manager.io).\n      --external-api-path string     Specify the Go package import path for the external API. This is used to scaffold controllers for resources defined outside this project (e.g., github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1).\n      --force                        attempt to create resource even if it already exists\n      --group string                 resource Group\n  -h, --help                         help for api\n      --kind string                  resource Kind\n      --make make generate           if true, run make generate after generating files (default true)\n      --namespaced                   resource is namespaced (default true)\n      --plural string                resource irregular plural form\n      --resource                     if set, generate the resource without prompting the user (default true)\n      --version string               resource Version\n```\n\n### Options inherited from parent commands\n\n```\n      --plugins strings   plugin keys to be used for this subcommand execution\n      --verbose           Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk create](../operator-sdk_create)\t - Scaffold a Kubernetes API or webhook\n\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk_create_webhook.md",
    "content": "---\ntitle: \"operator-sdk create webhook\"\n---\n## operator-sdk create webhook\n\nScaffold a webhook for an API resource\n\n### Synopsis\n\nScaffold a webhook for an API resource. You can choose to scaffold defaulting,\nvalidating and/or conversion webhooks.\n\n\n```\noperator-sdk create webhook [flags]\n```\n\n### Examples\n\n```\n  # Create defaulting and validating webhooks for Group: ship, Version: v1beta1\n  # and Kind: Frigate\n  operator-sdk create webhook --group ship --version v1beta1 --kind Frigate --defaulting --programmatic-validation\n\n  # Create conversion webhook for Group: ship, Version: v1beta1\n  # and Kind: Frigate\n  operator-sdk create webhook --group ship --version v1beta1 --kind Frigate --conversion --spoke v1\n\n```\n\n### Options\n\n```\n      --conversion                   if set, scaffold the conversion webhook\n      --defaulting                   if set, scaffold the defaulting webhook\n      --external-api-domain string   Specify the domain name for the external API. This domain is used to generate accurate RBAC markers and permissions for the external resources (e.g., cert-manager.io).\n      --external-api-path string     Specify the Go package import path for the external API. This is used to scaffold controllers for resources defined outside this project (e.g., github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1).\n      --force                        attempt to create resource even if it already exists\n      --group string                 resource Group\n  -h, --help                         help for webhook\n      --kind string                  resource Kind\n      --legacy                       [DEPRECATED] Attempts to create resource under the API directory (legacy path). This option will be removed in future versions.\n      --make make generate           if true, run make generate after generating files (default true)\n      --plural string                resource irregular plural form\n      --programmatic-validation      if set, scaffold the validating webhook\n      --spoke strings                Comma-separated list of spoke versions to be added to the conversion webhook (e.g., --spoke v1,v2)\n      --version string               resource Version\n```\n\n### Options inherited from parent commands\n\n```\n      --plugins strings   plugin keys to be used for this subcommand execution\n      --verbose           Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk create](../operator-sdk_create)\t - Scaffold a Kubernetes API or webhook\n\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk_edit.md",
    "content": "---\ntitle: \"operator-sdk edit\"\n---\n## operator-sdk edit\n\nUpdate the project configuration\n\n### Synopsis\n\nThis command will edit the project configuration.\nFeatures supported:\n  - Toggle between single or multi group projects.\n\n\n```\noperator-sdk edit [flags]\n```\n\n### Examples\n\n```\n  # Enable the multigroup layout\n  operator-sdk edit --multigroup\n\n  # Disable the multigroup layout\n  operator-sdk edit --multigroup=false\n\n```\n\n### Options\n\n```\n  -h, --help         help for edit\n      --multigroup   enable or disable multigroup layout\n```\n\n### Options inherited from parent commands\n\n```\n      --plugins strings   plugin keys to be used for this subcommand execution\n      --verbose           Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk](../operator-sdk)\t - \n\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk_generate.md",
    "content": "---\ntitle: \"operator-sdk generate\"\n---\n## operator-sdk generate\n\nInvokes a specific generator\n\n### Synopsis\n\nThe 'operator-sdk generate' command invokes a specific generator to generate\ncode or manifests.\n\n### Options\n\n```\n  -h, --help   help for generate\n```\n\n### Options inherited from parent commands\n\n```\n      --plugins strings   plugin keys to be used for this subcommand execution\n      --verbose           Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk](../operator-sdk)\t - \n* [operator-sdk generate bundle](../operator-sdk_generate_bundle)\t - Generates bundle data for the operator\n* [operator-sdk generate kustomize](../operator-sdk_generate_kustomize)\t - Contains subcommands that generate operator-framework kustomize data for the operator\n\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk_generate_bundle.md",
    "content": "---\ntitle: \"operator-sdk generate bundle\"\n---\n## operator-sdk generate bundle\n\nGenerates bundle data for the operator\n\n### Synopsis\n\n\nRunning 'generate bundle' is the first step to publishing your operator to a catalog and deploying it with OLM.\nThis command both generates and packages files into an on-disk representation of an operator called a bundle.\nA bundle consists of a ClusterServiceVersion (CSV), CustomResourceDefinitions (CRDs),\nmanifests not part of the CSV but required by the operator, some metadata (annotations.yaml),\nand a bundle.Dockerfile to build a bundle image.\n\nA CSV manifest is generated by collecting data from the set of manifests passed to this command (see below),\nsuch as CRDs, RBAC, etc., and applying that data to a \"base\" CSV manifest. This base CSV can contain metadata,\nadded by hand or by the 'generate kustomize manifests' command, and can be passed in like any other manifest\n(see below) or by file at the exact path '&lt;kustomize-dir&gt;/bases/&lt;package-name&gt;.clusterserviceversion.yaml'.\nBe aware that 'generate bundle' idempotently regenerates a bundle, so all non-metadata values in a base\nwill be overwritten. If no base was passed in, input manifest data will be applied to an empty CSV.\n\nThere are two ways to pass the to-be-bundled set of manifests to this command: stdin via a Unix pipe,\nor in a directory using '--input-dir'. See command help for more information on these modes.\nPassing a directory is useful for running 'generate bundle' outside of a project or within a project\nthat does not use kustomize and/or contains cluster-ready manifests on disk.\n\nSet '--version' to supply a semantic version for your bundle if you are creating one\nfor the first time or upgrading an existing one.\n\nIf '--output-dir' is set and you wish to build bundle images from that directory,\neither manually update your bundle.Dockerfile or set '--overwrite'.\n\nMore information on bundles:\nhttps://github.com/operator-framework/operator-registry/#manifest-format\n\n\n```\noperator-sdk generate bundle [flags]\n```\n\n### Examples\n\n```\n\n  # If running within a project or in a project that uses kustomize to generate manifests,\n\t# make sure a kustomize directory exists that looks like the following 'config/manifests' directory:\n  $ tree config/manifests\n  config/manifests\n  ├── bases\n  │   └── memcached-operator.clusterserviceversion.yaml\n  └── kustomization.yaml\n\n  # Generate a 0.0.1 bundle by passing manifests to stdin:\n  $ kustomize build config/manifests | operator-sdk generate bundle --version 0.0.1\n  Generating bundle version 0.0.1\n  ...\n\n  # If running outside of a project or in a project that does not use kustomize to generate manifests,\n\t# make sure cluster-ready manifests are available on disk:\n  $ tree deploy/\n  deploy/\n  ├── crds\n  │   └── cache.my.domain_memcacheds.yaml\n  ├── deployment.yaml\n  ├── role.yaml\n  ├── role_binding.yaml\n  ├── service_account.yaml\n  └── webhooks.yaml\n\n  # Generate a 0.0.1 bundle by passing manifests by dir:\n  $ operator-sdk generate bundle --input-dir deploy --version 0.0.1\n  Generating bundle version 0.0.1\n  ...\n\n  # After running in either of the above modes, you should see this directory structure:\n  $ tree bundle/\n  bundle/\n  ├── manifests\n  │   ├── cache.my.domain_memcacheds.yaml\n  │   └── memcached-operator.clusterserviceversion.yaml\n  └── metadata\n      └── annotations.yaml\n\n```\n\n### Options\n\n```\n      --channels string                  A comma-separated list of channels the bundle belongs to (default \"alpha\")\n      --crds-dir string                  Directory to read cluster-ready CustomResoureDefinition manifests from. This option can only be used if --deploy-dir is set\n      --default-channel string           The default channel for the bundle\n      --deploy-dir string                Directory to read cluster-ready operator manifests from. If --crds-dir is not set, CRDs are ready from this directory. This option is mutually exclusive with --input-dir and piping to stdin\n      --extra-service-accounts strings   Names of service accounts, outside of the operator's Deployment account, that have bindings to {Cluster}Roles that should be added to the CSV\n  -h, --help                             help for bundle\n      --input-dir string                 Directory to read cluster-ready operator manifests from. This option is mutually exclusive with --deploy-dir/--crds-dir and piping to stdin. This option should not be passed an existing bundle directory, as this bundle will not contain the correct set of manifests required to generate a CSV. Use --kustomize-dir to pass a base CSV\n      --kustomize-dir string             Directory containing kustomize bases in a \"bases\" dir and a kustomization.yaml for operator-framework manifests (default \"config/manifests\")\n      --manifests                        Generate bundle manifests\n      --metadata                         Generate bundle metadata and Dockerfile\n      --output-dir string                Directory to write the bundle to\n      --overwrite                        Overwrite the bundle's metadata and Dockerfile if they exist (default true)\n      --package string                   Bundle's package name\n  -q, --quiet                            Run in quiet mode\n      --stdout                           Write bundle manifest to stdout\n      --use-image-digests                Use SHA Digest for images\n  -v, --version string                   Semantic version of the operator in the generated bundle. Only set if creating a new bundle or upgrading your operator\n```\n\n### Options inherited from parent commands\n\n```\n      --plugins strings   plugin keys to be used for this subcommand execution\n      --verbose           Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk generate](../operator-sdk_generate)\t - Invokes a specific generator\n\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk_generate_kustomize.md",
    "content": "---\ntitle: \"operator-sdk generate kustomize\"\n---\n## operator-sdk generate kustomize\n\nContains subcommands that generate operator-framework kustomize data for the operator\n\n### Options\n\n```\n  -h, --help   help for kustomize\n```\n\n### Options inherited from parent commands\n\n```\n      --plugins strings   plugin keys to be used for this subcommand execution\n      --verbose           Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk generate](../operator-sdk_generate)\t - Invokes a specific generator\n* [operator-sdk generate kustomize manifests](../operator-sdk_generate_kustomize_manifests)\t - Generates kustomize bases and a kustomization.yaml for operator-framework manifests\n\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk_generate_kustomize_manifests.md",
    "content": "---\ntitle: \"operator-sdk generate kustomize manifests\"\n---\n## operator-sdk generate kustomize manifests\n\nGenerates kustomize bases and a kustomization.yaml for operator-framework manifests\n\n### Synopsis\n\n\nRunning 'generate kustomize manifests' will (re)generate kustomize bases and a kustomization.yaml in\n'config/manifests', which are used to build operator-framework manifests by other operator-sdk commands.\nThis command will interactively ask for UI metadata, an important component of manifest bases,\nby default unless a base already exists or you set '--interactive=false'.\n\n\n```\noperator-sdk generate kustomize manifests [flags]\n```\n\n### Examples\n\n```\n\n  $ operator-sdk generate kustomize manifests\n\n  Display name for the operator (required):\n  > memcached-operator\n  ...\n\n  $ tree config/manifests\n  config/manifests\n  ├── bases\n  │   └── memcached-operator.clusterserviceversion.yaml\n  └── kustomization.yaml\n\n  # After generating kustomize bases and a kustomization.yaml, you can generate a bundle or package manifests.\n\n  # To generate a bundle:\n  $ kustomize build config/manifests | operator-sdk generate bundle --version 0.0.1\n\n  # To generate package manifests:\n  $ kustomize build config/manifests | operator-sdk generate packagemanifests --version 0.0.1\n\n```\n\n### Options\n\n```\n      --apis-dir string     Root directory for API type defintions\n  -h, --help                help for manifests\n      --input-dir string    Directory containing existing kustomize files\n      --interactive         When set to false, if no kustomize base exists, an interactive command prompt will be presented to accept non-inferrable metadata\n      --output-dir string   Directory to write kustomize files\n      --package string      Package name\n  -q, --quiet               Run in quiet mode\n```\n\n### Options inherited from parent commands\n\n```\n      --plugins strings   plugin keys to be used for this subcommand execution\n      --verbose           Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk generate kustomize](../operator-sdk_generate_kustomize)\t - Contains subcommands that generate operator-framework kustomize data for the operator\n\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk_init.md",
    "content": "---\ntitle: \"operator-sdk init\"\n---\n## operator-sdk init\n\nInitialize a new project\n\n### Synopsis\n\nInitialize a new project including the following files:\n  - a \"go.mod\" with project dependencies\n  - a \"PROJECT\" file that stores project configuration\n  - a \"Makefile\" with several useful make targets for the project\n  - several YAML files for project deployment under the \"config\" directory\n  - a \"cmd/main.go\" file that creates the manager that will run the project controllers\n\n\n```\noperator-sdk init [flags]\n```\n\n### Examples\n\n```\n  # Initialize a new project with your domain and name in copyright\n  operator-sdk init --plugins go/v4 --domain example.org --owner \"Your name\"\n\n  # Initialize a new project defining a specific project version\n  operator-sdk init --plugins go/v4 --project-version 3\n\n```\n\n### Options\n\n```\n      --domain string            domain for groups (default \"my.domain\")\n      --fetch-deps               ensure dependencies are downloaded (default true)\n  -h, --help                     help for init\n      --license string           license to use to boilerplate, may be one of 'apache2', 'none' (default \"apache2\")\n      --owner string             owner to add to the copyright\n      --project-name string      name of this project\n      --project-version string   project version (default \"3\")\n      --repo string              name to use for go module (e.g., github.com/user/repo), defaults to the go package of the current working directory.\n      --skip-go-version-check    if specified, skip checking the Go version\n```\n\n### Options inherited from parent commands\n\n```\n      --plugins strings   plugin keys to be used for this subcommand execution\n      --verbose           Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk](../operator-sdk)\t - \n\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk_olm.md",
    "content": "---\ntitle: \"operator-sdk olm\"\n---\n## operator-sdk olm\n\nManage the Operator Lifecycle Manager installation in your cluster\n\n### Options\n\n```\n  -h, --help   help for olm\n```\n\n### Options inherited from parent commands\n\n```\n      --plugins strings   plugin keys to be used for this subcommand execution\n      --verbose           Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk](../operator-sdk)\t - \n* [operator-sdk olm install](../operator-sdk_olm_install)\t - Install Operator Lifecycle Manager in your cluster\n* [operator-sdk olm status](../operator-sdk_olm_status)\t - Get the status of the Operator Lifecycle Manager installation in your cluster\n* [operator-sdk olm uninstall](../operator-sdk_olm_uninstall)\t - Uninstall Operator Lifecycle Manager from your cluster\n\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk_olm_install.md",
    "content": "---\ntitle: \"operator-sdk olm install\"\n---\n## operator-sdk olm install\n\nInstall Operator Lifecycle Manager in your cluster\n\n```\noperator-sdk olm install [flags]\n```\n\n### Options\n\n```\n  -h, --help               help for install\n      --timeout duration   time to wait for the command to complete before failing (default 2m0s)\n      --version string     version of OLM resources to install (default \"0.28.0\")\n```\n\n### Options inherited from parent commands\n\n```\n      --plugins strings   plugin keys to be used for this subcommand execution\n      --verbose           Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk olm](../operator-sdk_olm)\t - Manage the Operator Lifecycle Manager installation in your cluster\n\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk_olm_status.md",
    "content": "---\ntitle: \"operator-sdk olm status\"\n---\n## operator-sdk olm status\n\nGet the status of the Operator Lifecycle Manager installation in your cluster\n\n```\noperator-sdk olm status [flags]\n```\n\n### Options\n\n```\n  -h, --help                   help for status\n      --olm-namespace string   namespace where OLM is installed (default \"olm\")\n      --timeout duration       time to wait for the command to complete before failing (default 2m0s)\n      --version string         version of OLM installed on cluster; if unsetoperator-sdk attempts to auto-discover the version\n```\n\n### Options inherited from parent commands\n\n```\n      --plugins strings   plugin keys to be used for this subcommand execution\n      --verbose           Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk olm](../operator-sdk_olm)\t - Manage the Operator Lifecycle Manager installation in your cluster\n\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk_olm_uninstall.md",
    "content": "---\ntitle: \"operator-sdk olm uninstall\"\n---\n## operator-sdk olm uninstall\n\nUninstall Operator Lifecycle Manager from your cluster\n\n```\noperator-sdk olm uninstall [flags]\n```\n\n### Options\n\n```\n  -h, --help                   help for uninstall\n      --olm-namespace string   namespace from where OLM is to be uninstalled. (default \"olm\")\n      --timeout duration       time to wait for the command to complete before failing (default 2m0s)\n      --version string         version of OLM resources to uninstall.\n```\n\n### Options inherited from parent commands\n\n```\n      --plugins strings   plugin keys to be used for this subcommand execution\n      --verbose           Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk olm](../operator-sdk_olm)\t - Manage the Operator Lifecycle Manager installation in your cluster\n\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk_pkgman-to-bundle.md",
    "content": "---\ntitle: \"operator-sdk pkgman-to-bundle\"\n---\n## operator-sdk pkgman-to-bundle\n\nMigrates packagemanifests to bundles\n\n### Synopsis\n\n\n'pkgman-to-bundle' command helps in migrating OLM packagemanifests to bundles which is the preferred OLM packaging format.\nThis command takes an input packagemanifest directory and generates bundles for each of the versions of manifests present in\nthe input directory. Additionally, it also provides the flexibility to build bundle images for each of the generated bundles.\n\nThe generated bundles are always written on disk. Location for the generated bundles can be specified using '--output-dir'. If not\nspecified, the default location would be 'bundle/' directory.\n\nThe base container image name for the bundles can be provided using '--image-tag-base' flag. This should be provided without the tag, since the tag\nfor the images would be the bundle version, (ie) image names will be in the format &lt;base_image&gt;:&lt;bundle_version&gt;.\n\nSpecify the build command for building container images using '--build-cmd' flag. The default build command is 'docker build'. The command will\nneed to be in the 'PATH' or fully qualified path name should be provided.\n\n\n```\noperator-sdk pkgman-to-bundle <packagemanifestdir> [flags]\n```\n\n### Examples\n\n```\n\n\n# Provide the packagemanifests directory as input to the command. Consider the packagemanifests directory to have the following\n# structure:\n\n$ tree packagemanifests/\npackagemanifests\n└── etcd\n    ├── 0.0.1\n    │   ├── etcdcluster.crd.yaml\n    │   └── etcdoperator.clusterserviceversion.yaml\n    ├── 0.0.2\n    │   ├── etcdbackup.crd.yaml\n    │   ├── etcdcluster.crd.yaml\n    │   ├── etcdoperator.v0.0.2.clusterserviceversion.yaml\n    │   └── etcdrestore.crd.yaml\n    └── etcd.package.yaml\n\n# Run the following command to generate bundles in the default 'bundle/' directory with the base-container image name\n# to be 'quay.io/example/etcd'\n$ operator-sdk pkgman-to-bundle packagemanifests --image-tag-base quay.io/example/etcd\nINFO[0000] Packagemanifests will be migrated to bundles in bundle directory\nINFO[0000] Creating bundle/bundle-0.0.1/bundle.Dockerfile\nINFO[0000] Creating bundle/bundle-0.0.1/metadata/annotations.yaml\n...\n\n# After running the above command, the bundles will be generated in 'bundles/' directory.\n$ tree bundles/\nbundles/\n├── bundle-0.0.1\n│   ├── bundle\n│   │   ├── manifests\n│   │   │   ├── etcdcluster.crd.yaml\n│   │   │   ├── etcdoperator.clusterserviceversion.yaml\n│   │   ├── metadata\n│   │   │   └── annotations.yaml\n│   │   └── tests\n│   │       └── scorecard\n│   │           └── config.yaml\n│   └── bundle.Dockerfile\n└── bundle-0.0.2\n    ├── bundle\n    │   ├── manifests\n    │   │   ├── etcdbackup.crd.yaml\n    │   │   ├── etcdcluster.crd.yaml\n    │   │   ├── etcdoperator.v0.0.2.clusterserviceversion.yaml\n    │   │   ├── etcdrestore.crd.yaml\n    │   └── metadata\n    │       └── annotations.yaml\n    └── bundle.Dockerfile\n\nA custom command to build bundle images can also be specified using the '--build-cmd' flag. For example,\n\n$ operator-sdk pkgman-to-bundle packagemanifests --image-tag-base quay.io/example/etcd --build-cmd \"podman build -f bundle.Dockerfile . -t\"\n\nImages for the both the bundles will be built with the following names: quay.io/example/etcd:0.0.1 and quay.io/example/etcd:0.0.2.\n\n```\n\n### Options\n\n```\n      --build-cmd string        Build command to be run for building images. By default 'docker build' is run.\n  -h, --help                    help for pkgman-to-bundle\n      --image-tag-base string   Base container image name for bundle image tags, ex. my.reg/foo/bar-operator-bundle will become my.reg/foo/bar-operator-bundle:${package-dir-name} for each child directory name in the packagemanifests directory\n      --output-dir string       Directory to write bundle to. (default \"bundles\")\n```\n\n### Options inherited from parent commands\n\n```\n      --plugins strings   plugin keys to be used for this subcommand execution\n      --verbose           Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk](../operator-sdk)\t - \n\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk_run.md",
    "content": "---\ntitle: \"operator-sdk run\"\n---\n## operator-sdk run\n\nRun an Operator in a variety of environments\n\n### Synopsis\n\nThis command has subcommands that will deploy your Operator with OLM.\n\n### Options\n\n```\n  -h, --help   help for run\n```\n\n### Options inherited from parent commands\n\n```\n      --plugins strings   plugin keys to be used for this subcommand execution\n      --verbose           Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk](../operator-sdk)\t - \n* [operator-sdk run bundle](../operator-sdk_run_bundle)\t - Deploy an Operator in the bundle format with OLM\n* [operator-sdk run bundle-upgrade](../operator-sdk_run_bundle-upgrade)\t - Upgrade an Operator previously installed in the bundle format with OLM\n\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk_run_bundle-upgrade.md",
    "content": "---\ntitle: \"operator-sdk run bundle-upgrade\"\n---\n## operator-sdk run bundle-upgrade\n\nUpgrade an Operator previously installed in the bundle format with OLM\n\n### Synopsis\n\nThe single argument to this command is a bundle image, with the full registry path specified.\nIf using a docker.io image, you must specify docker.io(/&lt;namespace&gt;)?/&lt;bundle-image-name&gt;:&lt;tag&gt;.\nIf the bundle image provided is a SQLite index, it must be pullable by the cluster as SQLite images are pulled from the cluster.\nIf the bundle image provided is a File-Based Catalog (FBC) index, it will be pulled on the local machine.\n\n```\noperator-sdk run bundle-upgrade <bundle-image> [flags]\n```\n\n### Options\n\n```\n      --ca-secret-name string                     Name of a generic secret containing a PEM root certificate file required to pull bundle images. This secret *must* be in the namespace that this command is configured to run in, and the file *must* be encoded under the key \"cert.pem\"\n  -h, --help                                      help for bundle-upgrade\n      --image-pull-policy string                  image pull policy for the registry pod (default \"Always\")\n      --kubeconfig string                         Path to the kubeconfig file to use for CLI requests.\n  -n, --namespace string                          If present, namespace scope for this CLI request\n      --pull-secret-name string                   Name of image pull secret (\"type: kubernetes.io/dockerconfigjson\") required to pull bundle images. This secret *must* be both in the namespace and an imagePullSecret of the service account that this command is configured to run in\n      --security-context-config SecurityContext   specifies the security context to use for the catalog pod. allowed: 'restricted', 'legacy'. (default legacy)\n      --service-account string                    Service account name to bind registry objects to. If unset, the default service account is used. This value does not override the operator's service account\n      --skip-tls                                  skip authentication of image registry TLS certificate when pulling a bundle image in-cluster\n      --skip-tls-verify                           skip TLS certificate verification for container image registries while pulling bundles\n      --timeout duration                          Duration to wait for the command to complete before failing (default 2m0s)\n      --use-http                                  use plain HTTP for container image registries while pulling bundles\n```\n\n### Options inherited from parent commands\n\n```\n      --plugins strings   plugin keys to be used for this subcommand execution\n      --verbose           Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk run](../operator-sdk_run)\t - Run an Operator in a variety of environments\n\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk_run_bundle.md",
    "content": "---\ntitle: \"operator-sdk run bundle\"\n---\n## operator-sdk run bundle\n\nDeploy an Operator in the bundle format with OLM\n\n### Synopsis\n\nThe single argument to this command is a bundle image, with the full registry path specified.\nIf using a docker.io image, you must specify docker.io(/&lt;namespace&gt;)?/&lt;bundle-image-name&gt;:&lt;tag&gt;.\nIf the bundle image provided is a SQLite index, it must be pullable by the cluster as SQLite images are pulled from the cluster.\nIf the bundle image provided is a File-Based Catalog (FBC) index, it will be pulled on the local machine.\n\nThe main purpose of this command is to streamline running the bundle without having to provide an index image with the bundle already included.\n\nThe `--index-image` flag specifies an index image in which to inject the given bundle. It can be specified to resolve dependencies for a bundle. \nThis is an optional flag which will default to `quay.io/operator-framework/opm:latest`.\nThe index image provided should **NOT** already have the bundle. A limitation of the index image flag is that it does not check the upgrade graph\nas the annotations for channels are ignored but it is still a useful flag to have to validate the dependencies. \nFor example: It does not fail fast when the bundle version provided is &lt;= ChannelHead.\n\n\n```\noperator-sdk run bundle <bundle-image> [flags]\n```\n\n### Options\n\n```\n      --ca-secret-name string                     Name of a generic secret containing a PEM root certificate file required to pull bundle images. This secret *must* be in the namespace that this command is configured to run in, and the file *must* be encoded under the key \"cert.pem\"\n      --decompression-image string                image used in an init container in the registry pod to decompress the compressed catalog contents. cat and gzip binaries are expected to exist in the PATH (default \"registry.access.redhat.com/ubi9/ubi:9.7\")\n  -h, --help                                      help for bundle\n      --image-pull-policy string                  image pull policy for the registry pod (default \"Always\")\n      --index-image string                        index image in which to inject bundle (default \"quay.io/operator-framework/opm:latest\")\n      --install-mode InstallModeValue             install mode\n      --kubeconfig string                         Path to the kubeconfig file to use for CLI requests.\n  -n, --namespace string                          If present, namespace scope for this CLI request\n      --pull-secret-name string                   Name of image pull secret (\"type: kubernetes.io/dockerconfigjson\") required to pull bundle images. This secret *must* be both in the namespace and an imagePullSecret of the service account that this command is configured to run in\n      --security-context-config SecurityContext   specifies the security context to use for the catalog pod. allowed: 'restricted', 'legacy'. (default legacy)\n      --service-account string                    Service account name to bind registry objects to. If unset, the default service account is used. This value does not override the operator's service account\n      --skip-tls                                  skip authentication of image registry TLS certificate when pulling a bundle image in-cluster\n      --skip-tls-verify                           skip TLS certificate verification for container image registries while pulling bundles\n      --timeout duration                          Duration to wait for the command to complete before failing (default 2m0s)\n      --use-http                                  use plain HTTP for container image registries while pulling bundles\n```\n\n### Options inherited from parent commands\n\n```\n      --plugins strings   plugin keys to be used for this subcommand execution\n      --verbose           Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk run](../operator-sdk_run)\t - Run an Operator in a variety of environments\n\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk_scorecard.md",
    "content": "---\ntitle: \"operator-sdk scorecard\"\n---\n## operator-sdk scorecard\n\nRuns scorecard\n\n### Synopsis\n\nHas flags to configure dsl, bundle, and selector. This command takes\none argument, either a bundle image or directory containing manifests and metadata.\nIf the argument holds an image tag, it must be present remotely.\n\n```\noperator-sdk scorecard [flags]\n```\n\n### Options\n\n```\n  -c, --config string            path to scorecard config file\n  -h, --help                     help for scorecard\n      --kubeconfig string        kubeconfig path\n  -L, --list                     Option to enable listing which tests are run\n  -n, --namespace string         namespace to run the test images in\n  -o, --output string            Output format for results. Valid values: text, json, xunit (default \"text\")\n      --pod-security string      option to run scorecard with legacy pod security context (default \"legacy\")\n  -l, --selector string          label selector to determine which tests are run\n  -s, --service-account string   Service account to use for tests (default \"default\")\n  -x, --skip-cleanup             Disable resource cleanup after tests are run\n  -b, --storage-image string     Storage image to be used by the Scorecard pod (default \"quay.io/operator-framework/scorecard-storage@sha256:a3bfda71281393c7794cabdd39c563fb050d3020fd0b642ea164646bdd39a0e2\")\n  -t, --test-output string       Test output directory. (default \"test-output\")\n  -u, --untar-image string       Untar image to be used by the Scorecard pod (default \"quay.io/operator-framework/scorecard-untar@sha256:2e728c5e67a7f4dec0df157a322dd5671212e8ae60f69137463bd4fdfbff8747\")\n  -w, --wait-time duration       seconds to wait for tests to complete. Example: 35s (default 30s)\n```\n\n### Options inherited from parent commands\n\n```\n      --plugins strings   plugin keys to be used for this subcommand execution\n      --verbose           Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk](../operator-sdk)\t - \n\n"
  },
  {
    "path": "website/content/en/docs/cli/operator-sdk_version.md",
    "content": "---\ntitle: \"operator-sdk version\"\n---\n## operator-sdk version\n\nPrint the operator-sdk version\n\n### Synopsis\n\nPrint the operator-sdk version\n\n```\noperator-sdk version [flags]\n```\n\n### Examples\n\n```\noperator-sdk version\n```\n\n### Options\n\n```\n  -h, --help   help for version\n```\n\n### Options inherited from parent commands\n\n```\n      --plugins strings   plugin keys to be used for this subcommand execution\n      --verbose           Enable verbose logging\n```\n\n### SEE ALSO\n\n* [operator-sdk](../operator-sdk)\t - \n\n"
  },
  {
    "path": "website/content/en/docs/contribution-guidelines/_index.md",
    "content": "---\ntitle: How to Contribute\nlinkTitle: Contribution Guide\nweight: 11\ndescription: Contribute to Operator SDK\n---\n"
  },
  {
    "path": "website/content/en/docs/contribution-guidelines/changelog.md",
    "content": "---\ntitle: Changelog\nweight: 25\n---\n\nThe Operator SDK project tracks changes across releases by maintaining a live changelog. This changelog is compiled via fragments located in `changelog/fragments`\n\nContributors are asked to add these changelog fragments when creating pull requests by following this [template][changelog-template].\n\nThe changlog fragments document the following information:\n\n* Description of Changes\n* Types of Changes\n  * One of: addition, change, deprecation, removal, bugfix\n* Migration Guide for Changes\n  * These are required for breaking changes, and essential (but not required) for scaffolding-related changes.\n\n[changelog-template]: https://github.com/operator-framework/operator-sdk/blob/master/changelog/fragments/00-template.yaml\n"
  },
  {
    "path": "website/content/en/docs/contribution-guidelines/developer-guide.md",
    "content": "---\ntitle: Development\nlinkTitle: Development\nweight: 1\n---\n\n## Installation\n\n### Prerequisites\n\n- [git][git-tool]\n- [go][go-tool] version 1.23\n\n### Download Operator SDK\n\nGo to the [operator-sdk repo][repo-sdk] and follow the [fork guide][fork-guide] to fork and set up a local repository.\n\n### Build the Operator SDK CLI\n\nBuild the Operator SDK CLI `operator-sdk` binary:\n\n```sh\nmake install\n```\n\n## Testing\n\nSee the [testing][dev-testing] and [documentation][dev-docs] guides for more information.\n\n## Releasing\n\nSee the [release guide][dev-release] for more information.\n\n## Continuous Integration (CI)\n\nThe operator-sdk repo uses [Github Actions][sdk-actions] to test each pull request and build images for both master commits\nand release tags. You can alter these processes by modifying the appropriate [Action config][sdk-action-cfgs].\n\n### Adding new architectures\n\nThe operator-sdk project builds binaries for [several os's/architectures][readme-platforms].\nIf you wish to add support for a new one, please create a feature request issue before\nimplementing support for that platform and submitting a PR.\n\nIf you'd like to implement support yourself, you can test a new architecture by enabling Actions\nin your repository, add a platform pair to the [`deploy`][deploy-workflow] workflow's `build and push` step,\nand push to your main branch. Once the updated Action passes, submit a PR linking the passing Action run.\n\n\n[git-tool]:https://git-scm.com/downloads\n[go-tool]:https://golang.org/dl/\n[repo-sdk]:https://github.com/operator-framework/operator-sdk\n[fork-guide]:https://docs.github.com/en/get-started/quickstart/fork-a-repo\n[dev-testing]: /docs/contribution-guidelines/testing\n[dev-docs]: /docs/contribution-guidelines/documentation\n[dev-release]: /docs/contribution-guidelines/releasing\n[sdk-actions]:https://github.com/operator-framework/operator-sdk/actions\n[sdk-action-cfgs]:https://github.com/operator-framework/operator-sdk/tree/master/.github/workflows\n[readme-platforms]:https://github.com/operator-framework/operator-sdk/tree/master/README.md#platforms\n[deploy-workflow]:https://github.com/operator-framework/operator-sdk/tree/master/.github/workflows/deploy.yml\n"
  },
  {
    "path": "website/content/en/docs/contribution-guidelines/documentation.md",
    "content": "---\ntitle: Documentation\nlinkTitle: Documentation\nweight: 20\n---\n\nIf a contribution changes the user interface or existing APIs it must include new or updated documentation.\nSince the operator-sdk repository does not expose many public packages, documentation mostly comes in the form of our website's [markdown docs][website-md].\nGood [godocs][godocs] are expected nonetheless.\n\nLikewise a [changelog fragment][changelog-template] should be added containing a summary of the change and optionally a migration guide.\n\n## Testing docs changes\n\nThis document discusses how to visually inspect documentation changes as they would be applied\nto the live website. All changes to documentation should be inspected locally before being pushed\nto a PR.\n\n### Prerequisites\n\nThe docs are built with [Hugo][hugo] which can be installed along with the\nrequired extensions by following the [docsy install guide][docsy-install].\n\nNote: Be sure to install hugo-extended.\n\nWe use `git submodules` to install the docsy theme. From the\n`operator-sdk` directory, update the submodules to install the theme.\n\n```sh\ngit submodule update --init --recursive\n```\n\n### Build and Serve\n\nYou can build and serve your docs to `localhost:1313`. From the `website/`\ndirectory run:\n\n```sh\nhugo server\n```\n\nAny changes will be included in real time.\n\n### Check Docs\n\n`make test-docs` will validate changelog fragments, build doc HTML in a container, and check its links.\nPlease consider running this locally before creating a PR to save CI resources.\n\n[hugo]:https://gohugo.io/\n[docsy-install]:https://www.docsy.dev/docs/get-started/other-options/#prerequisites-and-installation\n[website-md]:https://github.com/operator-framework/operator-sdk/tree/master/website/content/en/docs\n[changelog-template]:https://github.com/operator-framework/operator-sdk/blob/master/changelog/fragments/00-template.yaml\n[godocs]:https://blog.golang.org/godoc\n"
  },
  {
    "path": "website/content/en/docs/contribution-guidelines/faq.md",
    "content": "---\ntitle: FAQ\nweight: 200\n---\n\n#### Q: If I find a problem, should I file a Pull Request or an Issue?\n\nA: We suggest that you start by filing an issue to potentially save\ncontributors the implementation time if the change cannot be accepted\nfor some reason. However, if it is easier to just submit a PR that is\nalways fine. If you do choose to start with a Pull Request, please make\nsure that the motivation is included.\n"
  },
  {
    "path": "website/content/en/docs/contribution-guidelines/issue-lifecycle.md",
    "content": "---\ntitle: Issue Lifecycle\nweight: 30\n---\n\nThe Operator SDK project tracks bugs, feature requests, and questions\nwith [GitHub issues][gh-issues].\n\n## Triage\n\nEach week, there is a [triage meeting][triage-meeting] to review new\nissues. Each issue that has been filed since the previous meeting is\ndiscussed, GitHub labels are applied, and the issue is added to a\n[Milestone][gh-milestones]. Additionally, anyone can request that a\npreviously triaged issue can be retriaged.\n\n## Grooming\n\nFollowing a release, there is a [grooming meeting][grooming-meeting] to\nreview issues that are desired in the next release. Issues are discussed\nin the following order:\n\n- Issues in the next release milestone\n- Issues labeled as `priority/important-soon`\n- Issues in other milestones/backlog if specifically requested\n\n\n[gh-issues]:https://github.com/operator-framework/operator-sdk/issues\n[gh-milestones]:https://github.com/operator-framework/operator-sdk/milestones\n[grooming-meeting]:https://github.com/operator-framework/community#operator-sdk-grooming-meeting\n[triage-meeting]:https://github.com/operator-framework/community#operator-sdk-issue-triage\n"
  },
  {
    "path": "website/content/en/docs/contribution-guidelines/opening-pull-requests.md",
    "content": "---\ntitle: Opening Pull Requests\nweight: 30\n---\n\nChanges to Operator SDK are submitted via [Github Pull Request (PR)][gh-pr]\nto the relevant repository. Most PRs will be to the [main Operator SDK repo][operator-sdk-repo].\n\n## PR Checklist\n1. Add [tests][adding-tests] for your change, and ensure they run and pass in CI.\n1. Add a [changelog entry][changelog-docs] if necessary.\n1. Add relevant [documentation][adding-docs].\n1. Rebase your commits on master and squash them into a single commit.\n1. Write a concise commit message that references the issue number.\n1. Push your commit to your fork and [open a pull request][gh-fork-pr].\n\n\n## Review\n\nBefore a pull request can be merged, tests must pass in CI and it must be reviewed. A PR\nmust be approved by 2 reviewers, one of which must be at least at least a reviewer and one\nof which must be at least an approver, per the [Operator Framework community guidelines][of-contributor-ladder].\n\nPlease feel free to message the developers to get eyes on your PR, whether through @'ing on the PR itself,\nthe #operator-sdk-dev channel on Kubernetes slack, or by attending the Operator SDK [triage meeting][triage-meeting].\n\n[adding-docs]:https://sdk.operatorframework.io/docs/contribution-guidelines/documentation/\n[adding-tests]:https://sdk.operatorframework.io/docs/contribution-guidelines/testing/\n[changelog-docs]:https://sdk.operatorframework.io/docs/contribution-guidelines/changelog/#m-docscontribution-guidelineschangelog\n[gh-fork-pr]:https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork\n[gh-pr]:https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests\n[of-contributor-ladder]:https://github.com/operator-framework/community/blob/master/contributor-ladder.md\n[operator-sdk-repo]:https://github.com/operator-framework/operator-sdk\n[triage-meeting]:https://github.com/operator-framework/community#operator-sdk-issue-triage\n"
  },
  {
    "path": "website/content/en/docs/contribution-guidelines/plugins.md",
    "content": "---\ntitle: Plugins\nlinkTitle: Plugins\nweight: 7\n---\n\n## Overview\n\nSDK uses the project [Kubebuilder][kubebuilder] as a library for the CLI and plugins features. For further information see the [Plugins][kb-plugins-doc] document. To better understand its motivations, check the design documentation [Integrating Kubebuilder and Operator SDK][kb-int-sdk].\n\n## SDK Language-based plugins\n\nAll language-based operator projects provided by SDK (Ansible/Helm/Golang) follow the Kubebuilder standard and have a common base. The common base is generated using [kustomize][kustomize] which is a project maintained and adopted by Kubernetes community to help work with the Kubernertes manifests (YAML files) that are used to configure the resources on the clusters.\n\nThe specific files for each language are scaffolded for the language's plugins. The Operator SDK CLI tool can provide custom plugins and helpers which are common and useful for all language types. To check the common base, you can also run:\n\n```sh\noperator-sdk init --plugins=kustomize\n```\n\nAlso, see the topic [External Plugins][kb-language-plugins] to understand how it works.\n\n### Common scaffolds \n\nFollowing the default common scaffolds for the projects which are built with SDK.\n\n| File/Directory | Description | \n| ------ | ----- |\n|  Dockerfile |  Defines the operator(manager) image |  \n|  Makefile |  Provides the helpers and options for the users. (e.g. `make bundle` which generate/update the OLM [bundle][bundle] manifests ) |  \n|  PROJECT |  Project configuration. Stores the data used to do the scaffolds. For further information see [Project Config][kb-project] | \n|  bundle.Dockerfile | Docker image which is used to provide the helpers to integrate the project with OLM. (e.g. [operator-sdk run ./bundle][sdk-cli-run-bundle]) | \n|  config/ |  Directory which has all [kustomize's][kustomize] manifest to configure and test the project | \n\nYou can check the [Project Layout][project-layout] to better understand the files and directories scaffolded by SDK CLI, which may be common for each language-type.\n\n## Custom Plugins\n\nBy default plugins are used by the Operator SDK to provide the following features:\n\n- [manifests.sdk.operatorframework.io][plugin-manifest]: perform the required scaffolds to provide the helpers to allow the projects to be integrated with OLM. \n- [scorecard.sdk.operatorframework.io][plugin-scorecard]: perform the required scaffolds to provide the [Scorecard][scorecard] feature.\n\n### Optional/custom plugins\n\nUsers can also use custom plugins when they execute the SDK CLI sub-commands as a helper which includes the following options:\n\n```sh\noperator-sdk create api --plugins=\"go/v3,declarative\"\n```\n\nThe above example will scaffold custom code in the controllers after an API is created to allow the users to develop solutions using the [kubebuilder declarative pattern][kubebuilder-declarative-pattern]. (e.g [default scaffold][default-scaffold] versus [example][kubebuilder-declarative-pattern-example]).\n\nNote that custom plugins are called via the init sub-command to work as global plugins, and will be added in the `layout` field of the PROJECT file. Any sub-command executed will then also be called.\n\n## Plugins Vision\n\nContributors are able to create their own plugin(s) using the same standards and approach described by this document. Following them facilitates in-tree (in other words, built with the `operator-sdk` binary) addition of such community-driven plugins to the Operator SDK project by making review easier and code maintainable. Currently, the SDK cannot discover and use plugins that are not in-tree. However, out-of-tree plugins have been discussed in [kubebuilder/issues/1378][kb-issue].\n\n## How to create your own plugins\n\nIf you are looking to develop similar solutions to allow users for example to create projects using other languages or that could work as helpers for the projects built with SDK/Kubebuilder projects, then see the [Creating your own plugins][create-your-own-plugins] to see how you can benefit and apply this approach.\n\n[kb-plugins-doc]: https://master.book.kubebuilder.io/plugins/plugins.html\n[kb-int-sdk]: https://github.com/kubernetes-sigs/kubebuilder/blob/master/designs/integrating-kubebuilder-and-osdk.md\n[kb-language-plugins]: https://book.kubebuilder.io/plugins/extending/external-plugins\n[kustomize]: https://github.com/kubernetes-sigs/kustomize\n[bundle]: https://github.com/operator-framework/operator-registry/blob/v1.16.1/docs/design/operator-bundle.md#operator-bundle\n[kb-project]: https://master.book.kubebuilder.io/reference/project-config.html\n[sdk-cli-run-bundle]: /docs/cli/operator-sdk_run\n[project-layout]: /docs/overview/project-layout\n[plugin-manifest]: https://github.com/operator-framework/operator-sdk/tree/master/internal/plugins/manifests/v2\n[plugin-scorecard]: https://github.com/operator-framework/operator-sdk/tree/master/internal/plugins/scorecard/v2\n[kubebuilder-declarative-pattern]: https://github.com/kubernetes-sigs/kubebuilder-declarative-pattern\n[kubebuilder-declarative-pattern-example]: https://github.com/kubernetes-sigs/kubebuilder/blob/v3.13.0/testdata/project-v3/controllers/firstmate_controller.go\n[default-scaffold]: https://github.com/kubernetes-sigs/kubebuilder/blob/v3.13.0/testdata/project-v3/controllers/admiral_controller.go\n[kb-issue]: https://github.com/kubernetes-sigs/kubebuilder/issues/1378\n[create-your-own-plugins]: https://book.kubebuilder.io/plugins/extending\n[scorecard]: /docs/testing-operators/scorecard/\n[kubebuilder]: https://github.com/kubernetes-sigs/kubebuilder \n"
  },
  {
    "path": "website/content/en/docs/contribution-guidelines/releasing.md",
    "content": "---\ntitle: Release Guide\nlinkTitle: Releasing\nweight: 4\n---\n\nThese steps describe how to conduct a release of the operator-sdk repo using example versions.\nReplace these versions with the current and new version you are releasing, respectively.\n\n## Table of Contents:\n\n- [Prerequisites](#prerequisites)\n- [Major and minor releases](#major-and-minor-releases)\n- [Patch releases](#patch-releases)\n- [`scorecard-test-kuttl` image releases](#scorecard-test-kuttl-image-releases)\n- [Release tips](#helpful-tips-and-information)\n\n## Prerequisites\n\nThe following tools and permissions are needed to conduct a release of the operator-sdk repo.\n\n### Tools\n\n- [`git`](https://git-scm.com/downloads): version 2.2+\n- [`make`](https://www.gnu.org/software/make/): version 4.2+\n- [`sed`](https://www.gnu.org/software/sed/): version 4.3+\n\n### Permissions\n\n- Must be a [Netlify admin][doc-owners]\n- Must be an admin on the [operator-sdk repo](https://github.com/operator-framework/operator-sdk/settings/access)\n\n### Setting Up Tools for MacOS Users\n\nTo install the prerequisite tools on MacOS, complete the following steps:\n\n1. Install GNU `sed` and `make`, which may not be installed by default: \n\n   - ```sh\n      brew install gnu-sed make\n     ```\n\n1. Verify that the version of `make` is higher than 4.2 using command `make --version`.\n\n1. Add the gnubin directory for `make` to your PATH from your `~/.bashrc`\nto allow you to use `gmake` as `make`:\n\n   - ```sh\n     echo 'export PATH=\"/usr/local/opt/make/libexec/gnubin:$PATH\"' >> ~/.bashrc\n     ```\n\n1. Verify that the version of `sed` is higher than 4.3 using command `gnu-sed --version`.\n\n1. Add the gnubin directory for `gnu-sed` to your PATH from your `~/.bashrc`\nto allow you to use `gnu-sed` as `sed`:\n\n   - ```sh\n     echo 'export PATH=\"/usr/local/opt/gnu-sed/libexec/gnubin:$PATH\"' >> ~/.bashrc\n     ```\n\n## Major and Minor Releases\n\nWe will use the `v1.3.0` release version in this example.\n\n**Be sure to substitute\nthe version you are releasing into the provided commands.**\n\nTo perform a major or minor release, you must perform the following actions:\n\n- Ensure a new Netlify branch is created\n- Create a release branch and lock down the master branch\n- Create and merge a PR for the release branch\n- Unlock the master branch and push a release tag to it\n- Perform some clean up actions and announce the new release to the community\n\n### Procedure\n\n1. **Before creating a new release branch**, it is imperative to perform the following initial setup steps:\n   1. In the [Branches and deploy contexts](https://app.netlify.com/sites/operator-sdk/settings/deploys#branches)\n   pane in Netlify, click into the Additional branches list section and add `v1.13.x`.\n      - This will watch the branch when there are changes on Github (creating the branch, or adding a commit).\n      - NOTE: You must be a [Netlify admin][doc-owners] in order to edit the branches list.\n1. Create a release branch by running the following, assuming the upstream SDK repo is the `upstream` remote on your machine:\n\n   - ```sh\n     git checkout master\n     git fetch upstream master\n     git pull master\n     git checkout -b v1.3.x\n     git push upstream v1.3.x\n     ```\n\n1. Make sure that the list of supported OLM versions is up to date:\n   1. Identify if a new version of OLM needs to be officially supported by ensuring that the latest three releases listed on the [OLM release page](https://github.com/operator-framework/operator-lifecycle-manager/releases) are all listed as supported in the [Overview][overview] section of the SDK docs.\n   1. If a new version of OLM needs to be added and an old version removed, follow the steps in the [updating OLM bindata](#updating-olm-bindata) section before moving onto the next step.\n\n1. Lock down the `master` branch to prevent further commits before the release completes:\n   1. Go to `Settings -> Branches` in the SDK repo.\n   1. Under `Branch protection rules`, click `Edit` on the `master` branch rule.\n   1. In section `Protect matching branches` of the `Rule settings` box, increase the number of required approving reviewers to 6.\n   1. Scroll down to save your changes to protect the `master` branch.\n\n1. Create and push a release commit\n   1. Create a new branch to push the release commit:\n\n      - ```sh\n        export RELEASE_VERSION=v1.3.0\n        git checkout master\n        git pull master\n        git checkout -b release-$RELEASE_VERSION\n        ```\n\n   1. Update the top-level [Makefile] variable `IMAGE_VERSION`\nto the upcoming release tag `v1.3.0`. This variable ensures sample projects have been tagged\ncorrectly prior to the release commit.\n\n      - ```sh\n        sed -i -E 's/(IMAGE_VERSION = ).+/\\1v1\\.3\\.0/g' Makefile\n        ```\n\n        If this command fails on MacOS with a warning \"sed is not found\", follow the step 5 in the [Setting Up Tools for MacOS Users](#setting-up-tools-for-macos-users) section to map `gsed` to `sed`. \n   1. Run the pre-release `make` target:\n\n      - ```sh\n        make prerelease\n        ```\n\n      The following changes should be present:\n      - `Makefile`: IMAGE_VERSION should be modified to the upcoming release tag. (This variable ensures sampleprojects have been tagged correctly prior to the release commit.)\n      - `changelog/generated/v1.3.0.md`: commit changes (created by changelog generation).\n      - `changelog/fragments/*`: commit deleted fragment files (deleted by changelog generation).\n      - `website/content/en/docs/upgrading-sdk-version/v1.3.0.md`: commit changes (created by changelog generation).\n      - `website/config.toml`: commit changes (modified by release script).\n      - `testdata/*`: Generated sample code.\n   1. Commit these changes and push to your remote (assuming your remote is named `origin`):\n\n      - ```sh\n        git add Makefile changelog website testdata\n        git commit -sm \"Release $RELEASE_VERSION\"\n        git push origin release-$RELEASE_VERSION\n        ```\n\n1. Create and merge a new PR for the release-v1.3.0 branch created in step 5.4.\n   - You can force-merge your PR to the locked-down `master`\nif you have admin access to the operator-sdk repo, or ask an administrator to do so.\n   - Note that the docs PR check will fail because the site isn't published yet; the PR can be merged anyways.\n\n1. Unlock the `master` branch\n   1. Go to `Settings -> Branches` in the SDK repo.\n   1. Under `Branch protection rules`, click `Edit` on the `master` branch rule.\n   1. In section `Protect matching branches` of the `Rule settings` box, reduce the number of required approving reviewers back to 1.\n\n1. Create and push a release tag on `master`\n   1. Refresh your local `master` branch, tag the release PR commit, and push to the main operator-sdk repo (assumes the remote's name is `upstream`):\n\n      - ```sh\n        git checkout master\n        git pull master\n        make tag\n        git push upstream refs/tags/$RELEASE_VERSION\n        ```\n\n1. Fast-forward the `latest` and release branches\n   1. The `latest` branch points to the latest release tag to keep the main website subdomain up-to-date.\n   Run the following commands to do so:\n\n      - ```sh\n        git checkout latest\n        git reset --hard refs/tags/$RELEASE_VERSION\n        git push -f upstream latest\n        ```\n\n   1. Similarly, to update the release branch, run:\n\n      - ```sh\n        git checkout v1.3.x\n        git reset --hard refs/tags/$RELEASE_VERSION\n        git push -f upstream v1.3.x\n        ```\n\n1. Post release steps\n   1. Publish the new Netlify subdomain for version-specific docs. \n      1. Assuming that the Netlify prestep was done before the new branch was created, a new [branch option](https://app.netlify.com/sites/operator-sdk/settings/domain#branch-subdomains)\n      should be visible to Netlify Admins under Domain management > Branch subdomains and can be mapped to a subdomain. (Note: you may have to scroll down to the bottom of the Branch subdomains section to find the branch that is ready to be mapped.)\n      1. Please test that this subdomain works by going to the link in a browser. You can use the link in the second column to jump to the docs page for this release.\n   1. Make an [operator-framework Google Group][of-ggroup] post.\n      - You can use [this post](https://groups.google.com/g/operator-framework/c/2fBHHLQOKs8/m/VAd_zd_IAwAJ) as an example.\n   1. Post to Kubernetes slack in #kubernetes-operators and #operator-sdk-dev.\n      - You can use [this post](https://kubernetes.slack.com/archives/C017UU45SHL/p1679082546359389) as an example. \n   1. Clean up the GitHub milestone\n      1. In the [GitHub milestone][gh-milestones], bump any open issues to the following release.\n      1. Close out the milestone.\n   1. Update the newly unsupported branch documentation (1.1.x in this example)to mark it as archived. (Note that this step does not need to be merged before the release is complete.)\n      1. Checkout the newly unsupported release branch:\n\n         - ```sh\n           git checkout v1.1.x\n           ```\n\n      1. Modify the `website/config.toml` file on lines 88-90 to be the following:\n\n        - ```toml\n          version = \"v1.1\"\n          archived_version = true\n          url_latest_version = \"https://sdk.operatorframework.io\"\n          ```\n\n## Patch releases\n\nWe will use the `v1.3.1` release version in this example.\n\n### 0. Lock down release branches on GitHub\n\n1. Lock down the `v1.3.x` branch to prevent further commits before the release completes:\n   1. Go to `Settings -> Branches` in the SDK repo.\n   1. Under `Branch protection rules`, click `Edit` on the `v*.` branch rule.\n   1. In section `Protect matching branches` of the `Rule settings` box, increase the number of required approving reviewers to `6`.\n\n### 1. Branch\n\nCreate a new branch from the release branch (v1.3.x in this example). This branch should already exist prior to cutting a patch release.\n\n```sh\nexport RELEASE_VERSION=v1.3.1\ngit checkout v1.3.x\ngit pull\ngit checkout -b release-$RELEASE_VERSION\n```\n\n### 2. Prepare the release commit\n\nUsing the version for your release as the IMAGE_VERSION, execute the\nfollowing commands from the root of the project.\n\n```sh\n# Update the IMAGE_VERSION in the Makefile\nsed -i -E 's/(IMAGE_VERSION = ).+/\\1v1\\.3\\.1/g' Makefile\n#  Run the pre-release `make` target:\nmake prerelease\n```\n\nAll of the following changes should be present (and no others).\n\n- Makefile: IMAGE_VERSION should be modified to the upcoming release tag. (This variable ensures sampleprojects have been tagged correctpy priror to the release commit.)\n- changelog/: all fragments should be deleted and consolidated into the new file `changelog/generated/v1.3.1.md`\n- docs: If there are migration steps, a new migration doc will be created. The installation docs should also contain a link update.\n- testdata/: Generated samples and tests should have version bumps\n\nCommit these changes and push these changes **to your fork**:\n\n```sh\ngit add Makefile changelog website testdata\ngit commit -sm \"Release $RELEASE_VERSION\"\ngit push -u origin release-$RELEASE_VERSION\n```\n\n### 3. Create and merge Pull Request\n\n- Create a pull request against the `v1.3.x` branch.\n- Once approving review is given, merge. You may have to unlock the branch by setting\n\"required approving reviewers\" to back to `1`. (See step 0).\n\n### 4. Create a release tag\n\nPull down `v1.3.x` and tag it.\n\n```sh\ngit checkout v1.3.x\ngit pull upstream v1.3.x\nmake tag\ngit push upstream refs/tags/$RELEASE_VERSION\n```\n\n### 5. Fast-forward the `latest` branch\n\nIf the patch release is on the latest y-stream (in the example you would\nnot ff latest if there was a y-stream for v1.4.x), you will need to\nfast-forward the `latest` git branch.\n\n(The `latest` branch points to the latest release tag to keep the main website subdomain up-to-date.)\n\n```sh\ngit checkout latest\ngit reset --hard tags/$RELEASE_VERSION\ngit push -f upstream latest\n```\n\n### 6. Post release steps\n\n- Make an [operator-framework Google Group][of-ggroup] post.\n- Post to Kubernetes slack in #kubernetes-operators and #operator-sdk-dev.\n- In the [GitHub milestone][gh-milestones], bump any open issues to the following release.\n\n**Note**\nIn case there are non-transient errors while building the release job, you must:\n\n1. Revert the release PR. To do so, create a PR which reverts the patch release PR created in step [3](#3-create-and-merge-pull-request).\n2. Fix what broke in the release branch.\n3. Re-run the release with an incremented minor version to avoid Go module errors (ex. if v1.3.1 broke, then re-run the release as v1.3.2). Patch versions are cheap so this is not a big deal.\n\n## `scorecard-test-kuttl` image releases\n\nThe `quay.io/operator-framework/scorecard-test-kuttl` image is released separately from other images because it\ncontains the [`kudobuilder/kuttl`](https://hub.docker.com/r/kudobuilder/kuttl/tags) image, which is subject to breaking changes.\n\nRelease tags of this image are of the form: `scorecard-kuttl/vX.Y.Z`, where `X.Y.Z` is _not_ the current operator-sdk version.\nFor the latest version, query the [operator-sdk repo tags](https://github.com/operator-framework/operator-sdk/tags) for `scorecard-kuttl/v`.\n\nThe only step required is to create and push a tag.\nThis example uses version `v2.0.0`, the first independent release version of this image:\n\n```sh\nexport RELEASE_VERSION=scorecard-kuttl/v2.0.0\nmake tag\ngit push upstream refs/tags/$RELEASE_VERSION\n```\n\nThe [`deploy/image-scorecard-test-kuttl`](https://github.com/operator-framework/operator-sdk/actions/workflows/deploy.yml)\nAction workflow will build and push this image.\n\n## Helpful Tips and Information\n\n### Binaries and Signatures\n\nBinaries will be signed using our CI system's GPG key. Both binary and signature will be uploaded to the release.\n\n### Release Branches\n\nEach minor release has a corresponding release branch of the form `vX.Y.x`, where `X` and `Y` are the major and minor\nrelease version numbers and the `x` is literal. This branch accepts bug fixes according to our [backport policy][backports].\n\n### Cherry-picking\n\nOnce a minor release is complete, bug fixes can be merged into the release branch for the next patch release.\nFixes can be added automatically by posting a `/cherry-pick v1.3.x` comment in the `master` PR, or manually by running:\n\n```sh\ngit checkout v1.3.x\ngit checkout -b cherrypick/some-bug\ngit cherry-pick <commit>\ngit push upstream cherrypick/some-bug\n```\n\nCreate and merge a PR from your branch to `v1.3.x`.\n\n### GitHub Release Information\n\nGitHub releases live under the [`Releases` tab][release-page] in the operator-sdk repo.\n\n### Updating OLM Bindata\n\nPrior to an Operator SDK release, add bindata (if required) for a new OLM version by following these steps:\n\n1. Add the new version to the [`OLM_VERSIONS`][olm_version] variable in the Makefile.\n2. Remove the _lowest_ version from that variable, as `operator-sdk` only supports 3 versions at a time.\n3. Run `make bindata`.\n4. Check that all files were correctly updated by running this script from the root directory of the repository:\n\n   - ```sh\n     ./hack/check-olm.sh\n     ```\n\n     If the check shows that files were missed by the make target, manually edit them to add the new version and remove the obsolete version.\n5. Check that the list of supported OLM versions stated in the [`Overview`][overview] section of SDK documentation is updated.\n6. Add the changed files to ensure that they will be committed as part of the release commit:\n\n   - ```sh\n     git add -u\n     ```\n\n### Patch Releases in Parallel\n\nThe following should be considered when doing parallel patch releases:\n\n- Releasing in order is nice but not worth the inconvenience. Release order affects the order on GitHub releases, and which\n    is labeled \"latest release\".\n- Do not unlock v.* branches while other releases are in progress. Instead, have an admin do the merges.\n- Release announcements should be consolidated.\n\n[doc-owners]: https://github.com/operator-framework/operator-sdk/blob/master/OWNERS\n[release-page]:https://github.com/operator-framework/operator-sdk/releases\n[backports]:/docs/upgrading-sdk-version/backport-policy\n[of-ggroup]:https://groups.google.com/g/operator-framework\n[gh-milestones]:https://github.com/operator-framework/operator-sdk/milestones\n[Makefile]:https://github.com/operator-framework/operator-sdk/blob/master/Makefile\n[olm_version]:https://github.com/operator-framework/operator-sdk/blob/6002c70fe770cdaba9ba99da72685e0e7b6b69e8/Makefile#L45\n[overview]: https://github.com/operator-framework/operator-sdk/blob/master/website/content/en/docs/overview/_index.md#olm-version-compatibility\n"
  },
  {
    "path": "website/content/en/docs/contribution-guidelines/reporting-issues.md",
    "content": "---\ntitle: Reporting Issues\nlinkTitle: Reporting Issues\nweight: 5\n---\n\nIf any part of the operator-sdk project has bugs or documentation mistakes, please let us know by [opening an issue][operator-sdk-issue]. We treat bugs and mistakes very seriously and believe no issue is too small. Before creating a bug report, please check that an issue reporting the same problem does not already exist.\n\nTo make the bug report accurate and easy to understand, please try to create bug reports that are:\n\n- Specific. Include as much details as possible: which version, what environment, what configuration, etc.\n\n- Reproducible. Include the steps to reproduce the problem. We understand some issues might be hard to reproduce, please include the steps that might lead to the problem.\n\n- Isolated. Please try to isolate and reproduce the bug with minimum dependencies. It would significantly slow down the speed to fix a bug if too many dependencies are involved in a bug report. Debugging external systems that rely on operator-sdk is out of scope, but we are happy to provide guidance in the right direction or help with using operator-sdk itself.\n\n- Unique. Do not duplicate existing bug report.\n\n- Scoped. One bug per report. Do not follow up with another bug inside one report.\n\nIt may be worthwhile to read [Elika Etemad’s article on filing good bug reports][filing-good-bugs] before creating a bug report.\n\nWe might ask for further information to locate a bug. A duplicated bug report will be closed.\n\n[operator-sdk-issue]: https://github.com/operator-framework/operator-sdk/issues/new\n[filing-good-bugs]: https://fantasai.inkedblade.net/style/talks/filing-good-bugs/\n"
  },
  {
    "path": "website/content/en/docs/contribution-guidelines/testing.md",
    "content": "---\ntitle: Testing\nlinkTitle: Testing\nweight: 6\n---\n\nOn all PRs, a suite of static and cluster tests is run against your changes in a CI environment.\nThese tests can also be run locally, which is discussed [below](#local-test-environment).\n\nStatic tests consist of [unit][unit-tests], formatting, and doc link tests.\n\nCluster tests consist of several test types:\n- End-to-end (e2e): simulate the \"happy path\" usage of the `operator-sdk` binary and resulting operator project.\n- Integration: test components of the `operator-sdk` binary and features of scaffolded projects that are\nbound to external projects, such as [OLM][olm].\n- Subcommand: ensure individual subcommands function as intended with a variety of input options.\n\n## Before submitting a PR\n\nAlways run tests before submitting a PR to reduce the number of needless CI errors.\n\n##### Docs only\n\n```sh\nmake test-static\n```\n\n##### Code\n\n```sh\nmake test-all\n```\n\n\n## Local Test Environment\n\nIf running tests locally, access to a Kubernetes cluster of a [compatible version][k8s-version-compat] is required.\nThese tests require `KUBECONFIG` be set or kubeconfig file be present in a default location like `$HOME/.kube/config`.\n\nYou will also need to set up an `envtest` environment for cluster tests. Follow [this doc][envtest-setup]\nfor setup instructions.\n\n### Local clusters\n\nA local [kind][kind] cluster is used for running tests.\n\n## Running Tests\n\nAll the tests are run through the [`Makefile`][makefile]. Run `make help` for a full list of available tests.\n\n[unit-tests]: https://onsi.github.io/gomega/\n[olm]: https://olm.operatorframework.io/\n[minikube]: https://kubernetes.io/docs/setup/learning-environment/minikube/\n[kind]: https://kind.sigs.k8s.io/\n[envtest-setup]:https://book.kubebuilder.io/reference/envtest.html\n[makefile]: https://github.com/operator-framework/operator-sdk/blob/master/Makefile\n[k8s-version-compat]:/docs/overview#kubernetes-version-compatibility\n"
  },
  {
    "path": "website/content/en/docs/faqs/_index.md",
    "content": "---\ntitle: Operator SDK FAQ\nlinkTitle: FAQ\nweight: 12\n---\n\n## What are the differences between Kubebuilder and Operator-SDK?\n\nKubebuilder and Operator SDK are both projects that allow you to quickly create and manage an operator project. Operator SDK uses Kubebuilder under the hood to do so for Go projects, such that the `operator-sdk` CLI tool will work with a project created by `kubebuilder`. Therefore each project makes use of [controller-runtime][controller-runtime] and will have the same [basic layout][kb-doc-what-is-a-basic-project]. For further information also check the [SDK Project Layout][project-doc].\n\nOperator SDK offers additional features on top of the basic project scaffolding that Kubebuilder provides. By default, `operator-sdk init` generates a project integrated with:\n- [Operator Lifecycle Manager][olm], an installation and runtime management system for operators\n- [OperatorHub][operatorhub.io], a community hub for publishing operators\n- Operator SDK [scorecard][scorecard-doc], a tool for ensuring operator best-practices and developing cluster tests\n\nOperator SDK supports operator types other than Go as well, such as Ansible and Helm.\n\nFor further context about the relationship between Kubebuilder and Operator SDK, see [this blog post][operator-sdk-reaches-v1.0].\n\n## Can I use the Kubebuilder docs?\n\nYes, you can use [https://book.kubebuilder.io/](https://book.kubebuilder.io/). Just keep in mind that when you see an instruction such as:\n`$ kubebuilder <command>` you will use `$ operator-sdk <command>`.\n\n## Controller Runtime FAQ\n\nPlease see the upstream [Controller Runtime FAQ][cr-faq] first for any questions related to runtime mechanics or controller-runtime APIs.\n\n## Can I customize the projects initialized with `operator-sdk`?\n\nAfter using the CLI to create your project, you are free to customize based on how you see fit. Please note that it is not recommended to deviate from the proposed layout unless you know what you are doing.\n\nFor example, you should refrain from moving the scaffolded files, doing so will make it difficult to upgrade your project in the future. You may also lose the ability to use some of the CLI features and helpers. For further information on the project layout, see the doc [Project Layout][project-doc]\n\n## How can I have separate logic for Create, Update, and Delete events? When reconciling an object can I access its previous state?\n\nYou should not have separate logic. Instead design your reconciler to be idempotent. See the [controller-runtime FAQ][cr-faq] for more details.\n\n## How do I wait for some specific cluster state such as a resource being deleted?\n\nYou don't. Instead, design your reconciler to be idempotent by  taking the next step based on the current state, and then returning and requeuing. For example, waiting for an object to be deleted might look something like this:\n\n```\nfunc (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (res ctrl.Result, err error) {\n    ...\n    if !r.IfPodWasDeleted(ctx, pod) {\n        if err := r.Delete(ctx, pod); err != nil {\n            return ctrl.Result{}, err\n        }\n        return ctrl.Result{Requeue: true}, nil\n    }\n    // This code will be invoked only after pod deletion    \n    r.DeployBiggerPod(ctx)\n    ...\n}\n```\n\n\n## When my Custom Resource is deleted, I need to know its contents or perform cleanup tasks. How can I do that?\n\nUse a [finalizer].\n\n## I see the warning in my Operator's logs: `The resourceVersion for the provided watch is too old.` What's wrong?\n\nThis is completely normal and expected behavior.\n\nThe `kube-apiserver` watch request handler is designed to periodically close a watch to spread out load among controller node instances. Once disconnected, your Operator's informer will automatically reconnect and re-establish the watch. If an event is missed during re-establishment, the watch will fail with the above warning message. The Operator's informer then does a list request and uses the new `resourceVersion` from that list to restablish the watch and replace the cache with the latest objects.\n\nThis warning should not be stifled. It ensures that the informer is not stuck or wedged.\n\nNever seeing this warning may suggest that your watch or cache is not healthy. If the message is repeating every few seconds, this may signal a network connection problem or issue with etcd.\n\nFor more information on `kube-apiserver` request timeout options, see the [Kubernetes API Server Command Line Tool Reference][kube-apiserver_options]\n\n\n## My Ansible module is missing a dependency. How do I add it to the image?\n\nUnfortunately, adding the entire dependency tree for all Ansible modules would be excessive. Fortunately, you can add it easily. Simply edit your build/Dockerfile. You'll want to change to root for the install command, just be sure to swap back using a series of commands like the following right after the `FROM` line.\n\n```docker\nUSER 0\nRUN yum -y install my-dependency\nRUN pip3 install my-python-dependency\nUSER 1001\n```\n\nIf you aren't sure what dependencies are required, start up a container using the image in the `FROM` line as root. That will look something like this:\n```sh\ndocker run -u 0 -it --rm --entrypoint /bin/bash quay.io/operator-framework/ansible-operator:<sdk-tag-version>\n```\n\n## After deploying my operator, I see errors like \"Failed to watch <external type>\"\n\nIf you run into the following error message, it means that your operator is unable to watch the resource:\n\n```\nE0320 15:42:17.676888       1 reflector.go:280] pkg/mod/k8s.io/client-go@v0.0.0-20191016111102-bec269661e48/tools/cache/reflector.go:96: Failed to watch *v1.ImageStreamTag: unknown (get imagestreamtags.image.openshift.io)\n{\"level\":\"info\",\"ts\":1584718937.766342,\"logger\":\"controller_memcached\",\"msg\":\"ImageStreamTag resource not found.\n```\n\nUsing controller-runtime's split client means that read operations (gets and lists) are read from a cache, and write operations are written directly to the API server. To populate the cache for reads, controller-runtime initiates a `list` and then a `watch` even when your operator is only attempting to `get` a single resource. The above scenario occurs when the operator does not have an [RBAC][rbac] permission to `watch` the resource. The solution is to add an RBAC directive to generate a `config/rbac/role.yaml` with `watch` privileges:\n\n```go\n//+kubebuilder:rbac:groups=some.group.com,resources=myresources,verbs=watch\n```\n\nAlternatively, if the resource you're attempting to cannot be watched (like `v1.ImageStreamTag` above), you can specify that objects of this type should not be cached by adding the following to `main.go`:\n\n```go\nimport (\n\t...\n\timagev1 \"github.com/openshift/api/image/v1\"\n)\n\nvar (\n\tscheme = runtime.NewScheme()\n)\n\nfunc init() {\n\tutilruntime.Must(clientgoscheme.AddToScheme(scheme))\n\t// Add imagev1's scheme.\n\tutilruntime.Must(imagev1.AddToScheme(scheme))\n}\n\nfunc main() {\n\tmgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{\n\t\tScheme:        scheme,\n\t\t// Specify that ImageStreamTag's should not be cached.\n\t\tClientDisableCacheFor:  []client.Object{&imagev1.ImageStreamTag{}},\n\t})\n}\n```\n\nThen in your controller file, add an RBAC directive to generate a `config/rbac/role.yaml` with `get` privileges:\n\n```go\n//+kubebuilder:rbac:groups=image.openshift.io,resources=imagestreamtags,verbs=get\n```\n\nNow run `make manifests` to update your `role.yaml`.\n\n\n## After deploying my operator, why do I see errors like \"is forbidden: cannot set blockOwnerDeletion if an ownerReference refers to a resource you can't set finalizers on: ...\"?\n\nIf you are facing this issue, it means that the operator is missing the required RBAC permissions to update finalizers on the APIs it manages. This permission is necessary if the [OwnerReferencesPermissionEnforcement][owner-references-permission-enforcement] plugin is enabled in your cluster.\n\nFor Helm and Ansible operators, this permission is configured by default. However for Go operators, it may be necessary to add this permission yourself\nby adding an RBAC directive to generate a `config/rbac/role.yaml` with `update` privileges on your CR's finalizers:\n\n```go\n//+kubebuilder:rbac:groups=cache.example.com,resources=memcacheds/finalizers,verbs=update\n```\n\nNow run `make manifests` to update your `role.yaml`.\n\n## When invoking `make` targets, why do I see errors like `fork/exec /usr/local/kubebuilder/bin/etcd: no such file or directory occurred`?\n\nIf using an OS or distro that does not point `sh` to the `bash` shell (Ubuntu for example), add the following line to the `Makefile`:\n\n```make\nSHELL := /bin/bash\n```\n\n## How do I make my Operator proxy-friendly?\n---\n\nAdministrators can configure proxy-friendly Operators to support network proxies by\nspecifying `HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY` environment\nvariables in the Operator deployment. (These variables can be handled by OLM.)\n\nProxy-friendly Operators are responsible for inspecting the Operator\nenvironment and passing these variables along to the rquired operands.\nFor more information and examples, please see the type-specific docs:\n- [Ansible][ansible-proxy-vars]\n- [Golang][go-proxy-vars]\n- [Helm][helm-proxy-vars]\n\n\n## After running `make manifests`, `rbac` permissions are not updated in config\n\n[RBAC markers][rbac-markers] that are not followed by a newline will not be\nparsed correctly, resulting in missing `rbac` configuration.\n\nThis is a known issue with `controller-tools`, see [issue #551][controller-tools-issue-551]\nThe current workaround is to add a new line after the `rbac` marker.\n\n```go\n// +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete\n// +kubebuilder:rbac:groups=core,resources=pods,verbs=get;list;\n\nfunc (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {\n```\n\n[ansible-proxy-vars]: /docs/building-operators/ansible/reference/proxy-vars/\n[client.Reader]:https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/client#Reader\n[controller-runtime]: https://github.com/kubernetes-sigs/controller-runtime\n[cr-faq]:https://github.com/kubernetes-sigs/controller-runtime/blob/master/FAQ.md\n[finalizer]:/docs/building-operators/golang/advanced-topics/#handle-cleanup-on-deletion\n[go-proxy-vars]: /docs/building-operators/golang/references/proxy-vars/\n[helm-proxy-vars]: /docs/building-operators/helm/reference/proxy-vars/\n[kb-doc-what-is-a-basic-project]: https://book.kubebuilder.io/cronjob-tutorial/basic-project.html\n[kube-apiserver_options]: https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/#options\n[olm]:  https://github.com/operator-framework/operator-lifecycle-manager\n[operator-sdk-reaches-v1.0]: https://www.openshift.com/blog/operator-sdk-reaches-v1.0\n[operatorhub.io]: https://operatorhub.io/\n[owner-references-permission-enforcement]: https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#ownerreferencespermissionenforcement\n[rbac-markers]: https://book.kubebuilder.io/reference/markers/rbac.html\n[rbac]:https://kubernetes.io/docs/reference/access-authn-authz/rbac/\n[scorecard-doc]: https://sdk.operatorframework.io/docs/testing-operators/scorecard/\n[project-doc]: /docs/overview/project-layout\n[controller-tools-issue-551]: https://github.com/kubernetes-sigs/controller-tools/issues/551\n\n## Preserve the `preserveUnknownFields` in your CRDs\n\nThe [`preserveUnknownFields`](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#field-pruning) will be removed if set to false when running `make bundle`. Because of some underlying data structure changes and how yaml is unmarshalled, it is best to add them back in after they have been written.\n\nYou can use this script to post process the files to add the `preserveUnknownFields` back in.\n\n```sh\nfunction generate_preserveUnknownFieldsdata() {\n    for j in config/crd/patches/*.yaml ; do\n        if grep -qF \"preserveUnknownFields\" \"$j\";then\n            variable=`awk '/metadata/{flag=1} flag && /name:/{print $NF;flag=\"\"}' \"$j\"`\n            for k in config/crd/bases/*.yaml ; do\n                if grep -qF \"$variable\" \"$j\";then\n                    filename=`awk 'END{ var=FILENAME; split (var,a,/\\//); print a[4]}' \"$k\"`\n                    awk '/^spec:/{print;print \"  preserveUnknownFields: false\";next}1' \"bundle/manifests/$filename\" > testfile.tmp && mv testfile.tmp \"bundle/manifests/$filename\"\n                fi\n            done\n        fi\n    done\n}\n\ngenerate_preserveUnknownFieldsdata\n```\n\nYou can then modify the `bundle` target in your `Makefile` by adding a call to the script at the end of the target. See the example below:\n\n```\n.PHONY: bundle\nbundle: manifests kustomize ## Generate bundle manifests and metadata, then validate generated files.\n\toperator-sdk generate kustomize manifests -q\n\tcd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG)\n\t$(KUSTOMIZE) build config/manifests | operator-sdk generate bundle -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS)\n\toperator-sdk bundle validate ./bundle | ./preserve_script.sh\n```\n\nNote:\nThough this is a bug with controller-gen which is used by Operator SDK to generate CRD, this is a workaround from our end to enable users to preserve the field after controller-gen has run.\n\n## What is the bundle limit size? Was this amount increased?\n\nBundles have a size limitation because their manifests are used to create a configMap, and the Kubernetes API does not \nallow configMaps larger than `~1MB`. Beginning with [OLM](https://github.com/operator-framework/operator-lifecycle-manager) version `v0.19.0` \nand [OPM](https://github.com/operator-framework/operator-registry) `1.17.5`, \nthese values are now compressed accommodating larger bundles. ([More info](https://github.com/operator-framework/operator-registry/pull/685)).\n\nThe change to allow bigger bundles from [OLM](https://github.com/operator-framework/operator-lifecycle-manager) version `v0.19.0` only impacts the full bundle size amount. \nAny single manifest within the bundle such as the CRD will still make the bundle uninstallable if it exceeds the default file size limit on clusters (`~1MB`).\n\n## The size of my Operator bundle is too big. What can I do?\n\nIf your bundle is too large, there are a few things you can try:\n\n  * Reducing the number of [CRD versions][k8s-crd-versions] supported in your Operator by deprecating and then removing older API versions. It is a good idea to have a clear plan for deprecation and removal of old CRDs versions when new ones get added, see [Kubernetes API change practices][k8s-api-change]. Also, refer to the [Kubernetes API conventions][k8s-api-convention].\n  * Reduce the verbosity of your API documentation. (We do not recommend eliminating documenting the APIs)\n\n## How can I update dependencies for an unsupported release image?\n\nThe Operator-SDK community releases updated images for supported\nreleases. If you are using an older version of Operator-SDK, sometimes\nthe dependencies will need to be updated in the images. For users in\nthis situation we recommend updating to the latest version. If this is\nnot possible, users can build and push their own versions of any of the\nimages provided by the Operator-SDK. \n\n**Operator-SDK**\ndocker buildx build  -t quay.io/operator-framework/operator-sdk:dev -f ./images/operator-sdk/Dockerfile --load .\n\n**Helm-Operator**\ndocker buildx build  -t quay.io/operator-framework/helm-operator:dev -f ./images/helm-operator/Dockerfile --load .\n\n**Scorecard-test**\ndocker buildx build  -t quay.io/operator-framework/scorecard-test:dev -f ./images/scorecard-test/Dockerfile --load .\n\n**Scorecard-test-kuttl**\ndocker buildx build  -t quay.io/operator-framework/scorecard-test-kuttl:dev -f ./images/scorecard-test-kuttl/Dockerfile --load .\n\n\n### Ansible\n\nAnsible images are built in 2 layers, and both will need to be rebuilt.\nBuild and push the dependency image\n`images/ansible-operator/base.Dockerfile`, and then update `FROM` in\n`images/ansible-operator/Dockerfile` to point to your image, and build\nand push this image, which can be added to your operator's  `FROM`.\n\n**Ansible Operator (2.9) base**\n`docker buildx build  -t quay.io/operator-framework/ansible-operator-base:dev -f ./images/ansible-operator/base.Dockerfile --load images/ansible-operator`\n\n**Ansible Operator (2.9)**\n`docker buildx build  -t quay.io/operator-framework/ansible-operator:dev -f ./images/ansible-operator/Dockerfile --load .`\n\n**Ansible Operator (2.11) Dependencies**\n`docker buildx build  -t quay.io/operator-framework/ansible-operator-2.11-preview-base:dev -f ./images/ansible-operator-2.11-preview/base.Dockerfile --load images/ansible-operator-2.11-preview`\n\n**Ansible Operator (2.11)**\n`docker buildx build  -t quay.io/operator-framework/ansible-operator-2.11-preview:dev -f ./images/ansible-operator-2.11-preview/Dockerfile --load .`\n\n\n[k8s-crd-versions]: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definition-versioning/#specify-multiple-versions\n[k8s-api-change]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api_changes.md\n[k8s-api-convention]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md\n\n## Running `operator-sdk create api` results in an error with `/usr/local/go/src/net/cgo_linux.go:13:8: no such package located` in the error message\n\nBy default Go will set the `CGO_ENABLED` environment variable to `1` which means that [cgo][cgo-docs] is enabled. Depending on the architecture and OS of your system you may run into an issue similar to this one: \n\n```sh\n/usr/local/go/src/net/cgo_linux.go:13:8: no such package located\nError: not all generators ran successfully\nrun `controller-gen object:headerFile=hack/boilerplate.go.txt paths=./... -w` to see all available markers, or `controller-gen object:headerFile=hack/boilerplate.go.txt paths=./... -h` for usage\nmake: *** [Makefile:95: generate] Error 1\nError: failed to create API: unable to run post-scaffold tasks of \"base.go.kubebuilder.io/v3\": exit status 2\n```\n\nHere are a couple workarounds to try to resolve the issue:\n\n- Ensure `gcc` is installed\n- Set the `CGO_ENABLED` environment variable to `0` to disable [cgo][cgo-docs]\n\nIf neither of those solutions work for you, please [open an issue][open-issue]\n\n## After updating my project to use a Kustomize 4.x version, 'make bundle' does not work\n\n**Valid only for Golang/Hybrid projects using webhooks**\n\n> `Error: remove operation does not apply:doc is missing path: \"/spec/template/spec/containers/1/volumeMounts/0\": missing value` \n\nThe error occurs due to a change in the Kustomize 4.x versions where the containers used in the Deployment spec of your CSV\nare no longer added at the same order. To sort it out you can update replace the target `/spec/template/spec/containers/1/volumeMounts/0`\nwith `/spec/template/spec/containers/0/volumeMounts/0` in `config/manifest/kustomization.yaml`.\n\n**NOTE** You MUST use SDK CLI versions > 1.22. Previous versions have a bug \nwhere the command `operator-sdk generate kustomize manifests` is not respecting the changes\nmade on this manifest. \n\n[cgo-docs]: https://pkg.go.dev/cmd/cgo\n[open-issue]: https://github.com/operator-framework/operator-sdk/issues/new/choose\n\n## 'operator-sdk run bundle' command fails and the registry pod has an error of 'mkdir: can't create directory '/database': Permission denied'\n\nIn Operator SDK version `v1.22.0`, the `operator-sdk run bundle` command started using the new file-based catalog (FBC) bundle format by default. Earlier releases used the deprecated SQLite format. The command uses `quay.io/operator-framework/opm:latest` as the index image for creating a registry pod. Due to recent pod security updates, using the latest version of `opm` does not work as expected with the SQLite bundle format.\n\nThere are two workarounds available to resolve this issue:\n1. You can update the Operator SDK to version `v1.22.0` or later. Updating to a more recent version makes `operator-sdk run bundle` utilize the new FBC bundle format.\n2. If you are not ready to update your version of the Operator SDK, you can manually specify the index image by using the `--index-image=quay.io/operator-framework/opm:v1.23.0` flag.\n\n**Note:** The SQLite bundle format is deprecated and will be removed in a future release. If you can, it is recommended that you upgrade a newer version of the Operator SDK to resolve the issue.\n"
  },
  {
    "path": "website/content/en/docs/installation/_index.md",
    "content": "---\ntitle: Installation\nlinkTitle: Installation\nweight: 2\ndescription: Install the Operator SDK CLI\n---\n\n- [Install from Homebrew (macOS)](#install-from-homebrew-macos)\n- [Install from GitHub release](#install-from-github-release)\n- [Compile and install from master](#compile-and-install-from-master)\n\n## Install from Homebrew (macOS)\n\nIf you are using [Homebrew][homebrew_tool], you can install the SDK CLI tool with the following command:\n\n```sh\nbrew install operator-sdk\n```\n\n## Install from GitHub release\n\n#### Prerequisites\n\n- [curl](https://curl.haxx.se/)\n- [gpg](https://gnupg.org/) version 2.0+\n\n#### 1. Download the release binary\n\nSet platform information:\n\n```sh\nexport ARCH=$(case $(uname -m) in x86_64) echo -n amd64 ;; aarch64) echo -n arm64 ;; *) echo -n $(uname -m) ;; esac)\nexport OS=$(uname | awk '{print tolower($0)}')\n```\n\nDownload the binary for your platform:\n\n```sh\nexport OPERATOR_SDK_DL_URL=https://github.com/operator-framework/operator-sdk/releases/download/v1.42.2\ncurl -LO ${OPERATOR_SDK_DL_URL}/operator-sdk_${OS}_${ARCH}\n```\n\n#### 2. Verify the downloaded binary\n\nImport the operator-sdk release GPG key from `keyserver.ubuntu.com`:\n\n```sh\ngpg --keyserver keyserver.ubuntu.com --recv-keys 052996E2A20B5C7E\n```\n\nDownload the checksums file and its signature, then verify the signature:\n\n```sh\ncurl -LO ${OPERATOR_SDK_DL_URL}/checksums.txt\ncurl -LO ${OPERATOR_SDK_DL_URL}/checksums.txt.asc\ngpg -u \"Operator SDK (release) <cncf-operator-sdk@cncf.io>\" --verify checksums.txt.asc\n```\n\nYou should see something similar to the following:\n\n```console\ngpg: assuming signed data in 'checksums.txt'\ngpg: Signature made Fri 30 Oct 2020 12:15:15 PM PDT\ngpg:                using RSA key ADE83605E945FA5A1BD8639C59E5B47624962185\ngpg: Good signature from \"Operator SDK (release) <cncf-operator-sdk@cncf.io>\" [ultimate]\n```\n\nMake sure the checksums match:\n\n```sh\ngrep operator-sdk_${OS}_${ARCH} checksums.txt | sha256sum -c -\n```\n\nYou should see something similar to the following:\n\n```console\noperator-sdk_linux_amd64: OK\n```\n\n#### 3. Install the release binary in your PATH\n\n```sh\nchmod +x operator-sdk_${OS}_${ARCH} && sudo mv operator-sdk_${OS}_${ARCH} /usr/local/bin/operator-sdk\n```\n\n## Compile and install from master\n\n#### Prerequisites\n\n- [git][git_tool]\n- [go][go_tool] version 1.23\n  - Ensure that your `GOPROXY` is set to `\"https://proxy.golang.org|direct\"`\n\n```sh\ngit clone https://github.com/operator-framework/operator-sdk\ncd operator-sdk\ngit checkout master\nmake install\n```\n\n[homebrew_tool]:https://brew.sh/\n[git_tool]:https://git-scm.com/downloads\n[go_tool]:https://golang.org/dl/\n"
  },
  {
    "path": "website/content/en/docs/olm-integration/_index.md",
    "content": "---\ntitle: Operator SDK Integration with Operator Lifecycle Manager\nlinkTitle: OLM Integration\nweight: 8\ndescription: Use operator-sdk to install OLM, package operators for OLM, and install and run Operators with OLM\n---\n"
  },
  {
    "path": "website/content/en/docs/olm-integration/cli-overview.md",
    "content": "---\ntitle: OLM and Bundle CLI Overview\nlinkTitle: CLI Overview\nweight: 10\n---\n\nThis document gives an overview of using `operator-sdk` to work with Operator manifests related to OLM,\nnamely [bundles][bundle] and [package manifests][package-manifests]. See the [manifests generation][doc-olm-generate]\ndoc for an in-depth discussion of these commands.\n\n## OLM installation\n\nThe following `operator-sdk` subcommands manage an OLM installation:\n\n- [`olm install`][cli-olm-install]: install a particular version of OLM.\n- [`olm status`][cli-olm-status]: check the status of a particular version of OLM running in a cluster. This command\ncan infer the version of an error-free OLM installation.\n- [`olm uninstall`][cli-olm-uninstall]: uninstall a particular version of OLM running in a cluster. This command\ncan infer the version of an error-free OLM installation.\n\n## Manifests and metadata\n\nThe following `make` recipes and `operator-sdk` subcommands create or interact with Operator package manifests and bundles:\n\n- [`generate kustomize manifests`][cli-gen-kustomize-manifests]: creates kustomize bases and a `kustomization.yaml` in `config/manifests`.\n\n### Bundles\n\n- `make bundle`: runs the following commands:\n  - `generate kustomize manifests`: see [above](#manifests-and-metadata).\n  - [`generate bundle`][cli-gen-bundle]: creates a new or updates an existing bundle in the `<project-root>/bundle`\n  directory. This command generates both manifests and metadata.\n  - [`bundle validate`][cli-bundle-validate]: validates an Operator bundle image or unpacked manifests and metadata.\n- `make bundle-build`: builds a bundle image using the `bundle.Dockerfile` generated by `make bundle`.\n- [`run bundle`][cli-run-bundle]: runs the given Operator's bundle image with an\n  existing OLM installation.\n- [`run bundle-upgrade`][cli-run-bundle-upgrade]: upgrades the Operator bundle to a specified newer version.\n\n#### Private bundle and catalog image registries\n\nBy default, projects are configured to push to and pull from a [docker.io] registry\nwith namespace being the value passed to `operator-sdk init --domain=<value>`.\nModify this value to push/pull bundle and catalog images with a different registry host or namespace.\n\nAll bundle and catalog image-related commands invoke [`opm`][opm] (except for bundle image builds,\nfor which `docker` is used directly). `opm` leverages the host's image build/pull tools indirectly\nto perform various image tasks, so if your image registry is private or has a custom CA you\nmust ensure the in-use build tool is able to push to/pull from the registry:\n- `docker`: [`config.json`][docker-pull-sec], [certificate configuration][docker-certs]\n- `podman`: [`auth.json`][podman-pull-sec], [certificate configuration][podman-certs]\n- `none` (containerd): uses docker's `config.json`, [certificate configuration][none-certs]\n\nThe `run bundle` or `run bundle-upgrade` commands use the `none` image tool, described above, in-cluster.\nThese commands accept the names of secrets available in the deployment namespace that contain configuration file data.\nIdeally a cluster admin will provision a namespace and service account for bundle testing,\nsuch that they include and reference these secrets:\n- Create an [image pull secret][k8s-image-pull-sec] for your `config.json` and [add it to your service account][k8s-pull-sec-sa].\n<!-- TODO(estroz): remove the service account requirement once OLM releases a patch or new\nminor release containing https://github.com/operator-framework/operator-lifecycle-manager/pull/1941 -->\n- Create a [generic secret][k8s-gen-sec] with a `cert.pem` key containing root certificate(s) for your registry.\n\nOnce the above secrets have been created, run the either command with `--pull-secret-name=<image pull secret>` and `--ca-secret-name=<certificate secret>`:\n\n```sh\noperator-sdk run bundle private-custom-ca-reg.com/memcached-operator-bundle:v0.0.2 \\\n    --index-image private-custom-ca-reg.com/memcached-operator-catalog:v0.0.1 \\\n    --pull-secret-name foo-pull-sec \\\n    --ca-secret-name foo-cert-sec\n```\n\nYou may have to set `--namespace=<provisioned namespace>` if the namespace encoded in your kubeconfig's current context\nwas not provisioned with these secrets.\n\n[docker.io]:https://hub.docker.com/\n[opm]:https://github.com/operator-framework/operator-registry/blob/496ccce/docs/design/opm-tooling.md\n[docker-pull-sec]:https://docs.docker.com/engine/reference/commandline/login/\n[docker-certs]:https://docs.docker.com/engine/security/certificates/\n[podman-pull-sec]:http://docs.podman.io/en/latest/markdown/podman-login.1.html#description\n[podman-certs]:http://docs.podman.io/en/latest/markdown/podman-image-sign.1.html#cert-dir-path\n[none-certs]:https://github.com/operator-framework/operator-registry/blob/master/docs/design/opm-tooling.md#add\n[k8s-image-pull-sec]:https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/\n[k8s-pull-sec-sa]:https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#add-image-pull-secret-to-service-account\n[k8s-gen-sec]:https://kubernetes.io/docs/tasks/configmap-secret/managing-secret-using-kubectl/#create-a-secret\n\n### Package Manifests\n\nThe operator-framework is removing support for the packagemanifests format in the near future, and migration efforts are currently underway. Therefore `generate packagemanifests` and `run packagemanifests` commands have been deprecated. For more\ndetails on bundle format refer [here][bundle]. To migrate from packagemanifests to the bundle format, use the [`operator-sdk pkgman-to-bundle`][cli-pkgman-to-bundle] command.\n\n\n\n[bundle]:https://github.com/operator-framework/operator-registry/blob/v1.16.1/docs/design/operator-bundle.md\n[package-manifests]:https://github.com/operator-framework/operator-registry/tree/v1.5.3#manifest-format\n[doc-olm-generate]:/docs/olm-integration/generation\n[cli-olm-install]:/docs/cli/operator-sdk_olm_install\n[cli-olm-status]:/docs/cli/operator-sdk_olm_status\n[cli-olm-uninstall]:/docs/cli/operator-sdk_olm_uninstall\n[cli-gen-bundle]:/docs/cli/operator-sdk_generate_bundle\n[cli-run-bundle]:/docs/cli/operator-sdk_run_bundle\n[cli-gen-kustomize-manifests]:/docs/cli/operator-sdk_generate_kustomize_manifests\n[cli-bundle-validate]:/docs/cli/operator-sdk_bundle_validate\n[doc-testing-deployment]:/docs/olm-integration/testing-deployment\n[cli-run-bundle-upgrade]: /docs/cli/operator-sdk_run_bundle-upgrade\n[cli-pkgman-to-bundle]: /docs/cli/operator-sdk_pkgman-to-bundle\n"
  },
  {
    "path": "website/content/en/docs/olm-integration/generation.md",
    "content": "---\ntitle: Generating Manifests and Metadata\nlinkTitle: Generating Manifests and Metadata\nweight: 20\n---\n\nThis document describes how to manage packaging and shipping your Operator in the following stages:\n\n* **Generate your first release** - encapsulate the metadata needed to install your Operator with the\n[Operator Lifecycle Manager][olm] and configure the permissions it needs from the generated SDK files.\n* **Update your Operator** - apply any updates to Operator manifests made during development.\n* **Upgrade your Operator** - carry over any customizations you have made and ensure a rolling update to the\nnext version of your Operator.\n\n## Overview\n\nSeveral `operator-sdk` subcommands manage operator-framework manifests and metadata,\nin particular [`ClusterServiceVersion`'s (CSVs)][doc-csv], for an Operator: [`generate bundle`][cli-gen-bundle] and [`generate kustomize manifests`][cli-gen-kustomize-manifests].\nSee this [CLI overview][cli-overview] for details on each command.\n\n**Note:** The packagemanifests format is deprecated and support will be removed in `operator-sdk` v2.0.0.\n\n### Kustomize files\n\n`operator-sdk generate kustomize manifests` generates a CSV kustomize base\n`config/manifests/bases/<project-name>.clusterserviceversion.yaml` and a `config/manifests/kustomization.yaml`\nby default. These files are required as `kustomize build` input in downstream commands.\n\nBy default, the command starts an interactive prompt if a CSV base in `config/manifests/bases` is not present\nto collect [UI metadata](#csv-fields). You can disable the interactive prompt by passing `--interactive=false`.\n\n```console\n$ operator-sdk generate kustomize manifests\nINFO[0000] Generating CSV manifest version 0.1.0\n\nDisplay name for the operator (required):\n> memcached\n\nComma-separated list of keywords for your operator (required):\n> app, operator\n...\n```\n\nOnce this base is written, you may modify any of the fields labeled _user_ in the [fields section](#csv-fields) below.\nThese values will persist when generating a bundle, so make necessary metadata changes here and not the generated bundle.\n\n**For Go Operators only:** the command parses [CSV markers][csv-markers] from Go API type definitions, located\nin `./api` for single group projects and `./apis` for multigroup projects, to populate certain CSV fields.\nYou can set an alternative path to the API types root directory with `--apis-dir`. These markers are not available\nto Ansible or Helm project types. \n\nThe command attempts to process the local types defined in your API.\nIf you import a package that uses the same name as a local type, running the command causes an infinite loop. For example:\n```go\ntype PodStatus struct {\n  SomeField string\n  // imported type with the same name will infinitely trigger\n  // the parser to process the local PodStatus type\n  Status v1.PodStatus \n}\n```\nTo prevent an infinite loop, edit the local type definition to use a different name. For example:\n```go\ntype PodStatusWrapper struct {\n  SomeField string\n  Status v1.PodStatus \n}\n```\n\n### ClusterServiceVersion manifests\n\nCSV's are manifests that define all aspects of an Operator, from what CustomResourceDefinitions (CRDs) it uses to\nmetadata describing the Operator's maintainers. They are typically versioned by semver, much like Operator projects\nthemselves; this version is present in both their `metadata.name` and `spec.version` fields. The CSV generator called\nby `generate <bundle|packagemanifests>` requires certain input manifests to construct a CSV manifest; all inputs\nare read when either command is invoked, along with a CSV's [base](#kustomize-files), to idempotently regenerate a CSV.\n\nThe following resource kinds are typically included in a CSV, which are addressed by `config/manifests/kustomization.yaml`:\n  - `Role`: define Operator permissions within a namespace.\n  - `ClusterRole`: define cluster-wide Operator permissions.\n  - `Deployment`: define how the Operator's operand is run in pods.\n  - `ValidatingWebhookConfiguration`, `MutatingWebhookConfiguration`: configures webhooks for your manager to handle.\n  - `CustomResourceDefinition`: definitions of custom objects your Operator reconciles.\n  - Custom resource examples: examples of objects adhering to the spec of a particular CRD.\n\nYou can optionally specify an input `ClusterServiceVersion` manifest to the set of manifests passed to\nthese `generate` subcommands instead of having them read from the [base path](#kustomize-files).\nThis is advantageous for those who would like to take full advantage of `kustomize` for their base.\nAll fields unlabeled or labeled with _marker_ [below](#csv-fields) will be overwritten by these command,\nso make sure you do not `kustomize build` those fields!\n\n#### Webhooks\n\nA CSV allows you to [define][olm-whs] both [admission][doc-admission-whs] and [conversion][doc-conv-whs] webhooks\nat [`spec.webhookdefinitions`][wh-defs]. The `generate <bundle|packagemanifests>` commands, described below,\nwill automatically add webhooks to your CSV if the following holds true:\n1. A webhook configuration must be associated with a `Service` by name and namespace,\nwhether in a [CRD][crd-wh-serviceref] or in a [`*WebhookConfiguration`][wh-serviceref] file,\n1. The associated `Service` must expose one `spec.ports[*].targetPort` that matches both `containerPort`\nand `protocol` of one element in the Operator `Deployment`'s `spec.template.spec.containers[*].ports`.\n\nBy default, the manager's Deployment is configured to mount a volume containing TLS cert data\ncreated by [cert-manager][cert-manager] into the manager's container.\nOLM does [not yet support cert-manager][olm-cert-support], so a [JSON patch][cm-patch] was added\nto remove this volume and mount such that OLM can itself create and manage certs for your Operator.\n\n**Note (for Go Operators only):** If targeting OLM < v0.17.0, the manager's default webhook server\nis not configured with the correct cert/key paths; the correct path is\n`/apiserver.local.config/certificates/apiserver.{cert,key}`.\nTo cover this case, make the following changes to your `main.go`:\n\n```go\nimport (\n  ...\n  ctrl \"sigs.k8s.io/controller-runtime\"\n  \"sigs.k8s.io/controller-runtime/pkg/webhook\"\n)\n\nfunc main() {\n  ...\n\n  // Configure a webhook.Server with the correct path and file names.\n  // If webhookServer is nil, which will be the case of OLM >= 0.17 is available,\n  // the manager will create a server for you using Host, Port,\n  // and the default CertDir, KeyName, and CertName.\n  var webhookServer *webhook.Server\n  const legacyOLMCertDir = \"/apiserver.local.config/certificates\"\n  if info, err := os.Stat(legacyOLMCertDir); err == nil && info.IsDir() {\n    webhookServer = &webhook.Server{\n      Host:     <some host>, // Set this only if normally set in ctrl.Options below.\n      Port:     <some port>, // Set this only if normally set in ctrl.Options below.\n      CertDir:  legacyOLMCertDir,\n      CertName: \"apiserver.crt\",\n      KeyName:  \"apiserver.key\",\n    }\n  }\n\n  mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{\n    Host:          <some host>,\n    Port:          <some port>,\n    WebhookServer: webhookServer, // Host/Port will not be used if webhookServer is nil.\n  })\n \n  // Now you can register webhooks.\n  ...\n}\n```\n\n**Note:** The `Service` itself will still be placed into the `manifests/` directory,\nin case other Operator resources require routing. Feel free to remove it otherwise.\n\n\n[olm-whs]:https://olm.operatorframework.io/docs/advanced-tasks/adding-admission-and-conversion-webhooks\n[doc-admission-whs]:https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/\n[doc-conv-whs]:https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definition-versioning/#webhook-conversion\n[wh-defs]:https://pkg.go.dev/github.com/operator-framework/api/pkg/operators/v1alpha1#WebhookDefinition\n[crd-wh-serviceref]:https://pkg.go.dev/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1?utm_source=godoc#ServiceReference\n[wh-serviceref]:https://pkg.go.dev/k8s.io/api/admissionregistration/v1?utm_source=godoc#ServiceReference\n[olm-cert-support]:https://olm.operatorframework.io/docs/advanced-tasks/adding-admission-and-conversion-webhooks/#certificate-authority-requirements\n[cm-patch]:https://github.com/operator-framework/operator-sdk/blob/163c657/testdata/go/v3/memcached-operator/config/manifests/kustomization.yaml#L12\n\n## Generate your first release\n\nYou've recently run `operator-sdk init` and created your APIs with `operator-sdk create api`. Now you'd like to\npackage your Operator for deployment by OLM. Your Operator is at version `v0.0.1`; the `Makefile` variable `VERSION`\nshould be set to `0.0.1`. You've also built your operator image, `example.com/memcached-operator:v0.0.1`;\nif this image tag does not match yours, swap in the correct one in the docs below.\n\n### Bundle format\n\nA [bundle][bundle] consists of manifests (CSV, CRDs, and other supported kinds) and metadata that define an Operator\nat a particular version, and an optional [scorecard][scorecard] configuration file. You may have also heard of a\nbundle image. From the bundle docs:\n\n> An Operator Bundle is built as a scratch (non-runnable) container image that\n> contains operator manifests and specific metadata in designated directories\n> inside the image. Then, it can be pushed and pulled from an OCI-compliant\n> container registry. Ultimately, an operator bundle will be used by Operator\n> Registry and OLM to install an operator in OLM-enabled clusters.\n\nAt this stage in your Operator's development, we only need to worry about generating bundle files;\nbundle images become important once you're ready to [publish][operatorhub] your Operator.\n\nSDK projects are scaffolded with a `Makefile` containing the `bundle` recipe by default,\nwhich wraps `generate kustomize manifests`, `generate bundle`, and other related commands.\n\nBy default `make bundle` will generate a CSV, copy CRDs and other supported kinds, generate metadata,\nand add your scorecard configuration in the bundle format:\n\n```console\n$ make bundle\n$ tree ./bundle\n./bundle\n├── manifests\n│   ├── cache.example.com_memcacheds.yaml\n│   ├── memcached-operator.clusterserviceversion.yaml\n│   ├── memcached-operator-controller-manager-metrics-monitor_monitoring.coreos.com_v1_servicemonitor.yaml\n│   ├── memcached-operator-controller-manager-metrics-service_v1_service.yaml\n│   ├── memcached-operator-metrics-reader_rbac.authorization.k8s.io_v1beta1_clusterrole.yaml\n│   └── memcached-operator-webhook-service_v1_service.yaml\n├── metadata\n│   └── annotations.yaml\n└── tests\n    └── scorecard\n        └── config.yaml\n```\n\n**Important:** bundle generation is supposed to be idempotent, so any changes to CSV fields able to be persisted\n(marked _(user)_ or _(marker)_ [below](#csv-fields)) must be made to the base set of manifests, typically found in `config/`.\n\nBundle metadata in `bundle/metadata/annotations.yaml` contains information about a particular Operator version\navailable in a registry. OLM uses this information to install specific Operator versions and resolve dependencies.\nThat file and `bundle.Dockerfile` contain the same [annotations][bundle-metadata], the latter as `LABEL`s,\nwhich do not need to be modified in most cases; if you do decide to modify them, both sets of annotations _must_\nbe the same to ensure consistent Operator deployment.\n\n##### Channels\n\nMetadata for each bundle contains channel information as well:\n\n> Channels allow package authors to write different upgrade paths for different users (e.g. beta vs. stable).\n\nChannels become important when publishing, but we should still be aware of them beforehand as they're required\nvalues in our metadata. `make bundle` writes the channel `alpha` by default.\n\n#### Validation\n\nThe `bundle` recipe includes a call to `operator-sdk bundle validate`, which runs a set of required object\nvalidators on your bundle that ensure both its format and content meet the [bundle specification][bundle].\nThese will always be run and cannot be disabled.\n\nYou may also have added [CSV fields](#csv-fields) containing useful UI metadata for cluster console display,\nand want to ensure that metadata matches some hosted catalog's submission requirements.\nThe `bundle validate` command supports optional validators that can validate these bundle metadata.\nThese validators are disabled by default, and can be selectively enabled with `--select-optional <label-selector>`.\nYou can list all available optional validators by setting the `--list-optional` flag:\n\n```console\n$ operator-sdk bundle validate --list-optional\nNAME           LABELS                                                DESCRIPTION\noperatorhub    name=operatorhub                                      OperatorHub.io metadata validation. \n               suite=operatorframework    \ncommunity      name=community                                        (stage: alpha) Community Operator bundle validation      \n...\n```\n\nFor example, you want to turn on the `operatorhub` validator shown above so you can publish the `0.0.1` operator\nyou recently created on [OperatorHub.io][operatorhub]. To do so, you can modify your Makefile's `bundle` recipe\nto validate any further changes you make to bundle UI metadata related to OperatorHub requirements:\n\n```make\nbundle: ...\n  ...\n  operator-sdk bundle validate ./bundle --select-optional name=operatorhub\n```\n\nAlso, see that you can test the bundle against the suite of test to ensure it against all criteria:\n\n```sh \noperator-sdk bundle validate ./bundle --select-optional suite=operatorframework \n```  \n\n**Note**: The `OperatorHub.io` validator in the `operatorframework` optional suite allows you to validate that your manifests can work with a Kubernetes cluster of a particular version using the `k8s-version` optional key value:\n\n```sh \noperator-sdk bundle validate ./bundle --select-optional suite=operatorframework --optional-values=k8s-version=1.22\n```\n\nDocumentation on optional validators:\n- [`operatorhub`][operatorhub_validator]\n\n**Note**: (stage: alpha) The `Community` validator allows you to validate your `bundle.Dockerfile` configuration against its specific criteria using the `image-path` optional key value:\n\n```sh \noperator-sdk bundle validate ./bundle --select-optional name=community --optional-values=image-path=bundle.Dockerfile\n```\n\n### Package manifests format\n\nA [package manifests][package-manifests] format consists of on-disk manifests (CSV, CRDs and other supported kinds)\nand metadata that define an Operator at all versions of that Operator. Each version is contained in its own directory,\nwith a parent package manifest YAML file containing channel-to-version mappings, much like a bundle's metadata.\n\nIf your Operator is already formatted as a package manifests and you do not wish to migrate to the bundle format yet,\nyou should add the following to your `Makefile` to make development easier:\n\n**For Go-based Operator projects**\n\n```make\n# Options for \"packagemanifests\".\nifneq ($(origin FROM_VERSION), undefined)\nPKG_FROM_VERSION := --from-version=$(FROM_VERSION)\nendif\nifneq ($(origin CHANNEL), undefined)\nPKG_CHANNELS := --channel=$(CHANNEL)\nendif\nifeq ($(IS_CHANNEL_DEFAULT), 1)\nPKG_IS_DEFAULT_CHANNEL := --default-channel\nendif\nPKG_MAN_OPTS ?= $(PKG_FROM_VERSION) $(PKG_CHANNELS) $(PKG_IS_DEFAULT_CHANNEL)\n\n# Generate package manifests.\npackagemanifests: kustomize manifests\n  operator-sdk generate kustomize manifests -q\n  cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG)\n  $(KUSTOMIZE) build config/manifests | operator-sdk generate packagemanifests -q --version $(VERSION) $(PKG_MAN_OPTS)\n```\n\n**For Helm/Ansible-based Operator projects**\n\n```make\n# Options for \"packagemanifests\".\nifneq ($(origin FROM_VERSION), undefined)\nPKG_FROM_VERSION := --from-version=$(FROM_VERSION)\nendif\nifneq ($(origin CHANNEL), undefined)\nPKG_CHANNELS := --channel=$(CHANNEL)\nendif\nifeq ($(IS_CHANNEL_DEFAULT), 1)\nPKG_IS_DEFAULT_CHANNEL := --default-channel\nendif\nPKG_MAN_OPTS ?= $(PKG_FROM_VERSION) $(PKG_CHANNELS) $(PKG_IS_DEFAULT_CHANNEL)\n\n# Generate package manifests.\npackagemanifests: kustomize\n  operator-sdk generate kustomize manifests -q\n  cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG)\n  $(KUSTOMIZE) build config/manifests | operator-sdk generate packagemanifests -q --version $(VERSION) $(PKG_MAN_OPTS)\n```\n\nBy default `make packagemanifests` will generate a CSV, a package manifest file, and copy CRDs in the package manifests format:\n\n```console\n$ make packagemanifests IMG=example.com/memcached-operator:v0.0.1\n$ tree ./packagemanifests\n./packagemanifests\n├── 0.0.1\n│   ├── cache.my.domain_memcacheds.yaml\n│   └── memcached-operator.clusterserviceversion.yaml\n└── memcached-operator.package.yaml\n```\n\n## Update your Operator\n\nLet's say you added a new API `App` with group `app` and version `v1alpha1` to your Operator project,\nand added a port to your manager Deployment in `config/manager/manager.yaml`.\n\nIf using a bundle format, the current version of your CSV can be updated by running:\n\n```console\n$ make bundle IMG=example.com/memcached-operator:v0.0.1\n```\n\nIf using a package manifests format, run:\n\n```console\n$ make packagemanifests IMG=example.com/memcached-operator:v0.0.1\n```\n\nRunning the command for either format will append your new CRD to `spec.customresourcedefinitions.owned`,\nreplace the old data at `spec.install.spec.deployments` with your updated Deployment,\nand update your existing CSV manifest. The SDK will not overwrite [user-defined](#csv-fields)\nfields like `spec.maintainers`.\n\n## Upgrade your Operator\n\nLet's say you're upgrading your Operator to version `v0.0.2`, you've already updated the `VERSION` variable\nin your `Makefile` to `0.0.2`, and built a new operator image `example.com/memcached-operator:v0.0.2`.\nYou also want to add a new channel `beta`, and use it as the default channel.\n\nFirst, update `spec.replaces` in your [base CSV manifest](#kustomize-files) to the _current_ CSV name.\nIn this case, the change would look like:\n\n```yaml\nspec:\n  ...\n  replaces: memcached-operator.v0.0.1\n```\n\nNext, upgrade your bundle. If using a bundle format, a new version of your CSV can be created by running:\n\n```console\n$ make bundle CHANNELS=beta DEFAULT_CHANNEL=beta IMG=example.com/memcached-operator:v0.0.2\n```\n\nIf using a package manifests format, run:\n\n```console\n$ make packagemanifests FROM_VERSION=0.0.1 CHANNEL=beta IS_CHANNEL_DEFAULT=1 IMG=example.com/memcached-operator:v0.0.2\n```\n\nRunning the command for either format will persist user-defined fields, and updates `spec.version` and `metadata.name`.\n\n**For `packagemanifests` only** The command will also populate `spec.replaces` with the old CSV version's name.\n\n## CSV fields\n\nBelow are two lists of fields: the first is a list of all fields the SDK and OLM expect in a CSV, and the second are optional.\n\n**For Go Operators only:** Several fields require user input (labeled _user_) or a [CSV marker][csv-markers]\n(labeled _marker_). This list may change as the SDK becomes better at generating CSV's.\nThese markers are not available to Ansible or Helm project types.\n\nRequired:\n- `metadata.name` _(user*)_: a *unique* name for this CSV of the format `<project-name>.vX.Y.Z`, ex. `app-operator.v0.0.1`.\n- `spec.displayName` _(user)_ : a name to display for the Operator in Operator Hub.\n- `spec.version` _(user*)_: semantic version of the Operator, ex. `0.0.1`.\n- `spec.installModes` _(user)_: what mode of [installation namespacing][install-modes] OLM should use.\nCurrently all but `MultiNamespace` are supported by SDK Operators.\n- `spec.customresourcedefinitions`: any CRDs the Operator uses. Certain fields in elements of `owned` will be filled by the SDK.\n    - `owned`: all CRDs the Operator deploys itself from it's bundle.\n        - `name`: CRD's `metadata.name`.\n        - `kind`: CRD's `spec.names.kind`.\n        - `version`: CRD's `spec.version`.\n        - `description` _(marker)_ : description of the CRD.\n        - `displayName` _(marker)_ : display name of the CRD.\n        - `resources` _(marker)_ : any Kubernetes resources used by the CRD, ex. `Pod`'s and `ConfigMap`'s.\n        - `specDescriptors` _(marker)_ : UI hints for inputs and outputs of the Operator's spec.\n        - `statusDescriptors` _(marker)_ : UI hints for inputs and outputs of the Operator's status.\n        - `actionDescriptors` _(user)_ : UI hints for an Operator's in-cluster actions.\n    - `required` _(user)_ : all CRDs the Operator expects to be present in-cluster, if any.\n    All `required` element fields must be populated manually.\n\nOptional:\n- `spec.description` _(user)_ : a thorough description of the Operator's functionality.\n- `spec.keywords` _(user)_ : a list of keywords describing the Operator.\n- `spec.maintainers` _(user)_ : a list of human or organizational entities maintaining the Operator, with a `name` and `email`.\n- `spec.provider` _(user)_ : the Operator provider, with a `name`; usually an organization.\n- `spec.labels` _(user)_ : a list of `key:value` pairs to be used by Operator internals.\n- `metadata.annotations.alm-examples`: CR examples, in JSON string literal format, for your CRD's. Ideally one per CRD.\n- `metadata.annotations.capabilities`: level of Operator capability. See the [Operator maturity model][olm-capabilities]\nfor a list of valid values.\n- `spec.replaces` _(user)_: the name of the CSV being replaced by this CSV.\n- `spec.links` _(user)_ : a list of URL's to websites, documentation, etc. pertaining to the Operator or application\nbeing managed, each with a `name` and `url`.\n- `spec.selector` _(user)_ : selectors by which the Operator can pair resources in a cluster.\n- `spec.icon` _(user)_ : a base64-encoded icon unique to the Operator, set in a `base64data` field with a `mediatype`.\n- `spec.maturity` _(user)_: the Operator's maturity, ex. `alpha`.\n- `spec.minKubeVersion` _(user)_: the minimal Kubernetes version supported by the Operator, ex. `1.16.0`.\n- `spec.webhookdefinitions`: any webhooks the Operator uses.\n- `spec.relatedImages` _(user)_: a list of image tags containing SHA digests [mapped to in-CSV names][relatedimages]\nthat your Operator might require to perform their functions.\n    - To get the correct tag for an image available in some remote registry, run `docker inspect --format='{{range $i, $d := .RepoDigests}}{{$d}}{{\"\\n\"}}{{end}}'`\n    and choose the tag for the desired registry.\n- `spec.skips` _(user)_: the names of one or more CSVs that should be skipped in a catalog's upgrade graph.\n\n**\\*** `metadata.name` and `spec.version` will only be automatically updated from the base CSV\nwhen you set `--version` when running `generate <bundle|packagemanifests>`.\n\n[olm]:https://github.com/operator-framework/operator-lifecycle-manager\n[doc-csv]:https://github.com/operator-framework/operator-lifecycle-manager/blob/0.15.1/doc/design/building-your-csv.md\n[cli-overview]:/docs/olm-integration/cli-overview\n[cli-gen-kustomize-manifests]:/docs/cli/operator-sdk_generate_kustomize_manifests\n[cli-gen-bundle]:/docs/cli/operator-sdk_generate_bundle\n[bundle]: https://github.com/operator-framework/operator-registry/blob/v1.16.1/docs/design/operator-bundle.md\n[bundle-metadata]:https://github.com/operator-framework/operator-registry/blob/v1.12.6/docs/design/operator-bundle.md#bundle-annotations\n[install-modes]:https://github.com/operator-framework/operator-lifecycle-manager/blob/4197455/Documentation/design/building-your-csv.md#operator-metadata\n[olm-capabilities]:/docs/overview/operator-capabilities/\n[csv-markers]:/docs/building-operators/golang/references/markers\n[operatorhub]:https://operatorhub.io/\n[scorecard]:/docs/testing-operators/scorecard/\n[operatorhub_validator]:https://olm.operatorframework.io/docs/tasks/creating-operator-bundle/#validating-your-bundle\n[relatedimages]:https://pkg.go.dev/github.com/operator-framework/api@v0.8.1/pkg/operators/v1alpha1#RelatedImage\n"
  },
  {
    "path": "website/content/en/docs/olm-integration/quickstart-bundle.md",
    "content": "---\ntitle: OLM Integration Bundle Quickstart\nlinkTitle: Bundle Quickstart\nweight: 1\n---\n\nThe [Operator Lifecycle Manager (OLM)][olm] is a set of cluster resources that manage the lifecycle of an Operator.\nThe Operator SDK supports both creating manifests for OLM deployment, and testing your Operator on an OLM-enabled\nKubernetes cluster.\n\nThis document is intended to quickly walk through the steps to generate an OLM bundle. For further explanation,\nor if you're using package manifests, see the [Bundle Tutorial][tutorial-bundle].\n\n**Important:** this guide assumes your project was scaffolded with `operator-sdk init --project-version=3`.\nThese features are unavailable to projects of version `2` or less; this information can be found by inspecting\nyour `PROJECT` file's `version` value.\n\n## Prerequisites\n\n- Have a working operator that you have uploaded to a container registry. This guide assumes the simple Golang Memcached operator from [the building operators section][sdk-user-guide-go] at version `0.0.1`.\n- Make sure your user is authorized with `cluster-admin` permissions.\n- Have OLM installed on your cluster. The command `operator-sdk olm install` will attempt to install a basic OLM deployment on your cluster.\n\n## Steps\n\n1. Export environment variables\n\n```sh\n$ export USERNAME=<container-registry-username>\n$ export VERSION=0.0.1\n$ export IMG=docker.io/$USERNAME/memcached-operator:v$VERSION // location where your operator image is hosted\n$ export BUNDLE_IMG=docker.io/$USERNAME/memcached-operator-bundle:v$VERSION // location where your bundle will be hosted\n```\n\n- Create a bundle from the root directory of your project\n\n```sh\n$ make bundle\n```\n\nThis will prompt you to enter basic information about your operator.\n\n- Build and push the bundle image\n\n```sh\n$ make bundle-build bundle-push\n```\n\n- Validate the bundle\n\n```sh\n$ operator-sdk bundle validate $BUNDLE_IMG\n```\n\n- Install the bundle with OLM\n\n```sh\n$ operator-sdk run bundle $BUNDLE_IMG\n```\n\n## Next Steps\n\nRead the [full tutorial][tutorial-bundle] for a more in-depth look at creating and using a bundle.\n\n[tutorial-bundle]:/docs/olm-integration/tutorial-bundle\n[sdk-user-guide-go]:/docs/building-operators/golang/quickstart\n[olm]:https://github.com/operator-framework/operator-lifecycle-manager/\n"
  },
  {
    "path": "website/content/en/docs/olm-integration/testing-deployment.md",
    "content": "---\ntitle: Testing Operator Deployment with OLM\nlinkTitle: Testing Deployment\nweight: 30\n---\n\nThis document discusses the behavior of `operator-sdk <run|cleanup>` subcommands related to OLM deployment,\nand assumes you are familiar with [OLM][olm], related terminology,\nand have read the SDK-OLM integration [design proposal][sdk-olm-design].\n\n### Caveats\n\n- `run bundle`, `run bundle-upgrade`, `run packagemanifests`, and `cleanup` are intended to be used for testing purposes only,\nsince these commands create a transient image registry that should not be used in production.\nTypically a registry is deployed separately and a set of catalog manifests are created in the cluster\nto inform OLM of that registry and which Operator versions it can deploy and where to deploy the Operator.\n- `run bundle` and `run packagemanifests` can only deploy one Operator and one version of that Operator at a time, \nand `run bundle-upgrade` can only upgrade one Operator and one version of that Operator at a time, \nhence their intended purpose being testing only.\n- If testing a bundle or catalog whose image will be hosted in a registry that is private and/or\nhas a custom CA, these [configuration steps][image-reg-config] must be complete.\n\n\n## `operator-sdk run bundle` command overview\n\n`operator-sdk run bundle` assumes OLM is already installed and running on your\ncluster. It also assumes that your Operator has a valid [bundle][bundle-format].\nSee the [creating a bundle][creating-bundle] guide for more information. See the\n[CLI overview][doc-cli-overview] for commands to work with an OLM installation\nand generate a bundle.\n\n```\noperator-sdk run bundle <bundle-image> [--index-image=] [--kubeconfig=] [--namespace=] [--timeout=] [--install-mode=(AllNamespace|OwnNamespace|SingleNamespace=)]\n```\n\nLet's look at the configuration shared between `run bundle`, `run\npackagemanifests`, `run bundle-upgrade` and `cleanup`:\n\n- **kubeconfig**: the local path to a kubeconfig. This uses well-defined default\n  loading rules to load the config if empty.\n- **namespace**: the cluster namespace in which Operator resources are created.\n  This namespace must already exist in the cluster. This is an optional field\n  which will default to the kubeconfig context if not provided.\n- **timeout**: a time string dictating the maximum time that `run` can run. The\n  command will return an error if the timeout is exceeded.\n\nLet's look at the anatomy of the `run bundle` configuration model:\n\n- **bundle-image**: specifies the Operator bundle image, this is a\n  required parameter. The bundle image must be pullable.\n- **index-image**: specifies an index image in which to inject the given bundle.\n  This is an optional field which will default to\n  `quay.io/operator-framework/opm:latest`\n- **install-mode**: specifies which supported [`installMode`][csv-install-modes]\n  should be used to create an `OperatorGroup` by configuring its\n  `spec.targetNamespaces` field. The `InstallModeType` string passed must be\n  marked as \"supported\" in the CSV being installed.\n  - This option understands the following strings (assuming your CSV does as\n    well):\n    - `AllNamespaces`: the Operator will watch all namespaces (cluster-scoped\n      Operators). This is the default.\n    - `OwnNamespace`: the Operator will watch its own namespace (from\n      **namespace** or the kubeconfig default).\n    - `SingleNamespace=\"my-ns\"`: the Operator will watch a namespace, not\n      necessarily its own.\n  - This is an optional parameter, but if the CSV does not support\n    `AllNamespaces` then this parameter becomes **required** to instruct\n    `run bundle` with the appropriate `InstallModeType`.\n\n## `operator-sdk run packagemanifests` command overview\n\n`operator-sdk run packagemanifests` assumes OLM is already installed and\nrunning on your cluster, and that your Operator has a valid\n[package manifests format][package-manifests]. See the\n[CLI overview][doc-cli-overview] for commands to work with an OLM installation\nand generate a package manifests format.\n\n```\noperator-sdk run packagemanifests <packagemanifests-root-dir> [--version=] [--kubeconfig=] [--namespace=] [--timeout=] [--install-mode=(AllNamespace|OwnNamespace|SingleNamespace=)]\n```\n\nLet's look at the configuration shared between `run bundle`, `run\npackagemanifests` and `cleanup`:\n\n- **kubeconfig**: the local path to a kubeconfig. This uses well-defined default\n  loading rules to load the config if empty.\n- **namespace**: the cluster namespace in which Operator resources are created.\n  This namespace must already exist in the cluster. This is an optional field\n  which will default to the kubeconfig context if not provided.\n- **timeout**: a time string dictating the maximum time that `run` can run. The\n  command will return an error if the timeout is exceeded.\n\nLet's look at the anatomy of the `run packagemanifests` configuration model:\n\n- **packagemanifests-root-dir**: a directory containing the Operator's package\n  manifests, this is a required parameter.\n- **install-mode**: specifies which supported [`installMode`][csv-install-modes]\n  should be used to create an `OperatorGroup` by configuring its\n  `spec.targetNamespaces` field. The `InstallModeType` string passed must be\n  marked as \"supported\" in the CSV being installed.\n  - This option understands the following strings (assuming your CSV does as\n    well):\n    - `AllNamespaces`: the Operator will watch all namespaces (cluster-scoped\n      Operators). This is the default.\n    - `OwnNamespace`: the Operator will watch its own namespace (from\n      **namespace** or the kubeconfig default).\n    - `SingleNamespace=\"my-ns\"`: the Operator will watch a namespace, not\n      necessarily its own.\n  - This is an optional parameter, but if the CSV does not support\n    `AllNamespaces` then this parameter becomes **required** to instruct\n    `run packagemanifests` with the appropriate `InstallModeType`.\n- **version**: the version of the Operator to deploy. It must be a semantic\n  version, ex. 0.0.1. This version must match the version of the CSV manifest\n  found in **manifests-dir**, e.g. `packagemanifests/0.0.1` in an Operator\n  SDK project.\n\n## `operator-sdk run bundle-upgrade` command overview\n\n`operator-sdk run bundle-upgrade` assumes OLM is already installed and running on your \ncluster and that the Operator has a valid [bundle][bundle-format]. It also assumes that \nthe previous version of the Operator was either deployed on the cluster using `run bundle` \ncommand or traditionally via OLM. Another assumption of this command is that the newer operator bundle\nshould not exist in the index image, if the previous version of the operator bundle was installed \ntraditionally using OLM. This will cause the registry pod to fail as the bundle is already added to the \nindex that provides package and csv. See the [CLI overview][doc-cli-overview] for commands to work with \nan OLM installation and generate a bundle.\n\n```\noperator-sdk run bundle-upgrade <bundle-image> [--kubeconfig=] [--namespace=] [--timeout=] \n```\nLet's look at the anatomy of the `run bundle-upgrade` configuration model:\n\n- **bundle-image**: specifies the Operator bundle image, this is a\n  required parameter. The bundle image must be pullable.\n\n## `operator-sdk cleanup` command overview\n\n`operator-sdk cleanup` assumes an Operator was deployed using `run bundle` or\n`run packagemanifests`.\n\n```\noperator-sdk cleanup <operatorPackageName> [--delete-all=] [--delete-crds=] [--delete-operator-groups=] [--kubeconfig=] [--namespace=] [--timeout=]\n```\n\nLet's look at the configuration shared between `run bundle`, `run\npackagemanifests` and `cleanup`:\n\n- **kubeconfig**: the local path to a kubeconfig. This uses well-defined default\n  loading rules to load the config if empty.\n- **namespace**: the cluster namespace in which Operator resources are created.\n  This namespace must already exist in the cluster. This is an optional field\n  which will default to the kubeconfig context if not provided.\n- **timeout**: a time string dictating the maximum time that `run` can run. The\n  command will return an error if the timeout is exceeded.\n\nLet's look at the anatomy of the `cleanup` configuration model:\n\n- **operatorPackageName**: the Operator's package name which you want to remove\n  from the cluster, e.g. memcached-operator. This is a required parameter.\n- **delete-all**: a boolean indicating to enable all the delete flags that are present. This is an optional\n  field which will default to true if not provided. If set to true, it will enable all the delete flags to be true. If set to false, it will enable specific delete flags.\n- **delete-crds**: a boolean indicating to delete all owned CRDs and CRs. This is an optional field\n  which will default to false if not provided. If set to true, owned CRDs and CRs\n  will be deleted.\n- **delete-operator-groups**: a boolean indicating to delete all operator groups. This is an optional field\n  which will default to false if not provided. If set to true, operator groups will be deleted.\n\n\n[olm]:https://github.com/operator-framework/operator-lifecycle-manager/\n[sdk-olm-design]:https://github.com/operator-framework/operator-sdk/blob/master/proposals/sdk-integration-with-olm.md\n[doc-cli-overview]:/docs/olm-integration/cli-overview\n[bundle-format]:https://github.com/operator-framework/operator-registry/tree/v1.15.3#manifest-format\n[package-manifests]:https://github.com/operator-framework/operator-registry/tree/v1.5.3#manifest-format\n[csv-install-modes]:https://github.com/operator-framework/operator-lifecycle-manager/blob/master/doc/design/building-your-csv.md#operator-metadata\n[cli-olm-install]:/docs/cli/operator-sdk_olm_install\n[cli-olm-status]:/docs/cli/operator-sdk_olm_status\n[creating-bundles]:/docs/olm-integration/tutorial-bundle/#creating-a-bundle\n[add-sa-secret]:https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account\n[image-reg-config]:/docs/olm-integration/cli-overview#private-bundle-and-catalog-image-registries\n"
  },
  {
    "path": "website/content/en/docs/olm-integration/tutorial-bundle.md",
    "content": "---\ntitle: OLM Integration Bundle Tutorial\nlinkTitle: Bundle Tutorial\nweight: 1\n---\n\nThe [Operator Lifecycle Manager (OLM)][olm] is a set of cluster resources that manage the lifecycle of an Operator.\nThe Operator SDK supports both creating manifests for OLM deployment, and testing your Operator on an OLM-enabled\nKubernetes cluster.\n\nThis document succinctly walks through getting an Operator OLM-ready with [bundles][bundle], and glosses over\nexplanations of certain steps for brevity. The following documents contain more detail on these steps:\n- All operator-framework manifest commands supported by the SDK: [CLI overview][doc-cli-overview].\n- Generating operator-framework manifests: [generation overview][doc-olm-generate].\n\nIf you are working with package manifests, see the [package manifests tutorial][tutorial-package-manifests]\nonce you have completed the *Setup* section below.\n\n**Important:** this guide assumes your project was scaffolded with `operator-sdk init --project-version=3`.\nThese features are unavailable to projects of version `2` or less; this information can be found by inspecting\nyour `PROJECT` file's `version` value.\n\n## Setup\n\nLet's first walk through creating an Operator for `memcached`, a distributed key-value store.\n\nFollow one of the user guides to develop the memcached-operator in either [Go][sdk-user-guide-go],\n[Ansible][sdk-user-guide-ansible], or [Helm][sdk-user-guide-helm], depending on which Operator type you are interested in.\nThis guide assumes memcached-operator is on version `0.0.1`, which is set in the `Makefile` variable `VERSION`.\n\n### Enabling OLM\n\nEnsure OLM is enabled on your cluster before following this guide. [`operator-sdk olm`][cli-olm]\nhas several subcommands that can install, uninstall, and check the status of particular OLM versions in a cluster.\n\n**Note:** Certain cluster types may already have OLM enabled, but under a non-default (`\"olm\"`) namespace,\nwhich can be configured by setting `--olm-namespace=[non-default-olm-namespace]` for `operator-sdk olm status|uninstall` subcommands.\n\nYou can check if OLM is already installed by running the following command,\nwhich will detect the installed OLM version automatically (0.15.1 in this example):\n\n```console\n$ operator-sdk olm status\nINFO[0000] Fetching CRDs for version \"0.15.1\"\nINFO[0002] Fetching resources for version \"0.15.1\"\nINFO[0002] Successfully got OLM status for version \"0.15.1\"\n\nNAME                                            NAMESPACE    KIND                        STATUS\nolm                                                          Namespace                   Installed\noperatorgroups.operators.coreos.com                          CustomResourceDefinition    Installed\ncatalogsources.operators.coreos.com                          CustomResourceDefinition    Installed\nsubscriptions.operators.coreos.com                           CustomResourceDefinition    Installed\n...\n```\n\nAll resources listed should have status `Installed`.\n\n\n**Note:** The `operator-sdk olm status` command is geared to detect the status of OLM that was installed by installation methods like `operator-sdk olm install` or by applying OLM [manifests][olm-manifests] directly on the cluster. This command retrieves the resources that were compiled into SDK at the time of installation from the OLM [manifests][olm-manifests]. However, if OLM was installed in a cluster in a custom fashion (such as in OpenShift clusters), it is possible that some resources will show a `Not Found` status when the `operator-sdk olm status` command is issued.\n\nTo check the true status of such resources in OCP clusters, run:\n\n```\noc get <resource-name> -n <resource-namespace>\n```\n\nIf OLM is not already installed, go ahead and install the latest version:\n\n```console\n$ operator-sdk olm install\nINFO[0000] Fetching CRDs for version \"latest\"\nINFO[0001] Fetching resources for version \"latest\"\nINFO[0007] Creating CRDs and resources\nINFO[0007]   Creating CustomResourceDefinition \"clusterserviceversions.operators.coreos.com\"\nINFO[0007]   Creating CustomResourceDefinition \"installplans.operators.coreos.com\"\nINFO[0007]   Creating CustomResourceDefinition \"subscriptions.operators.coreos.com\"\n...\nNAME                                            NAMESPACE    KIND                        STATUS\nclusterserviceversions.operators.coreos.com                  CustomResourceDefinition    Installed\ninstallplans.operators.coreos.com                            CustomResourceDefinition    Installed\nsubscriptions.operators.coreos.com                           CustomResourceDefinition    Installed\ncatalogsources.operators.coreos.com                          CustomResourceDefinition    Installed\n...\n```\n\n**Note:** By default, `olm status` and `olm uninstall` auto-detect the OLM version installed in your cluster.\nThis can fail if the installation is broken in some way, so the version of OLM can be overridden using the\n`--version` flag provided with these commands.\n\n## Creating a bundle\n\n_If working with package manifests, see the [package manifests tutorial][tutorial-package-manifests]._\n\nWe will now create bundle manifests by running `make bundle` in the root of the memcached-operator project.\n\n```console\n$ make bundle\n/home/user/go/bin/controller-gen rbac:roleName=manager-role crd webhook paths=\"./...\" output:crd:artifacts:config=config/crd/bases\noperator-sdk generate kustomize manifests -q\nkustomize build config/manifests | operator-sdk generate bundle -q --overwrite --version 0.0.1\nINFO[0000] Building annotations.yaml\nINFO[0000] Writing annotations.yaml in /home/user/go/src/github.com/test-org/memcached-operator/bundle/metadata\nINFO[0000] Building Dockerfile\nINFO[0000] Writing bundle.Dockerfile in /home/user/go/src/github.com/test-org/memcached-operator\noperator-sdk bundle validate ./bundle\nINFO[0000] Found annotations file                        bundle-dir=bundle container-tool=docker\nINFO[0000] Could not find optional dependencies file     bundle-dir=bundle container-tool=docker\nINFO[0000] All validation tests have completed successfully\n```\n\nThe above command will have created the following bundle artifacts: a manifests directory\n(`bundle/manifests`) containing a CSV and all CRDs from `config/crds`, [metadata][bundle-metadata]\ndirectory (`bundle/metadata`), and [`bundle.Dockerfile`][bundle-dockerfile] have been created in\nthe Operator project. These files have been statically validated by `operator-sdk bundle validate`\nto ensure the on-disk bundle representation is correct.\n\n## Deploying an Operator with OLM\n\nAt this point in development we've generated all files necessary to build the memcached-operator bundle.\nNow we're ready to test and deploy the Operator with OLM.\n\n**Note:** If testing a bundle whose image will be hosted in a registry that is private and/or\nhas a custom CA, these [configuration steps][image-reg-config] must be complete.\n\n### Testing bundles\n\nBefore proceeding, make sure you've [Installed OLM](#enabling-olm) onto your\ncluster.\n\nFirst, we need to build our bundle. To build a memcached-operator bundle, run:\n\n```console\n$ make bundle-build bundle-push BUNDLE_IMG=<some-registry>/memcached-operator-bundle:v0.0.1\n```\n\nNow that the bundle image is present in a registry, [`operator-sdk run bundle`][cli-run-bundle]\ncan create a pod to serve that bundle to OLM via a [`Subscription`][install-your-operator],\nalong with other OLM objects, ephemerally.\n\n```console\n$ operator-sdk run bundle <some-registry>/memcached-operator-bundle:v0.0.1\nINFO[0008] Successfully created registry pod: <some-registry>-memcached-operator-bundle-0-0-1\nINFO[0008] Created CatalogSource: memcached-operator-catalog\nINFO[0008] OperatorGroup \"operator-sdk-og\" created\nINFO[0008] Created Subscription: memcached-operator-v0-0-1-sub\nINFO[0019] Approved InstallPlan install-krv7q for the Subscription: memcached-operator-v0-0-1-sub\nINFO[0019] Waiting for ClusterServiceVersion \"default/memcached-operator.v0.0.1\" to reach 'Succeeded' phase\nINFO[0019]   Waiting for ClusterServiceVersion \"default/memcached-operator.v0.0.1\" to appear\nINFO[0031]   Found ClusterServiceVersion \"default/memcached-operator.v0.0.1\" phase: Pending\nINFO[0032]   Found ClusterServiceVersion \"default/memcached-operator.v0.0.1\" phase: Installing\nINFO[0040]   Found ClusterServiceVersion \"default/memcached-operator.v0.0.1\" phase: Succeeded\nINFO[0040] OLM has successfully installed \"memcached-operator.v0.0.1\"\n```\n\n**Note:** If the bundle that is being installed has dependencies, the `--index-image` flag allows adding a bundle to a catalog that contains that bundle's dependencies.\n\n**Note:** Version `v1.22.0` and later of the `operator-sdk` use the new file-based catalog (FBC) bundle format by default. Earlier releases use the deprecated SQLite bundle format. If you use an earlier version of the Operator SDK, you must update to a newer version or specify the index image by adding the `--index-image=quay.io/operator-framework/opm:v1.23.0` flag. For more information about this known issue, see the [FAQ][run-bundle-fbc-sqlite-faq].\n<!-- TODO(jmccormick2001): add `scorecard` usage here -->\n\n### Upgrading a bundle to a newer version\n\nWe can use the `operator-sdk run bundle-upgrade` command with a newer version of bundle image to upgrade\nan existing operator bundle deployed on cluster. The command automates the manual orchestration typically required to upgrade an operator\nfrom one version to another. It extracts the package name from bundle, finds the existing subscription, updates the catalog\nsource, deletes the existing registry pod and creates a new registry pod with the version of bundle image provided in the command.\n\nLet's upgrade the previously deployed memcached-operator bundle from version `0.0.1` to `0.0.2`.\n\n```console\n$ operator-sdk run bundle-upgrade <some-registry>/memcached-operator-bundle:v0.0.2\nINFO[0002] Found existing subscription with name memcached-operator-bundle-0-0-1-sub and namespace default\nINFO[0002] Found existing catalog source with name memcached-operator-catalog and namespace default\nINFO[0007] Successfully created registry pod: <some-registry>-memcached-operator-bundle-0-0-2\nINFO[0007] Updated catalog source memcached-operator-catalog with address and annotations\nINFO[0008] Deleted previous registry pod with name \"<some-registry>-memcached-operator-bundle-0-0-1\"\nINFO[0050] Approved InstallPlan install-c8fkh for the Subscription: memcached-operator-bundle-0-0-1-sub\nINFO[0050] Waiting for ClusterServiceVersion \"default/memcached-operator.v0.0.2\" to reach 'Succeeded' phase\nINFO[0050]   Waiting for ClusterServiceVersion \"default/memcached-operator.v0.0.2\" to appear\nINFO[0052]   Found ClusterServiceVersion \"default/memcached-operator.v0.0.2\" phase: Pending\nINFO[0057]   Found ClusterServiceVersion \"default/memcached-operator.v0.0.2\" phase: InstallReady\nINFO[0058]   Found ClusterServiceVersion \"default/memcached-operator.v0.0.2\" phase: Installing\nINFO[0095]   Found ClusterServiceVersion \"default/memcached-operator.v0.0.2\" phase: Succeeded\nINFO[0095] Successfully upgraded to \"memcached-operator.v0.0.2\"\n```\n\n**Note:** If a bundle was installed using [`operator-sdk run bundle`][run-bundle] with a SQLite index image, the `replaces` field *must* be present and populated in the upgraded CSV's spec. \n\n#### Upgrading a bundle that was installed traditionally using OLM\n\nAn operator bundle can be upgraded even if it was originally deployed using OLM without using the `run bundle` command.\n\nLet's see how to deploy an operator bundle traditionally using OLM and then upgrade the operator bundle to a newer version.\n\nFirst, create a CatalogSource by building the CatalogSource from a catalog.\n\n```console\n$ oc create -f catalogsource.yaml\n```\n\n```yaml\n# catalogsource.yaml\napiVersion: operators.coreos.com/v1alpha1\nkind: CatalogSource\nmetadata:\n  name: etcdoperator\n  namespace: default\nspec:\n  displayName: Etcd Operators\n  image: <some-registry>/etcd-catalog:latest\n  sourceType: grpc\n```\n\nNext, install the operator bundle by creating a subscription.\n\n```console\n$ oc create -f subscription.yaml\n```\n\n```yaml\n# subscription.yaml\napiVersion: v1\nitems:\n- apiVersion: operators.coreos.com/v1alpha1\n  kind: Subscription\n  metadata:\n    name: etcd\n    namespace: default\n  spec:\n    channel: \"stable\"\n    installPlanApproval: Manual\n    name: etcd\n    source: etcdoperator\n    sourceNamespace: default\n    startingCSV: etcdoperator.v0.0.1\n```\n\nOnce the Operator bundle is deployed, you can use the `run bundle-upgrade` command by specifying the new bundle image that you want to upgrade to.\n\n```console\n$ operator-sdk run bundle-upgrade <some-registry>/etcd-bundle:v0.0.2\nINFO[0000] Found existing subscription with name etcd and namespace default\nINFO[0000] Found existing catalog source with name etcdoperator and namespace default\nINFO[0005] Successfully created registry pod: <some-registry>-etcd-bundle-0-0-2\nINFO[0005] Updated catalog source etcdoperator with address and annotations\nINFO[0005] Deleted previous registry pod with name \"<some-registry>-etcd-bundle-0-0-1\"\nINFO[0005] Approved InstallPlan install-6vrzh for the Subscription: etcd\nINFO[0005] Waiting for ClusterServiceVersion \"default/etcdoperator.v0.0.2\" to reach 'Succeeded' phase\nINFO[0005]   Waiting for ClusterServiceVersion \"default/etcdoperator.v0.0.2\" to appear\nINFO[0007]   Found ClusterServiceVersion \"default/etcdoperator.v0.0.2\" phase: Pending\nINFO[0008]   Found ClusterServiceVersion \"default/etcdoperator.v0.0.2\" phase: Installing\nINFO[0018]   Found ClusterServiceVersion \"default/etcdoperator.v0.0.2\" phase: Succeeded\nINFO[0018] Successfully upgraded to \"etcdoperator.v0.0.2\"\n```\n\n### Deploying bundles in production\n\nOLM and Operator Registry consumes Operator bundles via a catalog of Operators, implemented as an\n[index image][index-image], which are composed of one or more bundles. To build and push a\nmemcached-operator bundle image for version v0.0.1, run:\n\n```console\n$ make bundle-build bundle-push BUNDLE_IMG=<some-registry>/memcached-operator-bundle:v0.0.1\n```\n\nNow you can build and push the catalog by running `catalog-*` Makfile targets, which use\nthe Operator package manager tool [`opm`][opm] to [build][doc-index-build] the catalog:\n\n```console\n$ make catalog-build catalog-push CATALOG_IMG=<some-registry>/memcached-operator-catalog:v0.0.1\n```\n\nAssuming `IMAGE_TAG_BASE = <some-registry>/memcached-operator` has the desired tag base, you can inline\nthe above two commands to:\n\n```console\n$ make bundle-build bundle-push catalog-build catalog-push\n```\n\nWhich will build and push both `<some-registry>/memcached-operator-bundle:v0.0.1`\nand `<some-registry>/memcached-operator-catalog:v0.0.1`.\n\n## Further reading\n\nIn-depth discussions of OLM concepts mentioned here:\n- [CatalogSource][catalogsource]\n- [Subscription][subscription]\n- [Install an Operator from a catalog][olm-install]\n\n\n[sdk-user-guide-go]:/docs/building-operators/golang/quickstart\n[sdk-user-guide-ansible]:/docs/building-operators/ansible/quickstart\n[sdk-user-guide-helm]:/docs/building-operators/helm/quickstart\n[tutorial-package-manifests]:/docs/olm-integration/tutorial-package-manifests\n[olm]:https://github.com/operator-framework/operator-lifecycle-manager/\n[bundle]:https://github.com/operator-framework/operator-registry/blob/v1.16.1/docs/design/operator-bundle.md\n[bundle-metadata]:https://github.com/operator-framework/operator-registry/blob/v1.12.6/docs/design/operator-bundle.md#bundle-annotations\n[bundle-dockerfile]:https://github.com/operator-framework/operator-registry/blob/v1.12.6/docs/design/operator-bundle.md#bundle-dockerfile\n[image-reg-config]:/docs/olm-integration/cli-overview#private-bundle-and-catalog-image-registries\n[cli-olm]:/docs/cli/operator-sdk_olm\n[cli-run-bundle]:/docs/cli/operator-sdk_run_bundle\n[doc-cli-overview]:/docs/olm-integration/cli-overview\n[doc-olm-generate]:/docs/olm-integration/generation\n[opm]:https://github.com/operator-framework/operator-registry/blob/master/docs/design/opm-tooling.md\n[index-image]:https://github.com/operator-framework/operator-registry/blob/master/docs/design/opm-tooling.md#index\n[doc-index-build]:https://github.com/operator-framework/operator-registry#building-an-index-of-operators-using-opm\n[install-your-operator]:https://olm.operatorframework.io/docs/tasks/install-operator-with-olm/#install-your-operator\n[catalogsource]:https://olm.operatorframework.io/docs/concepts/crds/catalogsource/\n[subscription]:https://olm.operatorframework.io/docs/concepts/crds/subscription/\n[olm-install]:https://olm.operatorframework.io/docs/tasks/install-operator-with-olm/\n[olm-manifests]:https://github.com/operator-framework/operator-lifecycle-manager/blob/master/deploy/upstream/quickstart/olm.yaml\n[run-bundle]: https://sdk.operatorframework.io/docs/cli/operator-sdk_run_bundle/\n[run-bundle-fbc-sqlite-faq]: https://sdk.operatorframework.io/docs/faqs/#operator-sdk-run-bundle-command-fails-and-the-registry-pod-has-an-error-of-mkdir-cant-create-directory-database-permission-denied\n"
  },
  {
    "path": "website/content/en/docs/olm-integration/tutorial-package-manifests.md",
    "content": "---\ntitle: OLM Integration Package Manifests Quickstart\nlinkTitle: Package Manifests Quickstart\nweight: 2\n---\n<!-- TODO(2.0.0): remove this document -->\n\n**Note**\nAs operator framework has moved to using bundle format by default, the package manifest commands have been deprecated and will be removed soon. It is suggested that you follow the [bundle quickstart][quickstart-bundle] to package your operator. \n\nThis guide assumes you have followed the introduction and *Setup* section of the [bundle quickstart][quickstart-bundle],\nand have added the `packagemanifests` target to your `Makefile` as described [here][doc-packagemanifests-makefile].\n\n**Important:** this guide assumes your project was scaffolded with `operator-sdk init --project-version=3`.\nThese features are unavailable to projects of version `2` or less; this information can be found by inspecting\nyour `PROJECT` file's `version` value.\n\n## Creating package manifests\n\nWe will now create a package manifests format by running `make packagemanifests` in the root of the memcached-operator project:\n\n```console\n$ make packagemanifests\n/home/user/go/bin/controller-gen rbac:roleName=manager-role crd webhook paths=\"./...\" output:crd:artifacts:config=config/crd/bases\noperator-sdk generate kustomize manifests -q\nkustomize build config/manifests | operator-sdk generate packagemanifests -q --version 0.0.1\n```\n\nA versioned manifests directory `packagemanifests/0.0.1` containing a CSV and all CRDs in `config/crds` and a\npackage manifest YAML file `packagemanifests/<project-name>.package.yaml` have been created in the Operator project.\n\n## Deploying an Operator with OLM\n\nAt this point in development we've generated all files necessary to build a memcached-operator registry.\nNow we're ready to test the Operator with OLM.\n\n### Testing package manifests\n\n`operator-sdk run packagemanifests` will create an Operator [registry][operator-registry]\nfrom manifests and metadata in the memcached-operator project, and inform OLM that memcached-operator v0.0.1\nis ready to be deployed. This process effectively replicates production deployment in a constrained manner\nto make sure OLM can deploy our Operator successfully before attempting real production deployment.\n\n`run packagemanifests` performs some optionally configurable setup [under the hood][doc-testing-deployment], but for\nmost use cases the following invocation is all we need:\n\n```console\n$ operator-sdk run packagemanifests --version 0.0.1\nINFO[0000] Running operator from directory packagemanifests\nINFO[0000] Creating memcached-operator registry         \nINFO[0000]   Creating ConfigMap \"olm/memcached-operator-registry-manifests-package\"\nINFO[0000]   Creating ConfigMap \"olm/memcached-operator-registry-manifests-0-0-1\"\nINFO[0000]   Creating Deployment \"olm/memcached-operator-registry-server\"\nINFO[0000]   Creating Service \"olm/memcached-operator-registry-server\"\nINFO[0000] Waiting for Deployment \"olm/memcached-operator-registry-server\" rollout to complete\nINFO[0000]   Waiting for Deployment \"olm/memcached-operator-registry-server\" to rollout: 0 of 1 updated replicas are available\nINFO[0066]   Deployment \"olm/memcached-operator-registry-server\" successfully rolled out\nINFO[0066] Creating resources                           \nINFO[0066]   Creating CatalogSource \"default/memcached-operator-ocs\"\nINFO[0066]   Creating Subscription \"default/memcached-operator-v0-0-1-sub\"\nINFO[0066]   Creating OperatorGroup \"default/operator-sdk-og\"\nINFO[0066] Waiting for ClusterServiceVersion \"default/memcached-operator.v0.0.1\" to reach 'Succeeded' phase\nINFO[0066]   Waiting for ClusterServiceVersion \"default/memcached-operator.v0.0.1\" to appear\nINFO[0073]   Found ClusterServiceVersion \"default/memcached-operator.v0.0.1\" phase: Pending\nINFO[0077]   Found ClusterServiceVersion \"default/memcached-operator.v0.0.1\" phase: InstallReady\nINFO[0078]   Found ClusterServiceVersion \"default/memcached-operator.v0.0.1\" phase: Installing\nINFO[0036]   Found ClusterServiceVersion \"default/memcached-operator.v0.0.1\" phase: Succeeded\nINFO[0037] Successfully installed \"memcached-operator.v0.0.1\" on OLM version \"0.15.1\"\n\nNAME                            NAMESPACE    KIND                        STATUS\nmemcacheds.cache.example.com    default      CustomResourceDefinition    Installed\nmemcached-operator.v0.0.1       default      ClusterServiceVersion       Installed\n```\n\nAs long as both the `ClusterServiceVersion` and all `CustomResourceDefinition`'s return an `Installed` status,\nthe memcached-operator has been deployed successfully.\n\nNow that we're done testing the memcached-operator, we should probably clean up the Operator's resources.\n[`operator-sdk cleanup`][cli-cleanup] will do this for you:\n\n```console\n$ operator-sdk cleanup memcached-operator\nINFO[0000] subscription \"memcached-operator-v0-0-1-sub\" deleted\nINFO[0000] customresourcedefinition \"memcacheds.cache.example.com\" deleted\nINFO[0000] clusterserviceversion \"memcached-operator.v0.0.1\" deleted\nINFO[0000] clusterrole \"memcached-operator-metrics-reader\" deleted\nINFO[0000] serviceaccount \"default\" deleted\nINFO[0000] role \"memcached-operator.v0.0.1-jhjk7\" deleted\nINFO[0000] rolebinding \"memcached-operator.v0.0.1-jhjk7-default-mxv6m\" deleted\nINFO[0000] catalogsource \"memcached-operator-ocs\" deleted\nINFO[0000] operatorgroup \"operator-sdk-og\" deleted\nINFO[0001] operator \"memcached-operator\" uninstalled\n```\n\n## Migrating packagemanifests to bundles\n\nIn order to migrate packagemanifests to bundles, `operator-sdk pkgman-to-bundle` command can be used.\n\nAs an example, consider the packagemanifests directory to have the following structure:\n\n```\npackagemanifests\n└── etcd\n    ├── 0.0.1\n    │   ├── etcdcluster.crd.yaml\n    │   └── etcdoperator.clusterserviceversion.yaml\n    ├── 0.0.2\n    │   ├── etcdbackup.crd.yaml\n    │   ├── etcdcluster.crd.yaml\n    │   ├── etcdoperator.v0.0.2.clusterserviceversion.yaml\n    │   └── etcdrestore.crd.yaml\n    └── etcd.package.yaml\n```\n\nHere, we have manifests for two versions of the `etcd` operator. The following command will generate bundles for each of these versions.\n\n```console\n$ operator-sdk pkgman-to-bundle packagemanifests --output-dir etcd-bundle/\nINFO[0000] Packagemanifests will be migrated to bundles in bundle directory\nINFO[0000] Creating etcd-bundle/bundle-0.0.1/bundle.Dockerfile\nINFO[0000] Creating etcd-bundle/bundle-0.0.1/metadata/annotations.yaml\n...\n```\n\nThis will create output bundles in the directory `etcd-bundle`. The output directory will look like:\n\n```\netcd-bundle/\n├── bundle-0.0.1\n│   ├── bundle\n│   │   ├── manifests\n│   │   │   ├── etcdcluster.crd.yaml\n│   │   │   ├── etcdoperator.clusterserviceversion.yaml\n│   │   ├── metadata\n│   │   │   └── annotations.yaml\n│   │   └── tests\n│   │       └── scorecard\n│   │           └── config.yaml\n│   └── bundle.Dockerfile\n└── bundle-0.0.2\n    ├── bundle\n    │   ├── manifests\n    │   │   ├── etcdbackup.crd.yaml\n    │   │   ├── etcdcluster.crd.yaml\n    │   │   ├── etcdoperator.v0.0.2.clusterserviceversion.yaml\n    │   │   ├── etcdrestore.crd.yaml\n    │   └── metadata\n    │       └── annotations.yaml\n    └── bundle.Dockerfile\n```\n\nTo build images for the bundles, the base container image name can be provided using `--image-tag-base` flag. This name should be provided without the tag (`:` and characters following), as the command will tag each bundle image with its packagemanifests directory name, i.e. `<image-tag-base>:<dir-name>`. For example, the following command for the above `packagemnifests` directory would build the bundles `quay.io/example/etcd-bundle:0.0.1` and `quay.io/example/etcd-bundle:0.0.2`.\n\n```sh\noperator-sdk pkgman-to-bundle packagemanifests --image-tag-base quay.io/example/etcd-bundle\n```\n\nA custom command can also be specified to build images, using the `--build-cmd` flag. The default command is `docker build`. For example:\n\n```console\n$ operator-sdk pkgman-to-bundle packagemanifests --output-dir etcd-bundle/ --image-tag-base quay.io/example/etcd --build-cmd \"podman build -f bundle.Dockerfile . -t\"\n```\n\nHowever, if using a custom command, it needs to be made sure that the command is in the `PATH` or a fully qualified path name is provided as input to the flag.\n\nOnce the command has finished building your bundle images and they have been added to a catalog image, delete all bundle directories except for the latest one. This directory will contain manifests for your operator's head bundle, and should be versioned with version control system like git. Move this directory and its `bundle.Dockerfile` to your project's root:\n\n```console\n$ cp -r ./etcd-bundle/bundle-0.0.2/* .\n$ rm -rf ./etcd-bundle\n```\n\nTry building then running your bundle on a live cluster to make sure it works as expected:\n\n```console\n$ make bundle bundle-build bundle-push\n$ operator-sdk run bundle quay.io/example/etcd-bundle:0.0.2\n```\n\n[quickstart-bundle]:/docs/olm-integration/quickstart-bundle\n[operator-registry]:https://github.com/operator-framework/operator-registry\n[cli-cleanup]:/docs/cli/operator-sdk_cleanup\n[doc-packagemanifests-makefile]:/docs/olm-integration/generation/#package-manifests-format\n[doc-testing-deployment]:/docs/olm-integration/testing-deployment\n"
  },
  {
    "path": "website/content/en/docs/overview/_index.md",
    "content": "---\ntitle: \"Overview\"\nlinkTitle: \"Overview\"\nweight: 1\ndescription: >\n    What is Operator SDK? Why should I use it?\n---\n\n## What is Operator SDK and why should I use it?\n\nThis project is a component of the [Operator Framework][of-home], an open source toolkit to manage Kubernetes native applications, called Operators, in an effective, automated, and scalable way. Read more in the [introduction blog post][of-blog].\n\n[Operators][operator_link] make it easy to manage complex stateful applications on top of Kubernetes. However writing an operator today can be difficult because of challenges such as using low level APIs, writing boilerplate, and a lack of modularity which leads to duplication.\n\nThe Operator SDK is a framework that uses the [controller-runtime][controller_runtime] library to make writing operators easier by providing:\n\n  - High level APIs and abstractions to write the operational logic more intuitively\n  - Tools for scaffolding and code generation to bootstrap a new project fast\n  - Extensions to cover common operator use cases\n\n## Workflow\n\nThe SDK provides workflows to develop operators in Go, Ansible, or Helm.\n\nThe following workflow is for a new [Go operator][golang-guide]:\n\n  1. Create a new operator project using the SDK Command Line Interface(CLI)\n  2. Define new resource APIs by adding Custom Resource Definitions(CRD)\n  3. Define Controllers to watch and reconcile resources\n  4. Write the reconciling logic for your Controller using the SDK and controller-runtime APIs\n  5. Use the SDK CLI to build and generate the operator deployment manifests\n\nThe following workflow is for a new [Ansible operator][ansible-guide]:\n\n  1. Create a new operator project using the SDK Command Line Interface(CLI)\n  2. Write the reconciling logic for your object using ansible playbooks and roles\n  3. Use the SDK CLI to build and generate the operator deployment manifests\n  4. Optionally add additional CRD's using the SDK CLI and repeat steps 2 and 3\n\nThe following workflow is for a new [Helm operator][helm-guide]:\n\n  1. Create a new operator project using the SDK Command Line Interface(CLI)\n  2. Create a new (or add your existing) Helm chart for use by the operator's reconciling logic\n  3. Use the SDK CLI to build and generate the operator deployment manifests\n  4. Optionally add additional CRD's using the SDK CLI and repeat steps 2 and 3\n\n## Command Line Interface\n\nTo learn more about the SDK CLI, see the [SDK CLI Reference][sdk_cli_ref], or run `operator-sdk [command] -h`.\n\n### Operator capability level\n\nNote that each operator type has a different set of capabilities. When choosing what type to use for your project, it is important to understand the features and limitations of each of the project types and the use cases for your operator.\n\n![operator-capability-level](/operator-capability-level.png)\n\nFind more details about the various levels and the feature requirements for them in the [capability level documentation][capability_levels].\n\n## Kubernetes version compatibility\n\nEach `operator-sdk` release is tested with a specific version of Kubernetes. This version matches\nthat of [kubernetes/kubernetes][k-k] or [client-go][client-go] that `operator-sdk` depends on directly,\nor that generated Operator projects depend on.\n\nIn general, client-go's [compatibility matrix][client-go-compat] will determine whether\na particular Kubernetes version is compatible with a particular `operator-sdk` version\nor generated Operator project. The following tables contains the canonical way per\nbinary or project type to look up a Y-axis version to plug into the compatibility matrix.\n\nBy binary:\n\n| Binary                  | Lookup strategy               | Kubernetes version    | `client-go` version        |\n|-------------------------|-------------------------------|-----------------------|----------------------------|\n| `operator-sdk`          | `$ operator-sdk version`      | {{% kube-version %}}  | {{% client-go-version %}}  |\n| `ansible-operator`      | `$ ansible-operator version`  | {{% kube-version %}}  | {{% client-go-version %}}  |\n| `helm-operator`         | `$ helm-operator version`     | {{% kube-version %}}  | {{% client-go-version %}}  |\n\nBy project type (replace `${IMAGE_VERSION}` with base image version in your project `Dockerfile`):\n\n| Project type   | Lookup strategy                           |\n|----------------|-------------------------------------------|\n| Go             | controller-runtime version (see `go.mod`) |\n| Ansible        | `$ docker run --entrypoint ansible-operator quay.io/operator-framework/ansible-operator:${IMAGE_VERSION} version` |\n| Helm           | `$ docker run --entrypoint helm-operator quay.io/operator-framework/helm-operator:${IMAGE_VERSION} version` |\n\n\n[k-k]:https://github.com/kubernetes/kubernetes\n[client-go]:https://github.com/kubernetes/client-go\n[client-go-compat]:https://github.com/kubernetes/client-go#compatibility-matrix\n\n## OLM version compatibility\n\nOperator SDK officially supports the latest 3 minor versions of OLM present at the time of a given Operator SDK release. These versions of OLM manifests are packaged with the SDK binary in the form of `bindata` to support low-latency installations of OLM with [`operator-sdk olm install`][olm-install-cmd]. Any other version installed with this command may work but is not tested nor officially supported.\n\nCurrently, the officially supported OLM Versions are: 0.26.0, 0.27.0, and 0.28.0\n\n## Platform support\n\nOfficial build architectures for binaries:\n\n| Binary                    | `linux/amd64` | `linux/arm64` |`linux/ppc64le` | `linux/s390x` | `darwin/amd64` | `darwin/arm64` |\n|---------------------------|---------------|---------------|----------------|---------------|----------------|----------------|\n| `operator-sdk`            | ✓             | ✓             | ✓              | ✓             | ✓              | ✓              |\n| `ansible-operator`        | ✓             | ✓             | ✓              | ✓             | ✓              | ✓              |\n| `helm-operator`           | ✓             | ✓             | ✓              | ✓             | ✓              | ✓              |\n\nOfficial build architectures for images:\n\n| Binary                    | `linux/amd64` | `linux/arm64` |`linux/ppc64le` | `linux/s390x` |\n|---------------------------|---------------|---------------|----------------|---------------|\n| `operator-sdk`            | ✓             | ✓             | ✓              | ✓             |\n| `ansible-operator`        | ✓             | ✓             | ✓              | ✓             |\n| `helm-operator`           | ✓             | ✓             | ✓              | ✓             |\n| `scorecard-test`          | ✓             | ✓             | ✓              | ✓             |\n| `scorecard-test-kuttl`    | ✓             | ✓             | ✓              | -             |\n\nOfficial support for any Windows architecture is not on the roadmap at this time.\n\n## Samples\n\nTo explore any operator samples built using the operator-sdk, see the samples in [operator-sdk/testdata/][testdata_samples].\n\n## FAQ\n\nFor common Operator SDK related questions, see the [FAQ][faq].\n\n## Contributing\n\nSee [CONTRIBUTING][contrib] for details on submitting patches and the contribution workflow.\n\nSee the [proposal docs][proposals_docs] and issues for ongoing or planned work.\n\n## Reporting bugs\n\nSee [reporting bugs][bug_guide] for details about reporting any issues.\n\n## License\n\nOperator SDK is under Apache 2.0 license. See the [LICENSE][license_file] file for details.\n\n[ansible-guide]:/docs/building-operators/ansible/quickstart/\n[bug_guide]:/docs/contribution-guidelines/reporting-issues/\n[capability_levels]: /docs/overview/operator-capabilities/\n[contrib]: https://github.com/operator-framework/operator-sdk/blob/master/CONTRIBUTING.MD\n[controller_runtime]: https://github.com/kubernetes-sigs/controller-runtime\n[faq]: /docs/faqs/\n[getting_started]: https://github.com/operator-framework/getting-started/blob/master/README.md\n[golang-guide]:/docs/building-operators/golang/quickstart/\n[helm-guide]:/docs/building-operators/helm/quickstart/\n[install_guide]: /docs/installation/\n[license_file]:https://github.com/operator-framework/operator-sdk/blob/master/LICENSE\n[of-blog]:https://www.openshift.com/blog/introducing-the-operator-framework\n[of-home]: https://github.com/operator-framework\n[operator_link]: https://kubernetes.io/docs/concepts/extend-kubernetes/operator/\n[proposals_docs]: https://github.com/operator-framework/operator-sdk/tree/master/proposals\n[testdata_samples]: https://github.com/operator-framework/operator-sdk/tree/master/testdata\n[sdk_cli_ref]: /docs/cli/\n[olm-install-cmd]: /docs/cli/operator-sdk_olm_install/\n"
  },
  {
    "path": "website/content/en/docs/overview/cheat-sheet.md",
    "content": "---\ntitle: \"Cheat Sheet\"\nlinkTitle: \"Cheat Sheet\"\nweight: 3\ndescription: >\n    Operator-SDK Cheat Sheet commands and operations\n---\n\nBelow you will find a cheat sheet with options and helpers for projects, which are built with the SDK and are respecting its proposed layout.\n\n## Common commands and options\n\n| Command   | Description  |\n|-------|-----------|\n| `operator-sdk init`          | To initialize an operator project in the current directory. |\n| `operator-sdk init --plugins=<plugin-key>`          | To initialize an operator project in the current directory using a specific plugin. To check the available plugins you can run `operator-sdk --help`. E.g (`operator-sdk init --plugins=helm`).|\n| `operator-sdk create api [flags]`          | Lets you create your own APIs with its [GKV][gkvs] by [Extending the Kubernetes API with CustomResourceDefinitions][extend-k8s-api], or lets you use external/core-types. Also generates their respective [controllers][controllers-k8s-doc].|\n| `operator-sdk create webhook [flags]`          | To scaffold [Webhooks][webhooks-k8s-doc] for the APIs declared in the project. Currently, only the Go-based project supports this option. |\n| `make docker-build IMG=<some-registry>/<project-name>:<tag>`          | Build the operator image.      |\n| `make docker-build docker-push IMG=<some-registry>/<project-name>:<tag>`      | Build and push the operator image for your registry.  |\n| `make install`         | Install the CRDs into the cluster. |\n| `make uninstall`         | Uninstall the CRDs into the cluster. |\n| `make run`         | Run your controller locally and outside of the cluster. Note that this will run in the foreground, so switch to a new terminal if you want to leave it running. |\n| `make deploy`         | Deploy your project on the cluster. |\n| `make undeploy`         | Undeploy your project on the cluster. |\n\n## To create bundles, catalogs, and develop for OLM\n\nFor further information check [Operator SDK Integration with Operator Lifecycle Manager][olm-integration].\n\n| Command   | Description  |\n|-------|-----------|\n| `make bundle`          | Create/update the [bundle][bundle] based on the project manifests in the `bundle/` directory. For more info see [Create a bundle][creating-a-bundle].      |\n| `operator-sdk bundle validate ./bundle`          | To validate your [bundle][bundle] spec definition.      |\n| `operator-sdk bundle validate ./bundle --select-optional suite=operatorframework` | Validate your bundle against [OperatorHub.io][operatorhub-io] criteria. For further information use the flag `--help`. |\n| `operator-sdk olm install` | To install OLM on your cluster for development purposes. |\n| `operator-sdk olm uninstall` | To uninstall OLM from your cluster. |\n| `make bundle-build BUNDLE_IMG=<some-registry>/<project-name-bundle>:<tag>` | To build your bundle operator image. |\n| `make bundle-build bundle-push BUNDLE_IMG=<some-registry>/<project-name-bundle>:<tag>` | To build and push your bundle operator image. |\n| `operator-sdk run bundle <some-registry>/<project-name-bundle>:<tag>` | To deploy your bundle operator using OLM on your cluster for development purposes. |\n| `operator-sdk run bundle private-registry.org/bundle:v1.2.3 --service-account sa-with-secret --pull-secret-name regcred --ca-secret-name cert-sec` | Configure `run bundle` (and `run bundle-upgrade`) to use an image pull secret, non-default service account configured with that secret, and custom CA certificate secret |\n<!-- TODO(estroz): remove the service account requirement once OLM releases a patch or new\nminor release containing https://github.com/operator-framework/operator-lifecycle-manager/pull/1941 -->\n\n### Updating bundle channels\n \nThe following examples let you update the [bundle][bundle] with data-informed. For further information also check [Upgrade your Operator][upgrade-project] and see [Channel Naming][channel-namming-doc].  \n \n**NOTE:** Note that it will carry over any customizations you have made and ensure a rolling update to the next version of your Operator. \n\n```sh\nmake bundle CHANNELS=fast,preview DEFAULT_CHANNEL=stable VERSION=1.0.0 IMG=<some-registry>/<project-name-bundle>:<tag>\n```\n\n**NOTE** You can use environment variables to pass the values such as `export CHANNELS=fast,candidate`. Note that, their values will be used by `make bundle` command.\n\n## To test your projects\n\n| Command   | Description  |\n|-------|-----------|\n| `operator-sdk scorecard ./bundle`          |  Run the [Scorecard][scorcard] tests for your bundle.  |\n| `make test`          |  Run Go tests. It is valid only for Go-based operators.    |\n| `molecule test`          |  Run [Molecule][molecule-tests] tests.  It is valid only for Ansible-based operators. |\n| `helm test`          |  Run [Helm chart tests][helm-chart-tests].  It is valid only for Helm-based operators. |\n\n**NOTE:** This is not a comprehensive list of make targets or commands. Please see the scaffolded Makefile and `make help` for the full list of targets. Note that you can use `operator-sdk <command> --help` and check the [CLI][cli] section to check all options.\n \n[olm-integration]: /docs/olm-integration/\n[creating-a-bundle]: /docs/olm-integration/tutorial-bundle/#creating-a-bundle\n[bundle]:https://github.com/operator-framework/operator-registry/blob/v1.16.1/docs/design/operator-bundle.md\n[operatorhub-io]: https://operatorhub.io/\n[upgrade-project]: /docs/olm-integration/generation/#upgrade-your-operator\n[channel-namming-doc]: https://olm.operatorframework.io/docs/best-practices/channel-naming/\n[controllers-k8s-doc]: https://kubernetes.io/docs/concepts/architecture/controller\n[gkvs]: https://book.kubebuilder.io/cronjob-tutorial/gvks.html\n[extend-k8s-api]: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/\n[webhooks-k8s-doc]: https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/\n[scorcard]: /docs/testing-operators/scorecard/\n[molecule-tests]: /docs/building-operators/ansible/testing-guide\n[helm-chart-tests]: https://helm.sh/docs/topics/chart_tests/\n[cli]: /docs/cli/\n"
  },
  {
    "path": "website/content/en/docs/overview/operator-capabilities.md",
    "content": "---\ntitle: Operator Capability Levels\nlinkTitle: Capability Levels\nweight: 4\n---\n\nOperators come in different maturity levels in regards to their lifecycle management capabilities for the application or workload they deliver. The capability models aims to provide guidance in terminology to express what features users can expect from an operator.\n\n![operator-capability-level](/operator-capability-level.png)\n\nEach capability level is associated with a certain set of management features the Operator offers around the managed workload. Operator that do not manage a workload and/or are delegating to off-clusters orchestration services would remain at Level 1. Capability levels are designated from level 1 to level 5. Each capability represents its own set of features and may be independent of each other.\n\n\n## Terminology\n\n**Operator** - the custom controller installed on a Kubernetes cluster\n\n**Operand** - the managed workload provided by the Operator as a service\n\n**Custom Resource (CR)** - an instance of the [`CustomResourceDefinition`](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/) the Operator ships that represents the Operand or an Operation on an Operand (also known as primary resources)\n\n**Managed resources** - the Kubernetes objects or off-cluster services the Operator uses to constitute an Operand (also known as secondary resources)\n\n**Custom Resource Definition (CRD)** - an API of the Operator, providing the blueprint and validation rules for **Custom Resources**.\n\n---\n\n## Level 1 - Basic Install\n\nAutomated application provisioning and configuration management. This first capability level means your operator can fully provision an application through a custom resource, allowing all installation configuration details to be specified in the CR. It should also be possible to install the operator itself in multiple ways (kubectl, OLM, Catalog source). Any configuration required to make the Operand run should be configured through the CR if possible. Avoid the practice of requiring the user to create/manage configuration files outside of Kubernetes.\n\n### Installation of the workload\n\n- Operator deploys an Operand or configures off-cluster resources\n- Operator waits for managed resources to reach a healthy state\n- Operator conveys readiness of application or managed resources to the user leveraging the `status` block of the Custom Resource\n\n**Example:** an Operator deploys a database by creating `Deployment`, `ServiceAccount`, `RoleBinding`, `ConfigMap`, `PersistentVolumeClaim` and `Secret` object, initializes an empty database schema and signals readiness of the database to accept queries.\n\n### Configuration of the workload\n\n- Operator provides configuration via the `spec` section of the Custom Resource\n- Operator reconciles configuration and updates to it with the status of the managed resources\n\n**Example:** an Operator, managing a database, offers increasing the capacity of the database by resizing the underlying `PersistentVolumeClaim` based on changes the databases Custom Resource instance.\n\n**Guiding questions to determine Operator reaching Level 1**\n\n1. What installation configuration can be set in the CR?\n\n2. What additional installation configuration could still be added?\n\n3. Can you set operand configuration in the CR? If so, what configuration is supported for each operand?\n\n4. Can you override the operand images through the CR or an environment variable of the Operator deployment?\n\n5. Does the managed application / workload get updated in a non-disruptive fashion when the configuration of the CR is changed?\n\n6. Does the status of the CR reflect that configuration changes are currently applied?\n\n7. What additional operand configuration could still be added?\n\n8. Do all of the instantiated CRs include a status block? If so, does it provide enough insight to the user about the application state?\n\n9. Do all of your CRs have documentation listing valid values and mandatory fields?\n\n10. If your operator is packaged for OLM, does its CSV list all images used in the CSV under `spec.relatedImages`?\n\n---\n\n## Level 2 - Seamless Upgrades\n\nSeamless upgrades mean the upgrade is as easy as possible for the user. You should support seamless upgrades of both your operator and operand, these would normally go hand in hand, an upgrade of the operator would automatically ensure the instantiated resources for each CR are in the new desired state and which would upgrade your operand. Upgrade may also be defined in multiple ways, such as updating the software of the operand - and other internals specific to the application - such as schema migrations. It should be very clear what is upgraded when this takes place, and what is not.\n\n### Upgrade of the managed workload\n\n- Operand can be upgraded in the process of upgrading the Operator, or\n- Operand can be upgraded as part of changing the CR\n- Operator understands how to upgrade older versions of the Operand, managed previously by an older version of the Operator\n\n### Upgrade of the Operator\n\n- Operator can be upgraded seamlessly and can either still manage older versions of the Operand or update them\n- Operator conveys inability to manage an unsupported version of the Operand in the `status` section of the CR\n\n**Example:** An Operator managing a database can update an existing database from a previous to a newer version without data loss. The Operator might do so as part of a configuration change or as part of an update of the Operator itself.\n\n**Guiding questions to determine Operator reaching Level 2**\n\n1. Can your Operator upgrade your Operand?\n\n2. Does your Operator upgrade your Operand during updates of the Operator?\n\n3. Can your Operator manage older Operand version versions?\n\n4. Is the Operand upgrade non disruptive?\n\n5. If there is downtime during an upgrade, does the Operator convey this in the `status` of the CR?\n\n\n---\n\n## Level 3 - Full Lifecycle\n\nIt should be possible to backup and restore the operand from the operator itself without any additional manual intervention other than triggering these operations. The operand data that should be backed up is any stateful data managed by the operand. You don’t need to backup the CR itself or the k8s resources created by the operator as the operator should return all resources to the same state if the CR is recreated. If your operator does not already setup the operand with other k8s resilient best practices, this should be completed to achieve this capability level. This includes liveness and readiness probes, multiple replicas, rolling deployment strategies, pod disruption budgets, CPU and memory requests and limits.\n\n\n### Lifecycle features\n\n- Operator provides the ability to create backups of the Operand\n- Operator is able to restore a backup of an Operand\n- Operator orchestrates complex re-configuration flows on the Operand\n- Operator implements fail-over and fail-back of clustered Operands\n- Operator supports add/removing members to a clustered Operand\n- Operator enables application-aware scaling of the Operand\n\n**Example:** an Operator managing a database provides the ability to create an application consistent backup of the data by flushing the database log and quiescing the write activity to the database files.\n\n**Guiding questions to determine Operator reaching Level 3**\n\n1. Does your Operator support backing up the Operand?\n\n2. Does your Operator support restoring an Operand from a backup and get it under management again?\n\n3. Does your Operator wait for reconfiguration work to be finished and in the expected sequence?\n\n4. Is your Operator taking cluster quorum into account, if present?\n\n5. Does your Operator allow adding/removing read-only slave instances of your Operator?\n\n6. Does your operand have a Liveness probe?\n\n7. Does your operand have a Readiness probe which will fail if any aspect of the operand is not ready? e.g. if the connection to the database fails.\n\n8. Does your operand use a rolling deployment strategy?\n\n9. Does your operator create a PodDisruptionBudget resource for your operand pods?\n\n10. Does your operand have CPU requests and limits set?\n\n\n\n---\n\n## Level 4 - Deep Insights\n\nSetup full monitoring and alerting for your operand. All resources such as Prometheus rules (alerts) and Grafana dashboards should be created by the operator when the operand CR is instantiated. The RED method<sup>1</sup> is a good place to start with knowing what metrics to expose.\nAim to have as few alerts as possible, by alerting on symptoms that are associated with end-user pain rather than trying to catch every possible way that pain could be caused. Alerts should link to relevant consoles and make it easy to figure out which component is at fault\nNative k8s objects emit events (“Events” objects) for situations users or administrators should be alerted about. Your operator should do similar for state changes related to your operand. “Custom”, here, means that it should emit events specific to your operator/operand outside of the events already emitted by their deployment methodology.  This, in conjunction with status descriptors for the CR conditions, give much needed visibility into actions taken by your operator/operand. Operators are codified domain-specific knowledge. Your end user should not need this domain-specific knowledge to gain visibility into what’s happening with their resource.\nPlease, ensure that you look at the Kubernetes API conventions in the [Events][k8s-api-events] and [status][k8s-api-status] sections to know how to properly deal with them.\n\n### Monitoring\n\n- Operator exposing metrics about its health\n- Operator exposes health and performance metrics about the Operand\n\n### Alerting and Events\n\n- Operand sends useful alerts\n- Custom Resources emit custom events\n\n**Example:** A database Operator continues to parse the logging output of the database software and understands noteworthy log events, e.g. running out of space for database files and produces alerts. The operator also instruments the database and exposes application level, e.g. database queries per second\n\n**Guiding questions to determine Operator reaching Level 4**\n\n1. Does your Operator expose a health metrics endpoint?\n\n2. Does your Operator expose Operand alerts?\n\n4. Do you have Standard Operating Procedures (SOPs) for each alert?\n\n5. Does you operator create critical alerts when the service is down and warning alerts for all other alerts?\n\n6. Does your Operator watch the Operand to create alerts?\n\n7. Does your Operator emit custom Kubernetes events?\n\n8. Does your Operator expose Operand performance metrics?\n\n<sup>1</sup> The RED method\nThe RED Method defines the three key metrics for every service in your architecture.\n* Rate (the number of requests per second)\n* Errors (the number of those requests that are failing)\n* Duration (the amount of time those requests take)\n\nNote that by building projects using Operator-SDK or [Kubebuilder][kubebuilder] CLI tools your solution leverages [controller-runtime][controller-runtime] which provides the following [reference][metric-reference] exported by default. For further information, see the [metrics][metrics] documentation to understand how to enable monitoring and add custom metrics . Also, you may want to give a look at the [(grafana/v1-alpha)][grafana-plugin-docs] which provides some JSON manifests to create Grafana dashboards using the default metrics exported.\n\n---\n\n## Level 5 - Auto Pilot\n\nThe highest capability level aims to significantly reduce/eliminate any remaining manual intervention in managing the operand. The operator should configure the Operand to auto-scale as load picks up. The Operator should understand the application-level performance indicators and determine when it's healthy and performing well. The operator should attempt to automatically fix an unhealthy operand. The operator should tune the operands performance, this could include scheduling on another node the pods are running on or modifying operand configuration.\n\n### Auto-scaling\n\n- Operator scales the Operand up under increased load based on Operand metric\n- Operator scales the Operand down below a certain load based on Operand metric\n\n### Auto-Healing\n\n- Operator can automatically heal unhealthy Operands based on Operand metrics/alerts/logs\n- Operator can prevent the Operand from transitioning into an unhealthy state based on Operand metrics\n\n### Auto-tuning\n\n- Operator is able to automatically tune the Operand to a certain workload pattern\n- Operator dynamically shifts workloads onto best suited nodes\n\n### Abnormality detection\n\n- Operator determines deviations from a standard performance profile\n\n**Example:** A database operator monitors the query load of the database and automatically scales additional read-only slave replicas up and down. The operator also detects subpar index performance and automatically rebuilds the index in times of reduced load. Further, the operator understands the normal performance profile of the database and creates alerts on excessive amount of slow queries. In the event of slow queries and high disk latency the Operator automatically transitions the database files to another `PersistentVolume` of a higher performance class.\n\n**Guiding questions to determine Operator reaching Level 5**\n\n1. Can your operator read metrics such as requests per second or other relevant metrics and auto-scale horizontally or vertically, i.e., increasing the number of pods or  resources used by pods?\n\n2. Based on question number 1 can it scale down or decrease the number of pods or the total amount of resources used by pods?\n\n3. Based on the deep insights built upon level 4 capabilities can your operator determine when an operand became unhealthy and take action such as redeploying, changing configurations, restoring backups etc.?\n\n4. Again considering that with level 4 deep insights the operator has information to learn the performance baseline dynamically and can learn the best configurations for peak performance can it adjust the configurations to do so?\n\n5. Can it move the workloads to better nodes, storage or networks to do so?\n\n6. Can it detect and alert when anything is working below the learned performance baseline that can’t be corrected automatically?\n\n[kubebuilder]: https://github.com/kubernetes-sigs/kubebuilder\n[controller-runtime]: https://github.com/kubernetes-sigs/controller-runtime\n[metrics]: https://book.kubebuilder.io/reference/metrics.html\n[metric-reference]: https://book.kubebuilder.io/reference/metrics-reference.html\n[grafana-plugin-docs]: https://book.kubebuilder.io/plugins/available/grafana-v1-alpha\n[k8s-api-events]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#events\n[k8s-api-status]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status\n"
  },
  {
    "path": "website/content/en/docs/overview/project-layout.md",
    "content": "---\ntitle: \"Project Layout\"\nlinkTitle: \"Project Layout\"\nweight: 2\ndescription: A description of the layout of projects built with Operator SDK\n---\n\n## Operator SDK Project Layout\n\nAll projects initialized with `operator-sdk init` have a common base structure which builds on [kubebuilder's project layout][kb-whats in-a-basic-project?]. Each project type is customized further with code of that type's language.\n\n### Common Base\n\nThe common structure contains the following items:\n\n| File/Directory | Description | \n| ------ | ----- |\n| `Dockerfile` | The Dockerfile of your operator project, used to build the image with `make docker-build`. |\n| `Makefile` | Build file with helper targets to help you work with your project. |\n| `PROJECT` | This file represents the project's configuration and is used to track useful information for the CLI and plugins. |\n| `bin/` | This directory contains useful binaries such as the `manager` which is used to run your project locally and  the `kustomize` utility used for the project configuration. For other language types, it might have other binaries useful for developing your operator. |\n| `bundle/` | This directory contains all the files used to [integrate your project][olm-integrate] with [OLM][olm] with the [bundle][bundle] format. It is built from the Makefile target `make bundle`. |\n| `bundle/manifests/` | This directory has the [OLM manifests][olm-manifests] of your [bundle][bundle]. |\n| `bundle/metadata/`  | This directory has the [OLM metadata][olm-metadata] of your [bundle][bundle] e.g the index image annotations. |\n| `bundle/tests/` | This directory has the [Scorecard][scorecard] tests shipped with your operator bundle. |\n| `config/` | Contains configuration files to launch your project on a cluster. Plugins might use it to provide functionality. For example, for the CLI  to help create your operator bundle it will look for the CRD's and CR's which are scaffolded in this directory. You will also find all [Kustomize][Kustomize] YAML definitions as well. |\n| `config/crd/` | Contains the [Custom Resources Definitions][k8s-crd-doc]. |\n| `config/default/` | Contains a [Kustomize base][kustomize-base] for launching the controller in a standard configuration. |\n| `config/manager/` | Contains the manifests to launch your operator project as pods on the cluster. |\n| `config/manifests/` | Contains the base to generate your OLM manifests in the bundle directory. |\n| `config/prometheus/` | Contains the manifests required to enable project to serve metrics to [Prometheus][kb-metrics] such as the `ServiceMonitor` resource. |\n| `config/scorecard/` | Contains the manifests required to allow you test your project with [Scorecard][scorecard]. |\n| `config/rbac/` | Contains the [RBAC][k8s-rbac] permissions required to run your project. |\n| `config/samples/` | Contains the [Custom Resources][k8s-cr-doc]. |\n| `bundle.Dockerfile` |  The Dockerfile to build the [bundle][bundle] image. Used to build the operator bundle image with `make bundle-build. |\n\n### Ansible\n\nNow, let's look at the files and directories specific to Ansible-based operators.\n\n| File/Directory | Description | \n| ------ | ----- |\n|`config/testing/` | Manifest files to help you test your project. For example, to change the image policy for your [Molecule tests][ansible-test-guide] or to enable debug level in the Ansible logs. |\n|`molecule/` | Contain the manifests for your [Molecule][molecule] tests. |\n|`molecule/default` | Contains the default [Molecule][molecule] task. |\n|`molecule/kind` | Contains the [Molecule][molecule] task to be executed on the cluster. |\n|`playbooks/` | Contains the Ansible playbooks.|\n|`roles/` | Contains the Ansible role files for each Kind scaffold. |\n|`requirements.yml` | This file specifies Ansible dependencies that need to be installed for your operator to function. |\n|`watches.yaml` | Contains Group, Version, Kind, and the playbooks and rules location. Used to configure the [Ansible watches][ansible-watches]. |\n\n### Golang \n\nNow, let's look at the files and directories specific to Go-based operators.\n\n| File/Directory | Description |\n| ------ | ----- |\n|`api/` | Contains the api definition |\n|`config/certmanager` |  Contains the Kustomize manifests which configure the [cert-manager][cert-manager] by the Webhooks. |\n|`config/webhook` | Contains the Kustomize manifests to configure the Webhook. |\n|`controllers` |  Contains the controllers. |\n|`main.go` | Implements the project initialization. |\n| `hack/` | Contains utility files, e.g. the file used to scaffold the license header for your project files. |\n\n### Helm \n\nNow, let's look at the files and directories specific to Helm-based operators.\n\n| File/Directory | Description | \n| ------ | ----- |\n|`helm-charts` | Contains the Helm charts for each Kind scaffold which can be initialized with `operator-sdk init --plugins=helm [options]` or `operator-sdk create api [options]` . |\n|`watches.yaml` | Contains Group, Version, Kind, and Helm chart location. Used to configure the [Helm watches][helm-watches]. |\n\n[kb-whats in-a-basic-project?]: https://book.kubebuilder.io/cronjob-tutorial/basic-project.html\n[olm]: https://github.com/operator-framework/operator-lifecycle-manager\n[Kustomize]: https://github.com/kubernetes-sigs/kustomize\n[kustomize-base]: https://github.com/operator-framework/operator-sdk/blob/v1.4.2/testdata/go/v3/memcached-operator/config/default/kustomization.yaml\n[kb-metrics]: https://book.kubebuilder.io/reference/metrics.html\n[k8s-rbac]: https://kubernetes.io/docs/reference/access-authn-authz/rbac/\n[k8s-cr-doc]: https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/#custom-resources\n[k8s-crd-doc]: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/\n[scorecard]: /docs/testing-operators/scorecard/\n[olm-integrate]: /docs/olm-integration/\n[olm-manifests]: https://github.com/operator-framework/operator-registry/tree/v1.5.3#manifest-format  \n[olm-metadata]: https://github.com/operator-framework/operator-registry/blob/v1.16.1/docs/design/operator-bundle.md#bundle-manifest-format\n[bundle]:https://github.com/operator-framework/operator-registry/blob/v1.16.1/docs/design/operator-bundle.md\n[molecule]: https://molecule.readthedocs.io/\n[ansible-watches]: /docs/building-operators/ansible/reference/watches\n[ansible-test-guide]: /docs/building-operators/ansible/testing-guide\n[helm-watches]: /docs/building-operators/helm/reference/watches\n[cert-manager]: https://cert-manager.io/docs/\n"
  },
  {
    "path": "website/content/en/docs/testing-operators/_index.md",
    "content": "---\ntitle: Testing Operators\nweight: 3\ndescription: How to test your operators\n---\n"
  },
  {
    "path": "website/content/en/docs/testing-operators/scorecard/_index.md",
    "content": "---\ntitle: Scorecard\nlinkTitle: Scorecard\nweight: 3\ndescription: Statically validate your operator bundle using Scorecard. \n---\n\n## Overview\n\nThe scorecard command, part of the operator-sdk, executes tests\non your operator based upon a configuration file and test images.\n\nTests are implemented within test images that are configured\nand constructed to be executed by scorecard.\n\nScorecard assumes it is being executed with access to a configured\nKubernetes cluster.  Each test is executed within a Pod by scorecard,\nfrom which pod logs are aggregated and test results sent to the console.\n\nScorecard has built-in basic and OLM tests, and it also provides a\nmeans to execute custom test definitions.\n\n## Requirements\n\nThe scorecard tests make no assumptions as to the state of the\noperator being tested. Creating operators and custom resources\nfor an operator are left outside the scope of the scorecard itself.\n\nScorecard tests can however create whatever resources they\nrequire if the tests are designed for resource creation.\n\n## Running the Scorecard\n\n1. A default set of kustomize files should have been scaffolded by `operator-sdk init`.\nIf that is not the case, run `operator-sdk init` as you would have to initialize your project\nand copy scaffolded files:\n  ```sh\n  $ TMP_PROJECT=\"$(mktemp -d)/<current-project-name>\"\n  $ mkdir \"$TMP_PROJECT\"\n  $ pushd \"$TMP_PROJECT\"\n  $ operator-sdk init\n  $ popd\n  $ cp -r \"$TMP_PROJECT\"/config/scorecard ./config/\n  ```\nThe default config generated by this kustomization can be immediately run against your operator.\nSee the [config file section](#config-file) for an explanation of the configuration file format.\n1. (Re)generate [bundle][quickstart-bundle] manifests and metadata for your Operator.\n`make bundle` will automatically add scorecard annotations to your bundle's metadata,\nwhich is used by the `scorecard` command to run tests.\n1. Execute the [`scorecard` command][cli-scorecard]. See the [command args section](#command-args)\nfor an overview of command invocation.\n\n## Configuration\n\nThe scorecard test execution is driven by a configuration file named `config.yaml`, generated by `make bundle`.  Note that if run `make bundle` that any\nchanges you have made to `config.yaml` will be overwritten.  To persist\nany changes to `config.yaml` you can update the kustomize templates found in the\n`config/scorecard` directory.\nThe configuration file is located at the following location within your bundle directory (`bundle/` by default):\n```sh\n$ tree ./bundle\n./bundle\n...\n└── tests\n    └── scorecard\n        └── config.yaml\n```\n\n### Config File\n\nThe following YAML spec is an example of the scorecard configuration file:\n\n```yaml\nkind: Configuration\napiversion: scorecard.operatorframework.io/v1alpha3\nmetadata:\n  name: config\nstages:\n- parallel: true\n  tests:\n  - image: quay.io/operator-framework/scorecard-test:latest\n    entrypoint:\n    - scorecard-test\n    - basic-check-spec\n    labels:\n      suite: basic\n      test: basic-check-spec-test\n  - image: quay.io/operator-framework/scorecard-test:latest\n    entrypoint:\n    - scorecard-test\n    - olm-bundle-validation\n    labels:\n      suite: olm\n      test: olm-bundle-validation-test\n```\n\nThe configuration file defines the tests that scorecard executes. Tests are\ngrouped into stages for fine-grained control of [parallelism](#parallelism).\nThe following fields of the scorecard configuration file define the test as\nfollows:\n\n\n| Config Field | Description\n| ------------ | -----------\n| image        | the test container image name that implements a test\n| entrypoint   | the command and arguments that are invoked in the test image to execute a test\n| labels       | scorecard-defined or custom labels that [select](#selecting-tests) which tests to run\n\n### Command Args\n\nThe scorecard command has the following syntax:\n```sh\n$ operator-sdk scorecard <bundle_dir_or_image> [flags]\n```\n\nThe scorecard requires a positional argument that holds either the\non-disk path to your operator bundle or the name of a bundle image.  Note\nthat the scorecard does not run your operator but merely uses\nthe scorecard configuration within the bundle contents to know which tests\nto execute.\n\nFor further information about the flags see the [CLI documentation][cli-scorecard].\n\n## Parallelism\n\nThe configuration file allows operator developers to define separate stages for\ntheir tests. Stages run sequentially in the order they are defined in the\nconfiguration file. A stage contains a list of tests and a configurable\n`parallel` setting.\n\nBy default (or when a stage explicitly sets `parallel` to `false`), tests in\na stage are run sequentially in the order they are defined in the configuration\nfile. Running tests one at a time is helpful to guarantee that no two tests\ninteract and conflict with each other.\n\nHowever, if tests are designed to be fully isolated, they can be parallelized.\nTo run a set of isolated tests in parallel, include them in the same stage and\nset `parallel` to `true`. All tests in a parallel stage are executed\nsimultaneously, and scorecard waits for all of them to finish before proceeding\nto the next stage. This can make your tests run much faster.\n\n## Selecting Tests\n\nTests are selected by setting the `--selector` CLI flag to\na set of label strings.  If a selector flag is not supplied, then all\nthe tests within the scorecard configuration file are executed.\n\nTests are executed serially, one after the other, with test results\nbeing aggregated by scorecard and written to stdout.\n\nTo select a single test (`basic-check-spec-test`) you would enter the\nfollowing:\n```sh\n$ operator-sdk scorecard <bundle_dir_or_image> -o text --selector=test=basic-check-spec-test\n```\n\nTo select a suite of tests, olm in this case, you would specify\na label that is used by all the OLM tests:\n```sh\n$ operator-sdk scorecard <bundle_dir_or_image> -o text --selector=suite=olm\n```\n\nTo select multiple tests, you could specify them as follows:\n```sh\n$ operator-sdk scorecard <bundle_dir_or_image> -o text --selector='test in (basic-check-spec-test,olm-bundle-validation-test)'\n```\n\n## Built-in Tests\n\nThe scorecard ships with pre-defined tests that are arranged into suites.\n\n### Basic Test Suite\n\n| Test        | Description   | Test Name |\n| --------    | -------- | -------- |\n| Spec Block Exists | This test checks the Custom Resource (CRs) created in the cluster to make sure that all CRs have a spec block. | basic-check-spec-test |\n\n### OLM Test Suite\n\n| Test        | Description   | Short Name |\n| --------    | -------- | -------- |\n| Bundle Validation | This test validates the bundle manifests found in the bundle that is passed into scorecard.  If the bundle contents contain errors, then the test result output will include the validator log as well as error messages from the validation library.  See this [document][olm-bundle] for details on bundles.| olm-bundle-validation-test |\n| Provided APIs have validation |This test verifies that the CRDs for the provided CRs contain a validation section and that there is validation for each spec and status field detected in the CR. | olm-crds-have-validation-test |\n| Owned CRDs Have Resources Listed | This test makes sure that the CRDs for each CR provided via the `cr-manifest` option have a `resources` subsection in the [`owned` CRDs section][owned-crds] of the CSV. If the test detects used resources that are not listed in the resources section, it will list them in the suggestions at the end of the test. Users are required to fill out the resources section after initial code generation for this test to pass. For Go-based operators, use ClusterServiceVersion [API Markers](/docs/building-operators/golang/references/markers) to add resources. | olm-crds-have-resources-test |\n| Spec Fields With Descriptors | This test verifies that every field in the Custom Resources' spec sections have a corresponding descriptor listed in the CSV.| olm-spec-descriptors-test |\n| Status Fields With Descriptors | This test verifies that every field in the Custom Resources' status sections have a corresponding descriptor listed in the CSV.| olm-status-descriptors-test |\n\n## Scorecard Output\n\nThe `--output` flag specifies the scorecard results output format.\n\n### JSON format\n\nSee an example of the JSON format produced by a scorecard test:\n\n```json\n{\n  \"apiVersion\": \"scorecard.operatorframework.io/v1alpha3\",\n  \"kind\": \"TestList\",\n  \"items\": [\n    {\n      \"kind\": \"Test\",\n      \"apiVersion\": \"scorecard.operatorframework.io/v1alpha3\",\n      \"spec\": {\n        \"image\": \"quay.io/operator-framework/scorecard-test:latest\",\n        \"entrypoint\": [\n          \"scorecard-test\",\n          \"olm-bundle-validation\"\n        ],\n        \"labels\": {\n          \"suite\": \"olm\",\n          \"test\": \"olm-bundle-validation-test\"\n        }\n      },\n      \"status\": {\n        \"results\": [\n          {\n            \"name\": \"olm-bundle-validation\",\n            \"log\": \"time=\\\"2020-06-10T19:02:49Z\\\" level=debug msg=\\\"Found manifests directory\\\" name=bundle-test\\ntime=\\\"2020-06-10T19:02:49Z\\\" level=debug msg=\\\"Found metadata directory\\\" name=bundle-test\\ntime=\\\"2020-06-10T19:02:49Z\\\" level=debug msg=\\\"Getting mediaType info from manifests directory\\\" name=bundle-test\\ntime=\\\"2020-06-10T19:02:49Z\\\" level=info msg=\\\"Found annotations file\\\" name=bundle-test\\ntime=\\\"2020-06-10T19:02:49Z\\\" level=info msg=\\\"Could not find optional dependencies file\\\" name=bundle-test\\n\",\n            \"state\": \"pass\"\n          }\n        ]\n      }\n    }\n  ]\n}\n```\n\n### XML format\n\nSee the example below for the results of a scorecard test formatted in XML. The scorecard tool formats the XML output for XUnit schema compatibility. This format makes it easier for post-processing the test results.\n\n```xml\n<testsuites name=\"scorecard\">\n  <testsuite name=\"olm-bundle-validation-test\" tests=\"1\" skipped=\"0\" failures=\"0\" errors=\"0\">\n    <properties>\n      <property name=\"spec.image\" value=\"quay.io/operator-framework/scorecard-test:v1.19.0\"></property>\n      <property name=\"spec.entrypoint\" value=\"scorecard-test olm-bundle-validation\"></property>\n      <property name=\"labels.test\" value=\"olm-bundle-validation-test\"></property>\n    </properties>\n    <testcase name=\"olm-bundle-validation\" time=\"0001-01-01T00:00:00Z\">\n      <system-out>time=&#34;2022-04-12T19:21:52Z&#34; level=debug msg=&#34;Found manifests directory&#34; name=bundle-test&#xA;time=&#34;2022-04-12T19:21:52Z&#34; level=debug msg=&#34;Found metadata directory&#34; name=bundle-test&#xA;time=&#34;2022-04-12T19:21:52Z&#34; level=debug msg=&#34;Getting mediaType info from manifests directory&#34; name=bundle-test&#xA;time=&#34;2022-04-12T19:21:52Z&#34; level=debug msg=&#34;Found annotations file&#34; name=bundle-test&#xA;time=&#34;2022-04-12T19:21:52Z&#34; level=debug msg=&#34;Could not find optional dependencies file&#34; name=bundle-test&#xA;</system-out>\n    </testcase>\n  </testsuite>\n  <!-- Some suites omitted for readability -->\n</testsuites>\n```\n\n### Text format\n\nSee an example of the text format produced by a scorecard test:\n\n```\n--------------------------------------------------------------------------------\nImage:      quay.io/operator-framework/scorecard-test:latest\nEntrypoint: [scorecard-test olm-bundle-validation]\nLabels:\n\t\"suite\":\"olm\"\n\t\"test\":\"olm-bundle-validation-test\"\nResults:\n\tName: olm-bundle-validation\n\tState: pass\n\tLog:\n\t\ttime=\"2020-07-15T03:19:02Z\" level=debug msg=\"Found manifests directory\" name=bundle-test\n\t\ttime=\"2020-07-15T03:19:02Z\" level=debug msg=\"Found metadata directory\" name=bundle-test\n\t\ttime=\"2020-07-15T03:19:02Z\" level=debug msg=\"Getting mediaType info from manifests directory\" name=bundle-test\n\t\ttime=\"2020-07-15T03:19:02Z\" level=info msg=\"Found annotations file\" name=bundle-test\n\t\ttime=\"2020-07-15T03:19:02Z\" level=info msg=\"Could not find optional dependencies file\" name=bundle-test\n```\n\n**NOTE** The output format spec for each test matches the [`Test`](https://pkg.go.dev/github.com/operator-framework/api/pkg/apis/scorecard/v1alpha3#Test) type layout.\n\n\n## Exit Status\n\nThe scorecard return code is 1 if any of the tests executed did not\npass and 0 if all selected tests pass.\n\n## Extending the Scorecard with Custom Tests\n\nScorecard will execute custom tests if they follow these mandated conventions:\n\n * tests are implemented within a container image\n * tests accept an entrypoint which include a command and arguments\n * tests produce v1alpha3 scorecard output in JSON format with no extraneous logging in the test output\n * tests can obtain the bundle contents at a shared mount point of /bundle\n * tests can access the Kubernetes API using an in-cluster client connection\n\nSee the [example of a custom test image][custom-image] written in Go.\n\nWriting custom tests in other programming languages is possible\nif the test image follows the above guidelines.\n\n\n[quickstart-bundle]: /docs/olm-integration/quickstart-bundle\n[cli-scorecard]: /docs/cli/operator-sdk_scorecard/\n[custom-image]: https://github.com/operator-framework/operator-sdk/blob/09c3aa14625965af9f22f513cd5c891471dbded2/images/custom-scorecard-tests/main.go\n[olm-bundle]:https://github.com/operator-framework/operator-registry#manifest-format\n"
  },
  {
    "path": "website/content/en/docs/testing-operators/scorecard/custom-tests.md",
    "content": "---\ntitle: Writing Custom Scorecard Tests\nweight: 50\n---\n\nThis guide outlines the steps which can be followed to extend the existing scorecard tests and implement operator specific custom tests.\n\n## Run scorecard with custom tests:\n\n### Building test image:\n\nThe following steps explain creating of a custom test image which can be used with Scorecard to run operator specific tests. As an example, let us start by creating a sample go repository containing the test bundle data, custom scorecard tests and a Makefile to help us build a test image.\n\nThe sample test image repository present [here][custom_scorecard_repo] has the following project structure:\n\n```\n$ tree .\n.\n...\n├── config\n|   ...\n│   └── scorecard\n│       ├── bases\n│       │   └── config.yaml\n│       ├── kustomization.yaml\n│       └── patches\n│           ├── basic.config.yaml\n│           └── olm.config.yaml\n├── Makefile\n├── bundle\n│   ├── manifests\n│   │   ├── cache.example.com_memcached_crd.yaml\n│   │   └── memcached-operator.clusterserviceversion.yaml\n│   ├── metadata\n│   │   └── annotations.yaml\n│   └── tests\n│       └── scorecard\n│           └── config.yaml\n├── go.mod\n├── go.sum\n├── images\n│   └── custom-scorecard-tests\n│       ├── Dockerfile\n│       ├── bin\n│       │   ├── entrypoint\n│       │   └── user_setup\n│       ├── cmd\n│       │   └── test\n│       │       └── main.go\n│       └── custom-scorecard-tests\n└── internal\n    └── tests\n        └── tests.go\n```\n\n1. `config/scorecard` - Contains a kustomization for generating a config from a base and set of overlays.\n1. `bundle/` - Contains bundle manifests and metadata under test.\n1. `bundle/tests/scorecard/config.yaml` - Configuration file generated by `make bundle` from the `config/scorecard` kustomization.\n1. `images/custom-scorecard-tests/main.go` - Scorecard test binary.\n1. `internal/tests/tests.go` -  Contains the implementation of custom tests specific to the operator.\n\n#### Writing custom test logic:\n\nScorecard currently implements a few [basic][basic_tests] and [olm][olm_tests] tests for the image bundle, custom resources and custom resource definitions. Additional tests specific to the operator can also be included in the test suite of scorecard.\n\nThe `tests.go` file is where the custom tests are implemented in the sample test image project. These tests use `scapiv1alpha3.TestResult` struct to populate the result, which is then converted to json format for the output. For example, the format of a simple custom sample test can be as follows:\n\n```Go\npackage tests\n\nimport (\n  apimanifests \"github.com/operator-framework/api/pkg/manifests\"\n  scapiv1alpha3 \"github.com/operator-framework/api/pkg/apis/scorecard/v1alpha3\"\n)\n\nconst (\n  CustomTest1Name = \"customtest1\"\n)\n\n// CustomTest1\nfunc CustomTest1(bundle *apimanifests.Bundle) scapiv1alpha3.TestStatus {\n  r := scapiv1alpha3.TestResult{}\n  r.Name = CustomTest1Name\n  r.State = scapiv1alpha3.PassState\n  r.Errors = make([]string, 0)\n  r.Suggestions = make([]string, 0)\n\n  // Implement relevant custom test logic here\n\n  return wrapResult(r)\n}\n```\n\n### Scorecard Configuration file:\n\nThe [configuration file][config_yaml] includes test definitions and metadata to run the test.\nThis file is constructed using a kustomization under `config/scorecard`, with overlays for test sets.\n\nFor the example `CustomTest1` function, add the following to `config/scorecard/patches/customtest1.config.yaml`.\n\n```yaml\n- op: add\n  path: /stages/0/tests/-\n  value:\n    image: quay.io/<username>/custom-scorecard-tests:latest\n    entrypoint:\n    - custom-scorecard-tests\n    - customtest1\n    labels:\n      suite: custom\n      test: customtest1\n```\n\nThe important fields to note here are:\n1. `image` - name and tag of the test image which was specified in the Makefile.\n2. `labels` - the name of the `test` and `suite` the test function belongs to.\nThis can be specified in the `operator-sdk scorecard` command to run the desired test.\n\nNext, add a [JSON 6902 patch][kustomize-patchJson6902] to your `config/scorecard/kustomization.yaml`:\n\n```yaml\npatchesJson6902:\n...\n- path: patches/customtest1.config.yaml\n  target:\n    group: scorecard.operatorframework.io\n    version: v1alpha3\n    kind: Configuration\n    name: config\n```\n\nOnce you run `make bundle`, the `bundle/tests/scorecard/config.yaml` will be (re)generated with your custom test.\n\nIf generating a config file outside of the on-disk bundle, you can run:\n```console\n$ kustomize build config/scorecard > path/to/config.yaml\n```\n\n**Note**: The default location of `config.yaml` inside the bundle is `<bundle directory>/tests/scorecard/config.yaml`. It can be overridden using the `--config` flag. For more details regarding the configuration file refer to [user docs][user_doc].\n\n### Scorecard binary:\n\nThe scorecard test image implementation requires the bundle under test to be present in the test image. The `apimanifests.GetBundleFromDir()` function reads the pod's bundle to fetch the manifests and scorecard configuration from desired path.\n\n```Go\ncfg, err := apimanifests.GetBundleFromDir(scorecard.PodBundleRoot)\nif err != nil {\n  log.Fatal(err.Error())\n}\n```\nThe scorecard binary uses `config.yaml` file to locate tests and execute the them as Pods which scorecard creates. Custom test images are included into Pods that scorecard creates, passing in the bundle contents on a shared mount point to the test image container. The specific custom test that is executed is driven by the config.yaml's entry-point command and arguments.\n\nAn example custom scorecard test implementation is present [here][scorecard_binary].\n\nThe names with which the tests are identified in `config.yaml` and would be passed in the `scorecard` command, are to be specified here.\n\n```Go\n...\nswitch entrypoint[0] {\ncase tests.CustomTest1Name:\n  result = tests.CustomTest1(cfg)\n  ...\n}\n...\n```\n\nThe result of the custom tests which is in `scapiv1alpha3.TestResult` format, is converted to json for output.\n\n```Go\nprettyJSON, err := json.MarshalIndent(result, \"\", \"    \")\nif err != nil {\n  log.Fatal(\"Failed to generate json\", err)\n}\nfmt.Printf(\"%s\\n\", string(prettyJSON))\n```\n\nThe names of the custom tests are also included in `printValidTests()` function:\n\n```Go\nfunc printValidTests() (result scapiv1alpha3.TestStatus) {\n  ...\n  str := fmt.Sprintf(\"Valid tests for this image include: %s\", tests.CustomTest1Name)\n  result.Errors = append(result.Errors, str)\n  ...\n}\n\n```\n\n### Building the project\n\nThe SDK project makefile contains targets to build the sample custom test image.  The current makefile is found [here][sample_makefile].  You can use this makefile as a reference for your own custom test image makefile.\n\nTo build the sample custom test image, run:\n```\nmake image/custom-scorecard-tests\n```\n\n### Running scorecard command\n\nThe `operator-sdk scorecard` command is used to execute the scorecard tests by specifying the location of test bundle in the command. The name or suite of the tests which are to be executed can be specified with the `--selector` flag. The command will create scorecard pods with the image specified in `config.yaml` for the respective test. For example, the `CustomTest1Name` test provides the following json output.\n\n```console\n$ operator-sdk scorecard <bundle_dir_or_image> --selector=suite=custom -o json --wait-time=32s --skip-cleanup=false\n{\n  \"kind\": \"TestList\",\n  \"apiVersion\": \"scorecard.operatorframework.io/v1alpha3\",\n  \"items\": [\n    {\n      \"kind\": \"Test\",\n      \"apiVersion\": \"scorecard.operatorframework.io/v1alpha3\",\n      \"spec\": {\n        \"image\": \"quay.io/operator-framework/scorecard-test:latest\",\n        \"entrypoint\": [\n          \"custom-scorecard-tests\",\n          \"customtest1\"\n        ],\n        \"labels\": {\n          \"suite\": \"custom\",\n          \"test\": \"customtest1\"\n        }\n      },\n      \"status\": {\n        \"results\": [\n          {\n            \"name\": \"customtest1\",\n            \"log\": \"an ISV custom test\",\n            \"state\": \"pass\"\n          }\n        ]\n      }\n    }\n  ]\n}\n```\n\n**Note**: More details on the usage of `operator-sdk scorecard` command and its flags can be found in the [scorecard user documentation][user_doc]\n\n### Debugging scorecard custom tests\n\nThe `--skip-cleanup` flag can be used when executing the `operator-sdk scorecard` command to cause the scorecard created test pods to be unremoved.\nThis is useful when debugging or writing new tests so that you can view\nthe test logs or the pod manifests.\n\n### Storing scorecard test output\n\nThe `--test-output` flag can be used when executing the `operator-sdk scorecard` command with a config specifying [output persistence][storage] to store the output of the scorecard tests in a specific directory. Any persistent volume data will be stored in the specified local directory upon completion of the scorecard tests.\n\n```console\n$ operator-sdk scorecard ./bundle --test-output=/mytestoutput\n```\n\n**Note**: By default, the gathered test output will be stored in `$(pwd)/test-output`.\n\n### Overwrite storage and untar images to prevent downloading the images from external registries\n\nThe following options are useful to prevent downloading the images from external registries during scorecard job execution.\nThat could be a case of disconnected environments or to prevent an impact of the external registry's pull limits.\n- The `--storage-image` flag can be used when executing the `operator-sdk scorecard` command to overwrite the default `busybox` image used by the Scorecard pod.\n- The `--untar-image` flag can be used when executing the `operator-sdk scorecard` command to overwrite the default untar image used by the Scorecard pod.\n\n### Scorecard initContainer\n\nThe scorecard inserts an `initContainer` into the test pods it creates. The\n`initContainer` serves the purpose of uncompressing the operator bundle\ncontents, mounting them into a shared mount point accessible by test\nimages.  The operator bundle contents are stored within a ConfigMap, uniquely\nbuilt for each scorecard test execution.  Upon scorecard completion,\nthe ConfigMap is removed as part of normal cleanup, along with the test\npods created by scorecard.\n\n### Using Custom Service Accounts\n\nScorecard does not deploy service accounts, RBAC resources, or\nnamespaces for your test but instead considers these resources\nto be outside its scope. You can however specify whichever service account\nyour tests require, like `config/rbac/service_account.yaml` in\nGo operator projects, and then specify that service account\nfrom the command line:\n\n```console\n$ operator-sdk scorecard <bundle_dir_or_image> --service-account=my-project-controller-manager\n```\n\nAlso, you can specify a non-default namespace that scorecard will run in:\n\n```console\n$ operator-sdk scorecard <bundle_dir_or_image> --namespace=my-project-system\n```\n\nIf you do not specify either of these flags, the default namespace\nand service account will be used by the scorecard to run test pods.\n\n### Returning Multiple Test Results\n\nSome custom tests might require or be better implemented to return\nmore than a single test result. For this case, scorecard's output\nAPI allows [multiple test results][testresults] to be defined for a single test.\n\n### Accessing the Kube API\n\nWithin your custom tests you might require connecting to the Kube API.\nIn golang, you could use the [client-go][client_go] API for example to\ncheck Kube resources within your tests, or even create custom resources. Your\ncustom test image is being executed within a Pod, so you can use an in-cluster\nconnection to invoke the Kube API.\n\n<!-- TODO: this file shouldn't refer to the top-level operator-sdk repo as a reference, but a sample (in testdata?) -->\n\n[client_go]: https://github.com/kubernetes/client-go\n[olm_tests]: https://github.com/operator-framework/operator-sdk/blob/09c3aa14625965af9f22f513cd5c891471dbded2/internal/scorecard/tests/olm.go\n[basic_tests]: https://github.com/operator-framework/operator-sdk/blob/09c3aa14625965af9f22f513cd5c891471dbded2/internal/scorecard/tests/basic.go\n[config_yaml]: https://github.com/operator-framework/operator-sdk/blob/09c3aa14625965af9f22f513cd5c891471dbded2/internal/scorecard/testdata/bundle/tests/scorecard/config.yaml\n[scorecard_main_func]: https://github.com/operator-framework/operator-sdk/blob/09c3aa14625965af9f22f513cd5c891471dbded2/images/scorecard-test/main.go\n[custom_scorecard_repo]:https://github.com/operator-framework/operator-sdk/tree/master/testdata/go/v4/memcached-operator \n[user_doc]: /docs/testing-operators/scorecard/\n[scorecard_binary]: https://github.com/operator-framework/operator-sdk/blob/09c3aa14625965af9f22f513cd5c891471dbded2/images/custom-scorecard-tests/main.go\n[sample_makefile]: https://github.com/operator-framework/operator-sdk/blob/09c3aa14625965af9f22f513cd5c891471dbded2/Makefile\n[kustomize-patchJson6902]: https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesjson6902/\n[testresults]:https://github.com/operator-framework/api/blob/333d064/pkg/apis/scorecard/v1alpha3/test_types.go#L35\n[storage]:https://pkg.go.dev/github.com/operator-framework/api@v0.10.4/pkg/apis/scorecard/v1alpha3#Storage\n"
  },
  {
    "path": "website/content/en/docs/testing-operators/scorecard/kuttl-tests.md",
    "content": "---\ntitle: Writing Kuttl Scorecard Tests\nweight: 50\n---\n\nThis guide outlines the steps which can be followed to implement scorecard\ntests using the [kuttl][kuttl] project and specifically the scorecard\nkuttl test image.\n\n## Defining kuttl Tests in Scorecard\n\nScorecard users can include kuttl tests within their operator\nbundles as follows:\n```\n$ tree ./bundle\n./bundle\n├── manifests\n│   ├── cache.example.com_memcacheds_crd.yaml\n│   └── memcached-operator.clusterserviceversion.yaml\n├── metadata\n│   └── annotations.yaml\n└── tests\n    └── scorecard\n        ├── config.yaml\n        └── kuttl\n            ├── kuttl-test.yaml\n            └── list-pods\n                ├── 00-assert.yaml\n                └── 00-pod.yaml\n            └── list-other\n                ├── 00-assert.yaml\n                └── 00-pod.yaml\n```\n\n * `bundle/` - Contains bundle manifests and metadata under test.\n * `bundle/tests/scorecard/config.yaml` - Configuration yaml to define and run scorecard tests.\n * `bundle/tests/scorecard/kuttl` - Contains tests written for kuttl to execute\n * `bundle/tests/scorecard/kuttl/kuttl-test.yaml` - Contains the kuttl configuration, it is here that you would add any kuttl specific configuration settings that you might require.\n * `bundle/tests/scorecard/kuttl/list-pods` - Contains a kuttl test case\n * `bundle/tests/scorecard/kuttl/list-pods/00-assert.yaml` - Contains a kuttl test case assert\n * `bundle/tests/scorecard/kuttl/list-pods/00-pod.yaml` - Contains a kuttl test case step\n * `bundle/tests/scorecard/kuttl/list-other` - Contains another kuttl test case\n\nWhen the scorecard kuttl binary is executed, it will process all the test\ncases under the scorecard/kuttl directory within the bundle contents.\n\n## Configuring kuttl Tests in the Scorecard Configuration\n\nIn the scorecard configuration file, you might have the following\ndefinition of what the selector `suite=kuttlsuite` will translate to:\n```yaml\nstages:\n- tests:\n  - image: quay.io/operator-framework/scorecard-test-kuttl:v2.0.0\n    labels:\n      suite: kuttlsuite\n      test: kuttltest1\n```\n\nThis test configuration will execute the scorecard-test-kuttl\nimage which executes kuttl.  The kuttl output is translated\ninto scorecard compliant output which is displayed back to the\nend user along with any other test results.\n\nWith the above kuttl test configuration, you can execute that\nkuttl test using scorecard as follows:\n```bash\noperator-sdk scorecard <bundle_dir_or_image> --selector=suite=kuttlsuite\n```\n\n## Defining kuttl Specific Configuration Options\n\nThe [kuttl configuration file][kuttl_yaml] is documented within the\nkuttl project.\n\nAn example of the kuttl configuration file is as follows:\n\n```yaml\napiVersion: kudo.dev/v1beta1\nkind: TestSuite\nparallel: 4\ntimeout: 120\nstartControlPlane: false\n```\n\nThe important fields to note here are:\n\n * `startControlPlane` - Set to false since scorecard assumes it is running\nwithin a control plane already.\n\nOther kuttl configurations settings are available for more advanced kuttl\nuse cases.  See [kuttl configuration][kuttl_configuration] for more details on kuttl configuration.\n\n### kuttl Tests Explained\n\nThe kuttl test tool looks for tests to execute within the bundle\nfollowing a naming convention as follows:\n```\n        └── kuttl\n            ├── kuttl-test.yaml\n            └── list-pods\n                ├── 00-assert.yaml\n                └── 00-pod.yaml\n            └── list-other\n                ├── 00-assert.yaml\n                └── 00-pod.yaml\n```\n\nThe important fields to note here are:\n\n * `kuttl-test.yaml` - The name required for your kuttl configuration file.\n * `list-pods, list-other` - The names given by you for these test cases.\n * `00-assert.yaml` - The assert file is executed to test whether or\nnot the test was successful, this assertion determines whether or not\nthe test passed or failed.\n * `00-pod.yaml` - The pod file is used to define what the test will\ncreate, in this case a pod will be created based on the manifest within\n00-pod.yaml.\n\nThe number in front of the assert and pod manifests is used to determine\nthe order in which kuttl will execute the files.\n\nSee [kuttl tests][kuttl_tests] for a detailed description of how\nkuttl tests are named and executed.\n\n### kuttl Test Privileges\n\nThe kuttl tests a user might write can vary widely in functionality\nand in particular require special Kubernetes RBAC privileges outside\nof what the default service account for a namespace might have.\nIt is therefore very likely you will be required to run scorecard\nin a custom service account that holds the required RBAC permissions,\nlike `config/rbac/service_account.yaml` in Go operator projects.\nYou can specify a custom service account in scorecard as follows:\n\n```console\n$ operator-sdk scorecard <bundle_dir_or_image> --service-account=my-project-controller-manager\n```\n\nAlso, you can specify a non-default namespace that scorecard will run in:\n\n```console\n$ operator-sdk scorecard <bundle_dir_or_image> --namespace=my-project-system\n```\n\nIf you do not specify either of these flags, the default namespace\nand service account will be used by the scorecard to run test pods.\n\nIt is worth noting that scorecard-test-kuttl specifies a namespace\nto the kubectl-kuttl command which causes kuttl to not create a\nnamespace for each test.  This might impact your kuttl tests in\nthat you might need to perform resource cleanup in your tests\ninstead of depending upon namespace deletion to perform that cleanup.\n\nAlso of note is that in our example [kuttl configuration][kuttl_configuration]\nfile, we add the `suppressLog: events` setting which means that\nkuttl will not log kubernetes events and thereby means you do not\nhave to provide RBAC access for reading kubernetes events to the\nservice account used to run kuttl tests.\n\n[client_go]: https://github.com/kubernetes/client-go\n[kuttl]: https://github.com/kudobuilder/kuttl/\n[kuttl_yaml]: https://github.com/kudobuilder/kuttl/blob/main/docs/cli.md#examples\n[kuttl_tests]: https://github.com/kudobuilder/kuttl/blob/main/docs/kuttl-test-harness.md#writing-your-first-test\n[kuttl_configuration]:https://github.com/kudobuilder/kuttl/blob/main/docs/testing/reference.md#testsuite\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/_index.md",
    "content": "---\ntitle: Upgrade SDK Version \nweight: 4\ndescription: Guide to upgrading sdk version for your operator\n---\n\n## Backwards Compatibility when Upgrading Operator-sdk version\n\nWhen upgrading your version of Operator-sdk, it is intended that post-1.0.0 minor versions (i.e. 1.y) are backwards compatible and strictly additive. Therefore, you\nonly need to re-scaffold your operator with a newer version of Operator-SDK if you wish to take advantage of new features. If you do not wish to use new features,\nall that should be required is bumping the operator image dependency (if a Helm or Ansible operator) and rebuilding your operator image.\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/backport-policy.md",
    "content": "---\ntitle: Backport Policy\nweight: 2\n---\n\nMainly critical issue fixes are backported to the most recent minor release.\nSpecial backport requests can be discussed during the weekly Triage meeting; this does not guarantee an exceptional backport will be created.\nOccasionally non-critical issue fixes will be backported, either at an approver's discretion or by request as noted above.\nFor information on contacting maintainers and attending meetings, check the [community](https://github.com/operator-framework/community) repository.   \n\n## Process\n\nTypically an issue will be fixed in the `master` branch, which will then be cherry-picked to the most recent release's branch.\nThose with approver permissions and above can create a cherry-pick PR, assuming no conflicts, by commenting `/cherry-pick <release branch>`\nin the PR fixing the issue in master. Fixes that are only relevant to a specific release branch can be made against\nthat branch directly.\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v0.1.0-migration-guide.md",
    "content": "---\ntitle: v0.0.x to v0.1.0 \nlinkTitle: v0.0.x to v0.1.0\nweight: 999999000\ndescription: A guide to migrate an operator project built using Operator SDK `v0.0.x` to the project structure required by `v0.1.0`.\n---\n\nThe recommended way to migrate your project is to initialize a new `v0.1.0` project, then copy your code into the new project and modify as described below.\n\nThis guide goes over migrating the memcached-operator, an example project from the user guide, to illustrate migration steps. See the [v0.0.7 memcached-operator][v0.0.7-memcached-operator] and [v0.1.0 memcached-operator][v0.1.0-memcached-operator] project structures for pre- and post-migration examples, respectively.\n\n## Create a new v0.1.0 project\n\nRename your `v0.0.x` project and create a new `v0.1.0` project in its place.\n\n```sh\n# Ensure SDK version is v0.1.0\n$ operator-sdk --version\noperator-sdk version 0.1.0\n\n# Create new project\n$ cd $GOPATH/src/github.com/example/\n$ mv memcached-operator old-memcached-operator\n$ operator-sdk new memcached-operator --skip-git-init\n$ ls\nmemcached-operator old-memcached-operator\n\n# Copy over .git from old project\n$ cp -rf old-memcached-operator/.git memcached-operator/.git\n```\n\n## Migrate custom types from pkg/apis\n\n### Scaffold api for custom types\n\nCreate the api for your custom resource (CR) in the new project with `operator-sdk add api --api-version=<apiversion> --kind=<kind>`\n```sh\n$ cd memcached-operator\n$ operator-sdk add api --api-version=cache.example.com/v1alpha1 --kind=Memcached\n\n$ tree pkg/apis\npkg/apis/\n├── addtoscheme_cache_v1alpha1.go\n├── apis.go\n└── cache\n    └── v1alpha1\n        ├── doc.go\n        ├── memcached_types.go\n        ├── register.go\n        └── zz_generated.deepcopy.go\n```\n\nRepeat the above command for as many custom types as you had defined in your old project. Each type will be defined in the file `pkg/apis/<group>/<version>/<kind>_types.go`.\n\n### Copy the contents of the type\n\nCopy the `Spec` and `Status` contents of the `pkg/apis/<group>/<version>/types.go` file from the old project to the new project's `pkg/apis/<group>/<version>/<kind>_types.go` file.\n\n**Note:** Each `<kind>_types.go` file has an `init()` function. Be sure not to remove that since that registers the type with the Manager's scheme.\n```Go\nfunc init() {\n\tSchemeBuilder.Register(&Memcached{}, &MemcachedList{})\n}\n```\n\n## Migrate reconcile code\n\n### Add a controller to watch your CR\n\nIn a `v0.0.x` project you would define what resource to watch in `cmd/<operator-name>/main.go`\n```Go\nsdk.Watch(\"cache.example.com/v1alpha1\", \"Memcached\", \"default\", time.Duration(5)*time.Second)\n```\n\nFor a `v0.1.0` project you define a [Controller][controller-go-doc] to watch resources.\n\nAdd a controller to watch your CR type with `operator-sdk add controller --api-version=<apiversion> --kind=<kind>`.\n```\n$ operator-sdk add controller --api-version=cache.example.com/v1alpha1 --kind=Memcached\n$ tree pkg/controller\npkg/controller/\n├── add_memcached.go\n├── controller.go\n└── memcached\n    └── memcached_controller.go\n```\n\nInspect the `add()` function in your `pkg/controller/<kind>/<kind>_controller.go` file:\n```Go\nimport (\n    cachev1alpha1 \"github.com/example/memcached-operator/pkg/apis/cache/v1alpha1\"\n    ...\n)\n\nfunc add(mgr manager.Manager, r reconcile.Reconciler) error {\n    c, err := controller.New(\"memcached-controller\", mgr, controller.Options{Reconciler: r})\n\n    // Watch for changes to the primary resource Memcached\n    err = c.Watch(&source.Kind{Type: &cachev1alpha1.Memcached{}}, &handler.EnqueueRequestForObject{})\n\n    // Watch for changes to the secondary resource Pods and enqueue reconcile requests for the owner Memcached\n    err = c.Watch(&source.Kind{Type: &corev1.Pod{}}, &handler.EnqueueRequestForOwner{\n\t\tIsController: true,\n\t\tOwnerType:    &cachev1alpha1.Memcached{},\n\t})\n}\n```\nRemove the second `Watch()` or modify it to watch a secondary resource type that is owned by your CR.\n\nWatching multiple resources lets you trigger the reconcile loop for multiple resources relevant to your application. See the [watching and eventhandling][watching-eventhandling-doc] doc and the Kubernetes [controller conventions][controller-conventions] doc for more details.\n\n#### Multiple custom resources\n\nIf your operator is watching more than 1 CR type then you can do one of the following depending on your application:\n-  If the CR is owned by your primary CR then watch it as a secondary resource in the same controller to trigger the reconcile loop for the primary resource.\n    ```Go\n    // Watch for changes to the primary resource Memcached\n    err = c.Watch(&source.Kind{Type: &cachev1alpha1.Memcached{}}, &handler.EnqueueRequestForObject{})\n\n    // Watch for changes to the secondary resource AppService and enqueue reconcile requests for the owner Memcached\n    err = c.Watch(&source.Kind{Type: &appv1alpha1.AppService{}}, &handler.EnqueueRequestForOwner{\n\t\tIsController: true,\n\t\tOwnerType:    &cachev1alpha1.Memcached{},\n\t})\n    ```\n-  Add a new controller to watch and reconcile the CR independently of the other CR.\n    ```sh\n    $ operator-sdk add controller --api-version=app.example.com/v1alpha1 --kind=AppService\n    ```\n    ```Go\n    // Watch for changes to the primary resource AppService\n    err = c.Watch(&source.Kind{Type: &appv1alpha1.AppService{}}, &handler.EnqueueRequestForObject{})\n    ```\n\n### Copy and modify reconcile code from pkg/stub/handler.go\n\nIn a `v0.1.0` project the reconcile code is defined in the `Reconcile()` method of a controller's [Reconciler][reconciler-go-doc]. This is similar to the `Handle()` function in the older project. Note the difference in the arguments and return values:\n- Reconcile\n    ```Go\n    func (r *ReconcileMemcached) Reconcile(request reconcile.Request) (reconcile.Result, error)\n    ```\n- Handle\n    ```Go\n    func (h *Handler) Handle(ctx context.Context, event sdk.Event) error\n    ```\n\nInstead of receiving an `sdk.Event` (with the object), the `Reconcile()` function receives a [Request][request-go-doc] (Name/Namespace key) to lookup the object.\n\nIf the `Reconcile()` function returns an error, the controller will requeue and retry the `Request`. If no error is returned, then depending on the [Result][result-go-doc] the controller will either not retry the `Request`, immediately retry, or retry after a specified duration.\n\nCopy the code from the old project's `Handle()` function over the existing code in your controller's `Reconcile()` function.\nBe sure to keep the initial section in the `Reconcile()` code that looks up the object for the `Request` and checks to see if it's deleted.\n\n```Go\nimport (\n    apierrors \"k8s.io/apimachinery/pkg/api/errors\"\n    cachev1alpha1 \"github.com/example/memcached-operator/pkg/apis/cache/v1alpha1\"\n    ...\n)\nfunc (r *ReconcileMemcached) Reconcile(request reconcile.Request) (reconcile.Result, error) {\n    // Fetch the Memcached instance\n\tinstance := &cachev1alpha1.Memcached{}\n    err := r.client.Get(context.TODO()\n    request.NamespacedName, instance)\n    if err != nil {\n        if apierrors.IsNotFound(err) {\n            // Request object not found, could have been deleted after reconcile request.\n            // Owned objects are automatically garbage collected.\n            // Return and don't requeue\n            return reconcile.Result{}, nil\n        }\n        // Error reading the object - requeue the request.\n        return reconcile.Result{}, err\n    }\n\n    // Rest of your reconcile code goes here.\n    ...\n}\n```\n#### Update return values\n\nChange the return values in your reconcile code:\n- Replace `return err` with `return reconcile.Result{}, err`\n- Replace `return nil` with `return reconcile.Result{}, nil`\n\n#### Periodic reconcile\nIn order to periodically reconcile a CR in your controller you can set the [RequeueAfter][result-go-doc] field for reconcile.Result.\nThis will cause the controller to requeue the `Request` and trigger the reconcile after the desired duration. Note that the default value of 0 means no requeue.\n\n```Go\nreconcilePeriod := 30 * time.Second\nreconcileResult := reconcile.Result{RequeueAfter: reconcilePeriod}\n...\n\n// Update the status\nerr := r.client.Update(context.TODO(), memcached)\nif err != nil {\n    log.Info(fmt.Sprintf(\"Failed to update memcached status: %v\", err))\n    return reconcileResult, err\n}\nreturn reconcileResult, nil\n\n```\n\n#### Update client\n\nReplace the calls to the SDK client(Create, Update, Delete, Get, List) with the reconciler's client.\n\nSee the examples below and the controller-runtime [client API doc][client-api-doc] for more details.\n\n```Go\n// Create\ndep := &appsv1.Deployment{...}\n// v0.0.1\nerr := sdk.Create(dep)\n// v0.1.0\nerr := r.client.Create(context.TODO(), dep)\n\n// Update\n// v0.1.0\nerr := sdk.Update(dep)\n// v0.1.0\nerr := r.client.Update(context.TODO(), dep)\n\n// Delete\nerr := sdk.Delete(dep)\n// v0.1.0\nerr := r.client.Delete(context.TODO(), dep)\n\n// List\npodList := &corev1.PodList{}\nlabelSelector := labels.SelectorFromSet(labelsForMemcached(memcached.Name))\nlistOps := &metav1.ListOptions{LabelSelector: labelSelector}\nerr := sdk.List(memcached.Namespace, podList, sdk.WithListOptions(listOps))\n// v0.1.0\nlistOps := &client.ListOptions{Namespace: memcached.Namespace, LabelSelector: labelSelector}\nerr := r.client.List(context.TODO(), listOps, podList)\n\n// Get\ndep := &appsv1.Deployment{APIVersion: \"apps/v1\", Kind: \"Deployment\", Name: name, Namespace: namespace}\nerr := sdk.Get(dep)\n// v0.1.0\ndep := &appsv1.Deployment{}\nerr = r.client.Get(context.TODO(), types.NamespacedName{Name: name, Namespace: namespace}, dep)\n// v0.1.0 with unstructured\ndep := &unstructured.Unstructured{}\ndep.SetGroupVersionKind(schema.GroupVersionKind{Group:\"apps\", Version: \"v1\", Kind:\"Deployment\"})\nerr = r.client.Get(context.TODO(), types.NamespacedName{Name: name, Namespace: namespace}, dep)\n```\n\nLastly copy and initialize any other fields that you may have had in your `Handler` struct into the `Reconcile<Kind>` struct:\n\n```Go\n// newReconciler returns a new reconcile.Reconciler\nfunc newReconciler(mgr manager.Manager) reconcile.Reconciler {\n\treturn &ReconcileMemcached{client: mgr.GetClient(), scheme: mgr.GetScheme(), foo: \"bar\"}\n}\n\n// ReconcileMemcached reconciles a Memcached object\ntype ReconcileMemcached struct {\n    client client.Client\n    scheme *runtime.Scheme\n    // Other fields\n    foo string\n}\n```\n\n### Copy changes from main.go\n\nThe main function for a `v0.1.0` operator in `cmd/manager/main.go` sets up the [Manager][manager-go-doc] which registers the custom resources and starts all the controllers.\n\nThere is no need to migrate the SDK functions `sdk.Watch()`,`sdk.Handle()`, and `sdk.Run()` from the old `main.go` since that logic is now defined in a controller.\n\nHowever if there are any operator specific flags or settings defined in the old main file copy those over.\n\nIf you have any 3rd party resource types registered with the SDK's scheme, then register those with the Manager's scheme in the new project. See how to [register 3rd party resources][register-3rd-party-resources].\n\n`operator-sdk` now expects `cmd/manager/main.go` to be present in Go operator projects. Go project-specific commands, ex. `add [api, controller]`, will error if `main.go` is not found in its expected path.\n\n### Copy user defined files\n\nIf there are any user defined pkgs, scripts, and docs in the older project, copy these files into the new project.\n\n### Copy changes to deployment manifests\n\nFor any updates made to the following manifests in the old project, copy over the changes to their corresponding files in the new project. Be careful not to directly overwrite the files but inspect and make any changes necessary.\n- `tmp/build/Dockerfile` to `build/Dockerfile`\n  - There is no tmp directory in the new project layout\n- RBAC rules updates from `deploy/rbac.yaml` to `deploy/role.yaml` and `deploy/role_binding.yaml`\n- `deploy/cr.yaml` to `deploy/crds/<full group>_<version>_<kind>_cr.yaml`\n- `deploy/crd.yaml` to `deploy/crds/<group>_<version>_<kind>_crd.yaml`\n\n### Copy user defined dependencies\n\nFor any user defined dependencies added to the old project's Gopkg.toml, copy and append them to the new project's Gopkg.toml.\nRun `dep ensure` to update the vendor in the new project.\n\n### Confirmation\n\nAt this point you should be able to build and run your operator to verify that it works. See the [user-guide][user-guide-build-run] on how to build and run your operator.\n\n[v0.1.0-changes-doc]: ./v0.1.0-changes.md\n[v0.0.7-memcached-operator]: https://github.com/operator-framework/operator-sdk-samples/tree/aa15bd278eec0959595e0a0a7282a26055d7f9d6/memcached-operator\n[v0.1.0-memcached-operator]: https://github.com/operator-framework/operator-sdk-samples/tree/4c6934448684a6953ece4d3d9f3f77494b1c125e/memcached-operator\n[controller-conventions]: https://github.com/kubernetes/community/blob/cbe9c8ac5f71a99179d7ffe4a008b9018830af72/contributors/devel/sig-api-machinery/controllers.md#guidelines\n[reconciler-go-doc]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/reconcile#Reconciler\n[watching-eventhandling-doc]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg#hdr-Watching_and_EventHandling\n[controller-go-doc]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg#hdr-Controller\n[request-go-doc]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/reconcile#Request\n[result-go-doc]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/reconcile#Result\n[client-api-doc]: https://github.com/operator-framework/operator-sdk/blob/v0.19.x/website/content/en/docs/golang/references/client.md\n[manager-go-doc]: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager\n[register-3rd-party-resources]: https://github.com/operator-framework/operator-sdk/blob/v0.19.x/website/content/en/docs/golang/legacy/quickstart.md#adding-3rd-party-resources-to-your-operator\n[user-guide-build-run]: https://github.com/operator-framework/operator-sdk/blob/v0.19.x/website/content/en/docs/golang/legacy/quickstart.md#build-and-run-the-operator\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v0.18.0.md",
    "content": "---\ntitle: v0.18.0\nweight: 999982000\n---\n\n## Modules\n\n- Ensure that the following `require` and `replace` directives with these specific versions are present in your `go.mod` file:\n\n```go\nrequire (\n\tgithub.com/operator-framework/operator-sdk v0.18.0\n\tk8s.io/api v0.18.2\n\tk8s.io/apimachinery v0.18.2\n\tsigs.k8s.io/controller-runtime v0.6.0\n)\n\nreplace (\n\tgithub.com/Azure/go-autorest => github.com/Azure/go-autorest v13.3.2+incompatible // Required by OLM\n\tk8s.io/client-go => k8s.io/client-go v0.18.2 // Required by prometheus-operator\n)\n```\n\n## (Optional) Add livenessProbe check for Ansible-based operators\n\nExisting operators will have a healthz endpoint without intervention, but to take advantage of it, a liveness probe should be manually added to the operator manifest. For example, the `deploy/operator.yaml` file would need to include:\n```yaml\n  livenessProbe:\n    httpGet:\n      path: /healthz\n      port: 6789\n    initialDelaySeconds: 5\n    periodSeconds: 3\n```\n\n_See [#2936](https://github.com/operator-framework/operator-sdk/pull/2936) for more details._\n\n## Remove the file `/bin/ao-logs` for Ansible based-operators\n\nThe `inotify-tools` as a dependency of Ansible based-operator images which was deprecated in the version `v0.16.0` was removed. This dependency was used to output the Ansible logs in a side-car container called `ansible`, which has no longer been scaffolded by default. In this way, if you have any customization using this dependency be aware that it is no longer in the Ansible based-operator image and then, feel free to remove this file `/bin/ao-logs` for your projects since it has no longer usage. For further information also see the section `Remove Ansible container sidecar` on the migration guide of the version `v0.16.0`.\n\n_See [#2852](https://github.com/operator-framework/operator-sdk/pull/2852) for more details._\n\n## Modify permissions on your bundle manifests directory\n\nRun `chmod 0755 deploy/olm-catalog/<operator-name>/manifests` to update your operator's bundle directory permissions.\n\n_See [#3129](https://github.com/operator-framework/operator-sdk/pull/3129) for more details._\n## Default CRD version\n\nThe default CRD version was changed from `apiextensions.k8s.io/v1beta1`\nto `apiextensions.k8s.io/v1` for commands that create or generate\nCRDs. To migrate CRDs from `v1beta1` to `v1`, simply re-run\n`operator-sdk generate crds`. To continue generating CRDs with\n`apiextensions.k8s.io/v1beta1`, use `--crd-version=v1beta1`.\n\nThe following CRD versions are (or will be) compatible with the\nfollowing Kubernetes versions:\n\n  - Kubernetes <= v1.15 - Only `apiextensions.k8s.io/v1beta1` supported\n  - Kubernetes v1.16 through v1.18 - Both `apiextensions.k8s.io/v1beta1`\n    and `apiextensions.k8s.io/v1` supported\n  - Kubernetes >= v1.19 - Only `apiextensions.k8s.io/v1` supported\n\n_See [#2874](https://github.com/operator-framework/operator-sdk/pull/2874) for more details._\n\n## Helm-based operators should not use `k8s.io` API version suffix\n\nNewly created Helm-based operators no longer use the `k8s.io` domain\nsuffix as a default API version because it is reserved. APIs and CRDs\nusing this domain [require API review][api-review] and approval.\nExisting projects that do not have this approval should migrate to use\na new CRD API version suffix.\n\nMake the following changes to migrate to a new group name:\n\n  - `watches.yaml` - Update the `group` field.\n  - `deploy/role.yaml` - Update the `apiGroups` field in the policy rule giving access to the CRD.\n  - `deploy/crds/`\n    - Update the `metadata.name` and `spec.group` fields in the CRD files.\n    - Update the `apiVersion` field in the CR files.\n    - Rename the CRD and CR files to reflect the new group name.\n\n[api-review]: https://github.com/kubernetes/community/blob/81ec4af0ed02b4c5c0917a16563250b2f45250c2/sig-architecture/api-review-process.md#mandatory\n\n_See [#2859](https://github.com/operator-framework/operator-sdk/pull/2859) for more details._\n\n## Kubernetes client-go contexts\n\nOperators using client-go directly and operators\nthat have generated clientsets will be required to\nupdate many of their client-go function calls, which\nhave signature changes related to passing contexts\nand options.\n\nUsers can use http://sigs.k8s.io/clientgofix to\nrewrite method invocations to the new signatures.\n\n_See [#2918](https://github.com/operator-framework/operator-sdk/pull/2918) for more details._\n\n## Controller-runtime changes\n\nThere were various breaking changes in controller-runtime\nv0.6.0.\n\n  - Informers methods now require a context parameter\n  - Owns, For, and Watches funtions now take variadic\n    functional option arguments.\n\n_See [#2918](https://github.com/operator-framework/operator-sdk/pull/2918) for more details._\n\n## Helm operator no longer migrates v2 releases to v3\n\nThe deprecated support for Helm v2 releases has been removed. If\nyou require automigration of Helm v2 releases, continue using\nv0.17.x.\n\nThis removal does NOT affect support for v2 Helm charts, which\nare still supported by Helm v3.\n\n_See [#2918](https://github.com/operator-framework/operator-sdk/pull/2918) for more details._\n\n## Helm operator no longer supports deprecated UID-based release names\n\n\nIn v0.11.0, the Helm operator began using the CR name as the release\nname while also maintaining backwards compatibility for legacy\nUID-based release names. Continued support for the UID-based release\nnames has been removed.\n\nBefore upgrading to this release, delete and recreate custom resources\nthat are still using the deprecated UID-based release name. To determine\nif you have any UID-based release names still in use, inspect the\n`status.deployedRelease` field of your custom resources and look for\nrelease names that end with a 25-character random string.\n\n_See [#2918](https://github.com/operator-framework/operator-sdk/pull/2918) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v0.19.0.md",
    "content": "---\ntitle: v0.19.0\nweight: 999981000\n---\n\n## Prevent mangling of Ansible variable names containing special words by the Ansible operator\n\nInput variable names containing special words IP, HTTP, and URL were incorrectly converted to contiguous lowercase\nsnake case. [#3265](https://github.com/operator-framework/operator-sdk/pull/3265) fixes this issue, and the Ansible\noperator now correctly wraps special words in underscores and lower-cases them within snake-cased variable names.\nFor example:\n\n```\n  egressIPs                    -->  egress_ips\n\n  URLsegressIPsEgressHTTPs     -->  _urls_egress_ips_egress_https\n```\n\nNothing needs to be changed in an existing project to fix this issue.\n\n_See [#3265](https://github.com/operator-framework/operator-sdk/pull/3265) for more details._\n\n## Migrating Go projects to the new Kubebuilder aligned project layout\n\nSee the [v0.19.0 project migration guide][migration-guide-v0.19.0] that walks through an example of how\nto migrate a Go based operator project from the old layout to the v0.19.0 layout. Migrating to v0.19.0\nbefore v1.0.0 is practical if you plan to migrate your project between one minor version at a time.\n\nIf you wish to migrate directly from the old layout to the latest v1.0.0+ layout, see\nthe [latest migration guide][migration-guide].\n\n_See [#3190](https://github.com/operator-framework/operator-sdk/pull/3190) for more details._\n\n## Helm: rename condition reason `UpdateSuccessful` to `UpgradeSuccessful`\n\nFor Helm-based operators to be more aligned with Helm, the `UpdateSuccessful` condition\nreason was renamed to `UpgradeSuccessful` for the `ReleaseFailed` condition.\nNote that this is **NOT** a breaking change for Helm-based operators themselves.\nHowever, any script or code that is depending on this condition reason must be updated\nto use `UpgradeSuccessful` instead of `UpdateSuccessful`.\n\n_See [#3345](https://github.com/operator-framework/operator-sdk/pull/3345) for more details._\n\n## Helm: rename condition reason `UpdateError` to `UpgradeError`\n\nFor Helm-based operators to be more aligned with Helm, the `UpdateError` condition\nreason was renamed to `UpgradeError` for the `ReleaseFailed` condition.\nNote that this is **NOT** a breaking change for Helm-based operators themselves.\nHowever, any script or code that is depending on this condition reason must be updated\nto use `UpgradeError` instead of `UpdateError`.\n\n_See [#3269](https://github.com/operator-framework/operator-sdk/pull/3269) for more details._\n\n[migration-guide]: /docs/building-operators/golang/migration/\n[migration-guide-v0.19.0]: https://github.com/operator-framework/operator-sdk/blob/v0.19.x/website/content/en/docs/golang/project_migration_guide.md\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.0.0.md",
    "content": "---\ntitle: v1.0.0\nweight: 999000000\n---\n\nThis is the first major version release of `operator-sdk`, which comes with a project structure rewrite\nand many breaking CLI changes that are incompatible with all prior minor versions (except for Go projects,\nwhich changed in [v0.19.0][go-mig-guide-v0-19]).\n\nEach project type has an appropriate migration guide, which we recommend following before reading\nthis guide:\n- [Go][go-mig-guide]\n- [Ansible][ansible-mig-guide]\n- [Helm][helm-mig-guide]\n\n### CLI changes\n\nThe following subcommands were removed:\n\n| Command                       | Guidance                                                                                                 | PR(s)\n|-------------------------------|----------------------------------------------------------------------------------------------------------|-------\n| `operator-sdk new`            | Use `operator-sdk init`                                                                                  | [#3385](https://github.com/operator-framework/operator-sdk/pull/3385), [#3343](https://github.com/operator-framework/operator-sdk/pull/3343), [#3531](https://github.com/operator-framework/operator-sdk/pull/3531)\n| `operator-sdk add api`        | Use `operator-sdk create api`                                                                            | [#3385](https://github.com/operator-framework/operator-sdk/pull/3385), [#3343](https://github.com/operator-framework/operator-sdk/pull/3343), [#3531](https://github.com/operator-framework/operator-sdk/pull/3531)\n| `operator-sdk add controller` | Use `operator-sdk create api`                                                                            | [#3385](https://github.com/operator-framework/operator-sdk/pull/3385)\n| `operator-sdk add crd`        | Use `operator-sdk create api`                                                                            | [#3547](https://github.com/operator-framework/operator-sdk/pull/3547)\n| `operator-sdk build`          | Use `make docker-build`                                                                                  | [#3566](https://github.com/operator-framework/operator-sdk/pull/3566)\n| `operator-sdk bundle create`  | Use `make bundle`                                                                                        | [#3414](https://github.com/operator-framework/operator-sdk/pull/3414)\n| `operator-sdk generate k8s`   | Use `make generate`                                                                                      | [#3385](https://github.com/operator-framework/operator-sdk/pull/3385)\n| `operator-sdk generate crds`  | Use `make manifests`                                                                                     | [#3385](https://github.com/operator-framework/operator-sdk/pull/3385)\n| `operator-sdk generate csv`   | Use `operator-sdk generate kustomize manifests`                                                          | [#3414](https://github.com/operator-framework/operator-sdk/pull/3414)\n| `operator-sdk migrate`        | Removed support for hybrid operators, no migration                                                       | [#3385](https://github.com/operator-framework/operator-sdk/pull/3385)\n| `operator-sdk print-deps`     | Removed, no migration                                                                                    | [#3385](https://github.com/operator-framework/operator-sdk/pull/3385)\n| `operator-sdk run local`      | Use `make run`                                                                                           | [#3406](https://github.com/operator-framework/operator-sdk/pull/3406)\n| `operator-sdk test`           | Use controller-runtime's [envtest](https://book.kubebuilder.io/reference/envtest.html) framework          | [#3409](https://github.com/operator-framework/operator-sdk/pull/3409)\n\n### Library changes\n\nSubpackages of the `pkg/` directory have either been removed or moved from the `operator-sdk` repo\nto the [`operator-lib` repo][operator-lib].\n\nRemoved packages:\n- [`pkg/k8sutil`](#removed-package-pkgk8sutil)\n- [`pkg/kube-metrics`](#removed-packages-pkgkube-metrics-and-pkgmetrics)\n- [`pkg/metrics`](#removed-packages-pkgkube-metrics-and-pkgmetrics)\n- [`pkg/ready`](#removed-package-pkgready)\n- [`pkg/tls`](#removed-package-pkgtls)\n\nPackages that have been moved can be used by making the following changes:\n- The `EnqueueRequestForAnnotation` watch handler is now available in package `github.com/operator-framework/operator-lib/handler`\n- The `GenerationChangedPredicate` was refactored and moved. Rewrite it as a composite predicate like the following:\n\n    ```go\n    import (\n      crpredicate \"sigs.k8s.io/controller-runtime/pkg/predicate\"\n      libpredicate \"github.com/operator-framework/operator-lib/predicate\"\n    )\n\n    ...\n\n    crpredicate.Or(\n      crpredicate.GenerationChangedPredicate{},\n      libpredicate.NoGenerationPredicate{},\n    )\n    ```\n- The leader-for-life leader election library at `pkg/leader` was moved to `github.com/operator-framework/operator-lib/leader`.\n- The `pkg/status` library with status conditions helpers was moved to `github.com/operator-framework/operator-lib/status`.\n\nSee the following PRs for details:\n- [#3506](https://github.com/operator-framework/operator-sdk/pull/3506)\n- [#3532](https://github.com/operator-framework/operator-sdk/pull/3532)\n- [#3503](https://github.com/operator-framework/operator-sdk/pull/3503)\n\n[go-mig-guide-v0-19]:/docs/upgrading-sdk-version/v0.19.0#migrating-go-projects-to-the-new-kubebuilder-aligned-project-layout\n[go-mig-guide]:/docs/building-operators/golang/migration\n[ansible-mig-guide]:/docs/building-operators/ansible/migration\n[helm-mig-guide]:/docs/building-operators/helm/migration\n[operator-lib]:https://github.com/operator-framework/operator-lib\n\n### Upgrade your project from version \"2\" to \"3-alpha\"\n\nThe SDK's default Go plugin no longer supports OLM- or scorecard-related project files\nnor writes a `plugins` PROJECT field for projects scaffolded previously with `operator-sdk init --project-version=2`,\nPlease migrate to project version \"3-alpha\" for support of these features by adding the following to your `PROJECT` file:\n```yaml\nversion: \"3-alpha\" # Updated from \"2\"\nprojectName: <output of \"$(basename $(pwd))\">\nlayout: go.kubebuilder.io/v2\nplugins:\n  go.sdk.operatorframework.io/v2-alpha: {}\n```\n\n_See [#3438](https://github.com/operator-framework/operator-sdk/pull/3438) and [#3697](https://github.com/operator-framework/operator-sdk/pull/3697) for more details._\n\n### Add the samples scaffold marker to your `config/samples/kustomization.yaml`\n\nAdd the `+kubebuilder:scaffold:manifestskustomizesamples` to your `config/samples/kustomization.yaml` file like so (using an example sample file):\n```yaml\nresources:\n- cache_v1alpha1_memcached.yaml\n#+kubebuilder:scaffold:manifestskustomizesamples\n```\n\n_See [#3645](https://github.com/operator-framework/operator-sdk/pull/3645) for more details._\n\n### Update your Makefile's `bundle` recipe to inject an operator image tag.\n\nMake the following update to your Makefile's `bundle` recipe, which will allow you to set `make bundle IMG=<tag>`:\n```make\nbundle:\n  ...\n  operator-sdk generate kustomize manifests -q\n  cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) # Add this line\n  ...\n```\n\n_See [#3634](https://github.com/operator-framework/operator-sdk/pull/3634) for more details._\n\n### Update usage of `operator-sdk cleanup`\n\nThe `operator-sdk cleanup packagemanifests` command has been\nremoved and replaced with a simpler `operator-sdk cleanup`\ncommand.\n\nUpdate usages of `operator-sdk cleanup packagemanifests` to\nuse `operator-sdk cleanup <packageName>`.\n\nThe value for `<packageName>` can be found in the `*.package.yaml`\nfile in the root of your packagemanifests folder. It is typically\nyour project name.\n\n_See [#3644](https://github.com/operator-framework/operator-sdk/pull/3644) for more details._\n\n### Remove `olm-namespace` flag from `operator-sdk olm install` command\n\nThe `olm-namespace` flag has been removed from `operator-sdk olm install`\ncommand, as the olm manifests published in github have a hardcoded\nnamespace value. Hence, the olm operators can only be installed in `olm`\nnamespace using this command.\n\n_See [#3670](https://github.com/operator-framework/operator-sdk/pull/3670) for more details._\n\n### Docker images for `s390x` are no longer created automatically\n\nIf you require an `s390x` image for a particular release, please open an issue in the operator-sdk GitHub project, and the maintainers will manually build and push an s390x image for supported versions\n\n_See [#3710](https://github.com/operator-framework/operator-sdk/pull/3710) for more details._\n\n### Default install mode for `run packagemanifests` changed from `OwnNamespace` to `AllNamespaces`\n\nBy default all operators are scaffolded to run at the cluster scope and watch all namespaces.\nHowever, if you are relying on the default behavior of the `run packagemanifests` command to use the default `OwnNamespace` install mode, you must now specify it explicitly with `--install-mode=OwnNamespace`.\n\n_See [#3663](https://github.com/operator-framework/operator-sdk/pull/3663) for more details._\n\n### Use new logging flags when running the Ansible and Helm operators\n\nThe Ansible and Helm operators now use controller-runtime's zap package\nto define logging flags.\n\nThe `--zap-sample` and `--zap-time-encoding` flag have been removed since\nthey are not present in controller-runtime's flagset. These flags are no\nlonger supported.\n\nThe `--zap-level` flag is called `--zap-log-level` now. Rename any usage of\n`--zap-level` to `--zap-log-level`\n\n_See [#3596](https://github.com/operator-framework/operator-sdk/pull/3596) for more details._\n\n### Core Ansible and Helm operator logic moved to `<ansible-operator|helm-operator> run` subcommand\n\nIf you are using the `ansible-operator` and `helm-operator` binaries\ndirectly, update your usage to call `ansible-operator run` and\n`helm-operator run` (e.g. in your Makefile's `make run` target).\n\nIf you are using the base image and you are not overriding the operator\nentrypoint, no change is necessary because the base image has been updated\nto call the `run` subcommand by default.\n\n_See [#3596](https://github.com/operator-framework/operator-sdk/pull/3596) for more details._\n\n### Rename `--update-crds` flag to `--update-objects` in `generate packagemanifests` invocations\n\nThis flag has been renamed to account for all objects that can be written to the package directory, ex. Roles.\n\n_See [#3610](https://github.com/operator-framework/operator-sdk/pull/3610) for more details._\n\n### Update scorecard API Go import paths\n\nThe scorecard v1alpha3 API has been moved to a separate repo. Update your Go import paths:\n\nOld:\n```go\nimport \"github.com/operator-framework/operator-framework/pkg/apis/scorecard/v1alpha3\"\n```\n\nNew:\n```go\nimport \"github.com/operator-framework/api/pkg/apis/scorecard/v1alpha3\"\n```\n\n_See [#3622](https://github.com/operator-framework/operator-sdk/pull/3622) for more details._\n\n### Package `version` is no longer public\n\nIt is no longer possible to import package `version`. To\ndetermine the version of operator-sdk, run `operator-sdk version`.\n\n_See [#3617](https://github.com/operator-framework/operator-sdk/pull/3617) for more details._\n\n### Remove `--operator-name` from scripts\n\nThe `--operator-name` flag has been removed from `generate bundle` and `generate packagemanifests` subcommands. Remove this flag from your scripts, and make sure the `projectName` key is set in your PROJECT file. If this key is not set, the current working directory's base name will be used.\n\n_See [#3530](https://github.com/operator-framework/operator-sdk/pull/3530) for more details._\n\n### Create resources manually that were passed to `run packagemanifests --include-paths`\n\nThe `run packagemanifests` subcommand no longer has the `--include-paths` flag to create additional resources. Instead, use `kubectl apply -f <paths>` before invoking `run packagemanifests`.\n\n_See [#3599](https://github.com/operator-framework/operator-sdk/pull/3599) for more details._\n\n### Change the `run packagemanifests` flag `--operator-version` to `--version`\n\n`--operator-version` is now `--version`.\n\n_See [#3599](https://github.com/operator-framework/operator-sdk/pull/3599) for more details._\n\n### Remove `--olm-namespace` from `run packagemanifests` invocations\n\nOLM namespace is no longer required by this command.\n\n_See [#3601](https://github.com/operator-framework/operator-sdk/pull/3601) for more details._\n\n### Change the `run packagemanifests` flag `--operator-namespace` to `--namespace`\n\n`--operator-namespace` is now `--namespace`.\n\n_See [#3601](https://github.com/operator-framework/operator-sdk/pull/3601) for more details._\n\n### `pkg/log/zap` is no longer a public API\n\nMigrate to the upstream controller-runtime implementation in [sigs.k8s.io/controller-runtime/pkg/log/zap](https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.6.1/pkg/log/zap?tab=doc#Options.BindFlags).\n\n_See [#3525](https://github.com/operator-framework/operator-sdk/pull/3525) for more details._\n\n### Default Ansible and Helm operator metrics port has changed\n\nTo continue using port 8383, specify `--metrics-bind-address=:8383` when you start the operator.\n\n_See [#3489](https://github.com/operator-framework/operator-sdk/pull/3489) and [#3440](https://github.com/operator-framework/operator-sdk/pull/3440) for more details._\n\n### Update references to legacy operator-sdk domain strings\n\nUpdate various usages of domains in plugin keys and annotations:\n\n  * In Kubebuilder-style projects, change the `.operator-sdk.io` suffix to `.sdk.operatorframework.io` in the `PROJECT` file.\n\n  * In Ansible and Helm projects, change legacy annotation keys to new annotation keys in sample CR files in your repository.\n\n  * In live clusters containing CRs for Ansible and Helm-based operators:\n    1. Patch all existing CRs that use a legacy annotation to ADD the new equivalent annotations alongside the legacy annotations.\n    2. Upgrade the operator\n    3. Patch all existing CRs that used a legacy annotation to REMOVE the legacy annotations.\n\n| Location         | Legacy                                      | New                                                     |\n|------------------|---------------------------------------------|---------------------------------------------------------|\n| `PROJECT` file   | `go.operator-sdk.io`                        | `go.sdk.operatorframework.io`                           |\n| Custom resources | `ansible.operator-sdk/reconcile-period`     | `ansible.sdk.operatorframework.io/reconcile-period`     |\n| Custom resources | `ansible.operator-sdk/max-runner-artifacts` | `ansible.sdk.operatorframework.io/max-runner-artifacts` |\n| Custom resources | `ansible.operator-sdk/verbosity`            | `ansible.sdk.operatorframework.io/verbosity`            |\n| Custom resources | `helm.operator-sdk/upgrade-force`           | `helm.sdk.operatorframework.io/upgrade-force`           |\n\n_See [#3527](https://github.com/operator-framework/operator-sdk/pull/3527) for more details._\n\n### Hybrid Ansible and Helm operator use cases are not supported\n\nThere is no migration path that enables continued use of the Ansible-based or Helm-based operator Go libraries.\n\n_See [#3560](https://github.com/operator-framework/operator-sdk/pull/3560) and [#3537](https://github.com/operator-framework/operator-sdk/pull/3537) for more details._\n\n### Changes to Ansible and Helm configuration of max workers\n\n- Flag `max-workers` was renamed to `max-concurrent-reconciles` in Ansible and Helm operators.\n  Change all usage of `--max-workers` to `--max-concurrent-reconciles`. Functionality is identical; this\n  is just a name change to align more with controller runtime terminology.\n\n- The `WORKERS_<Kind>_<Group>` environment variable was deprecated. Change all usage of these\n  environment variables to `MAX_CONCURRENT_RECONCILES_<Kind>_<Group>`.\n\n_See [#3435](https://github.com/operator-framework/operator-sdk/pull/3435), [#3452](https://github.com/operator-framework/operator-sdk/pull/3452), and [#3456](https://github.com/operator-framework/operator-sdk/pull/3456) for more details._\n\n### Ansible Operator `meta` variable renamed to `ansible_operator_meta`\n\nAll existing references to the `meta` variable in your Ansible content will\nno longer work. Instead, your Ansible content should reference the\n`ansible_operator_meta` variable.\n\nAlternatively, you can use the `vars` keyword in your `watches.yaml` in order\nto map the new `ansible_operator_meta` variable to `meta`. Below is a sample\n`watches.yaml` that has made this change:\n\n```yaml\n    - version: v1alpha1\n      group: test.example.com\n      kind: Example\n      role: test\n      vars:\n        meta: '{{ ansible_operator_meta }}'\n```\n\n_See [#3562](https://github.com/operator-framework/operator-sdk/pull/3562) for more details._\n\n### Migrated Ansible and Helm operators to use new Kubebuilder-style metrics\n\n- Replaced kube-state-metrics style metrics on port `:8686` with a similar `resource_created_at` metric\n  registered with the controller-runtime metrics registry\n\n- Replace runtime creation of the metrics `Service` and `ServiceMonitor` with deploy-time kustomize manifests\n\n_See [#3466](https://github.com/operator-framework/operator-sdk/pull/3466) and [#3451](https://github.com/operator-framework/operator-sdk/pull/3451) for more details._\n\n### Removed package `pkg/k8sutil`\n\nWith the transition to Kubebuilder-style projects, `pkg/k8sutil` is no longer used in the default scaffolding\nfor Go operators. Migrate your project to the new Kubebuilder-style layout to remove the need for this\npackage.\n\n_See [#3475](https://github.com/operator-framework/operator-sdk/pull/3475) for more details._\n\n### Removed packages `pkg/kube-metrics` and `pkg/metrics`\n\nRemove the call to `addMetrics` in your `main.go` file and begin using the\n`InstrumentedEnqueueRequestForObject` handler when setting up controller-runtime\nwatches for your primary CRs.\n\n`InstrumentedEnqueueRequestForObject` can be imported from `github.com/operator-framework/operator-lib/handler`.\n\n_See [#3484](https://github.com/operator-framework/operator-sdk/pull/3484) for more details._\n\n### Removed package `pkg/ready`\n\nUse `controller-runtime`'s readyz server that supports custom http handlers. Add a `healthz.Checker` (e.g. [`healthz.Ping`](\nhttps://github.com/kubernetes-sigs/controller-runtime/blob/229c3c357d9e6b07c3d6774010c35161a82b08f9/pkg/healthz/healthz.go#L187-L188))\nusing [`manager.AddReadyzCheck`](https://github.com/kubernetes-sigs/controller-runtime/blob/229c3c357d9e6b07c3d6774010c35161a82b08f9/pkg/manager/manager.go#L73-L74).\n\n_See [#3476](https://github.com/operator-framework/operator-sdk/pull/3476) for more details._\n\n### Removed package `pkg/tls`\n\nSee the [Kubebuilder docs](https://book.kubebuilder.io/cronjob-tutorial/cert-manager.html#deploying-the-cert-manager) on\nhow to deploy and manage TLS certificates with cert-manager.\n\n_See [#3468](https://github.com/operator-framework/operator-sdk/pull/3468) for more details._\n\n### Update your scorecard config file to the new format\n\nSee the updated scorecard [config documentation](/docs/testing-operators/scorecard/#config-file)\nfor details.\n\n_See [#3434](https://github.com/operator-framework/operator-sdk/pull/3434) and\n[#3490](https://github.com/operator-framework/operator-sdk/pull/3490) for more details._\n\n### Use `scorecard` instead of `alpha scorecard`\n\nIf you have been using `operator-sdk alpha scorecard`, update to use `operator-sdk scorecard`.\nIf you have been using `operator-sdk scorecard`, migrate to the new scorecard. See the new\n[scorecard documentation](/docs/testing-operators/scorecard/).\n\n_See [#3444](https://github.com/operator-framework/operator-sdk/pull/3444) for more details._\n\n### Scorecard output formatting has changed\n\nUpdate any scripts interpretting the scorecard output to\nunderstand the `v1alpha3.TestList` format.\n\nSee the [`json`](/docs/testing-operators/scorecard/#json-format) and\n[`text`](/docs/testing-operators/scorecard/#text-format) format\ndescriptions for details.\n\n_See [#3427](https://github.com/operator-framework/operator-sdk/pull/3427) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.1.0.md",
    "content": "---\ntitle: v1.1.0\nweight: 998999000\n---\n\n## Ansible Operator fact gathering causes performance regression\n\nTo disable fact gathering by default for your operator, you will need to\nadd the following entry to the manager container in`config/manager/manager.yaml`:\n\n```yaml\n          env:\n            - name: ANSIBLE_GATHERING\n              value: explicit\n```\n\n_See [#3933](https://github.com/operator-framework/operator-sdk/pull/3933) for more details._\n\n## Update scorecard-test-kuttl image to use latest kuttl\n\nThe scorecard-test-kuttl image is updated to use kuttl:v0.5.2\nas the base image.\n\n_See [#3711](https://github.com/operator-framework/operator-sdk/pull/3711) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.10.0.md",
    "content": "---\ntitle: v1.10.0\nweight: 998990000\n---\n\n## (ansible/v1) Bump Kustomize version in helm project scaffolding to 3.8.7\n\nAnsible projects are now scaffolded with `Kustomize` version `3.8.7`. This version of kustomize requires that the path to patch file be provided with the `--path` flag in `add patch` command. In `molecule/default/prepare.yml` file, update the command under `Set pull policy`, to be:\n```diff\n     - name: Set pull policy\n-      command: '{{ \"{{ kustomize }}\" }} edit add patch pull_policy/{{ \"{{ operator_pull_policy }}\" }}.yaml'\n+      command: '{{ \"{{ kustomize }}\" }} edit add patch --path pull_policy/{{ \"{{ operator_pull_policy }}\" }}.yaml'\n```\n\n_See [#5057](https://github.com/operator-framework/operator-sdk/pull/5057) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.11.0.md",
    "content": "---\ntitle: v1.11.0\nweight: 998989000\n---\n\n## (optional) Add local Ansible Roles path to Env in `make run`\n\nIf you would like to run your operator locally using `make run`, modify the `run` target in the `Makefile` to: `ANSIBLE_ROLES_PATH=\"$(ANSIBLE_ROLES_PATH):$(shell pwd)/roles\" $(ANSIBLE_OPERATOR) run`\n\n_See [#5118](https://github.com/operator-framework/operator-sdk/pull/5118) for more details._\n\n## (go/v3) Export `KUBEBUILDER_ASSETS` in `Makefile`\n\nIn `go/v3` projects, after installing `setup-envtest` binary, the path to `KUBEBUILDER_ASSETS` needs to be exported. In `Makefile`, add the following:\n\n  ```diff\n    +# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary.\n    +ENVTEST_K8S_VERSION = 1.21\n\n    test: manifests generate fmt vet envtest ## Run tests.\n    - go test ./... -coverprofile cover.out\n    + KUBEBUILDER_ASSETS=\"$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)\" go test ./... -coverprofile cover.out\n  ```\n\n_See [#4863](https://github.com/operator-framework/operator-sdk/pull/4863) for more details._\n\n## (go/v3, ansible/v1, helm/v1) Add `containerPort` protocol field in manifests.\n\nIn `go/v3`, `ansible/v1`, `helm/v1` projects, specify the `containerPort` protocol in the following files: - `config/default/manager_auth_proxy_patch.yaml` - `config/rbac/auth_proxy_service.yaml`\n```diff\n  ports:\n - containerPort: 8443\n + protocol: TCP\n   name: https\n```\nAdditionally, in `go/v3` projects, add the `containerPort` protocol to `config/webhook/service.yaml`:\n```diff\n   ports:\n    - port: 443\n    + protocol: TCP\n      targetPort: 9443\n```\n\n_See [#4863](https://github.com/operator-framework/operator-sdk/pull/4863) for more details._\n\n## (go/v3, ansible/v1, helm/v1) Increase resource limits for controller manager.\n\nIn `go/v3`, `ansible/v1`, `helm/v1` projects, increase the `cpu` and `memory` resource limits to `200m` and `100Mi` respectively in `config/manager/manager.yaml`.\n```diff\n  resources:\n   limits:\n    - cpu: 100m\n    - memory: 30Mi\n    + cpu: 200m\n    + memory: 100Mi\n```\n\n_See [#4863](https://github.com/operator-framework/operator-sdk/pull/4863) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.12.0.md",
    "content": "---\ntitle: v1.12.0\nweight: 998988000\n---\n\nThere are no migrations for this release! 🎉\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.13.0.md",
    "content": "---\ntitle: v1.13.0\nweight: 998987000\n---\n\n## (Optional) Update local version of `ansible-runner`\n\n`ansible-runner` 2.0+ includes a backwards incompatible change in the command signature, so in order to use `make run` with Ansible-based operators, users will need to upgrade their local version of `ansible-runner` to 2.0.2+\n\n_See [#5205](https://github.com/operator-framework/operator-sdk/pull/5205) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.14.0.md",
    "content": "---\ntitle: v1.14.0\nweight: 998986000\n---\n\n## Upgrade K8s versions to use 1.22 (golang/v3)\n\nNote that to ensure the backwards compatibility SDK tool will try to downgrade the versions used if you need to still scaffold the v1beta1 for CRDs and Webhooks to publish your solutions into older cluster versions. However, note that this version is no longer supported in Kubernetes 1.22+, `sigs.k8s.io/controller-runtime v0.10.0` or `controller-gen v0.7.0`.\nFollowing are the changes to be addressed in your `Makefile` and `go.mod` file if you are not using the `v1beta1` K8s APIs which are no longer supported from k8s `1.22` version.\n1) Update your `go.mod` file to upgrade the dependencies and run `go mod tidy` to download then\n   ```\n   k8s.io/api v0.22.1\n   k8s.io/apimachinery v0.22.1\n   k8s.io/client-go v0.22.1\n   sigs.k8s.io/controller-runtime v0.10.0\n   ```\n2) Update your Makefile by making the following replacements:\n   ```diff\n   - ENVTEST_K8S_VERSION = 1.21\n   + ENVTEST_K8S_VERSION = 1.22\n   ```\n   ```diff\n   - $(CONTROLLER_GEN) $(CRD_OPTIONS) rbac:roleName=manager-role webhook paths=\"./...\" output:crd:artifacts:config=config/crd/bases\n   + $(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths=\"./...\" output:crd:artifacts:config=config/crd/bases\n   ```\n\n3) Remove from the `Makefile` the `CRD_OPTIONS`, see below:\n   ```\n   # Produce CRDs that work back to Kubernetes 1.11 (no version conversion)\n   CRD_OPTIONS ?= \"crd:trivialVersions=true,preserveUnknownFields=false\"\n   ```\n4) Replace your `admissionReviewVersions={v1,v1beta1}` markers with `admissionReviewVersions=v1`\n5) Run `make manifest` to re-generate your manifests with latest versions.\n\n_See [#5228](https://github.com/operator-framework/operator-sdk/pull/5228) for more details._\n\n## For Ansible-based Operators, update ansible collection `community.kubernetes` to `kubernetes.core`\n\nAdd the ``kubernetes.core`` collection (>= 2.2.0) to the requrements.yml file\n- name: kubernetes.core\n  version: \"2.2.0\"\n\n_See [#5249](https://github.com/operator-framework/operator-sdk/pull/5249) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.15.0.md",
    "content": "---\ntitle: v1.15.0\nweight: 998985000\n---\n\n## Update ansible collection ``community.kubernetes`` to ``kubernetes.core``\n\nAdd the ``kubernetes.core`` collection (>= 2.2.0) to the requrements.yml file\n- name: kubernetes.core\n  version: \"2.2.0\"\n\n_See [#5249](https://github.com/operator-framework/operator-sdk/pull/5249) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.16.0.md",
    "content": "---\ntitle: v1.16.0\nweight: 998984000\n---\n\n## Ansible-based operators: add resource limits\n\nAdd into the `config/manager/manager.yaml` the following limits which are now scaffolded by default:\n```yaml\n ... \n # TODO(user): Configure the resources accordingly based on the project requirements. # More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ resources:\n  limits:\n    cpu: 500m\n    memory: 768Mi\n  requests:\n    cpu: 10m\n    memory: 256Mi\n```\n**IMPORTANT:** Having resource limits is a best-practice and these values are reasonable defaults, but Operator authors should optimize these values based on their project's requirements.\n\n_See [#5274](https://github.com/operator-framework/operator-sdk/pull/5274) for more details._\n\n## Bump operator_sdk.util in requirements.yml\n\nUpdate `requirements.yml` to point to 0.3.1 of operator_sdk.util instead of 0.2.0\n\n_See [#5462](https://github.com/operator-framework/operator-sdk/pull/5462) for more details._\n\n## Add annotation to specify the default container\n\nAdd the following annotation into the file `config/manager/manager.yaml`\n```yaml\n...\ntemplate:\n  metadata:\n    annotations:\n      kubectl.kubernetes.io/default-container: manager\n...\n```\n\n_See [#5330](https://github.com/operator-framework/operator-sdk/pull/5330) for more details._\n\n## Add PHONY targets to Makefile\n\nAdd PHONY target to all Makefile targets. For example, refer to the `Makefile` in `operator-sdk/testdata` directory of [OperatorSDK](https://github.com/operator-framework/operator-sdk) tagged by the release containing this change.\n\n_See [#5330](https://github.com/operator-framework/operator-sdk/pull/5330) for more details._\n\n## For Golang-based projects, add the flag `ignore-not-found` into the Makefile for the `uninstall` and `undeploy` targets\n\nUpdate the Makefile with the following changes. \n1) Above `##@ Deployment` add the following:\n```\n...\nifndef ignore-not-found\n  ignore-not-found = false\nendif\n...\n```\n2) Replace: ```sh kubectl delete -f - ``` With: ```sh kubectl delete --ignore-not-found=$(ignore-not-found) -f - ``` \n\n**NOTE**  You can also compare your `Makefile` with the one tagged by this release, in `operator-sdk/testdata` of the [OperatorSDK](https://github.com/operator-framework/operator-sdk) project.\n\n_See [#5330](https://github.com/operator-framework/operator-sdk/pull/5330) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.17.0.md",
    "content": "---\ntitle: v1.17.0\nweight: 998983000\n---\n\n## (go/v3) Upgrade go and dependencies\n\nUpgrade controller-runtime from `0.10.0` to `0.11.0`, k8s from `1.22` to `1.23` and controller-gen from `v0.0.7` to `v0.8.0`.\nFollowing the steps to update your project.\n1) Update the go.mod file with:\n\n```\ngo 1.17\n\nrequire (\n  github.com/onsi/ginkgo v1.16.5\n  github.com/onsi/gomega v1.17.0\n  k8s.io/api v0.23.0\n  k8s.io/apimachinery v0.23.0\n  k8s.io/client-go v0.23.0\n  sigs.k8s.io/controller-runtime v0.11.0\n)\n```\n2) Run `go mod tidy`\n\nNow, let's update the Makefile targets accordingly:\n\n1) Replace `ENVTEST_K8S_VERSION = 1.22` with `ENVTEST_K8S_VERSION = 1.23`\n2) Replace `sigs.k8s.io/controller-tools/cmd/controller-gen@v0.7.0` with `sigs.k8s.io/controller-tools/cmd/controller-gen@v0.8.0`\n3) Run `make manifests` and `make generate` to ensure that you will update your manifests with the new versions\n4) You might want to run `make all` to ensure that all updates were done accordinly and succeffully\n\n_See [#5505](https://github.com/operator-framework/operator-sdk/pull/5505) for more details._\n\n## Reduce debug log level for the sidecar container kube-rbac-proxy from 10 to 0\n\nUpdate the file `config/default/manager_auth_proxy_patch.yaml` by replacing `\"--v=10\"` with `\"--v=0\"`\n\n_See [#5505](https://github.com/operator-framework/operator-sdk/pull/5505) for more details._\n\n## Add resource requests and limits to kube-rbac-proxy\n\nUpdate the file `config/default/manager_auth_proxy_patch.yaml` by adding:\n\n```\n...\nresources:\n  limits:\n    cpu: 500m\n    memory: 128Mi\n  requests:\n    cpu: 5m\n    memory: 64Mi\n```\n\n_See [#5505](https://github.com/operator-framework/operator-sdk/pull/5505) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.18.0.md",
    "content": "---\ntitle: v1.18.0\nweight: 998982000\n---\n\n## Bumped java-operator-plugins to v0.2.0\n\nAdditions:\n\n    - chore: bump go 1.17, k8s 1.23, and kubebuilder 3.3\n    - chore(deps): update to Quarkus SDK extension 3.0.2 and Quarkus 2.6.3\n    - chore(deps): update to use Quarkus JOSDK extension 3.0.1\n    - Remove useless file\n    - chore: bump k8s 1.22.2 and kubebuilder 3.2\n    - exposed exnpoints for micrometer metrics\n    - modified the Quarkus operator SDK version and tutorial too\n    - chore: bump fabric8 5.8.0 & quarkus 2.4.0\n    - modified the doc file and removed file after generation\n    - release: fix release script to understand release branches\n\nBug Fixes:\n\n    - Fix for wrongly generated file name\n\n_See [#5542](https://github.com/operator-framework/operator-sdk/pull/5542) for more details._\n\n## Support image digests instead of tags\n\nAdd following variables to your project's `Makefile` below the `BUNDLE_IMG ?=`.\n\n```\n# BUNDLE_GEN_FLAGS are the flags passed to the operator-sdk generate bundle command\nBUNDLE_GEN_FLAGS ?= -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS)\n\n# USE_IMAGE_DIGESTS defines if images are resolved via tags or digests\n# You can enable this value if you would like to use SHA Based Digests\n# To enable set flag to true\nUSE_IMAGE_DIGESTS ?= false\nifeq ($(USE_IMAGE_DIGESTS), true)\n    BUNDLE_GEN_FLAGS += --use-image-digests\nendif\n```\n\nUsing the YAML string '|' operator means that newlines in this string will\nThen in the `bundle` target we want to replace the flags passed to\n`generate bundle` with a reference to the `BUNDLE_GEN_FLAGS` above.\n\nThe `generate bundle` line should look like this\n\n```\n$(KUSTOMIZE) build config/manifests | operator-sdk generate bundle $(BUNDLE_GEN_FLAGS)\n```\n\nFor reference the *PREVIOUS* version looked as follows\n\n```\n$(KUSTOMIZE) build config/manifests | operator-sdk generate bundle -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS)\n```\n\n_See [#5567](https://github.com/operator-framework/operator-sdk/pull/5567) for more details._\n\n## Add requirement cloud.common for Ansible-based operators\n\nAdd the following line in `requirements.go` when using operator ansible sdk:\n```\n- name: cloud.common\n  version: \"2.1.0\"\n```\n\n_See [#5505](https://github.com/operator-framework/operator-sdk/pull/5505) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.19.0.md",
    "content": "---\ntitle: v1.19.0\nweight: 998981000\n---\n\nThere are no migrations for this release! 🎉\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.2.0.md",
    "content": "---\ntitle: v1.2.0\nweight: 998998000\n---\n\n## (Go-based operators) Update Makefile's bundle target\n\nIn the `Makefile` file, replace `bundle: manifests` with `bundle: manifests kustomize` to call the kustomize target when the `bundle` target is used.\n\n_See [#4090](https://github.com/operator-framework/operator-sdk/pull/4090) for more details._\n\n## (Go-based operators)  Upgrade sigs.k8s.io/controller-runtime version to v0.6.3\n\nIn the `go.mod` file replace `sigs.k8s.io/controller-runtime v0.6.2` with `sigs.k8s.io/controller-runtime v0.6.3` and then run `go mod tidy`.\n\n_See [#4062](https://github.com/operator-framework/operator-sdk/pull/4062) for more details._\n\n## (Go-based operators with multigroup support) Fix `CRDDirectoryPath` in `controllers/<group>/suite_test.go`\n\nIf your project is multi-group, then replace `CRDDirectoryPaths: []string{filepath.Join(\"..\", \"config\", \"crd\", \"bases\")},` with `CRDDirectoryPaths: []string{filepath.Join(\"..\", \"..\", \"config\", \"crd\", \"bases\")},` in `suite_test.go` files found in `controllers/<group>/` directories. Otherwise, the tests will fail since this EnvTest will not be looking for the CRD's in the correct location. For more info, see [kubebuilder#1665](https://github.com/kubernetes-sigs/kubebuilder/issues/1665).\n\n_See [#4062](https://github.com/operator-framework/operator-sdk/pull/4062) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.20.0.md",
    "content": "---\ntitle: v1.20.0\nweight: 998980000\n---\n\nThere are no migrations for this release! 🎉\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.21.0.md",
    "content": "---\ntitle: v1.21.0\nweight: 998979000\n---\n\n## (go/v3):For golang-language based operators, fix suite test using global cfg\n\nIn the suite test files, replace `cfg, err := testEnv.Start()` with:\n\n```go\nvar err error\n// cfg is defined in this file globally.\ncfg, err = testEnv.Start()\n```\n\nNote: You can find suite test files scaffold for the APIs created for your project\nsuch as `api/webhook_suitetest.go` directory as for your controllers in `controllers/suite_test.go`.\n\n_See [#4863](https://github.com/operator-framework/operator-sdk/pull/4863) for more details._\n\n## For Golang-based operators, update Dockerfile if you are using the [declarative/v1 plugin](https://book-v3.book.kubebuilder.io/plugins/declarative-v1.html)\n\nIf you are using the declarative/v1 plugin for your scaffolds, then following the steps to update the Dockerfile.\na) After `COPY controllers/ controllers/` add:\n\n```sh\n# https://github.com/kubernetes-sigs/kubebuilder-declarative-pattern/blob/master/docs/addon/walkthrough/README.md#adding-a-manifest\n# Stage channels and make readable\nCOPY channels/ /channels/\nRUN chmod -R a+rx /channels/\n```\n\nb)  After the `COPY --from=builder /workspace/manager .`\" add:\n\n```sh\n# copy channels\nCOPY --from=builder /channels /channels\n```\n\n_See [#4863](https://github.com/operator-framework/operator-sdk/pull/4863) for more details._\n\n## (go/v3):For Golang-based operators, upgrade controller-runtime from v0.11.0 to v0.11.2 and Kubernetes deps from 1.23.0 to 1.23.5\n\nUpdate your go.mod by replacing `sigs.k8s.io/controller-runtime v0.11.0` with `sigs.k8s.io/controller-runtime v0.11.2` and run `go mod tidy`\nto update the K8s dependencies.\n\n_See [#4863](https://github.com/operator-framework/operator-sdk/pull/4863) for more details._\n\n## For Golang/Helm/Ansible-based operators, upgrade kube-rbac-proxy image from v0.8.0 to v0.11.0. (For further information see the kube-rbac-proxy [release notes](https://github.com/brancz/kube-rbac-proxy/releases))\n\nUpdate the tag version used for the image `gcr.io/kubebuilder/kube-rbac-proxy` in the file config/default/manager_auth_proxy_patch.yaml.\nReplace `gcr.io/kubebuilder/kube-rbac-proxy:v0.8.0` with `gcr.io/kubebuilder/kube-rbac-proxy:v0.11.0`\n\n_See [#4863](https://github.com/operator-framework/operator-sdk/pull/4863) for more details._\n\n## For Golang-based operators,  change Makefile targets to replace go get with go install\n\nThe targets kustomize, controller-gen and envtest were changed. Update the Makefile replacing:\n\n```sh\nCONTROLLER_GEN = $(shell pwd)/bin/controller-gen\n.PHONY: controller-gen\ncontroller-gen: ## Download controller-gen locally if necessary.\n\t$(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.8.0)\n\nKUSTOMIZE = $(shell pwd)/bin/kustomize\n.PHONY: kustomize\nkustomize: ## Download kustomize locally if necessary.\n\t$(call go-get-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v3@v3.8.7)\n\nENVTEST = $(shell pwd)/bin/setup-envtest\n.PHONY: envtest\nenvtest: ## Download envtest-setup locally if necessary.\n\t$(call go-get-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest@latest)\n\n# go-get-tool will 'go get' any package $2 and install it to $1.\nPROJECT_DIR := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST))))\ndefine go-get-tool\n@[ -f $(1) ] || { \\\nset -e ;\\\nTMP_DIR=$$(mktemp -d) ;\\\ncd $$TMP_DIR ;\\\ngo mod init tmp ;\\\necho \"Downloading $(2)\" ;\\\nGOBIN=$(PROJECT_DIR)/bin go get $(2) ;\\\nrm -rf $$TMP_DIR ;\\\n}\nendef\n```\n\nWith:\n\n```sh\n##@ Build Dependencies\n\n## Location to install dependencies to\nLOCALBIN ?= $(shell pwd)/bin\n$(LOCALBIN):\n\tmkdir -p $(LOCALBIN)\n\n## Tool Binaries\nKUSTOMIZE ?= $(LOCALBIN)/kustomize\nCONTROLLER_GEN ?= $(LOCALBIN)/controller-gen\nENVTEST ?= $(LOCALBIN)/setup-envtest\n\n## Tool Versions\nKUSTOMIZE_VERSION ?= v3.8.7\nCONTROLLER_TOOLS_VERSION ?= v0.8.0\n\nKUSTOMIZE_INSTALL_SCRIPT ?= \"https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh\"\n.PHONY: kustomize\nkustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary.\n$(KUSTOMIZE): $(LOCALBIN)\n\tcurl -s $(KUSTOMIZE_INSTALL_SCRIPT) | bash -s -- $(subst v,,$(KUSTOMIZE_VERSION)) $(LOCALBIN)\n\n.PHONY: controller-gen\ncontroller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary.\n$(CONTROLLER_GEN): $(LOCALBIN)\n\tGOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION)\n\n.PHONY: envtest\nenvtest: $(ENVTEST) ## Download envtest-setup locally if necessary.\n$(ENVTEST): $(LOCALBIN)\n\tGOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest\n```\n\n_See [#4863](https://github.com/operator-framework/operator-sdk/pull/4863) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.22.0.md",
    "content": "---\ntitle: v1.22.0\nweight: 998978000\n---\n\n## For Ansible-based language operators, upgrade `community.kubernetes` from `1.2.1` to `2.0.1`.\n\n**IMPORTANT** The `community.kubernetes` collection is being renamed to `kubernetes.core`. As of version 2.0.0, the collection has been replaced by deprecated redirects for all content to kubernetes.core. If you are using FQCNs starting with `community.kubernetes`, please update them to `kubernetes.core`.\nEnsure that you check the [community.kubernetes changelog](https://github.com/ansible-collections/community.kubernetes/blob/main/CHANGELOG.rst) to verify if your Operator code must be updated and it is affected by the MAJOR changes.\n\nIn the `requirements.yml` file:\n\nReplace:\n\n```yaml\ncollections:\n  - name: community.kubernetes\n    version: \"1.2.1\"\n```\n\nWith:\n\n```yaml\ncollections:\n  - name: community.kubernetes\n    version: \"2.0.1\"\n```\n\n_See [#5846](https://github.com/operator-framework/operator-sdk/pull/5846) for more details._\n\n## For Ansible-based language operators, upgrade `kubernetes.core` from `2.2.0` to `2.3.1`.\n\nEnsure that you check the [kubernetes.core changelog](https://github.com/ansible-collections/kubernetes.core/blob/main/CHANGELOG.rst) to verify if your Operator code must be updated and it is affected by the MAJOR changes.\n\nIn the `requirements.yml` file:\n\nReplace:\n\n```yaml\ncollections:\n  ...\n  - name: kubernetes.core\n    version: \"2.2.0\"\n```\n\nWith:\n\n```yaml\ncollections:\n  ...\n  - name: kubernetes.core\n    version: \"2.3.1\"\n```\n\n_See [#5846](https://github.com/operator-framework/operator-sdk/pull/5846) for more details._\n\n## For Ansible-based language operators, upgrade `cloud.common` from `2.2.0` to `2.2.1`.\n\nIn the `requirements.yml` file:\n\nReplace:\n\n```ymal\ncollections:\n  ...\n  - name: cloud.common\n    version: \"2.1.0\"\n```\n\nWith:\n\n```ymal\ncollections:\n  ...\n  - name: cloud.common\n    version: \"2.1.1\"\n```\n\n_See [#5846](https://github.com/operator-framework/operator-sdk/pull/5846) for more details._\n\n## Go (go/v3) and Helm Hybrid (hybrid.helm/v1-alpha) language based operators - Upgrade Kubernetes dependencies from `1.23` to `1.24` and controller-gen from `v0.8.0` to `v0.9.0`\n\nTo update your project to support Kubernetes 1.24:\n\n1. In `go.mod`:\n\n- Replace `k8s.io/api v0.23.5` with `k8s.io/api v0.24.0`\n- Replace `k8s.io/apimachinery v0.23.5` with  `k8s.io/apimachinery v0.24.0`\n- Replace `k8s.io/client-go v0.23.5` with `k8s.io/client-go v0.24.0`\n- Replace `sigs.k8s.io/controller-runtime v0.11.2` with `sigs.k8s.io/controller-runtime v0.12.1`\n- Hybrid Helm (hybrid) only: Replace `github.com/operator-framework/helm-operator-plugins v0.0.11` with `github.com/operator-framework/helm-operator-plugins v0.0.12-0.20220608155702-d3967d2ae2ac`\n\n2. Run `go mod tidy` to ensure all dependencies are upgraded\n\n3. In `Makefile`:\n- Replace `CONTROLLER_TOOLS_VERSION ?= 0.8.0` with `CONTROLLER_TOOLS_VERSION ?= 0.9.0`\n- Replace `ENVTEST_K8S_VERSION = 1.23` with `ENVTEST_K8S_VERSION = 1.24`\n\n4. Run `make` to run all make targets\n\n_See [#5843](https://github.com/operator-framework/operator-sdk/pull/5843) for more details._\n\n## Go (go/v3) and Hybrid Helm (hybrid.helm/v1-alpha) language based operators - Add support for Go 1.18\n\nTo update your project to use Go 1.18:\n\n1. In the `go.mod` file:\n\n- Replace `go 1.17` with `go 1.18`   \n\n2. Run `go mod tidy` to ensure all dependencies are upgraded\n\n_See [#5843](https://github.com/operator-framework/operator-sdk/pull/5843) for more details._\n\n## For Go (go/v3, go/v2), Ansible (ansible/v1), Helm (helm/v1), and Helm Hybrid (hybrid.helm/v1-alpha) language based operators - Bump OPM version from `v1.19.1` to `v1.23.0` [More info](https://github.com/operator-framework/operator-registry/releases)\n\nTo update your project to use OPM `v1.23.0`:\n\n1. In the `Makefile`:\n\n- Replace `curl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/v1.19.1/$${OS}-$${ARCH}-opm` with `curl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/v1.23.0/$${OS}-$${ARCH}-opm`   \n\n2. Run `make opm`\n\n_See [#5843](https://github.com/operator-framework/operator-sdk/pull/5843) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.23.0.md",
    "content": "---\ntitle: v1.23.0\nweight: 998977000\n---\n\n## For Hybrid Helm (hybrid.helm/v1-alpha) language based operators - Bump Dockerfile Go version to 1.18\n\nIn the `Dockerfile`, replace the line `FROM golang:1.17 as builder` with `FROM golang:1.18 as builder`\n\n_See [#5772](https://github.com/operator-framework/operator-sdk/pull/5772) for more details._\n\n## (go/v3) Fix Makefile targets to not download binaries when they are found already\n\nUpdate the Makefile targets by adding `test -s $(LOCALBIN)/<binary-name> ||` before the instruction to download them, see:\n\n```sh\nKUSTOMIZE_INSTALL_SCRIPT ?= \"https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh\"\n.PHONY: kustomize\nkustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary.\n$(KUSTOMIZE): $(LOCALBIN)\n\ttest -s $(LOCALBIN)/kustomize || { curl -s $(KUSTOMIZE_INSTALL_SCRIPT) | bash -s -- $(subst v,,$(KUSTOMIZE_VERSION)) $(LOCALBIN); }\n\n.PHONY: controller-gen\ncontroller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary.\n$(CONTROLLER_GEN): $(LOCALBIN)\n\ttest -s $(LOCALBIN)/controller-gen || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION)\n\n.PHONY: envtest\nenvtest: $(ENVTEST) ## Download envtest-setup locally if necessary.\n$(ENVTEST): $(LOCALBIN)\n\ttest -s $(LOCALBIN)/setup-envtest || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest\n```\n\n_See [#5965](https://github.com/operator-framework/operator-sdk/pull/5965) for more details._\n\n## (go/v3) Update `controller-tools` from `0.9.0` to `0.9.2`.\n\nIn the `Makefile` file, replace `CONTROLLER_TOOLS_VERSION ?= v0.9.0` with `CONTROLLER_TOOLS_VERSION ?= v0.9.2`\n\n_See [#5965](https://github.com/operator-framework/operator-sdk/pull/5965) for more details._\n\n## (go/v3) Update `controller-runtime` from `v0.12.1` to `v0.12.2` and Kubernetes dependencies from `v0.24.0` to `v0.24.2`.\n\nIn the `go.mod` file, ensure the following dependencies versions and run `go mod tidy`:\n\n```go\nk8s.io/api v0.24.2\nk8s.io/apimachinery v0.24.2\nk8s.io/client-go v0.24.2\nsigs.k8s.io/controller-runtime v0.12.2\n```\n\n_See [#5965](https://github.com/operator-framework/operator-sdk/pull/5965) for more details._\n\n## Upgrade kube proxy image `gcr.io/kubebuilder/kube-rbac-proxy` from `v0.11.0` to `v0.13.0`\n\nIn the `config/default/manager_auth_proxy_patch.yaml` file, replace `gcr.io/kubebuilder/kube-rbac-proxy:0.11.0` with `gcr.io/kubebuilder/kube-rbac-proxy:0.13.0`\n\n_See [#5903](https://github.com/operator-framework/operator-sdk/pull/5903) and [#5965](https://github.com/operator-framework/operator-sdk/pull/5965) for more details._\n\n\n## (ansible/v1,helm/v1) Upgrade kustomize versions from `v3.8.7` to `v4.5.5`\n\nUpgrade kustomize versions from `v3.8.7` to `v4.5.5`\n\n**WARNING** If your project has customizations using kustomize you might be impacted by them. See its [Release Notes](https://github.com/kubernetes-sigs/kustomize/releases/tag/kustomize%2Fv4.0.0). (Note all changes are covered by its docs)\n- Update the kustomize version in your Makefile: ensure that the value used for `KUSTOMIZE_VERSION` is `v4.5.5`\n\n- In the `config/default/kustomization.yaml` file:\n   a) Replace:\n   ```yaml\n   #commonLabels:\n   #  someName: someValue\n   ```\n\n   With:\n   ```yaml\n   #labels:\n   #- includeSelectors: true\n   #  pairs:\n   #    someName: someValue\n   ```\n\n   b) Replace: `bases:` With: `resources:`\n\n**(Valid Only for Ansible Projects)**\n- In the molecule/default, replace `--load_restrictor none .` with `--load-restrictor LoadRestrictionsNone`\n\n_See [#5965](https://github.com/operator-framework/operator-sdk/pull/5965) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.24.0.md",
    "content": "---\ntitle: v1.24.0\nweight: 998976000\n---\n\n## Support for arm64\n\nIn Ansible & Helm-based operators, if you need to support `arm64`, add the following\n\n  `| sed 's/aarch64/arm64/'` \n\non the following line\n\n  `ARCH := $(shell uname -m | sed 's/x86_64/amd64/')`\n\nThe resulting line should look like this\n\n  `ARCH := $(shell uname -m | sed 's/x86_64/amd64/' | sed 's/aarch64/arm64/')`\n\n_See [#5480](https://github.com/operator-framework/operator-sdk/pull/5480) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.25.0.md",
    "content": "---\ntitle: v1.25.0\nweight: 998975000\n---\n\n## Kubebuilder bump brought changes that modified the `Makefile` scaffolding and also `multiarch` changes are also included.\n\n1. Makefile content is updated as shown below.\n\n    ```sh\n        `KUBEBUILDER_ASSETS=\"$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)\" go test ./... -coverprofile cover.out`,\n    ```\n\n2. Add support for building binary in multiple platforms.\n\n    Add the below content to the Makefile.\n\n    ```sh\n    # PLATFORMS defines the target platforms for  the manager image be build to provide support to multiple\n    # architectures. (i.e. make docker-buildx IMG=myregistry/mypoperator:0.0.1). To use this option you need to:\n    # - able to use docker buildx . More info: https://docs.docker.com/build/buildx/\n    # - have enable BuildKit, More info: https://docs.docker.com/develop/develop-images/build_enhancements/\n    # - be able to push the image for your registry (i.e. if you do not inform a valid value via IMG=<myregistry/image:<tag>> than the export will fail)\n    # To properly provided solutions that supports more than one platform you should use this option.\n    PLATFORMS ?= linux/arm64,linux/amd64,linux/s390x,linux/ppc64le\n    .PHONY: docker-buildx\n    docker-buildx: test ## Build and push docker image for the manager for cross-platform support\n        # copy existing Dockerfile and insert --platform=${BUILDPLATFORM} into Dockerfile.cross, and preserve the original Dockerfile\n        sed -e '1 s/\\(^FROM\\)/FROM --platform=\\$$\\{BUILDPLATFORM\\}/; t' -e ' 1,// s//FROM --platform=\\$$\\{BUILDPLATFORM\\}/' Dockerfile > Dockerfile.cross\n        - docker buildx create --name project-v3-builder\n        docker buildx use project-v3-builder\n        - docker buildx build --push --platform=$(PLATFORMS) --tag ${IMG} -f Dockerfile.cross\n        - docker buildx rm project-v3-builder\n        rm Dockerfile.cross\n    ```\n\n3. (go/v3) Bump dependencies in go.mod file\n\n    ```go\n        go 1.19   \n\n      \tgithub.com/onsi/ginkgo/v2 v2.1.4\n        github.com/onsi/gomega v1.19.0\n        github.com/prometheus/client_golang v1.12.2\n        k8s.io/api v0.25.0\n        k8s.io/apimachinery v0.25.0\n        k8s.io/client-go v0.25.0\n        sigs.k8s.io/controller-runtime v0.13.0\n    ```\n\n4. (go/v3) Update `controller-tools` from `0.9.2` to `0.10.0`. \n\n   In the `Makefile` file, replace `CONTROLLER_TOOLS_VERSION ?= v0.9.2` with `CONTROLLER_TOOLS_VERSION ?= v0.10.0`\n\n_See [#6047](https://github.com/operator-framework/operator-sdk/pull/6047) for more details._\n\n## For multi-arch build support, add docker-buildx target to project Makefile\n\nIn the project `Makefile` below the `docker-push` target add the new `docker-buildx`\ntarget.\n\n```sh\n# PLATFORMS defines the target platforms for  the manager image be build to provide support to multiple\n# architectures. (i.e. make docker-buildx IMG=myregistry/mypoperator:0.0.1). To use this option you need to:\n# - able to use docker buildx . More info: https://docs.docker.com/build/buildx/\n# - have enable BuildKit, More info: https://docs.docker.com/develop/develop-images/build_enhancements/\n# - be able to push the image for your registry (i.e. if you do not inform a valid value via IMG=<myregistry/image:<tag>> than the export will fail)\n# To properly provided solutions that supports more than one platform you should use this option.\nPLATFORMS ?= linux/arm64,linux/amd64,linux/s390x,linux/ppc64le\n.PHONY: docker-buildx\ndocker-buildx: test ## Build and push docker image for the manager for cross-platform support\n\t# copy existing Dockerfile and insert --platform=${BUILDPLATFORM} into Dockerfile.cross, and preserve the original Dockerfile\n\tsed -e '1 s/\\(^FROM\\)/FROM --platform=\\$$\\{BUILDPLATFORM\\}/; t' -e ' 1,// s//FROM --platform=\\$$\\{BUILDPLATFORM\\}/' Dockerfile > Dockerfile.cross\n\t- docker buildx create --name project-v3-builder\n\tdocker buildx use project-v3-builder\n\t- docker buildx build --push --platform=$(PLATFORMS) --tag ${IMG} -f Dockerfile.cross\n\t- docker buildx rm project-v3-builder\n\trm Dockerfile.cross\n```\n\n_See [#6093](https://github.com/operator-framework/operator-sdk/pull/6093) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.26.0.md",
    "content": "---\ntitle: v1.26.0\nweight: 998974000\n---\n\n## update ansible operator Makefile's run target\n\nFor an ansible operator, update the Makefile's run target to the\nfollowing to fix a bug in its implementation.\n\n```\n.PHONY: run\nANSIBLE_ROLES_PATH?=\"$(shell pwd)/roles\"\nrun: ansible-operator ## Run against the configured Kubernetes cluster in ~/.kube/config\n    $(ANSIBLE_OPERATOR) run\n```\n\n_See [#6110](https://github.com/operator-framework/operator-sdk/pull/6110) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.27.0.md",
    "content": "---\ntitle: v1.27.0\nweight: 998973000\n---\n\nThere are no migrations for this release! 🎉\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.28.0.md",
    "content": "---\ntitle: v1.28.0\nweight: 998972000\n---\n\n## (ansible) - Upgrade kubernetes.core collection to v2.4.0\n\nIn the requirements.yaml file replace:\n```yaml\n  - name: kubernetes.core\n    version: \"2.3.1\"\n```\nwith:\n```yaml\n  - name: kubernetes.core\n    version: \"2.4.0\"\n```\n\n_See [#6334](https://github.com/operator-framework/operator-sdk/pull/6334) for more details._\n\n## Upgrade K8s versions to use 1.26\n\nRegarding the upcoming major changes in the plugin, please note that `go/v3` is being deprecated by Kubebuilder hence Operator SDK would also be migrating to `go/v4` soon. Following are the changes to be addressed in your project structure, `Makefile` and `go.mod` files: 1) [go/v3, ansible/v1, helm/v1] Update your `go.mod` file to upgrade the dependencies and run `go mod tidy` to download them ```go k8s.io/api v0.26.2 k8s.io/apiextensions-apiserver v0.26.2 k8s.io/apimachinery v0.26.2 k8s.io/cli-runtime v0.26.2 k8s.io/client-go v0.26.2 k8s.io/kubectl v0.26.2 sigs.k8s.io/controller-runtime v0.14.5 sigs.k8s.io/controller-tools v0.11.3 sigs.k8s.io/kubebuilder/v3 v3.9.1 ``` 2) [go/v3, ansible/v1, helm/v1] With the bump to Kubebuilder 3.9.1, the `go/v3` projects are now scaffolded with 0.13.1 version of kube-rbac-proxy. Modify the version of kube-rbac-proxy in the following scaffolded files: - config/default/manager_auth_proxy_patch.yaml - bundle/manifests/memcached-operator.clusterserviceversion.yaml        \n\n  ```diff\n    - gcr.io/kubebuilder/kube-rbac-proxy:v0.13.0\n    + gcr.io/kubebuilder/kube-rbac-proxy:v0.13.1\n  ```\n3) [gov4alpha] For scaffolds, replace scaffoldings of v1beta1 by using `k8s.io/api/admission/v1` instead of `k8s.io/api/admission/v1beta1` as v1beta1 is removed in latest k8s.\n  ```diff\n    - admissionv1beta1 \"k8s.io/api/admission/v1beta1\"\n    + admissionv1 \"k8s.io/api/admission/v1\"\n  ```\n4) [gov4alpha] The project structure has changed from `/controllers` to `internal/controller/`. Modify the Dockerfile of the `go/v4-alpha` plugin to below:\n  ```diff\n    - COPY controllers/ controllers/\n    + COPY internal/controller/ internal/controller/\n  ```\n5) [go/v3, gov4alpha] Update your Makefile by\n  - Replacing `ENVTEST_K8S_VERSION = 1.25` with `ENVTEST_K8S_VERSION = 1.26`.\n  - Using `manifests generate fmt vet` to build manager binary by replacing `generate fmt vet` in the build target to `manifests generate fmt vet`:\n  ```diff\n    - build: generate fmt vet ## Build manager binary.\n    + build: manifests generate fmt vet ## Build manager binary.\n  ```\n6) [gov4alpha] The gov4alpha plugin is now being scaffolded with Kubebuilder's go/v4-alpha which has a modified project file structure according to Go's best practices. Refer https://github.com/kubernetes-sigs/kubebuilder/pull/2985 for changes. Make the following changes in your scaffolded project if gov4aplha plugin was used:          - Replacing `go run ./main.go` to `go run ./cmd/main.go` due to the change in project structure.\n   - Replacing \n  ```diff \n    - `test -s $(LOCALBIN)/controller-gen || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION)`\n    + test -s $(LOCALBIN)/controller-gen && $(LOCALBIN)/controller-gen --version | grep -q $(CONTROLLER_TOOLS_VERSION) || \\\n    GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION)\n  ```\n\n_See [#6352](https://github.com/operator-framework/operator-sdk/pull/6352) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.29.0.md",
    "content": "---\ntitle: v1.29.0\nweight: 998971000\n---\n\nThere are no migrations for this release! 🎉\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.3.0.md",
    "content": "---\ntitle: v1.3.0\nweight: 998997000\n---\n\n## Update `packagemanifests` make recipe variable `PKG_MAN_OPTS`\n\nIf your project uses the `packagemanifests` make recipe, update your `PKG_MAN_OPTS` variable to include `PKG_FROM_VERSION` instead of `FROM_VERSION`, ex:\n\n```make\nPKG_MAN_OPTS ?= $(PKG_FROM_VERSION) $(PKG_CHANNELS) $(PKG_IS_DEFAULT_CHANNEL)\n```\n\n_See [#4303](https://github.com/operator-framework/operator-sdk/pull/4303) for more details._\n\n## Update your Go project's controller-runtime version to v0.6.4\n\nIn your go.mod file, update the `sigs.k8s.io/controller-runtime` version to v0.6.4\n\n_See [#4282](https://github.com/operator-framework/operator-sdk/pull/4282) for more details._\n\n## Upgrade your Go project from \"go.kubebuilder.io/v2\" to \"go.kubebuilder.io/v3\"\n\nThe newly released go/v3 plugin has many new features and (breaking) changes incompatible with projects created by go/v2.\nYou are not required to upgrade and your go/v2 project will continue to work with new operator-sdk versions.\nIf you wish to upgrade, check out the upstream [migration guide](https://master.book.kubebuilder.io/migration/legacy/v2vsv3.html).\n\nAdditionally, if using project version \"3-alpha\", you must update your `plugins` config field:\n\nOld:\n```yaml\nplugins:\n  go.sdk.operatorframework.io/v2-alpha: {}\n```\n\nNew:\n```yaml\nplugins:\n  manifests.sdk.operatorframework.io/v2: {}\n  scorecard.sdk.operatorframework.io/v2: {}\n```\n\n_See [#4307](https://github.com/operator-framework/operator-sdk/pull/4307) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.30.0.md",
    "content": "---\ntitle: v1.30.0\nweight: 998970000\n---\n\n## Header text for the migration section\n\nBody of the migration section. This should be formatted as markdown and can\nspan multiple lines.\n\nUsing the YAML string '|' operator means that newlines in this string will\nbe honored and interpretted as newlines in the rendered markdown.\n\n_See [#6426](https://github.com/operator-framework/operator-sdk/pull/6426) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.31.0.md",
    "content": "---\ntitle: v1.31.0\nweight: 998969000\n---\n\n## Updating an Ansible Operator to use the updated Ansible 2.15.0 image\n\n1. Update the `FROM` directive in the `Dockerfile` to have a version tag > `v1.30.0`\n2. Evaluate your dependency requirements. The change to Ansible 2.15.0 also included removal of some pre-installed Python modules. You may need to update your `Dockerfile` to `pip install` modules required by your operator.\n\n_See [#6483](https://github.com/operator-framework/operator-sdk/pull/6483) for more details._\n\n## Upgrading an Ansible Operator project to match the latest `ansible/v1` plugin changes\n\n1. In the `requirements.yml` file:\n    - Remove the `community.kubernetes` collection entry\n    - Update the version of the `operator_sdk.util` collection entry to `v0.5.0`\n2. In the `molecule/kind/molecule.yml` and `molecule/default/molecule.yml` files:\n    - Remove all instances of the `lint` field. For an example of the diff, see: https://github.com/operator-framework/operator-sdk/pull/6483/files#diff-f159b0d7ec17de90f5b5c297ce997254e6ea4001269167be25615c45c489539e\n\n_See [#6483](https://github.com/operator-framework/operator-sdk/pull/6483) for more details._\n\n## Migrating away from the `quay.io/operator-framework/ansible-operator-2.11-preview` base image\n\n1. Update the `FROM` directive in the `Dockerfile` to use the base image `quay.io/operator-framework/ansible-operator:vX.Y.Z` where `vX.Y.Z` is > `v1.30.0`\n\n_See [#6483](https://github.com/operator-framework/operator-sdk/pull/6483) for more details._\n\n## Require `watch` on `secrets`\n\nThe operator now requires the watch operation on secrets.\nWhen using a custom ServiceAccount for deployment, the following additional role is now required:\n```\nrules:\n  - apiGroups:\n      - \"\"\n    resources:\n      - secrets\n    verbs:\n      - watch\n```\n\n_See [#6354](https://github.com/operator-framework/operator-sdk/pull/6354) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.32.0.md",
    "content": "---\ntitle: v1.32.0\nweight: 998968000\n---\n\nThere are no migrations for this release! 🎉\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.33.0.md",
    "content": "---\ntitle: v1.33.0\nweight: 998967000\n---\n\n## (go/v4-alpha) Move go/v4 plugin from alpha to stable\n\nThe transition from Golang v2 and v3 plugins to the new Golang v4 plugin introduces significant changes. \nTo gain insights into the reasoning behind these changes, you can refer to the explanation provided \nat https://book.kubebuilder.io/migration/v3vsv4#tldr-of-the-new-gov4-plugin.\n\nFor a comprehensive understanding of the migration process to the v4 plugin format, \nthe Kubebuilder documentation outlines the necessary steps. Detailed instructions\ncan be found at https://book.kubebuilder.io/migration/manually_migration_guide_gov3_to_gov4.\n\nThis migration is designed to enhance your project's functionality and compatibility, \nreflecting the evolving landscape of Golang development.\n\n_See [#6613](https://github.com/operator-framework/operator-sdk/pull/6613) for more details._\n\n## (kustomize/v2-alpha) Move kustomize/v2 plugin from alpha to stable\n\nFor more information on the kustomize/v2 plugin, please refer to the documentation at\nhttps://book.kubebuilder.io/plugins/available/kustomize-v2\n\n_See [#6613](https://github.com/operator-framework/operator-sdk/pull/6613) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.34.0.md",
    "content": "---\ntitle: v1.34.0\nweight: 998966000\n---\n\n## To fix multi-arch build, replace docker-buildx target in project Makefile\n\nIn the project `Makefile`, replace existing `docker-buildx` target with following definition.\n\n```make\ndocker-buildx: ## Build and push docker image for the manager for cross-platform support\n\t- docker buildx create --name project-v3-builder\n\tdocker buildx use project-v3-builder\n\t- docker buildx build --push --platform=$(PLATFORMS) --tag ${IMG} -f Dockerfile .\n\t- docker buildx rm project-v3-builder\n```\n\n_See [#6661](https://github.com/operator-framework/operator-sdk/pull/6661) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.35.0.md",
    "content": "---\ntitle: v1.35.0\nweight: 998965000\n---\n\n## Fix helm-operator scaffolding that was broken in 1.34.0, 1.34.1, and 1.34.2\n\nUsers who scaffolded a helm-operator project with 1.34.0, 1.34.1, or 1.34.2\nneed re-generate the project in order to get a fixed `config/rbac/role.yaml` file.\n\n_See [#6769](https://github.com/operator-framework/operator-sdk/pull/6769) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.36.0.md",
    "content": "---\ntitle: v1.36.0\nweight: 998964000\n---\n\n## Upgrade K8s versions to use 1.29\n\nRegarding the upcoming major changes in the plugin, please note that `go/v3` is being deprecated by Kubebuilder hence Operator SDK would also be migrating to `go/v4` soon. Following are the changes to be addressed in your project structure, `Makefile` and `go.mod` files:\n1) [go/v4] Update your `go.mod` file to upgrade the dependencies and run `go mod tidy` to download them:\n   ```go\n   k8s.io/api v0.29.2\n   k8s.io/apimachinery v0.29.2\n   k8s.io/client-go v0.29.2\n   sigs.k8s.io/controller-runtime v0.17.3\n   ```\n2) [go/v4, helm/v1] The projects are now scaffolded with 0.16.0 version of kube-rbac-proxy. Modify the version of kube-rbac-proxy in the following scaffolded files: - config/default/manager_auth_proxy_patch.yaml     \n   ```diff\n   - gcr.io/kubebuilder/kube-rbac-proxy:v0.15.0\n   + gcr.io/kubebuilder/kube-rbac-proxy:v0.16.0\n   ```\n3) [go/v4] You can now generate a file that contains all the resources built with Kustomize, which are necessary to install this project without its dependencies. Update your Makefile by adding: \n   ```diff\n   + .PHONY: build-installer\n   +   build-installer: manifests generate kustomize ## Generate a consolidated YAML with CRDs and deployment.\n   +   \tmkdir -p dist\n   +   \tcd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}\n   +   \t$(KUSTOMIZE) build config/default > dist/install.yaml\n   ```\n4) [go/v4] Update ENVTEST_K8S_VERSION in your Makefile:\n   ```diff\n   - ENVTEST_K8S_VERSION = 1.28.3\n   + ENVTEST_K8S_VERSION = 1.29.0\n   ```\n5) [go/v4] Remove the following section from your Makefile:\n   ```diff\n   - GOLANGCI_LINT = $(shell pwd)/bin/golangci-lint\n   - GOLANGCI_LINT_VERSION ?= v1.54.2\n   - golangci-lint:\n   - \t@[ -f $(GOLANGCI_LINT) ] || { \\\n   - \tset -e ;\\\n   - \tcurl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(shell dirname $(GOLANGCI_LINT)) $(GOLANGCI_LINT_VERSION) ;\\\n   - \t}\n   ```\n6) [go/v4] Update the following in your Makefile:\n   ```diff\n   - ## Tool Binaries\n   - KUBECTL ?= kubectl\n   - KUSTOMIZE ?= $(LOCALBIN)/kustomize\n   - CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen\n   - ENVTEST ?= $(LOCALBIN)/setup-envtest\n   - \n   - ## Tool Versions\n   - KUSTOMIZE_VERSION ?= v5.2.1\n   - CONTROLLER_TOOLS_VERSION ?= v0.13.0\n   - \n   - .PHONY: kustomize\n   - kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary. If wrong version is installed, it will be removed before downloading.\n   - $(KUSTOMIZE): $(LOCALBIN)\n   -   @if test -x $(LOCALBIN)/kustomize && ! $(LOCALBIN)/kustomize version | grep -q $(KUSTOMIZE_VERSION); then \\\n   -   echo \"$(LOCALBIN)/kustomize version is not expected $(KUSTOMIZE_VERSION). Removing it before installing.\"; \\\n   -   rm -rf $(LOCALBIN)/kustomize; \\\n   -   fi\n   -   test -s $(LOCALBIN)/kustomize || GOBIN=$(LOCALBIN) GO111MODULE=on go install sigs.k8s.io/kustomize/kustomize/v5@$(KUSTOMIZE_VERSION)\n   - \n   - .PHONY: controller-gen\n   - controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary. If wrong version is installed, it will be overwritten.\n   - $(CONTROLLER_GEN): $(LOCALBIN)\n   -   test -s $(LOCALBIN)/controller-gen && $(LOCALBIN)/controller-gen --version | grep -q $(CONTROLLER_TOOLS_VERSION) || \\\n   -   GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION)\n   - \n   - .PHONY: envtest\n   - envtest: $(ENVTEST) ## Download envtest-setup locally if necessary.\n   - $(ENVTEST): $(LOCALBIN)\n   -   test -s $(LOCALBIN)/setup-envtest || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest\n   + ## Tool Binaries\n   + KUBECTL ?= kubectl\n   + KUSTOMIZE ?= $(LOCALBIN)/kustomize-$(KUSTOMIZE_VERSION)\n   + CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen-$(CONTROLLER_TOOLS_VERSION)\n   + ENVTEST ?= $(LOCALBIN)/setup-envtest-$(ENVTEST_VERSION)\n   + GOLANGCI_LINT = $(LOCALBIN)/golangci-lint-$(GOLANGCI_LINT_VERSION)\n   + \n   + ## Tool Versions\n   + KUSTOMIZE_VERSION ?= v5.3.0\n   + CONTROLLER_TOOLS_VERSION ?= v0.14.0\n   + ENVTEST_VERSION ?= release-0.17\n   + GOLANGCI_LINT_VERSION ?= v1.57.2\n   + \n   + .PHONY: kustomize\n   + kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary.\n   + $(KUSTOMIZE): $(LOCALBIN)\n   + \t$(call go-install-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v5,$(KUSTOMIZE_VERSION))\n   + \n   + .PHONY: controller-gen\n   + controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary.\n   + $(CONTROLLER_GEN): $(LOCALBIN)\n   + \t$(call go-install-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen,$(CONTROLLER_TOOLS_VERSION))\n   + \n   + .PHONY: envtest\n   + envtest: $(ENVTEST) ## Download setup-envtest locally if necessary.\n   + $(ENVTEST): $(LOCALBIN)\n   + \t$(call go-install-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest,$(ENVTEST_VERSION))\n   + \n   + .PHONY: golangci-lint\n   + golangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary.\n   + $(GOLANGCI_LINT): $(LOCALBIN)\n   + \t$(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/cmd/golangci-lint,${GOLANGCI_LINT_VERSION})\n   + \n   + # go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist\n   + # $1 - target path with name of binary (ideally with version)\n   + # $2 - package url which can be installed\n   + # $3 - specific version of package\n   + define go-install-tool\n   + @[ -f $(1) ] || { \\\n   + set -e; \\\n   + package=$(2)@$(3) ;\\\n   + echo \"Downloading $${package}\" ;\\\n   + GOBIN=$(LOCALBIN) go install $${package} ;\\\n   + mv \"$$(echo \"$(1)\" | sed \"s/-$(3)$$//\")\" $(1) ;\\\n   + }\n   + endef\n   ```\n7) [helm/v1] Update the kustomize version in your Makefile:\n   ```diff\n   - curl -sSLo - https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v5.2.1/kustomize_v5.2.1_$(OS)_$(ARCH).tar.gz | \\\n   + curl -sSLo - https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v5.3.0/kustomize_v5.3.0_$(OS)_$(ARCH).tar.gz | \\\n   ```\n\n_See [#6736](https://github.com/operator-framework/operator-sdk/pull/6736) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.37.0.md",
    "content": "---\ntitle: v1.37.0\nweight: 998963000\n---\n\n## Migrate to the Quarkus extension provided bootstrap\n\nFrom now on, you can bootstrap your Quarkus-based operator\nwith the provided Quarkus tools as described in the bootstrapping\ninstructions - https://github.com/quarkiverse/quarkus-operator-sdk?tab=readme-ov-file#bootstrapping-a-project.\n\n_See [#6824](https://github.com/operator-framework/operator-sdk/pull/6824) for more details._\n\n## Remove hybrid-helm v1-alpha support\n\nAs an operator author you can switch to a go-based operator.\n\n_See [#6833](https://github.com/operator-framework/operator-sdk/pull/6833) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.38.0.md",
    "content": "---\ntitle: v1.38.0\nweight: 998962000\n---\n\n## Upgrade K8s versions to use 1.30 and Kubebuilder v4\n\nThis update has a lot of scaffolding changes due to the removal of [kube-rbac-proxy](https://github.com/brancz/kube-rbac-proxy),\nif these migrations become difficult to follow, it might be beneficial to scaffold a net new sample project to compare.\n\n1) [helm/v1, ansible/v1] Update the kustomize version in your Makefile\n   ```diff\n    - curl -sSLo - https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v5.3.0/kustomize_v5.3.0_$(OS)_$(ARCH).tar.gz | \\\n    + curl -sSLo - https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v5.4.2/kustomize_v5.4.2_$(OS)_$(ARCH).tar.gz | \\\n   ```\n\n2) [go/v4] Update your `go.mod` file to upgrade the dependencies and run `go mod tidy` to download them\n   ```go\n    go 1.22.0\n    \n    github.com/onsi/ginkgo/v2 v2.17.1\n    github.com/onsi/gomega v1.32.0\n    k8s.io/api v0.30.1\n    k8s.io/apimachinery v0.30.1\n    k8s.io/client-go v0.30.1\n    sigs.k8s.io/controller-runtime v0.18.4\n   ```\n3) [go/v4] Update your `Makefile` with the below changes:\n   ```diff\n    - ENVTEST_K8S_VERSION = 1.29.0\n    + ENVTEST_K8S_VERSION = 1.30.0\n   ```\n\n   ```diff\n    - KUSTOMIZE ?= $(LOCALBIN)/kustomize-$(KUSTOMIZE_VERSION)\n    - CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen-$(CONTROLLER_TOOLS_VERSION)\n    - ENVTEST ?= $(LOCALBIN)/setup-envtest-$(ENVTEST_VERSION)\n    - GOLANGCI_LINT = $(LOCALBIN)/golangci-lint-$(GOLANGCI_LINT_VERSION)\n    + KUSTOMIZE ?= $(LOCALBIN)/kustomize\n    + CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen\n    + ENVTEST ?= $(LOCALBIN)/setup-envtest\n    + GOLANGCI_LINT = $(LOCALBIN)/golangci-lint\n   ```\n\n   ```diff\n    - KUSTOMIZE_VERSION ?= v5.3.0\n    - CONTROLLER_TOOLS_VERSION ?= v0.14.0\n    - ENVTEST_VERSION ?= release-0.17\n    - GOLANGCI_LINT_VERSION ?= v1.57.2\n    + KUSTOMIZE_VERSION ?= v5.4.2\n    + CONTROLLER_TOOLS_VERSION ?= v0.15.0\n    + ENVTEST_VERSION ?= release-0.18\n    + GOLANGCI_LINT_VERSION ?= v1.59.1\n   ```\n\n   ```diff\n    - $(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/cmd/golangci-lint,${GOLANGCI_LINT_VERSION})\n    + $(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/cmd/golangci-lint,$(GOLANGCI_LINT_VERSION))\n   ```\n\n   ```diff\n    - @[ -f $(1) ] || { \\\n    + @[ -f \"$(1)-$(3)\" ] || { \\\n      echo \"Downloading $${package}\" ;\\\n    + rm -f $(1) || true ;\\\n    - mv \"$$(echo \"$(1)\" | sed \"s/-$(3)$$//\")\" $(1) ;\\\n    - }\n    + mv $(1) $(1)-$(3) ;\\\n    + } ;\\\n    + ln -sf $(1)-$(3) $(1) \n   ```\n\n4) [go/v4] Update your `.golangci.yml` with the below changes:\n   ```diff\n   -  exportloopref\n   +     - ginkgolinter\n         - prealloc\n   +     - revive\n   + \n   + linters-settings:\n   +   revive:\n   +     rules:\n   +       - name: comment-spacings\n   ```\n\n5) [go/v4] Update your `Dockerfile` file with the below changes:\n   ```diff\n   - FROM golang:1.21 AS builder\n   + FROM golang:1.22 AS builder\n   ```\n\n6) [go/v4] Update your `main.go` file with the below changes:\n   ```diff\n        \"sigs.k8s.io/controller-runtime/pkg/log/zap\"\n   +    \"sigs.k8s.io/controller-runtime/pkg/metrics/filters\"\n\n        var enableHTTP2 bool\n   -    flag.StringVar(&metricsAddr, \"metrics-bind-address\", \":8080\", \"The address the metric endpoint binds to.\")\n   +    var tlsOpts []func(*tls.Config)\n   +    flag.StringVar(&metricsAddr, \"metrics-bind-address\", \"0\", \"The address the metrics endpoint binds to. \"+\n   +        \"Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.\")\n        flag.StringVar(&probeAddr, \"health-probe-bind-address\", \":8081\", \"The address the probe endpoint binds to.\")\n        flag.BoolVar(&enableLeaderElection, \"leader-elect\", false,\n            \"Enable leader election for controller manager. \"+\n                \"Enabling this will ensure there is only one active controller manager.\")\n   -    flag.BoolVar(&secureMetrics, \"metrics-secure\", false,\n   -        \"If set the metrics endpoint is served securely\")\n   +    flag.BoolVar(&secureMetrics, \"metrics-secure\", true,\n   +        \"If set, the metrics endpoint is served securely via HTTPS. Use --metrics-secure=false to use HTTP instead.\")\n\n   -    tlsOpts := []func(*tls.Config){}\n\n   +    // Metrics endpoint is enabled in 'config/default/kustomization.yaml'. The Metrics options configure the server.\n   +    // More info:\n   +    // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.18.4/pkg/metrics/server\n   +    // - https://book.kubebuilder.io/reference/metrics.html\n   +    metricsServerOptions := metricsserver.Options{\n   +        BindAddress:   metricsAddr,\n   +        SecureServing: secureMetrics,\n   +        // TODO(user): TLSOpts is used to allow configuring the TLS config used for the server. If certificates are\n   +        // not provided, self-signed certificates will be generated by default. This option is not recommended for\n   +        // production environments as self-signed certificates do not offer the same level of trust and security\n   +        // as certificates issued by a trusted Certificate Authority (CA). The primary risk is potentially allowing\n   +        // unauthorized access to sensitive metrics data. Consider replacing with CertDir, CertName, and KeyName\n   +        // to provide certificates, ensuring the server communicates using trusted and secure certificates.\n   +        TLSOpts: tlsOpts,\n   +    }\n   +\n   +    if secureMetrics {\n   +        // FilterProvider is used to protect the metrics endpoint with authn/authz.\n   +        // These configurations ensure that only authorized users and service accounts\n   +        // can access the metrics endpoint. The RBAC are configured in 'config/rbac/kustomization.yaml'. More info:\n   +        // https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.18.4/pkg/metrics/filters#WithAuthenticationAndAuthorization\n   +        metricsServerOptions.FilterProvider = filters.WithAuthenticationAndAuthorization\n   +    }\n   +\n        mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{\n   -        Scheme: scheme,\n   -        Metrics: metricsserver.Options{\n   -            BindAddress:   metricsAddr,\n   -            SecureServing: secureMetrics,\n   -            TLSOpts:       tlsOpts,\n   -        },\n   +        Scheme:                 scheme,\n   +        Metrics:                metricsServerOptions,\n   ```\n\n7) [go/v4, helm/v1, ansible/v1] Update your `/config/default/kustomization.yaml` file with the below changes:\n   ```diff\n     # [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'.\n     #- ../prometheus\n   + # [METRICS] Expose the controller manager metrics service.\n   + - metrics_service.yaml\n \n   + # Uncomment the patches line if you enable Metrics, and/or are using webhooks and cert-manager\n     patches:\n   - # Protect the /metrics endpoint by putting it behind auth.\n   - # If you want your controller-manager to expose the /metrics\n   - # endpoint w/o any authn/z, please comment the following line.\n   - - path: manager_auth_proxy_patch.yaml\n   + # [METRICS] The following patch will enable the metrics endpoint using HTTPS and the port :8443.\n   + # More info: https://book.kubebuilder.io/reference/metrics\n   + - path: manager_metrics_patch.yaml\n   +   target:\n   +     kind: Deployment\n   ```\n\n8) [go/v4, helm/v1, ansible/v1] Remove `/config/default/manager_auth_proxy_patch.yaml` and `/config/default/manager_config_patch.yaml` files.\n\n9) [go/v4, helm/v1, ansible/v1] Add `/config/default/manager_metrics_patch.yaml` file with the below changes:\n   ```diff\n   # This patch adds the args to allow exposing the metrics endpoint using HTTPS\n   - op: add\n     path: /spec/template/spec/containers/0/args/0\n     value: --metrics-bind-address=:8443\n   ```\n\n10) [helm/v1, ansible/v1] Update `/config/default/manager_metrics_patch.yaml` file with the below changes:\n    ```diff\n    # This patch adds the args to allow securing the metrics endpoint\n    - op: add\n      path: /spec/template/spec/containers/0/args/0\n      value: --metrics-secure\n    # This patch adds the args to allow RBAC-based authn/authz the metrics endpoint\n    - op: add\n      path: /spec/template/spec/containers/0/args/0\n      value: --metrics-require-rbac\n    ```\n\n11) [go/v4, helm/v1, ansible/v1] Add `/config/default/metrics_service.yaml` file with the below changes:\n    ```diff\n    apiVersion: v1\n    kind: Service\n    metadata:\n      labels:\n        control-plane: controller-manager\n        app.kubernetes.io/name: <operator-name>\n        app.kubernetes.io/managed-by: kustomize\n      name: controller-manager-metrics-service\n      namespace: system\n    spec:\n      ports:\n        - name: https\n          port: 8443\n          protocol: TCP\n          targetPort: 8443\n      selector:\n        control-plane: controller-manager\n    ```\n\n12) [go/v4, helm/v1, ansible/v1] Update your `/config/manager/manager.yaml` file with the below changes (**Note: The port for ansible is 6789**):\n    ```diff\n      - --leader-elect\n    + - --health-probe-bind-address=:8081\n    ```\n\n13) [go/v4, helm/v1, ansible/v1] Update your `/config/prometheus/monitor.yaml` file with the below changes:\n    ```diff\n         - path: /metrics\n    -      port: https\n    +      port: https # Ensure this is the name of the port that exposes HTTPS metrics\n           tlsConfig:\n    +        # TODO(user): The option insecureSkipVerify: true is not recommended for production since it disables\n    +        # certificate verification. This poses a significant security risk by making the system vulnerable to\n    +        # man-in-the-middle attacks, where an attacker could intercept and manipulate the communication between\n    +        # Prometheus and the monitored services. This could lead to unauthorized access to sensitive metrics data,\n    +        # compromising the integrity and confidentiality of the information.\n    +        # Please use the following options for secure configurations:\n    +        # caFile: /etc/metrics-certs/ca.crt\n    +        # certFile: /etc/metrics-certs/tls.crt\n    +        # keyFile: /etc/metrics-certs/tls.key\n             insecureSkipVerify: true\n    ```\n\n14) [go/v4, helm/v1, ansible/v1] Remove the following files from `/config/rbac`\n    ```diff\n    - auth_proxy_client_clusterrole.yaml\n    - auth_proxy_role.yaml\n    - auth_proxy_role_binding.yaml\n    - auth_proxy_service.yaml\n    ```\n\n15) [go/v4, helm/v1, ansible/v1] Update your `/config/rbac/kustomization.yaml` file with the below changes:\n    ```diff\n      - leader_election_role_binding.yaml\n    - # Comment the following 4 lines if you want to disable\n    - # the auth proxy (https://github.com/brancz/kube-rbac-proxy)\n    - # which protects your /metrics endpoint.\n    - - auth_proxy_service.yaml\n    - - auth_proxy_role.yaml\n    - - auth_proxy_role_binding.yaml\n    - - auth_proxy_client_clusterrole.yaml\n    + # The following RBAC configurations are used to protect\n    + # the metrics endpoint with authn/authz. These configurations\n    + # ensure that only authorized users and service accounts\n    + # can access the metrics endpoint. Comment the following\n    + # permissions if you want to disable this protection.\n    + # More info: https://book.kubebuilder.io/reference/metrics.html\n    + - metrics_auth_role.yaml\n    + - metrics_auth_role_binding.yaml\n    + - metrics_reader_role.yaml\n    ```\n\n16) [go/v4, helm/v1, ansible/v1] Add `/config/rbac/metrics_auth_role.yaml` file with the below changes:\n    ```diff\n    apiVersion: rbac.authorization.k8s.io/v1\n    kind: ClusterRole\n    metadata:\n      name: metrics-auth-role\n    rules:\n      - apiGroups:\n          - authentication.k8s.io\n        resources:\n          - tokenreviews\n        verbs:\n          - create\n      - apiGroups:\n          - authorization.k8s.io\n        resources:\n          - subjectaccessreviews\n        verbs:\n          - create\n    ```\n\n17) [go/v4, helm/v1, ansible/v1] Add `/config/rbac/metrics_auth_role_binding.yaml` file with the below changes:\n    ```diff\n    apiVersion: rbac.authorization.k8s.io/v1\n    kind: ClusterRoleBinding\n    metadata:\n      name: metrics-auth-rolebinding\n    roleRef:\n      apiGroup: rbac.authorization.k8s.io\n      kind: ClusterRole\n      name: metrics-auth-role\n    subjects:\n      - kind: ServiceAccount\n        name: controller-manager\n        namespace: system\n    ```\n\n18) [go/v4, helm/v1, ansible/v1] Add `/config/rbac/metrics_reader_role.yaml` file with the below changes:\n    ```diff\n    apiVersion: rbac.authorization.k8s.io/v1\n    kind: ClusterRole\n    metadata:\n      name: metrics-reader\n    rules:\n    - nonResourceURLs:\n      - \"/metrics\"\n      verbs:\n      - get\n    ```\n\n_See [#6862](https://github.com/operator-framework/operator-sdk/pull/6862) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.39.0.md",
    "content": "---\ntitle: v1.39.0\nweight: 998961000\n---\n\n## Upgrade K8s versions to use 1.31 and Kubebuilder network-policy scaffolding\n\nThis release contains a decent amount of migrations, but not nearly as many as the [previous versions migrations](https://sdk.operatorframework.io/docs/upgrading-sdk-version/v1.38.0/)\nso this release should be easier to follow.\n\n1) [helm/v1, ansible/v1] Update the kustomize version in your Makefile\n   ```diff\n    - curl -sSLo - https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v5.3.2/kustomize_v5.3.0_$(OS)_$(ARCH).tar.gz | \\\n    + curl -sSLo - https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v5.4.3/kustomize_v5.4.2_$(OS)_$(ARCH).tar.gz | \\\n   ```\n\n2) [go/v4] Update your `go.mod` file to upgrade the dependencies and run `go mod tidy` to download them\n   ```go\n   - github.com/onsi/ginkgo/v2 v2.17.1\n   - github.com/onsi/gomega v1.32.0\n   - k8s.io/api v0.30.1\n   - k8s.io/apimachinery v0.30.1\n   - k8s.io/client-go v0.30.1\n   - sigs.k8s.io/controller-runtime v0.18.4\n   + github.com/onsi/ginkgo/v2 v2.19.0\n   + github.com/onsi/gomega v1.33.1\n   + k8s.io/api v0.31.0\n   + k8s.io/apimachinery v0.31.0\n   + k8s.io/client-go v0.31.0\n   + sigs.k8s.io/controller-runtime v0.19.0\n   ```\n\n3) [go/v4] Update your `Makefile` with the below changes:\n   ```diff\n    - ENVTEST_K8S_VERSION = 1.30.0\n    + ENVTEST_K8S_VERSION = 1.31.0\n   ```\n\n   ```diff\n    - KUSTOMIZE_VERSION ?= v5.4.2\n    - CONTROLLER_TOOLS_VERSION ?= v0.15.0\n    - ENVTEST_VERSION ?= release-0.18\n    + KUSTOMIZE_VERSION ?= v5.4.3\n    + CONTROLLER_TOOLS_VERSION ?= v0.16.1\n    + ENVTEST_VERSION ?= release-0.19\n   ```\n\n4) [go/v4] Update your `main.go` file with the below changes:\n   ```diff\n    - // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.18.4/pkg/metrics/server\n    + // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.19.0/pkg/metrics/server\n\n    - // https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.18.4/pkg/metrics/filters#WithAuthenticationAndAuthorization\n    + // https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.19.0/pkg/metrics/filters#WithAuthenticationAndAuthorization\n   ```\n\n5) [go/v4, helm/v1, ansible/v1] Update your `/config/default/kustomization.yaml` file with the below changes:\n   ```diff\n    +# [NETWORK POLICY] Protect the /metrics endpoint and Webhook Server with NetworkPolicy.\n    +# Only Pod(s) running a namespace labeled with 'metrics: enabled' will be able to gather the metrics.\n    +# Only CR(s) which requires webhooks and are applied on namespaces labeled with 'webhooks: enabled' will\n    +# be able to communicate with the Webhook Server.\n    +#- ../network-policy\n   ```\n\n6) [go/v4, helm/v1, ansible/v1] Add `/config/network-policy/allow-metrics-traffic.yaml`\n   ```diff\n    + # This NetworkPolicy allows ingress traffic\n    + # with Pods running on namespaces labeled with 'metrics: enabled'. Only Pods on those\n    + # namespaces are able to gathering data from the metrics endpoint.\n    + apiVersion: networking.k8s.io/v1\n    + kind: NetworkPolicy\n    + metadata:\n    +   labels:\n    +     app.kubernetes.io/name: <operator-name>\n    +     app.kubernetes.io/managed-by: kustomize\n    +   name: allow-metrics-traffic\n    +   namespace: system\n    + spec:\n    +   podSelector:\n    +     matchLabels:\n    +       control-plane: controller-manager\n    +   policyTypes:\n    +     - Ingress\n    +   ingress:\n    +     # This allows ingress traffic from any namespace with the label metrics: enabled\n    +     - from:\n    +       - namespaceSelector:\n    +           matchLabels:\n    +             metrics: enabled  # Only from namespaces with this label\n    +       ports:\n    +         - port: 8443\n    +           protocol: TCP\n   ```\n\n7) [helm/v1, ansible/v1] Add `/config/network-policy/kustomization.yaml`\n   ```diff\n    + resources:\n    + - allow-metrics-traffic.yaml\n\n8) [go/v4] Add `/config/network-policy/allow-webhook-traffic.yaml`\n   ```diff\n    + # This NetworkPolicy allows ingress traffic to your webhook server running\n    + # as part of the controller-manager from specific namespaces and pods. CR(s) which uses webhooks\n    + # will only work when applied in namespaces labeled with 'webhook: enabled'\n    + apiVersion: networking.k8s.io/v1\n    + kind: NetworkPolicy\n    + metadata:\n    +   labels:\n    +     app.kubernetes.io/name: <operator-name>\n    +     app.kubernetes.io/managed-by: kustomize\n    +   name: allow-webhook-traffic\n    +   namespace: system\n    + spec:\n    +   podSelector:\n    +     matchLabels:\n    +       control-plane: controller-manager\n    +   policyTypes:\n    +     - Ingress\n    +   ingress:\n    +     # This allows ingress traffic from any namespace with the label webhook: enabled\n    +     - from:\n    +       - namespaceSelector:\n    +           matchLabels:\n    +             webhook: enabled # Only from namespaces with this label\n    +       ports:\n    +         - port: 443\n    +           protocol: TCP\n   ```\n\n9) [go/v4] Add `/config/network-policy/kustomization.yaml`\n   ```diff\n    + resources:\n    + - allow-webhook-traffic.yaml\n    + - allow-metrics-traffic.yaml\n   ```\n\n_See [#6878](https://github.com/operator-framework/operator-sdk/pull/6878) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.39.1.md",
    "content": "---\ntitle: v1.39.1\nweight: 998960999\n---\n\nThere are no migrations for this release! 🎉\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.39.2.md",
    "content": "---\ntitle: v1.39.2\nweight: 998960998\n---\n\nThere are no migrations for this release! 🎉\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.4.0.md",
    "content": "---\ntitle: v1.4.0\nweight: 998996000\n---\n\n## Change your operator's finalizer names\n\nThe finalizer name format suggested by [Kubernetes docs](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#finalizers) is `<qualified-group>/<finalizer-name>`, while the format previously documented by Operator SDK docs was `<finalizer-name>.<qualified-group>`. If your operator uses any finalizers with names matching the incorrect format, change them to match the official format. For example, `finalizer.cache.example.com` should be changed to `cache.example.com/finalizer`.\n\n_See [#4472](https://github.com/operator-framework/operator-sdk/pull/4472) for more details._\n\n## For Helm and Ansible projects, fix the helm-operator and ansible-operator URLs in the Makefile\n\n- Helm projects:\n\tOld: `https://github.com/operator-framework/operator-sdk/releases/download/v1.3.0/helm-operator-v1.3.0-$(ARCHOPER)-$(OSOPER)`\n\tNew: `https://github.com/operator-framework/operator-sdk/releases/download/v1.3.1/helm-operator_$(OS)_$(ARCH)`\n- Ansible projects:\n\tOld: `https://github.com/operator-framework/operator-sdk/releases/download/v1.3.0/ansible-operator-v1.3.0-$(ARCHOPER)-$(OSOPER)`\n\tNew: `https://github.com/operator-framework/operator-sdk/releases/download/v1.3.1/ansible-operator_$(OS)_$(ARCH)`\n\n_See [#4407](https://github.com/operator-framework/operator-sdk/pull/4407) for more details._\n\n## For Helm and Ansible projects, fix the `helm-operator`, `ansible-operator`, and `kustomize` Makefile rules\n\nThese rules will download a local binary but not use it if a global binary is present.\nSee the diff in [this PR](https://github.com/operator-framework/operator-sdk/pull/4407) for how to fix this.\n\n_See [#4412](https://github.com/operator-framework/operator-sdk/pull/4407) for more details._\n\n## For Helm-based operators, add Liveness and Readiness probe\n\nNew projects built with the tool will have the probes configured by default. The endpoints `/healthz` and `/readyz` are available now in the image based provided.\nYou can update your pre-existing project to use them. For that update the Dockerfile to use the latest release base image, then add the following to the `manager` container in `config/manager/manager.yaml`:\n```yaml\n  livenessProbe:\n    httpGet:\n      path: /healthz\n      port: 8081\n    initialDelaySeconds: 15\n    periodSeconds: 20\n  readinessProbe:\n    httpGet:\n      path: /readyz\n      port: 8081\n    initialDelaySeconds: 5\n    periodSeconds: 10\n```\n\n_See [#4326](https://github.com/operator-framework/operator-sdk/pull/4326) for more details._\n\n## For Ansible-based operators, add Liveness and Readiness probe\n\nNew projects built with the tool will have the probes configured by default. The endpoints `/healthz` and `/readyz` are available now in the image based provided.\nYou can update your pre-existing project to use them. For that update the Dockerfile to use the latest release base image, then add the following to the `manager` container in `config/manager/manager.yaml`:\n```yaml\n  livenessProbe:\n    httpGet:\n      path: /healthz\n      port: 6789\n    initialDelaySeconds: 15\n    periodSeconds: 20\n  readinessProbe:\n    httpGet:\n      path: /readyz\n      port: 6789\n    initialDelaySeconds: 5\n    periodSeconds: 10\n```\n\n_See [#4326](https://github.com/operator-framework/operator-sdk/pull/4326) for more details._\n\n## (go/v2) Change `go` PROJECT plugin object to `manifests` and `scorecard` objects\n\nThe `manifests` and `scorecard` plugins that create OLM and scorecard manifests, respectively, now have plugin objects that direct `create` subcommands to create related files. While the old `go` plugin configuration object is still supported, these new objects will be useful in the future as configuration options are added to their respective plugins:\n\nOld:\n```yaml\nversion: 3-alpha\n...\nplugins:\n  go.sdk.operatorframework.io/v2-alpha: {}\n```\n\nNew:\n```yaml\nversion: 3-alpha\n...\nplugins:\n  manifests.sdk.operatorframework.io/v2: {}\n  scorecard.sdk.operatorframework.io/v2: {}\n```\n\n_See [#4419](https://github.com/operator-framework/operator-sdk/pull/4419) for more details._\n\n## (ansible/v1, helm/v1) Add `manifests` and `scorecard` plugin objects to your PROJECT\n\nThe `manifests` and `scorecard` plugins that create OLM and scorecard manifests, respectively, now have plugin objects that direct `create` subcommands to create related files. While not necessary to add, these new plugin configuration objects in the PROJECT file will be useful in the future as configuration options are added to their respective plugins:\n```yaml\nversion: 3-alpha\n...\nplugins:\n  manifests.sdk.operatorframework.io/v2: {}\n  scorecard.sdk.operatorframework.io/v2: {}\n```\n\n_See [#4419](https://github.com/operator-framework/operator-sdk/pull/4419) for more details._\n\n## Move positional directory argument `.` in `docker-build` make target\n\nThe directory argument `.` in the `docker-build` make target was moved to the last positional argument to align with `podman`'s expectations, making substitution cleaner.\n\nOld:\n```make\ndocker-build:\n  docker build . -t ${IMG}\n```\n\nNew:\n```make\ndocker-build:\n  docker build -t ${IMG} .\n```\n\nAlternatively, you could replace it programmatically\n```sh\nsed -i 's/docker build . -t ${IMG}/docker build -t ${IMG} ./' $(git grep -l 'docker.*build \\. ')\n```\n\n_See [#4466](https://github.com/operator-framework/operator-sdk/pull/4466) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.40.0.md",
    "content": "---\ntitle: v1.40.0\nweight: 998960000\n---\n\n## Upgrade OPM version to v1.55.0 in the Makefile\n\nUpdate the OPM version in your Makefile to `v1.55.0`:\n\n```makefile \n-const opmVersion = \"v1.23.0\"\n+const opmVersion = \"v1.55.0\"\n```\n\n```makefile \n-       curl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/v1.23.0/$${OS}-$${ARCH}-opm ;\\\n+       curl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/v1.55.0/$${OS}-$${ARCH}-opm ;\\\n```\n\n_See [#6953](https://github.com/operator-framework/operator-sdk/pull/6953) for more details._\n\n## Add a devcontainer for Go-based operators\n\nCreate the devcontainer configuration in the root of the repository\nunder `.devcontainer`. \n1. Create a new directory called `.devcontainer` in the root of your project.\n2. Copy the contents of the [testdata/go/v4/memcached-operator/.devcontainer](https://github.com/operator-framework/operator-sdk/tree/v1.40.0/testdata/go/v4/memcached-operator/.devcontainer)\n   available in the Operator SDK repository for the tag release `v1.40.0`.\n\n_See [#6928](https://github.com/operator-framework/operator-sdk/pull/6928) for more details._\n\n## Add new GitHub actions for Go-based operators\n\nAdd the actions configuration in the `.github/workflows` directory.\nThe new actions are:\n- lint.yaml: Lint the code using golangci-lint\n- test.yaml: Run the tests using go test\n- test-e2e.yaml: Run the e2e tests using go test\nYou can obtain this configuration to be added\nto your project by looking at the files available \nin `testdata/go/v4/memcached-operator/.github/workflows` for this release.\n[testdata/go/v4/memcached-operator/.github/workflows](https://github.com/operator-framework/operator-sdk/tree/v1.40.0/testdata/go/v4/memcached-operator/.github/workflows)\n\n_See [#6928](https://github.com/operator-framework/operator-sdk/pull/6928) for more details._\n\n## Update your project to properly support TLS certificates for webhooks and metrics server\n\n1. Update the `main.go` file in your project to support TLS certificates for webhooks and metrics server.\n\n- Add the new flag definitions to accept custom certificate file paths and names:\n\n    ```go\n    func main() {\n        ...\n        var metricsCertPath, metricsCertName, metricsCertKey string\n        var webhookCertPath, webhookCertName, webhookCertKey string\n        ...\n        flag.StringVar(&webhookCertPath, \"webhook-cert-path\", \"\", \"The directory that contains the webhook certificate.\")\n        flag.StringVar(&webhookCertName, \"webhook-cert-name\", \"tls.crt\", \"The name of the webhook certificate file.\")\n        flag.StringVar(&webhookCertKey, \"webhook-cert-key\", \"tls.key\", \"The name of the webhook key file.\")\n        flag.StringVar(&metricsCertPath, \"metrics-cert-path\", \"\", \"The directory that contains the metrics server certificate.\")\n        flag.StringVar(&metricsCertName, \"metrics-cert-name\", \"tls.crt\", \"The name of the metrics server certificate file.\")\n        flag.StringVar(&metricsCertKey, \"metrics-cert-key\", \"tls.key\", \"The name of the metrics server key file.\")\n    ```\n\n- After this conditional check:\n\n    ```go\n    if !enableHTTP2 {\n        tlsOpts = append(tlsOpts, disableHTTP2)\n    }\n    ```\n\n   Insert the following code to configure certificate watchers for webhooks and metrics:\n\n    ```go\n    var metricsCertWatcher, webhookCertWatcher *certwatcher.CertWatcher\n    webhookTLSOpts := tlsOpts\n\n    if len(webhookCertPath) > 0 {\n        setupLog.Info(\"Initializing webhook certificate watcher using provided certificates\",\n            \"webhook-cert-path\", webhookCertPath, \"webhook-cert-name\", webhookCertName, \"webhook-cert-key\", webhookCertKey)\n\n        var err error\n        webhookCertWatcher, err = certwatcher.New(\n            filepath.Join(webhookCertPath, webhookCertName),\n            filepath.Join(webhookCertPath, webhookCertKey),\n        )\n        if err != nil {\n            setupLog.Error(err, \"Failed to initialize webhook certificate watcher\")\n            os.Exit(1)\n        }\n\n        webhookTLSOpts = append(webhookTLSOpts, func(config *tls.Config) {\n            config.GetCertificate = webhookCertWatcher.GetCertificate\n        })\n    }\n    ```\n\n- Update the webhook server TLS options:\n\n    Replace:\n    ```go\n    TLSOpts: tlsOpts,\n    ```\n\n    With:\n    ```go\n    TLSOpts: webhookTLSOpts,\n    ```\n\n- Before initializing the manager, configure the metrics certificate watcher if metrics certs are provided:\n\n    ```go\n    if len(metricsCertPath) > 0 {\n        setupLog.Info(\"Initializing metrics certificate watcher using provided certificates\",\n            \"metrics-cert-path\", metricsCertPath, \"metrics-cert-name\", metricsCertName, \"metrics-cert-key\", metricsCertKey)\n\n        var err error\n        metricsCertWatcher, err = certwatcher.New(\n            filepath.Join(metricsCertPath, metricsCertName),\n            filepath.Join(metricsCertPath, metricsCertKey),\n        )\n        if err != nil {\n            setupLog.Error(err, \"Failed to initialize metrics certificate watcher\")\n            os.Exit(1)\n        }\n\n        metricsServerOptions.TLSOpts = append(metricsServerOptions.TLSOpts, func(config *tls.Config) {\n            config.GetCertificate = metricsCertWatcher.GetCertificate\n        })\n    }\n\n    mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{\n        ...\n    })\n    ```\n\n- Before calling `AddHealthzCheck`, ensure the certificate watchers are registered with the manager:\n\n    ```go\n    if metricsCertWatcher != nil {\n        setupLog.Info(\"Adding metrics certificate watcher to manager\")\n        if err := mgr.Add(metricsCertWatcher); err != nil {\n            setupLog.Error(err, \"Unable to add metrics certificate watcher to manager\")\n            os.Exit(1)\n        }\n    }\n\n    if webhookCertWatcher != nil {\n        setupLog.Info(\"Adding webhook certificate watcher to manager\")\n        if err := mgr.Add(webhookCertWatcher); err != nil {\n            setupLog.Error(err, \"Unable to add webhook certificate watcher to manager\")\n            os.Exit(1)\n        }\n    }\n\n    if err := mgr.AddHealthzCheck(\"healthz\", healthz.Ping); err != nil {\n        setupLog.Error(err, \"Unable to set up health check\")\n        os.Exit(1)\n    }\n    ```\n\nNote that you can use as reference the `main.go` file available in the\nOperator SDK repository for the tag release `v1.40.0` to see how the code should look like,\nsee:  [testdata/go/v4/memcached-operator/cmd/main.go](https://github.com/operator-framework/operator-sdk/tree/v1.40.0/testdata/go/v4/memcached-operator/cmd/main.go)\n\n2. Add the new certificates in the `config/certmanager` directory:\n\n- Add the new files:\n    - `certificate-metrics.yaml` with the content: [testdata/go/v4/memcached-operator/config/certmanager/certificate-metrics.yaml](https://github.com/operator-framework/operator-sdk/tree/v1.40.0/testdata/go/v4/memcached-operator/config/certmanager/certificate-metrics.yaml)\n    - `issuer.yaml` with the content: [testdata/go/v4/memcached-operator/config/certmanager/issuer.yaml](https://github.com/operator-framework/operator-sdk/tree/v1.40.0/testdata/go/v4/memcached-operator/config/certmanager/issuer.yaml)\n\n- Rename certificate.yaml to `certificate-webhook.yaml`\n\n- Update the `kustomization.yaml` file to include the new files and remove the old ones:\n    Replace: `- certificate.yaml`\n\n    With:\n    ```yaml\n    resources:\n      - certificate-metrics.yaml\n      - certificate-webhook.yaml\n      - issuer.yaml\n    ```\n    **NOTE**: You can see the complete file in the repository for the tag release `v1.40.0`: [testdata/go/v4/memcached-operator/config/certmanager/kustomization.yaml](https://github.com/operator-framework/operator-sdk/tree/v1.40.0/testdata/go/v4/memcached-operator/config/certmanager/kustomization.yaml)\n\n3. Update the `config/default/kustomization.yaml` to allow work with the new options:\n\nUnder `patches` ensure that you have:\n\n```\npatches:\n  ...\n  # Uncomment the patches line if you enable Metrics and CertManager\n  # [METRICS-WITH-CERTS] To enable metrics protected with certManager, uncomment the following line.\n  # This patch will protect the metrics with certManager self-signed certs.\n  - path: cert_metrics_manager_patch.yaml\n    target:\n      kind: Deployment\n\n  # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in\n  # crd/kustomization.yaml\n  - path: manager_webhook_patch.yaml\n    target:\n      kind: Deployment\n...\n```\n\nUnder the replacements section, replace:\n\n```yaml\n  - source: # Add cert-manager annotation to ValidatingWebhookConfiguration, MutatingWebhookConfiguration and CRDs\n    kind: Certificate\n    group: cert-manager.io\n    version: v1\n    name: serving-cert # this name should match the one in certificate.yaml\n    fieldPath: .metadata.namespace # namespace of the certificate CR\n  targets:\n    - select:\n        kind: ValidatingWebhookConfiguration\n      fieldPaths:\n        - .metadata.annotations.[cert-manager.io/inject-ca-from]\n      options:\n        delimiter: '/'\n        index: 0\n        create: true\n    - select:\n        kind: MutatingWebhookConfiguration\n      fieldPaths:\n        - .metadata.annotations.[cert-manager.io/inject-ca-from]\n      options:\n        delimiter: '/'\n        index: 0\n        create: true\n    - select:\n        kind: CustomResourceDefinition\n      fieldPaths:\n        - .metadata.annotations.[cert-manager.io/inject-ca-from]\n      options:\n        delimiter: '/'\n        index: 0\n        create: true\n```    \n\nWith: the code from Kubebuilder samples [testdata/project-v4/config/default/kustomization.yaml](https://github.com/kubernetes-sigs/kubebuilder/blob/v4.5.2/testdata/project-v4/config/default/kustomization.yaml#L60-L155)\n\n**NOTE:** You can see the complete file in the repository for the tag release `v1.40.0`: [testdata/go/v4/memcached-operator/config/default/kustomization.yaml](https://github.com/operator-framework/operator-sdk/tree/v1.40.0/testdata/go/v4/memcached-operator/config/default/kustomization.yaml)\n\n4. Add the new file to allow patch the certs for the metrics: [testdata/go/v4/memcached-operator/config/default/cert_metrics_manager_patch.yaml](https://github.com/operator-framework/operator-sdk/tree/v1.40.0/testdata/go/v4/memcached-operator/config/default/cert_metrics_manager_patch.yaml)\n5. Replace the content of `config/default/manager_webhook_patch.yaml` with:  [testdata/go/v4/memcached-operator/config/default/manager_webhook_patch.yaml](https://github.com/operator-framework/operator-sdk/tree/v1.40.0/testdata/go/v4/memcached-operator/config/default/manager_webhook_patch.yaml)\n6. Update the `config/manager/manager.yaml` to include the ports and volumes to allow the patch to work properly:\n\n```\n...\n         env:\n         - name: MEMCACHED_IMAGE\n           value: memcached:1.4.36-alpine\n+        ports: []\n...\n```\n\n```\n...\n           requests:\n             cpu: 10m\n             memory: 64Mi\n+        volumeMounts: []\n+      volumes: []\n  serviceAccountName: controller-manager\n  terminationGracePeriodSeconds: 10\n...\n```\n\n_See [#6928](https://github.com/operator-framework/operator-sdk/pull/6928) for more details._\n\n## Update your project to properly support TLS for Prometheus scraping\n\n**Changes required under the hood `config/prometheus/`**\n\n- 1. Update the `config/prometheus/kustomization.yaml` add at the bottom:\n\n```yaml\n      # [PROMETHEUS-WITH-CERTS] The following patch configures the ServiceMonitor in ../prometheus\n      # to securely reference certificates created and managed by cert-manager.\n      # Additionally, ensure that you uncomment the [METRICS WITH CERTMANAGER] patch under config/default/kustomization.yaml\n      # to mount the \"metrics-server-cert\" secret in the Manager Deployment.\n      #patches:\n      #  - path: monitor_tls_patch.yaml\n      #    target:\n      #      kind: ServiceMonitor\n```\n\n- 2. Add the file [config/prometheus/monitor_tls_patch.yaml](https://github.com/operator-framework/operator-sdk/tree/v1.40.0/testdata/go/v4/memcached-operator/config/prometheus/monitor_tls_patch.yaml) to do the patch for the ServiceMonitor.\n\n_See [#6928](https://github.com/operator-framework/operator-sdk/pull/6928) for more details._\n\n## Update your project to properly support CA injection for CRDs with conversion webhooks\n\n**Changes required under the hood `config/crd/`**\n\n- 1. Update the `config/crd/kustomization.yaml` for the file to include the new marker\n`+kubebuilder:scaffold:crdkustomizewebhookpatch` for the tool be able to inject\nthe path for any new CRD that is created with the `--conversion` flag.\n- 2. Ensure that under the patches section you have only patches for the CRDs which\nare created with the `--conversion` flag.\n- 3. Remove the files prefixed with `cainjection_<kind>.yaml`. You should have only\nthe files prefixed with `webhookpatch_<kind>.yaml` for the CRDs that have the\n`--conversion` flag. ([example](https://github.com/kubernetes-sigs/kubebuilder/tree/v4.5.2/testdata/project-v4/config/crd/patches))\n\n**Changes required under the hood `config/default/`**\n\n- 1. Update the `config/default/kustomization.yaml` for the file to include the new marker\n`+kubebuilder:scaffold:crdkustomizecainjectionns` for the tool be able to inject for any new CRD\nthat is created with the `--conversion` flag as well to have commented the default replacement.\nFor further information see an example in Kubebuilder testdata samples [testdata/project-v4/config/default/kustomization.yaml](https://github.com/kubernetes-sigs/kubebuilder/blob/7c707052daa2e8bd51f47548c02710b1f1f7a77e/testdata/project-v4/config/default/kustomization.yaml#L157-L252).\n\n**NOTE:** You can see the complete file in the repository for the tag release `v1.40.0`: [testdata/go/v4/memcached-operator/config/default/kustomization.yaml](https://github.com/operator-framework/operator-sdk/tree/v1.40.0/testdata/go/v4/memcached-operator/config/default/kustomization.yaml)\n\n_See [#6928](https://github.com/operator-framework/operator-sdk/pull/6928) for more details._\n\n## Use `.Named(\"<Kind>\")` in SetupWithManager for controller registration\n\nTo improve clarity and avoid naming collisions in multi-group Go-based operator projects,\neach controller's `SetupWithManager` call now includes an explicit `.Named(\"<Kind>\")` declaration.\n\nExample change:\n```go\nfunc (r *DeploymentReconciler) SetupWithManager(mgr ctrl.Manager) error {\n  return ctrl.NewControllerManagedBy(mgr).\n    For(&appsv1.Deployment{}).\n    Named(\"apps-deployment\").\n    Complete(r)\n  }\n```\n\nThis ensures controller names are unique and consistent across different APIs in multi-group scenarios,\nwhich improves controller lifecycle management and logging.\n\n_See [#6928](https://github.com/operator-framework/operator-sdk/pull/6928) for more details._\n\n## ENVTEST version automation and improved test binary discovery\n\nThe SDK now automates the setup of ENVTEST for Go-based operators by dynamically deriving\nthe required versions from `go.mod` rather than requiring manual updates in the Makefile.\n\n1. Update the `Makefile`:\n- The variables `ENVTEST_VERSION` and `ENVTEST_K8S_VERSION` are now computed using `go list`:\n  ```makefile\n  ENVTEST_VERSION := $(shell go list -m -f \"{{ .Version }}\" sigs.k8s.io/controller-runtime | awk -F'[v.]' '{printf \"release-%d.%d\", $$2, $$3}')\n  ENVTEST_K8S_VERSION := $(shell go list -m -f \"{{ .Version }}\" k8s.io/api | awk -F'[v.]' '{printf \"1.%d\", $$3}')\n  ```\n- A new target `setup-envtest` was introduced to automatically install the binaries:\n  ```makefile\n  .PHONY: setup-envtest\n  setup-envtest:\n  \t@$(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path || { \\\n  \t  echo \"Error setting up envtest\"; exit 1; }\n  ```\n- The `test` target now depends on `setup-envtest` to ensure binaries are ready before running tests.\n\n2. Update the suite_test.go files for controllers and webhooks:\nIn each `internal/controller/suite_test.go` and `internal/webhook/<version>/webhook/suite_test.go` file:\n- A new helper function `getFirstFoundEnvTestBinaryDir()` was added:\n  ```go\n  func getFirstFoundEnvTestBinaryDir() string {\n    basePath := filepath.Join(\"..\", \"..\", \"..\", \"bin\", \"k8s\")\n    entries, err := os.ReadDir(basePath)\n    if err != nil {\n        logf.Log.Error(err, \"Failed to read directory\", \"path\", basePath)\n        return \"\"\n    }\n    for _, entry := range entries {\n        if entry.IsDir() {\n            return filepath.Join(basePath, entry.Name())\n        }\n    }\n    return \"\"\n  }\n  ```\n- `testEnv.BinaryAssetsDirectory` now uses this helper to locate installed ENVTEST binaries:\n  ```go\n  testEnv = &envtest.Environment{\n    BinaryAssetsDirectory: getFirstFoundEnvTestBinaryDir(),\n    ...\n  }\n  ```\n\n_See [#6928](https://github.com/operator-framework/operator-sdk/pull/6928) for more details._\n\n## Replace `exportloopref` with `copyloopvar` in `.golangci.yaml`\n\nThe `exportloopref` linter has been deprecated in recent versions of GolangCI-Lint.\nIt is now replaced with the more accurate and actively maintained `copyloopvar` linter.\n\nUpdate your `.golangci.yaml` file by replacing:\n```yaml\n- exportloopref\n```\nWith:\n```yaml\n- copyloopvar\n```\n\n_See [#6928](https://github.com/operator-framework/operator-sdk/pull/6928) for more details._\n\n## Add `lint-config` target to Makefile to verify linter configuration\n\nThe target uses the `config verify` subcommand provided by `golangci-lint`:\n\n```makefile\n.PHONY: lint-config\nlint-config: golangci-lint ## Verify golangci-lint linter configuration\n\t$(GOLANGCI_LINT) config verify\n```\n\n_See [#6928](https://github.com/operator-framework/operator-sdk/pull/6928) for more details._\n\n## Upgrade to Go 1.23 and Kubernetes v0.32.1 dependencies\n\n1. Update your `go.mod` to reflect the new versions:\n```go\ngo 1.23\n\nrequire (\n  github.com/onsi/ginkgo/v2 v2.22.0\n  github.com/onsi/gomega v1.36.1\n  k8s.io/api v0.32.1\n  k8s.io/apimachinery v0.32.1\n  k8s.io/client-go v0.32.1\n  k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738\n  sigs.k8s.io/controller-runtime v0.20.4\n)\n```\n\n2. Update the Go toolchain in your `Dockerfile` to match:\n```dockerfile\nFROM golang:1.23 AS builder\n```\n\n_See [#6928](https://github.com/operator-framework/operator-sdk/pull/6928) for more details._\n\n## You must change your webhooks implementation to be able to use controller-runtime v0.20.0+\n\nIf you have no webhooks, you can skip this migration. Otherwise, ensure that you check the described\nsteps to update your project in the release notes of Kubebuilder `v4.3.0` release: https://github.com/kubernetes-sigs/kubebuilder/releases/tag/v4.3.0\n\n_See [#6928](https://github.com/operator-framework/operator-sdk/pull/6928) for more details._\n\n## Add `app.kubernetes.io/name` label to your manifests\n\nThe Operator SDK now adds the `app.kubernetes.io/name` label to scaffolded Kubernetes\nmanifests such as Deployments, Services, and RBAC resources. This label aligns with\nKubernetes labeling conventions and improves compatibility with observability and automation tools.\n\nIf upgrading from a previous version, you may want to add the following label manually\nto your existing manifests:\n\n```yaml\nmetadata:\n  labels:\n    app.kubernetes.io/name: <your-app-name>\n```\n\n_See [#6928](https://github.com/operator-framework/operator-sdk/pull/6928) for more details._\n\n## With you wish manually add those roles to your project\n\nSee the permissions and RBAC generate as an example to know how properly\ncreate those files for each CRD you have in your project by looking at the\nsample in the repository for the tag release `v1.40.0`: [testdata/go/v4/memcached-operator/config/rbac](https://github.com/operator-framework/operator-sdk/tree/v1.40.0/testdata/go/v4/memcached-operator/config/rbac)\n\n_See [#6928](https://github.com/operator-framework/operator-sdk/pull/6928) for more details._\n\n## With you wish manually add those roles to your project\n\nSee the permissions and RBAC generate as an example to know how properly\ncreate those files for each CRD you have in your project by looking at the\nsample in the repository for the tag release `v1.40.0`: [testdata/go/v4/memcached-operator/config/rbac](https://github.com/operator-framework/operator-sdk/tree/v1.40.0/testdata/go/v4/memcached-operator/config/rbac)\n\n_See [#6928](https://github.com/operator-framework/operator-sdk/pull/6928) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.41.0.md",
    "content": "---\ntitle: v1.41.0\nweight: 998959000\n---\n\n## Upgrade Go version to 1.24\n\nUpdate the Go version used to `1.24`. This affects:\n\n**Dockerfile:**\n```diff\n- FROM golang:1.23 AS builder\n+ FROM golang:1.24 AS builder\n```\n\n**.devcontainer/devcontainer.json:**\n```diff\n- \"image\": \"golang:1.23\",\n+ \"image\": \"golang:1.24\",\n```\n\n**go.mod:**\n```diff\n- go 1.23.0\n+ go 1.24.0\n```\n\n_See [#6954](https://github.com/operator-framework/operator-sdk/pull/6954) for more details._\n\n## Upgrade golangci-lint and use v2 config\n\nUpdate golangci-lint usage across the project:\n\n**Makefile:**\n```diff\n- GOLANGCI_LINT_VERSION ?= v1.63.4\n+ GOLANGCI_LINT_VERSION ?= v2.1.0\n\n- $(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/cmd/golangci-lint,$(GOLANGCI_LINT_VERSION))\n+ $(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/v2/cmd/golangci-lint,$(GOLANGCI_LINT_VERSION))\n```\n\n**GitHub Actions Workflow:**\n```diff\n- uses: golangci/golangci-lint-action@v6\n+ uses: golangci/golangci-lint-action@v8\n```\n\n**.golangci.yml:**  \nConvert to v2 layout with keys like `version`, `linters`, `settings`, `formatters`, `exclusions`.\nYou might want to copy and paste the file from the Memcached sample from the tag release `v1.40.0`: [testdata/go/v4/memcached-operator/.golangci.yml](https://github.com/operator-framework/operator-sdk/tree/v1.40.0/testdata/go/v4/memcached-operator/.golangci.yml)\n\n_See [#6954](https://github.com/operator-framework/operator-sdk/pull/6954) for more details._\n\n## Upgrade controller-gen to `v0.18.0`\n\nUpdate controller-gen tooling and annotations:\n\n**Makefile:**\n```diff\n- CONTROLLER_TOOLS_VERSION ?= v0.17.2\n+ CONTROLLER_TOOLS_VERSION ?= v0.18.0\n```\n\nRun `make generate` to regenerate code and manifests with the new version.\n\n_See [#6954](https://github.com/operator-framework/operator-sdk/pull/6954) for more details._\n\n## Upgrade controller-runtime to `v0.21.0`\n\nUpdate the `go.mod` import:\n```diff\n- sigs.k8s.io/controller-runtime v0.20.4\n+ sigs.k8s.io/controller-runtime v0.21.0\n```\n\nRun `go mod tidy` to upgrade the k8s dependencies.\n\n_See [#6954](https://github.com/operator-framework/operator-sdk/pull/6954) for more details._\n\n## Add cluster setup for e2e tests in Makefile and update CI workflow\n\nRemove direct Kind commands in GitHub workflows:\n\n**Removed:**\n```yaml\n- name: Create kind cluster\n  run: kind create cluster\n```\n\n**Added to Makefile:**\n```makefile\nKIND_CLUSTER ?= <project-name>-test-e2e\n\n.PHONY: setup-test-e2e\nsetup-test-e2e: ## Set up a Kind cluster for e2e tests if it does not exist\n  @command -v $(KIND) >/dev/null 2>&1 || { \\\n    echo \"Kind is not installed. Please install Kind manually.\"; \\\n    exit 1; \\\n  }\n  @case \"$$($(KIND) get clusters)\" in \\\n    *\"$(KIND_CLUSTER)\"*) \\\n      echo \"Kind cluster '$(KIND_CLUSTER)' already exists. Skipping creation.\" ;; \\\n    *) \\\n    echo \"Creating Kind cluster '$(KIND_CLUSTER)'...\"; \\\n    $(KIND) create cluster --name $(KIND_CLUSTER) ;; \\\n  esac\n\n.PHONY: cleanup-test-e2e\ncleanup-test-e2e:\n\t$(KIND) delete cluster --name $(KIND_CLUSTER)\n```\n\nUpdate `test-e2e` target to call these appropriately.\n\n_See [#6954](https://github.com/operator-framework/operator-sdk/pull/6954) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.42.0.md",
    "content": "---\ntitle: v1.42.0\nweight: 998958000\n---\n\nThere are no migrations for this release! 🎉\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.42.1.md",
    "content": "---\ntitle: v1.42.1\nweight: 998957999\n---\n\nThere are no migrations for this release! 🎉\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.42.2.md",
    "content": "---\ntitle: v1.42.2\nweight: 998957998\n---\n\nThere are no migrations for this release! 🎉\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.5.0.md",
    "content": "---\ntitle: v1.5.0\nweight: 998995000\n---\n\n## For Go-based operators, migrate your project to use the project version stable.\n\nThe PROJECT version config file represents the project configuration. It reach the maturate stability and it will store the data used to do the scaffolds. The motivation for this behaviour is to allow tools and helpers in the future such as to make easier the process to update the projects to use upper versions. More info: TBD. //TODO: add link for docs (see the PR kubernetes-sigs/kubebuilder#1916)\n\n_See [#4402](https://github.com/operator-framework/operator-sdk/pull/4402) for more details._\n\n## PROJECT config version 3-alpha must be upgraded to 3.\n\nPROJECT config version 3-alpha has been stabilized as [version 3](https://github.com/kubernetes-sigs/kubebuilder/blob/master/docs/book/src/migration/legacy/manually_migration_guide_v2_v3.md) (the `version` key in your PROJECT file), and contains a set of config fields sufficient to fully describe a project. While this change is not technically breaking because the spec at that version was alpha, it was used by default in `operator-sdk` commands so should be marked as breaking and have a convenient migration path. The `alpha config-3alpha-to-3` command will convert most of your PROJECT file from version 3-alpha to 3, and leave comments with directions where automatic conversion is not possible:\n\n```console\n$ cat PROJECT\nversion: 3-alpha\nresources:\n- crdVersion: v1\n...\n\n$ operator-sdk alpha config-3alpha-to-3\nYour PROJECT config file has been converted from version 3-alpha to 3. Please make sure all config data is correct.\n$ cat PROJECT\nversion: \"3\" \nesources:\n- api:\n  crdVersion: v1\n...\n```\n\n_See [#4613](https://github.com/operator-framework/operator-sdk/pull/4613) for more details._\n\n## (go/v3) Upgrade controller-runtime to v0.7.2.\n\nIn your go.mod file, upgrade `sigs.k8s.io/controller-runtime` to v0.7.2.\n\n_See [#4626](https://github.com/operator-framework/operator-sdk/pull/4626) for more details._\n\n## (go/v3) Add a `system:controller-manager` ServiceAccount to your project.\n\nA non-default ServiceAccount `controller-manager` is scaffolded on `operator-sdk init`, to improve security for operators installed in shared namespaces. To add this ServiceAccount to your project, do the following:\n\n```sh\n# Create the ServiceAccount.\ncat <<EOF > config/rbac/service_account.yaml\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: controller-manager\n  namespace: system\nEOF\n\n# Add it to the list of RBAC resources.\necho \"- service_account.yaml\" >> config/rbac/kustomization.yaml\n\n# Update all RoleBinding and ClusterRoleBinding subjects that reference the operator's ServiceAccount.\nfind config/rbac -name *_binding.yaml -exec sed -i -E 's/  name: default/  name: controller-manager/g' {} \\;\n\n# Add the ServiceAccount name to the manager Deployment's spec.template.spec.serviceAccountName.\nsed -i -E 's/([ ]+)(terminationGracePeriodSeconds:)/\\1serviceAccountName: controller-manager\\n\\1\\2/g' config/manager/manager.yaml\n```\n\nThe changes should look like:\n```diff \n# config/manager/manager.yaml\n           requests:\n             cpu: 100m\n             memory: 20Mi\n+      serviceAccountName: controller-manager\n       terminationGracePeriodSeconds: 10\n\n# config/rbac/auth_proxy_role_binding.yaml\n   name: proxy-role\n subjects:\n - kind: ServiceAccount\n-  name: default \n+  name: controller-manager\n   namespace: system\n\n# config/rbac/kustomization.yaml\n resources:\n+- service_account.yaml\n - role.yaml\n - role_binding.yaml\n - leader_election_role.yaml\n\n# config/rbac/leader_election_role_binding.yaml\n   name: leader-election-role\n subjects:\n - kind: ServiceAccount\n-  name: default \n+  name: controller-manager\n   namespace: system\n\n# config/rbac/role_binding.yaml\n   name: manager-role\n subjects:\n - kind: ServiceAccount\n-  name: default \n+  name: controller-manager\n   namespace: system\n\n# config/rbac/service_account.yaml\n+apiVersion: v1\n+kind: ServiceAccount\n+metadata:\n+  name: controller-manager\n+  namespace: system\n```\n\n_See [#4626](https://github.com/operator-framework/operator-sdk/pull/4626) for more details._\n\n## (ansible/v1, helm/v1) Swap the paths of liveness/readiness probes in `config/manager/manager.yaml`.\n\nThe liveness and readiness probe endpoints were incorrectly named, although this mismatch will not affect their behavior. To fix, swap the `readinessProbe` and `livenessProbe` HTTP paths in `config/manager/manager.yaml`:\n\n```yaml\n  livenessProbe:\n    httpGet:\n      path: /healthz\n      port: 6789\n    initialDelaySeconds: 15\n    periodSeconds: 20\n  readinessProbe:\n    httpGet:\n      path: /readyz\n      port: 6789\n    initialDelaySeconds: 5\n    periodSeconds: 10\n```\n\n_See [#4546](https://github.com/operator-framework/operator-sdk/pull/4546) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.6.0.md",
    "content": "---\ntitle: v1.6.0\nweight: 998994000\n---\n\n## (ansible/v1, helm/v1) Optional: configure `ansible-operator` and `helm-operator` with a component config.\n\nTo add this option your project you will need to: \n- Create the file [config/default/manager_config_patch.yaml](https://github.com/operator-framework/operator-sdk/blob/2a1bd03/testdata/ansible/memcached-operator/config/default/manager_config_patch.yaml). \n- Create the file [config/manager/controller_manager_config.yaml](https://github.com/operator-framework/operator-sdk/blob/2a1bd03/testdata/ansible/memcached-operator/config/manager/controller_manager_config.yaml). \n- Update the `config/default/kustomization.yaml` by adding the following to `resources`:\n  ```yaml\n  resources:\n  ...\n  - manager_config_patch.yaml\n  ```\n- Update the `config/manager/kustomization.yaml` by adding:\n```yaml\n  generatorOptions:\n    disableNameSuffixHash: true\n\n  configMapGenerator:\n  - files:\n    - controller_manager_config.yaml\n    name: manager-config\n  apiVersion: kustomize.config.k8s.io/v1beta1\n  kind: Kustomization\n  images:\n  - name: controller\n    newName: quay.io/example/memcached-operator\n    newTag: v0.0.1\n```\n\n_See [#4701](https://github.com/operator-framework/operator-sdk/pull/4701) for more details._\n\n## (ansible/v1, helm/v1) Add Role rules for leader election.\n\nAdd the rule for the `apiGroups` `coordination.k8s.io` and the resource `leases` in config/rbac/leader_election_role.yaml:\n```yaml\nrules:\n  - apiGroups:\n      - \"\"\n      - coordination.k8s.io\n    resources:\n      - configmaps\n      - leases\n```\n\n_See [#4701](https://github.com/operator-framework/operator-sdk/pull/4701) for more details._\n\n## (ansible/v1) Update Ansible collections\n\nIn your requirements.yml, change the `version` field for community.kubernetes to `1.2.1`, and the `version` field for `operator_sdk.util` to `0.2.0`.\n\n_See [#4734](https://github.com/operator-framework/operator-sdk/pull/4734) for more details._\n\n## (helm/v1) Replace deprecated leader election and metrics address flags\n\nReplace deprecated flags `--enable-leader-election` and `--metrics-addr` with `--leader-elect` and `--metrics-bind-address`, respectively.\n\n_See [#4654](https://github.com/operator-framework/operator-sdk/pull/4654) for more details._\n\n## (helm/v1) Explicitly set `--health-probe-bind-address` in the manager's auth proxy patch.\n\nAdd the arg `--health-probe-bind-address=:8081` to the `config/default/manager_auth_proxy_patch.yaml`:\n```yaml\nspec:\n  template:\n    spec:\n      containers:\n      - name: manager\n        args:\n        - \"--health-probe-bind-address=:8081\"\n        ...\n```\n\n_See [#4654](https://github.com/operator-framework/operator-sdk/pull/4654) for more details._\n\n## (ansible/v1) Explicitly set `--health-probe-bind-address` in the manager's auth proxy patch.\n\nAdd the arg `--health-probe-bind-address=:6789` to the `config/default/manager_auth_proxy_patch.yaml`:\n```yaml\nspec:\n  template:\n    spec:\n      containers:\n      - name: manager\n        args:\n        - \"--health-probe-bind-address=:6789\"\n        ...\n```\n\n_See [#4654](https://github.com/operator-framework/operator-sdk/pull/4654) for more details._\n\n## (helm/v1, ansible/v1) Add `help` target to Makefile.\n\nAnsible/Helm projects now provide a Makefile `help` target, similar to a `--help` flag. You can copy and paste this target from the relevant sample's Makefile ([helm](https://github.com/operator-framework/operator-sdk/blob/v1.5.0/testdata/helm/memcached-operator/Makefile), [ansible](https://github.com/operator-framework/operator-sdk/blob/v1.5.0/testdata/ansible/memcached-operator/Makefile)).\n\n_See [#4660](https://github.com/operator-framework/operator-sdk/pull/4660) for more details._\n\n## (ansible/v1, helm/v1) Add `securityContext`'s to your manager's Deployment.\n\nIn `config/manager/manager.yaml`, add the following security contexts:\n```yaml\nspec:\n  ...\n  template:\n    ...\n    spec:\n      securityContext:\n        runAsNonRoot: true\n      containers:\n      - name: manager\n        securityContext:\n          allowPrivilegeEscalation: false\n```\n\n_See [#4655](https://github.com/operator-framework/operator-sdk/pull/4655) for more details._\n\n## (manifests/v2) Add a kustomize patch to remove the cert-manager volume/volumeMount from your CSV\n\nOLM does [not yet support cert-manager](https://olm.operatorframework.io/docs/advanced-tasks/adding-admission-and-conversion-webhooks/#certificate-authority-requirements), so a JSON patch was added to remove this volume and mount such that OLM can itself create and manage certs for your Operator.\nIn `config/manifests/kustomization.yaml`, add the following:\n```yaml\n#patchesJson6902:\n#- target:\n#    group: apps\n#    version: v1\n#    kind: Deployment\n#    name: controller-manager\n#    namespace: system\n#  patch: |-\n#    # Remove the manager container's \"cert\" volumeMount, since OLM will create and mount a set of certs.\n#    # Update the indices in this path if adding or removing containers/volumeMounts in the manager's Deployment.\n#    - op: remove\n#      path: /spec/template/spec/containers/1/volumeMounts/0\n#    # Remove the \"cert\" volume, since OLM will create and mount a set of certs.\n#    # Update the indices in this path if adding or removing volumes in the manager's Deployment.\n#    - op: remove\n#      path: /spec/template/spec/volumes/0\n```\n\nIf you have configured your operator to use webhooks, add this YAML block uncommented.\n\n_See [#4623](https://github.com/operator-framework/operator-sdk/pull/4623) for more details._\n\n## (go/v2, go/v3, ansible/v1, helm/v1) Add scheme, token, and TLS config to the Prometheus `ServiceMonitor` metrics endpoint.\n\nThe `/metrics` endpoint, while specifying the `https` port on the manager Pod, was not actually configured to serve over https because no tlsConfig was set. Since kube-rbac-proxy secures this endpoint as a manager sidecar, using the service account token mounted into the Pod by default corrects this problem.\nThe changes should look like:\n```diff\n# config/prometheus/monitor.yaml\nspec:\n   endpoints:\n     - path: /metrics\n       port: https\n+      scheme: https\n+      bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token\n+      tlsConfig:\n+        insecureSkipVerify: true\n   selector:\n     matchLabels:\n       control-plane: controller-manager\n```\n**Note:** if you have removed kube-rbac-proxy from your project, make sure to secure the `/metrics` endpoint using a proper [TLS configuration](https://prometheus.io/docs/guides/tls-encryption/).\n\n_See [#4680](https://github.com/operator-framework/operator-sdk/pull/4680) for more details._\n\n## (go/v2, go/v3, ansible/v1, helm/v1) Add `opm` and `catalog-build` Makefile targets\n\nThe `opm` and `catalog-build` Makefile targets were added so operator developers who want to create their own catalogs for their operator or add their operator's bundle(s) to an existing catalog can do so. If this sounds like you, add the following lines to the bottom of your Makefile:\n```make\n.PHONY: opm\nOPM = ./bin/opm\nopm:\nifeq (,$(wildcard $(OPM)))\nifeq (,$(shell which opm 2>/dev/null))\n\t@{ \\\n\tset -e ;\\\n\tmkdir -p $(dir $(OPM)) ;\\\n\tcurl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/v1.19.1/$(OS)-$(ARCH)-opm ;\\\n\tchmod +x $(OPM) ;\\\n\t}\nelse \nOPM = $(shell which opm)\nendif\nendif\nBUNDLE_IMGS ?= $(BUNDLE_IMG) \nCATALOG_IMG ?= $(IMAGE_TAG_BASE)-catalog:v$(VERSION) ifneq ($(origin CATALOG_BASE_IMG), undefined) FROM_INDEX_OPT := --from-index $(CATALOG_BASE_IMG) endif \n.PHONY: catalog-build\ncatalog-build: opm\n\t$(OPM) index add --container-tool docker --mode semver --tag $(CATALOG_IMG) --bundles $(BUNDLE_IMGS) $(FROM_INDEX_OPT)\n\n.PHONY: catalog-push\ncatalog-push: ## Push the catalog image.\n\t$(MAKE) docker-push IMG=$(CATALOG_IMG)\n```\nIf updating a Go operator project, additionally add the following Makefile variables:\n```make\nOS = $(shell go env GOOS)\nARCH = $(shell go env GOARCH)\n```\n\n_See [#4406](https://github.com/operator-framework/operator-sdk/pull/4406) for more details._\n\n## (go/v2, go/v3, ansible/v1, helm/v1) Changed `BUNDLE_IMG` and added `IMAGE_TAG_BASE` Makefile variables\n\nThe following Makefile changes were made to allow `make bundle-build bundle-push catalog-build catalog-push` and encode image repo/namespace information in the Makefile by default:\n```diff\n+IMAGE_TAG_BASE ?= <registry>/<operator name>\n+ \n-BUNDLE_IMG ?= controller-bundle:$(VERSION)\n+BUNDLE_IMG ?= $(IMAGE_TAG_BASE)-bundle:v$(VERSION)\n```\n\nFor example, if `IMAGE_TAG_BASE ?= foo/bar-operator` then running `make bundle-build bundle-push catalog-build catalog-push` would build `foo/bar-operator-bundle:v0.0.1` and `foo/bar-operator-catalog:v0.0.1` then push them to the `docker.io/foo` namespaced registry.\n\n_See [#4406](https://github.com/operator-framework/operator-sdk/pull/4406) for more details._\n\n## (ansible/v1, helm/v1) Add the `controller-manager` ServiceAccount to your project.\n\nA non-default ServiceAccount `controller-manager` is scaffolded on `operator-sdk init`, to improve security for operators installed in shared namespaces. To add this ServiceAccount to your project, do the following:\n```sh\n# Create the ServiceAccount.\ncat <<EOF > config/rbac/service_account.yaml apiVersion: v1 \nkind: ServiceAccount\nmetadata:\n  name: controller-manager\n  namespace: system\nEOF\n# Add it to the list of RBAC resources.\necho \"- service_account.yaml\" >> config/rbac/kustomization.yaml\n# Update all RoleBinding and ClusterRoleBinding subjects that reference the operator's ServiceAccount.\nfind config/rbac -name *_binding.yaml -exec sed -i -E 's/  name: default/  name: controller-manager/g' {} \\; # Add the ServiceAccount name to the manager Deployment's spec.template.spec.serviceAccountName. sed -i -E 's/([ ]+)(terminationGracePeriodSeconds:)/\\1serviceAccountName: controller-manager\\n\\1\\2/g' config/manager/manager.yaml\n``` \n\nThe changes should look like: \n\n```diff \n# config/manager/manager.yaml\n           requests:\n             cpu: 100m\n             memory: 20Mi\n+      serviceAccountName: controller-manager\n       terminationGracePeriodSeconds: 10\n# config/rbac/auth_proxy_role_binding.yaml\n   name: proxy-role\n subjects:\n - kind: ServiceAccount\n-  name: default \n+  name: controller-manager\n   namespace: system\n# config/rbac/kustomization.yaml\n resources:\n+- service_account.yaml\n - role.yaml\n - role_binding.yaml\n - leader_election_role.yaml\n# config/rbac/leader_election_role_binding.yaml\n   name: leader-election-role\n subjects:\n - kind: ServiceAccount\n-  name: default\n+  name: controller-manager\n   namespace: system\n# config/rbac/role_binding.yaml\n   name: manager-role\n subjects:\n - kind: ServiceAccount\n-  name: default \n+  name: controller-manager\n   namespace: system\n# config/rbac/service_account.yaml \n+apiVersion: v1 \n+kind: ServiceAccount \n+metadata: \n+  name: controller-manager \n+  namespace: system\n```\n\n_See [#4653](https://github.com/operator-framework/operator-sdk/pull/4653) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.6.1.md",
    "content": "---\ntitle: v1.6.1\nweight: 998994000\n---\n\n## (ansible/v1, helm/v1) Optional: configure `ansible-operator` and `helm-operator` with a component config.\n\nTo add this option your project you will need to: \n- Create the file [config/default/manager_config_patch.yaml](https://github.com/operator-framework/operator-sdk/blob/2a1bd03/testdata/ansible/memcached-operator/config/default/manager_config_patch.yaml). \n- Create the file [config/manager/controller_manager_config.yaml](https://github.com/operator-framework/operator-sdk/blob/2a1bd03/testdata/ansible/memcached-operator/config/manager/controller_manager_config.yaml). \n- Update the `config/default/kustomization.yaml` by adding the following to `resources`:\n  ```yaml\n  resources:\n  ...\n  - manager_config_patch.yaml\n  ```\n- Update the `config/manager/kustomization.yaml` by adding:\n```yaml\n  generatorOptions:\n    disableNameSuffixHash: true\n\n  configMapGenerator:\n  - files:\n    - controller_manager_config.yaml\n    name: manager-config\n  apiVersion: kustomize.config.k8s.io/v1beta1\n  kind: Kustomization\n  images:\n  - name: controller\n    newName: quay.io/example/memcached-operator\n    newTag: v0.0.1\n```\n\n_See [#4701](https://github.com/operator-framework/operator-sdk/pull/4701) for more details._\n\n## (ansible/v1, helm/v1) Add Role rules for leader election.\n\nAdd the rule for the `apiGroups` `coordination.k8s.io` and the resource `leases` in config/rbac/leader_election_role.yaml:\n```yaml\nrules:\n  - apiGroups:\n      - \"\"\n      - coordination.k8s.io\n    resources:\n      - configmaps\n      - leases\n```\n\n_See [#4701](https://github.com/operator-framework/operator-sdk/pull/4701) for more details._\n\n## (ansible/v1) Update Ansible collections\n\nIn your requirements.yml, change the `version` field for community.kubernetes to `1.2.1`, and the `version` field for `operator_sdk.util` to `0.2.0`.\n\n_See [#4734](https://github.com/operator-framework/operator-sdk/pull/4734) for more details._\n\n## (helm/v1) Replace deprecated leader election and metrics address flags\n\nReplace deprecated flags `--enable-leader-election` and `--metrics-addr` with `--leader-elect` and `--metrics-bind-address`, respectively.\n\n_See [#4654](https://github.com/operator-framework/operator-sdk/pull/4654) for more details._\n\n## (helm/v1) Explicitly set `--health-probe-bind-address` in the manager's auth proxy patch.\n\nAdd the arg `--health-probe-bind-address=:8081` to the `config/default/manager_auth_proxy_patch.yaml`:\n```yaml\nspec:\n  template:\n    spec:\n      containers:\n      - name: manager\n        args:\n        - \"--health-probe-bind-address=:8081\"\n        ...\n```\n\n_See [#4654](https://github.com/operator-framework/operator-sdk/pull/4654) for more details._\n\n## (ansible/v1) Explicitly set `--health-probe-bind-address` in the manager's auth proxy patch.\n\nAdd the arg `--health-probe-bind-address=:6789` to the `config/default/manager_auth_proxy_patch.yaml`:\n```yaml\nspec:\n  template:\n    spec:\n      containers:\n      - name: manager\n        args:\n        - \"--health-probe-bind-address=:6789\"\n        ...\n```\n\n_See [#4654](https://github.com/operator-framework/operator-sdk/pull/4654) for more details._\n\n## (helm/v1, ansible/v1) Add `help` target to Makefile.\n\nAnsible/Helm projects now provide a Makefile `help` target, similar to a `--help` flag. You can copy and paste this target from the relevant sample's Makefile ([helm](https://github.com/operator-framework/operator-sdk/blob/v1.5.0/testdata/helm/memcached-operator/Makefile), [ansible](https://github.com/operator-framework/operator-sdk/blob/v1.5.0/testdata/ansible/memcached-operator/Makefile)).\n\n_See [#4660](https://github.com/operator-framework/operator-sdk/pull/4660) for more details._\n\n## (ansible/v1, helm/v1) Add `securityContext`'s to your manager's Deployment.\n\nIn `config/manager/manager.yaml`, add the following security contexts:\n```yaml\nspec:\n  ...\n  template:\n    ...\n    spec:\n      securityContext:\n        runAsNonRoot: true\n      containers:\n      - name: manager\n        securityContext:\n          allowPrivilegeEscalation: false\n```\n\n_See [#4655](https://github.com/operator-framework/operator-sdk/pull/4655) for more details._\n\n## (manifests/v2) Add a kustomize patch to remove the cert-manager volume/volumeMount from your CSV\n\nOLM does [not yet support cert-manager](https://olm.operatorframework.io/docs/advanced-tasks/adding-admission-and-conversion-webhooks/#certificate-authority-requirements), so a JSON patch was added to remove this volume and mount such that OLM can itself create and manage certs for your Operator.\nIn `config/manifests/kustomization.yaml`, add the following:\n```yaml\n#patchesJson6902:\n#- target:\n#    group: apps\n#    version: v1\n#    kind: Deployment\n#    name: controller-manager\n#    namespace: system\n#  patch: |-\n#    # Remove the manager container's \"cert\" volumeMount, since OLM will create and mount a set of certs.\n#    # Update the indices in this path if adding or removing containers/volumeMounts in the manager's Deployment.\n#    - op: remove\n#      path: /spec/template/spec/containers/1/volumeMounts/0\n#    # Remove the \"cert\" volume, since OLM will create and mount a set of certs.\n#    # Update the indices in this path if adding or removing volumes in the manager's Deployment.\n#    - op: remove\n#      path: /spec/template/spec/volumes/0\n```\n\nIf you have configured your operator to use webhooks, add this YAML block uncommented.\n\n_See [#4623](https://github.com/operator-framework/operator-sdk/pull/4623) for more details._\n\n## (go/v2, go/v3, ansible/v1, helm/v1) Add scheme, token, and TLS config to the Prometheus `ServiceMonitor` metrics endpoint.\n\nThe `/metrics` endpoint, while specifying the `https` port on the manager Pod, was not actually configured to serve over https because no tlsConfig was set. Since kube-rbac-proxy secures this endpoint as a manager sidecar, using the service account token mounted into the Pod by default corrects this problem.\nThe changes should look like:\n```diff\n# config/prometheus/monitor.yaml\nspec:\n   endpoints:\n     - path: /metrics\n       port: https\n+      scheme: https\n+      bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token\n+      tlsConfig:\n+        insecureSkipVerify: true\n   selector:\n     matchLabels:\n       control-plane: controller-manager\n```\n**Note:** if you have removed kube-rbac-proxy from your project, make sure to secure the `/metrics` endpoint using a proper [TLS configuration](https://prometheus.io/docs/guides/tls-encryption/).\n\n_See [#4680](https://github.com/operator-framework/operator-sdk/pull/4680) for more details._\n\n## (go/v2, go/v3, ansible/v1, helm/v1) Add `opm` and `catalog-build` Makefile targets\n\nThe `opm` and `catalog-build` Makefile targets were added so operator developers who want to create their own catalogs for their operator or add their operator's bundle(s) to an existing catalog can do so. If this sounds like you, add the following lines to the bottom of your Makefile:\n```make\n.PHONY: opm\nOPM = ./bin/opm\nopm:\nifeq (,$(wildcard $(OPM)))\nifeq (,$(shell which opm 2>/dev/null))\n\t@{ \\\n\tset -e ;\\\n\tmkdir -p $(dir $(OPM)) ;\\\n\tcurl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/v1.19.1/$(OS)-$(ARCH)-opm ;\\\n\tchmod +x $(OPM) ;\\\n\t}\nelse \nOPM = $(shell which opm)\nendif\nendif\nBUNDLE_IMGS ?= $(BUNDLE_IMG) \nCATALOG_IMG ?= $(IMAGE_TAG_BASE)-catalog:v$(VERSION) ifneq ($(origin CATALOG_BASE_IMG), undefined) FROM_INDEX_OPT := --from-index $(CATALOG_BASE_IMG) endif \n.PHONY: catalog-build\ncatalog-build: opm\n\t$(OPM) index add --container-tool docker --mode semver --tag $(CATALOG_IMG) --bundles $(BUNDLE_IMGS) $(FROM_INDEX_OPT)\n\n.PHONY: catalog-push\ncatalog-push: ## Push the catalog image.\n\t$(MAKE) docker-push IMG=$(CATALOG_IMG)\n```\nIf updating a Go operator project, additionally add the following Makefile variables:\n```make\nOS = $(shell go env GOOS)\nARCH = $(shell go env GOARCH)\n```\n\n_See [#4406](https://github.com/operator-framework/operator-sdk/pull/4406) for more details._\n\n## (go/v2, go/v3, ansible/v1, helm/v1) Changed `BUNDLE_IMG` and added `IMAGE_TAG_BASE` Makefile variables\n\nThe following Makefile changes were made to allow `make bundle-build bundle-push catalog-build catalog-push` and encode image repo/namespace information in the Makefile by default:\n```diff\n+IMAGE_TAG_BASE ?= <registry>/<operator name>\n+ \n-BUNDLE_IMG ?= controller-bundle:$(VERSION)\n+BUNDLE_IMG ?= $(IMAGE_TAG_BASE)-bundle:v$(VERSION)\n```\n\nFor example, if `IMAGE_TAG_BASE ?= foo/bar-operator` then running `make bundle-build bundle-push catalog-build catalog-push` would build `foo/bar-operator-bundle:v0.0.1` and `foo/bar-operator-catalog:v0.0.1` then push them to the `docker.io/foo` namespaced registry.\n\n_See [#4406](https://github.com/operator-framework/operator-sdk/pull/4406) for more details._\n\n## (ansible/v1, helm/v1) Add the `controller-manager` ServiceAccount to your project.\n\nA non-default ServiceAccount `controller-manager` is scaffolded on `operator-sdk init`, to improve security for operators installed in shared namespaces. To add this ServiceAccount to your project, do the following:\n```sh\n# Create the ServiceAccount.\ncat <<EOF > config/rbac/service_account.yaml apiVersion: v1 \nkind: ServiceAccount\nmetadata:\n  name: controller-manager\n  namespace: system\nEOF\n# Add it to the list of RBAC resources.\necho \"- service_account.yaml\" >> config/rbac/kustomization.yaml\n# Update all RoleBinding and ClusterRoleBinding subjects that reference the operator's ServiceAccount.\nfind config/rbac -name *_binding.yaml -exec sed -i -E 's/  name: default/  name: controller-manager/g' {} \\; \n# Add the ServiceAccount name to the manager Deployment's spec.template.spec.serviceAccountName. \nsed -i -E 's/([ ]+)(terminationGracePeriodSeconds:)/\\1serviceAccountName: controller-manager\\n\\1\\2/g' config/manager/manager.yaml\n```\n\nThe changes should look like: \n\n```diff \n# config/manager/manager.yaml\n           requests:\n             cpu: 100m\n             memory: 20Mi\n+      serviceAccountName: controller-manager\n       terminationGracePeriodSeconds: 10\n# config/rbac/auth_proxy_role_binding.yaml\n   name: proxy-role\n subjects:\n - kind: ServiceAccount\n-  name: default \n+  name: controller-manager\n   namespace: system\n# config/rbac/kustomization.yaml\n resources:\n+- service_account.yaml\n - role.yaml\n - role_binding.yaml\n - leader_election_role.yaml\n# config/rbac/leader_election_role_binding.yaml\n   name: leader-election-role\n subjects:\n - kind: ServiceAccount\n-  name: default\n+  name: controller-manager\n   namespace: system\n# config/rbac/role_binding.yaml\n   name: manager-role\n subjects:\n - kind: ServiceAccount\n-  name: default \n+  name: controller-manager\n   namespace: system\n# config/rbac/service_account.yaml \n+apiVersion: v1 \n+kind: ServiceAccount \n+metadata: \n+  name: controller-manager \n+  namespace: system\n```\n\n_See [#4653](https://github.com/operator-framework/operator-sdk/pull/4653) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.7.0.md",
    "content": "---\ntitle: v1.7.0\nweight: 998993000\n---\n\n## Add the manager config patch to config/default/kustomization.yaml\n\nThe scaffolded `--config` flag was not added to either ansible-/helm-operator binary when [config file](https://book-v3.book.kubebuilder.io/component-config-tutorial/tutorial.html) support was originally added, so does not currently work. The `--config` flag supports configuration of both binaries by file; this method of configuration only applies to the underlying [controller manager](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Manager), not the operator as a whole. To optionally configure the operator's Deployment with a config file, make the following update to config/default/kustomization.yaml:\n```diff\n# If you want your controller-manager to expose the /metrics # endpoint w/o any authn/z, please comment the following line.\n- manager_auth_proxy_patch.yaml\n+# Mount the controller config file for loading manager configurations\n+# through a ComponentConfig type\n+- manager_config_patch.yaml\n```\nThis feature is opt-in: flags can be used as-is or to override config file values.\n\n_See [#4776](https://github.com/operator-framework/operator-sdk/pull/4776) for more details._\n\n## Deprecate support for packagemanifests.\n\nThe operator-framework is removing support for the packagemanifests format in the near future. Hence, `operator-sdk generate packagemanifests` and `operator-sdk run packagemanifests` commands are deprecated. In order to migrate packagemanifests to bundles, `operator-sdk pkgman-to-bundle` command can be used. Run `operator-sdk pkgman-to-bundle --help` for more details.\n\n_See [#4838](https://github.com/operator-framework/operator-sdk/pull/4838) for more details._\n\n## (go/v3, ansible/v1, helm/v1) Move `leases.coordination.k8s.io` to its own proxy-role rule\n\nMake the following changes to config/rbac/leader_election_role.yaml:\n```diff\nrules: \\- apiGroups:\n  - \"\"\n-  - coordination.k8s.io\n  resources:\n  - configmaps\n+ verbs:\n+- get\n+- list\n+- watch\n+- create\n+- update\n+- patch\n+- delete\n+- apiGroups:\n+- coordination.k8s.io\n+ resources:\n    - leases\n  verbs:\n    - get\n```\n\n_See [#4835](https://github.com/operator-framework/operator-sdk/pull/4835) for more details._\n\n## (go/v3) Set the Makefile's `SHELL` variable to the system's `bash` binary\n\nImporting `setup-envtest.sh` needs bash, so your Makefile's `SHELL` variable should be set to `bash` with error options:\n```diff\nelse GOBIN=$(shell go env GOBIN)\nendif\n+# Setting SHELL to bash allows bash commands to be executed by recipes.\n+# This is a requirement for 'setup-envtest.sh' in the test target.\n+# Options are set to exit when a recipe line exits non-zero or a piped command fails.\n+SHELL = /usr/bin/env bash -o pipefail\n+.SHELLFLAGS = -ec\n+ all: build\n```\n_See [#4835](https://github.com/operator-framework/operator-sdk/pull/4835) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.7.1.md",
    "content": "---\ntitle: v1.7.1\nweight: 998992999\n---\n\n## Add the manager config patch to config/default/kustomization.yaml\n\nThe scaffolded `--config` flag was not added to either ansible-/helm-operator binary when [config file](https://book-v3.book.kubebuilder.io/component-config-tutorial/tutorial.html) support was originally added, so does not currently work. The `--config` flag supports configuration of both binaries by file; this method of configuration only applies to the underlying [controller manager](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/manager#Manager), not the operator as a whole. To optionally configure the operator's Deployment with a config file, make the following update to config/default/kustomization.yaml:\n```diff\n# If you want your controller-manager to expose the /metrics # endpoint w/o any authn/z, please comment the following line.\n\\- manager_auth_proxy_patch.yaml\n+# Mount the controller config file for loading manager configurations\n+# through a ComponentConfig type\n+- manager_config_patch.yaml\n```\nThis feature is opt-in: flags can be used as-is or to override config file values.\n\n_See [#4776](https://github.com/operator-framework/operator-sdk/pull/4776) for more details._\n\n## Deprecate support for packagemanifests.\n\nThe operator-framework is removing support for the packagemanifests format in the near future. Hence, `operator-sdk generate packagemanifests` and `operator-sdk run packagemanifests` commands are deprecated. In order to migrate packagemanifests to bundles, `operator-sdk pkgman-to-bundle` command can be used. Run `operator-sdk pkgman-to-bundle --help` for more details.\n\n_See [#4838](https://github.com/operator-framework/operator-sdk/pull/4838) for more details._\n\n## (go/v3, ansible/v1, helm/v1) Move `leases.coordination.k8s.io` to its own proxy-role rule\n\nMake the following changes to config/rbac/leader_election_role.yaml:\n```diff\nrules:\n\\- apiGroups:\n  - \"\"\n-  - coordination.k8s.io\n  resources:\n  - configmaps\n+ verbs:\n+- get\n+- list\n+- watch\n+- create\n+- update\n+- patch\n+- delete\n+- apiGroups:\n+- coordination.k8s.io\n+ resources:\n    - leases\n  verbs:\n    - get\n```\n\n_See [#4835](https://github.com/operator-framework/operator-sdk/pull/4835) for more details._\n\n## (go/v3) Set the Makefile's `SHELL` variable to the system's `bash` binary\n\nImporting `setup-envtest.sh` needs bash, so your Makefile's `SHELL` variable should be set to `bash` with error options:\n```diff\nelse GOBIN=$(shell go env GOBIN)\nendif\n+# Setting SHELL to bash allows bash commands to be executed by recipes.\n+# This is a requirement for 'setup-envtest.sh' in the test target.\n+# Options are set to exit when a recipe line exits non-zero or a piped command fails.\n+SHELL = /usr/bin/env bash -o pipefail\n+.SHELLFLAGS = -ec\n+ all: build\n```\n_See [#4835](https://github.com/operator-framework/operator-sdk/pull/4835) for more details._\n\n## Ensure that existing dependent resources have owner annotations\n\nFor Ansible-based operators, [owner reference annotations](https://sdk.operatorframework.io/docs/building-operators/ansible/reference/retroactively-owned-resources/)\non cluster-scoped dependent resources and dependent resources in other namespaces were not applied correctly.\nA workaround was to add these annotations manually, which is no longer required as this bug has been fixed.\n\n_See [#4850](https://github.com/operator-framework/operator-sdk/pull/4850) for more details._\n\n## (go/v3) Bump controller-runtime to v0.8.3 and kubernetes dependencies to v0.20.2\n\nIn your go.mod, change controller-runtime's version to v0.8.3 and kubernetes dependencies  to v0.20.2, then rebuild your project.\n\n_See [#4863](https://github.com/operator-framework/operator-sdk/pull/4863) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.8.0.md",
    "content": "---\ntitle: v1.8.0\nweight: 998992000\n---\n\nThere are no migrations for this release! 🎉\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/v1.9.0.md",
    "content": "---\ntitle: v1.9.0\nweight: 998991000\n---\n\n## The ansible-operator binary will reject the kubeconfig if the server URL contains a path.\n\nThere is currently no workaround other than running the operator as a pod in the cluster (where it will use the internal endpoint). The fix for this issue is currently blocked waiting on a fix to the apimachinery package. Once the upstream issue is merged then a proper fix will be done for ansible-operator. Work on this issue is being tracked here: https://github.com/operator-framework/operator-sdk/issues/4925\n\n_See [#4987](https://github.com/operator-framework/operator-sdk/pull/4987) for more details._\n"
  },
  {
    "path": "website/content/en/docs/upgrading-sdk-version/version-upgrade-guide.md",
    "content": "---\ntitle: Operator SDK Version upgrade guide\nlinkTitle: v0.2.x to v0.17.x\nweight: 999983000\ndescription: A guide to upgrading the Operator SDK version for an existing operator project from v0.2.x all the way through to 0.17.x.\n---\n\nIn most cases the upgrading the SDK version should only entail updating the operator's SDK dependency version in the `Gopkg.toml` or `go.mod` file.\nFor some versions it might also be necessary to update the upstream Kubernetes and controller-runtime dependencies.\n\nThe full list of dependencies and their versions required by a particular version of the SDK can be viewed by using the [`operator-sdk print-deps`][print-deps-cli] command. Use this command to update the project `Gopkg.toml`/`go.mod` file accordingly as you upgrade to a new SDK version.\n\nFor some SDK versions after `v0.1.0` there might be minor breaking changes in the controller-runtime APIs, `operator-sdk` CLI or the expected project layout and file names. These breaking changes will usually be outlined in the [CHANGELOG][changelog]/[release-notes][release-notes] for each release version.\n\nFor releases that have a large number of breaking changes or involve a significant refactoring of the APIs and project layout there will be a migration guide similar to the [v0.1.0 migration guide][v0.1.0-migration-guide].\n\nThe following sections outline the upgrade steps for each SDK version along with steps necessary for any associated breaking changes.\n\n## `v0.2.x`\n\n- Update the SDK constraint in `Gopkg.toml` to version `v0.2.1` and run `dep ensure` to update the vendor directory.\n  ```TOML\n  [[constraint]]\n    name = \"github.com/operator-framework/operator-sdk\"\n    version = \"=v0.2.1\"\n  ```\n\n## `v0.3.x`\n\n- Update the SDK constraint in `Gopkg.toml` to version `v0.3.0`, the kubernetes dependencies to `kubernetes-1.12.3` revisions, and the controller-runtime version to `v0.1.8`. Then run `dep ensure` to update the vendor directory.\n  ```TOML\n  [[override]]\n    name = \"k8s.io/code-generator\"\n    # **revision for tag \"kubernetes-1.12.3\"**\n    revision = \"3dcf91f64f638563e5106f21f50c31fa361c918d\"\n\n  [[override]]\n    name = \"k8s.io/api\"\n    # **revision for tag \"kubernetes-1.12.3\"**\n    revision = \"b503174bad5991eb66f18247f52e41c3258f6348\"\n\n  [[override]]\n    name = \"k8s.io/apiextensions-apiserver\"\n    # **revision for tag \"kubernetes-1.12.3\"**\n    revision = \"0cd23ebeb6882bd1cdc2cb15fc7b2d72e8a86a5b\"\n\n  [[override]]\n    name = \"k8s.io/apimachinery\"\n    # **revision for tag \"kubernetes-1.12.3\"**\n    revision = \"eddba98df674a16931d2d4ba75edc3a389bf633a\"\n\n  [[override]]\n    name = \"k8s.io/client-go\"\n    # **revision for tag \"kubernetes-1.12.3\"**\n    revision = \"d082d5923d3cc0bfbb066ee5fbdea3d0ca79acf8\"\n\n  [[override]]\n    name = \"sigs.k8s.io/controller-runtime\"\n    version = \"=v0.1.8\"\n\n  [[constraint]]\n    name = \"github.com/operator-framework/operator-sdk\"\n    version = \"=v0.3.0\"\n  ```\n\n## `v0.4.x`\n\n- Update the SDK constraint in `Gopkg.toml` to version `v0.4.1` and run `dep ensure` to update the vendor directory.\n  ```TOML\n  [[constraint]]\n    name = \"github.com/operator-framework/operator-sdk\"\n    version = \"=v0.4.1\"\n  ```\n\n## `v0.5.x`\n\n- Update the SDK constraint in `Gopkg.toml` to version `v0.5.0`, the kubernetes dependencies to `kubernetes-1.13.1` revisions, and the controller-runtime version to `v0.1.10`.\n  ```TOML\n  [[override]]\n    name = \"k8s.io/code-generator\"\n    # **revision for tag \"kubernetes-1.13.1\"**\n    revision = \"c2090bec4d9b1fb25de3812f868accc2bc9ecbae\"\n\n  [[override]]\n    name = \"k8s.io/api\"\n    # **revision for tag \"kubernetes-1.13.1\"**\n    revision = \"05914d821849570fba9eacfb29466f2d8d3cd229\"\n\n  [[override]]\n    name = \"k8s.io/apiextensions-apiserver\"\n    # **revision for tag \"kubernetes-1.13.1\"**\n    revision = \"0fe22c71c47604641d9aa352c785b7912c200562\"\n\n  [[override]]\n    name = \"k8s.io/apimachinery\"\n    # **revision for tag \"kubernetes-1.13.1\"**\n    revision = \"2b1284ed4c93a43499e781493253e2ac5959c4fd\"\n\n  [[override]]\n    name = \"k8s.io/client-go\"\n    # **revision for tag \"kubernetes-1.13.1\"**\n    revision = \"8d9ed539ba3134352c586810e749e58df4e94e4f\"\n\n  [[override]]\n    name = \"sigs.k8s.io/controller-runtime\"\n    version = \"=v0.1.10\"\n\n  [[constraint]]\n    name = \"github.com/operator-framework/operator-sdk\"\n    version = \"=v0.5.0\"\n  ```\n\n- Append the following new constraints to your `Gopkg.toml`.\n  ```TOML\n  [[override]]\n    name = \"k8s.io/kube-openapi\"\n    revision = \"0cf8f7e6ed1d2e3d47d02e3b6e559369af24d803\"\n\n  [[override]]\n    name = \"github.com/go-openapi/spec\"\n    branch = \"master\"\n\n  [[override]]\n    name = \"sigs.k8s.io/controller-tools\"\n    version = \"=v0.1.8\"\n  ```\n\n- Update the `required` dependencies in `Gopkg.toml` to include `sigs.k8s.io/controller-tools/pkg/crd/generator` and change `k8s.io/code-generator/cmd/openapi-gen` to `k8s.io/kube-openapi/cmd/openapi-gen`. Then run `dep ensure` to update the vendor directory.\n  ```TOML\n  required = [\n    \"k8s.io/code-generator/cmd/defaulter-gen\",\n    \"k8s.io/code-generator/cmd/deepcopy-gen\",\n    \"k8s.io/code-generator/cmd/conversion-gen\",\n    \"k8s.io/code-generator/cmd/client-gen\",\n    \"k8s.io/code-generator/cmd/lister-gen\",\n    \"k8s.io/code-generator/cmd/informer-gen\",\n    \"k8s.io/kube-openapi/cmd/openapi-gen\",\n    \"k8s.io/gengo/args\",\n    \"sigs.k8s.io/controller-tools/pkg/crd/generator\",\n  ]\n  ```\n\n## `v0.6.x`\n\n- Update the SDK constraint in `Gopkg.toml` to version `v0.6.0` and run `dep ensure` to update the vendor directory.\n  ```TOML\n  [[constraint]]\n    name = \"github.com/operator-framework/operator-sdk\"\n    version = \"=v0.6.0\"\n  ```\n\n- The `operator-sdk olm-catalog` command now expects and generates manifests in the operator-registry [manifest format][manifest-format]. Generate your CSVs in the new layout by using `operator-sdk olm-catalog gen-csv` command, or modify the layout of your existing CSV manifests directory similar to the example below.\n  ```console\n  $ tree deploy/olm-catalog\n  deploy/olm-catalog/\n  └── memcached-operator\n      ├── 0.1.0\n      │   └── memcached-operator.v0.1.0.clusterserviceversion.yaml\n      ├── 0.2.0\n      │   └── memcached-operator.v0.2.0.clusterserviceversion.yaml\n      └── memcached-operator.package.yaml\n  ```\n\n## `v0.7.x`\n\n- Update the SDK constraint in `Gopkg.toml` to version `v0.7.1` and run `dep ensure` to update the vendor directory.\n  ```TOML\n  [[constraint]]\n    name = \"github.com/operator-framework/operator-sdk\"\n    version = \"=v0.7.1\"\n  ```\n\n## `v0.8.x`\n\nThe SDK version `v0.8.x` supports scaffolding projects to use Go modules by default. It is recommended that you migrate your operator project to use modules for dependency management, however you can choose to keep using `dep`. The upgrade steps for both are outlined below:\n\n**`dep`**\n\n- Update the SDK constraint in `Gopkg.toml` to version `v0.8.2`.\n  ```TOML\n  [[constraint]]\n    name = \"github.com/operator-framework/operator-sdk\"\n    version = \"=v0.8.2\"\n  ```\n- Pin the controller-tools dependency to the following revision. See the release notes or [#1278](https://github.com/operator-framework/operator-sdk/pull/1278/) for why this is needed.\n  ```TOML\n  [[override]]\n    name = \"sigs.k8s.io/controller-tools\"\n    revision = \"9d55346c2bde73fb3326ac22eac2e5210a730207\"\n  ```\n- Run `dep ensure` to update the vendor directory.\n\n**`modules`**\n\nTo get familiar with Go modules read the [modules wiki][modules-wiki]. In particular the section on [migrating to modules][migrating-to-modules].\n\n- Ensure that you have Go 1.12+ and [Mercurial][mercurial] 3.9+ installed.\n- Activate Go modules support for your project in `$GOPATH/src` by setting the env `GO111MODULE=on`. See [activating modules][activating-modules] for more details.\n- Initialize a new `go.mod` file by running `go mod init`.\n- Append the following to the end of your `go.mod` file to pin the operator-sdk and other upstream dependencies to the required versions.\n```\n// Pinned to kubernetes-1.13.1\nreplace (\n\tk8s.io/api => k8s.io/api v0.0.0-20181213150558-05914d821849\n\tk8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.0.0-20181213153335-0fe22c71c476\n\tk8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20181127025237-2b1284ed4c93\n\tk8s.io/client-go => k8s.io/client-go v0.0.0-20181213151034-8d9ed539ba31\n)\n\nreplace (\n\tgithub.com/coreos/prometheus-operator => github.com/coreos/prometheus-operator v0.29.0\n\tk8s.io/code-generator => k8s.io/code-generator v0.0.0-20181117043124-c2090bec4d9b\n\tk8s.io/kube-openapi => k8s.io/kube-openapi v0.0.0-20180711000925-0cf8f7e6ed1d\n\tsigs.k8s.io/controller-runtime => sigs.k8s.io/controller-runtime v0.1.10\n\tsigs.k8s.io/controller-tools => sigs.k8s.io/controller-tools v0.1.11-0.20190411181648-9d55346c2bde\n)\n\nreplace github.com/operator-framework/operator-sdk => github.com/operator-framework/operator-sdk v0.8.2\n```\n- Run `go mod tidy` to clean up the `go.mod` file.\n  - In case of any go module loading errors, consult the default [`v0.8.2` go.mod dependencies][v0.8.2-go-mod] scaffolded by the operator-sdk to resolve any differences. You can also view this file by scaffolding a new project with operator-sdk `v0.8.2`.\n- Ensure that you can build the project with `operator-sdk build`\n- Finally remove `Gopkg.lock`, `Gopkg.toml` and the vendor directory.\n\n**Breaking changes**\n\nUpon updating the project to `v0.8.2` the following breaking changes apply:\n\n- On running the command `operator-sdk generate openapi`, the CRD manifests at `deploy/crds/<group>_<version>_<kind>.crd` for all API types will now be regenerated based on their source files `pkg/apis/..._types.go`. So if you have made any manual edits to the default generated CRD manifest, e.g manually written the validation block or specified the naming (`spec.names`), then that information be overwritten when the CRD is regenerated.\n\n  The correct way to specify CRD fields like naming, validation, subresources etc is by using `// +kubebuilder` marker comments. Consult the [legacy kubebuilder documentation][legacy-kubebuilder-doc-crd] to see what CRD fields can be generated via `// +kubebuilder` marker comments.\n\n  **Note:** The version of controller-tools tied to this release does not support settting the `spec.scope` field of the CRD. Use the marker comment `+genclient:nonNamespaced` to set `spec.scope=Cluster` if necessary. See the example below:\n  ```Go\n  // MemcachedSpec defines the desired state of Memcached\n  type MemcachedSpec struct {\n    //+kubebuilder:validation:Maximum=5\n    //+kubebuilder:validation:Minimum=1\n    Size int32 `json:\"size\"`\n  }\n\n  // MemcachedStatus defines the observed state of Memcached\n  type MemcachedStatus struct {\n    //+kubebuilder:validation:MaxItems=5\n    //+kubebuilder:validation:MinItems=1\n    Nodes []string `json:\"nodes\"`\n  }\n\n  // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object\n\n  // Memcached is the Schema for the memcacheds API\n  //+kubebuilder:subresource:status\n  //+kubebuilder:resource:shortName=\"mc\"\n  // +genclient:nonNamespaced\n  type Memcached struct {\n    metav1.TypeMeta   `json:\",inline\"`\n    metav1.ObjectMeta `json:\"metadata,omitempty\"`\n\n    Spec   MemcachedSpec   `json:\"spec,omitempty\"`\n    Status MemcachedStatus `json:\"status,omitempty\"`\n  }\n  ```\n\n## `v0.9.x`\n\n- The function `ExposeMetricsPort()` has been replaced with `CreateMetricsService()` [#1560](https://github.com/operator-framework/operator-sdk/pull/1560).\n\n  Replace the following line in `cmd/manager/main.go`\n  ```Go\n    _, err = metrics.ExposeMetricsPort(ctx, metricsPort)\n  ```\n  with\n  ```Go\n\tservicePorts := []v1.ServicePort{\n    {Port: metricsPort, Name: metrics.OperatorPortName, Protocol: v1.ProtocolTCP, TargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: metricsPort}},\n    {Port: operatorMetricsPort, Name: metrics.CRPortName, Protocol: v1.ProtocolTCP, TargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: operatorMetricsPort}},\n  }\n\n  _, err = metrics.CreateMetricsService(ctx, servicePorts)\n  ```\n\n**`dep`**\n\n- Update the SDK constraint in `Gopkg.toml` to version `v0.9.0`, the kubernetes dependencies to `kubernetes-1.13.4` revisions, and the controller-runtime version to `v0.1.12`.\n  ```TOML\n  [[override]]\n    name = \"k8s.io/api\"\n    # **revision for tag \"kubernetes-1.13.4\"**\n    revision = \"5cb15d34447165a97c76ed5a60e4e99c8a01ecfe\"\n  [[override]]\n    name = \"k8s.io/apiextensions-apiserver\"\n    # **revision for tag \"kubernetes-1.13.4\"**\n    revision = \"d002e88f6236312f0289d9d1deab106751718ff0\"\n  [[override]]\n    name = \"k8s.io/apimachinery\"\n    # **revision for tag \"kubernetes-1.13.4\"**\n    revision = \"86fb29eff6288413d76bd8506874fddd9fccdff0\"\n  [[override]]\n    name = \"k8s.io/client-go\"\n    # **revision for tag \"kubernetes-1.13.4\"**\n    revision = \"b40b2a5939e43f7ffe0028ad67586b7ce50bb675\"\n  [[override]]\n    name = \"github.com/coreos/prometheus-operator\"\n    version = \"=v0.29.0\"\n  [[override]]\n    name = \"sigs.k8s.io/controller-runtime\"\n    version = \"=v0.1.12\"\n  [[constraint]]\n    name = \"github.com/operator-framework/operator-sdk\"\n    version = \"=v0.9.0\"\n  ```\n- Append the contraint for `k8s.io/kube-state-metrics`.\n  ```TOML\n  [[override]]\n    name = \"k8s.io/kube-state-metrics\"\n    version = \"v1.6.0\"\n  ```\n- Run `dep ensure` to update the vendor directory.\n\n**modules**\n\n- Update the `replace` directives in your `go.mod` file for the SDK, kubernetes, controller-runtime and kube-state metrics dependencies to the following versions.\n  ```\n  // Pinned to kubernetes-1.13.4\n  replace (\n    k8s.io/api => k8s.io/api v0.0.0-20190222213804-5cb15d344471\n    k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.0.0-20190228180357-d002e88f6236\n    k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20190221213512-86fb29eff628\n    k8s.io/client-go => k8s.io/client-go v0.0.0-20190228174230-b40b2a5939e4\n  )\n  replace (\n    github.com/coreos/prometheus-operator => github.com/coreos/prometheus-operator v0.29.0\n    sigs.k8s.io/controller-runtime => sigs.k8s.io/controller-runtime v0.1.12\n    sigs.k8s.io/controller-tools => sigs.k8s.io/controller-tools v0.1.11-0.20190411181648-9d55346c2bde\n    k8s.io/kube-state-metrics => k8s.io/kube-state-metrics v1.6.0\n  )\n  replace github.com/operator-framework/operator-sdk => github.com/operator-framework/operator-sdk v0.9.0\n  ```\n\n## `v0.10.x`\n\n- The scorecard configuration format for the `operator-sdk scorecard` command has changed. See [`doc/test-framework/scorecard`](https://github.com/operator-framework/operator-sdk/blob/v0.10.x/doc/test-framework/scorecard.md) for more info.\n- The CSV config field `role-path` is now `role-paths` and takes a list of strings.\n    Replace:\n    ```yaml\n    role-path: path/to/role.yaml\n    ```\n    with:\n    ```yaml\n    role-paths:\n    - path/to/role.yaml\n    ```\n\n**modules**\n\n- Ensure the following `replace` directives are present in your `go.mod` file:\n    ```\n    replace (\n            github.com/coreos/prometheus-operator => github.com/coreos/prometheus-operator v0.29.0\n            // Pinned to v2.9.2 (kubernetes-1.13.1) so https://proxy.golang.org can\n            // resolve it correctly.\n            github.com/prometheus/prometheus => github.com/prometheus/prometheus v0.0.0-20190424153033-d3245f150225\n            k8s.io/kube-state-metrics => k8s.io/kube-state-metrics v1.6.0\n            sigs.k8s.io/controller-runtime => sigs.k8s.io/controller-runtime v0.1.12\n            sigs.k8s.io/controller-tools => sigs.k8s.io/controller-tools v0.1.11-0.20190411181648-9d55346c2bde\n    )\n\n    replace github.com/operator-framework/operator-sdk => github.com/operator-framework/operator-sdk v0.10.0\n    ```\n\n## `v0.11.x`\n\n**NOTE:** this version uses Kubernetes v1.14.x and controller-runtime v0.2.x, both of which have breaking API changes. See the [changelog][changelog] for more details.\n\n**dep**\n\n- Remove the `required = [ ... ]` section and comment from the top of your `Gopkg.toml` file.\n- Update the following overrides in `Gopkg.toml`:\n    ```TOML\n    [[override]]\n      name = \"k8s.io/api\"\n      # **revision for tag \"kubernetes-1.14.1\"**\n      revision = \"6e4e0e4f393bf5e8bbff570acd13217aa5a770cd\"\n    [[override]]\n      name = \"k8s.io/apiextensions-apiserver\"\n      # **revision for tag \"kubernetes-1.14.1\"**\n      revision = \"727a075fdec8319bf095330e344b3ccc668abc73\"\n    [[override]]\n      name = \"k8s.io/apimachinery\"\n      # **revision for tag \"kubernetes-1.14.1\"**\n      revision = \"6a84e37a896db9780c75367af8d2ed2bb944022e\"\n    [[override]]\n      name = \"k8s.io/client-go\"\n      # **revision for tag \"kubernetes-1.14.1\"**\n      revision = \"1a26190bd76a9017e289958b9fba936430aa3704\"\n    [[override]]\n      name = \"github.com/coreos/prometheus-operator\"\n      version = \"=v0.31.1\"\n    [[override]]\n      name = \"sigs.k8s.io/controller-runtime\"\n      version = \"=v0.2.2\"\n    [[constraint]]\n      name = \"github.com/operator-framework/operator-sdk\"\n      version = \"=v0.11.0\"\n    ```\n- Append an override for `gopkg.in/fsnotify.v1`, which is required when resolving controller-runtime dependencies:\n    ```TOML\n    [[override]]\n      name = \"gopkg.in/fsnotify.v1\"\n      source = \"https://github.com/fsnotify/fsnotify.git\"\n    ```\n- Remove the `k8s.io/kube-state-metrics` override.\n- Run `dep ensure` to update the vendor directory.\n\n**modules**\n\n- Ensure the following `replace` directives are present in your `go.mod` file:\n    ```\n    // Pinned to kubernetes-1.14.1\n    replace (\n    \tk8s.io/api => k8s.io/api kubernetes-1.14.1\n    \tk8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver kubernetes-1.14.1\n    \tk8s.io/apimachinery => k8s.io/apimachinery kubernetes-1.14.1\n    \tk8s.io/client-go => k8s.io/client-go kubernetes-1.14.1\n    \tk8s.io/cloud-provider => k8s.io/cloud-provider kubernetes-1.14.1\n    )\n\n    replace (\n    \t// Indirect operator-sdk dependencies use git.apache.org, which is frequently\n    \t// down. The github mirror should be used instead.\n    \t// Locking to a specific version (from 'go mod graph'):\n    \tgit.apache.org/thrift.git => github.com/apache/thrift v0.0.0-20180902110319-2566ecd5d999\n    \tgithub.com/coreos/prometheus-operator => github.com/coreos/prometheus-operator v0.31.1\n    \t// Pinned to v2.10.0 (kubernetes-1.14.1) so https://proxy.golang.org can\n    \t// resolve it correctly.\n    \tgithub.com/prometheus/prometheus => github.com/prometheus/prometheus d20e84d0fb64aff2f62a977adc8cfb656da4e286\n    )\n\n    replace github.com/operator-framework/operator-sdk => github.com/operator-framework/operator-sdk v0.11.0\n    ```\n\n**Import updates**\n\n- Replace import `sigs.k8s.io/controller-runtime/pkg/runtime/scheme` with `sigs.k8s.io/controller-runtime/pkg/scheme` in:\n  - `./pkg/apis/<group>/<version>/register.go`\n- Replace import `sigs.k8s.io/controller-runtime/pkg/runtime/log` with `sigs.k8s.io/controller-runtime/pkg/log` in:\n  - `cmd/manager/main.go`\n  - `./pkg/controller/<kind>/<kind>_controller.go`\n- Replace import `sigs.k8s.io/controller-runtime/pkg/runtime/signals` with `sigs.k8s.io/controller-runtime/pkg/manager/signals` in:\n  - `cmd/manager/main.go`\n- Remove import `sigs.k8s.io/controller-tools/pkg/crd/generator` from:\n  - `tools.go`\n\n**controller-runtime API updates**\n\nAll method signatures for [`sigs.k8s.io/controller-runtime/pkg/client.Client`](https://github.com/kubernetes-sigs/controller-runtime/blob/v0.2.0/pkg/client/interfaces.go#L104) and [`sigs.k8s.io/controller-runtime/pkg/client.StatusWriter`](https://github.com/kubernetes-sigs/controller-runtime/blob/v0.2.0/pkg/client/interfaces.go#L91) (except for `Client.Get()`) have been updated. Each now uses a variadic option interface parameter typed for each method.\n- `Client.List(ctx context.Context, opts *client.ListOptions, list runtime.Object) error` is now [`Client.List(ctx context.Context, list runtime.Object, opts ...client.ListOption) error`](https://github.com/kubernetes-sigs/controller-runtime/blob/v0.2.0/pkg/client/interfaces.go#L61).\n    Replace:\n    ```go\n    listOpts := &client.ListOptions{}\n    listOpts.InNamespace(\"namespace\")\n    err = r.client.List(context.TODO(), listOps, podList)\n    ```\n    with:\n    ```go\n    listOpts := []client.ListOption{\n      client.InNamespace(\"namespace\"),\n    }\n    err = r.client.List(context.TODO(), podList, listOpts...)\n    ```\n- `Client.Create(ctx context.Context, obj runtime.Object) error` is now [`Client.Create(ctx context.Context, obj runtime.Object, opts ...client.CreateOption) error`](https://github.com/kubernetes-sigs/controller-runtime/blob/v0.2.0/pkg/client/interfaces.go#L67). No updates need to be made. See the [client doc][client-doc] for a discussion of `client.CreateOption`.\n- `Client.Update(ctx context.Context, obj runtime.Object) error` is now [`Client.Update(ctx context.Context, obj runtime.Object, opts ...client.UpdateOption) error`](https://github.com/kubernetes-sigs/controller-runtime/blob/v0.2.0/pkg/client/interfaces.go#L74). No updates need to be made. See the [client doc][client-doc] for a discussion of `client.UpdateOption`.\n- `Client.Delete(ctx context.Context, obj runtime.Object, opts ...DeleteOptionFunc) error` is now [`Client.Delete(ctx context.Context, obj runtime.Object, opts ...DeleteOption) error`](https://github.com/kubernetes-sigs/controller-runtime/blob/v0.2.0/pkg/client/interfaces.go#L70). Although the option interface has changed, the way each `client.DeleteOption` is created is the same as before. No updates need to be made. See the [client doc][client-doc] for a discussion of `client.DeleteOption`.\n- `StatusWriter.Update(ctx context.Context, obj runtime.Object) error` is now [`Update(ctx context.Context, obj runtime.Object, opts ...UpdateOption) error`](https://github.com/kubernetes-sigs/controller-runtime/blob/v0.2.0/pkg/client/interfaces.go#L95). No updates need to be made. See the [client doc][client-doc] for a discussion of `client.UpdateOption`.\n\n**OpenAPI updates**\n\n- Run the command `operator-sdk generate openapi` and ensure that no errors such as `API rule violation` are raised. For further information see the [API rules][api-rules] documentation.\n\n**NOTE:** You may need to add or remove markers (code annotations) to fix issues found when running `generate openapi`. Usage of markers in API code is discussed in the kubebuilder CRD generation [documentation][generating-crd] and in marker [documentation][markers]. A full list of OpenAPIv3 validation markers can be found [here](https://book.kubebuilder.io/reference/markers/crd-validation.html).\n\n**TIPS:**\n- If the `+kubebuilder:validation:Pattern` has commas, then surround the expressions in backticks.\n- If you are using `+kubebuilder:validation:Enum` then either surround the expression list in curly braces and quote each expression, or separate each expression using semicolons.\n\n**Operator SDK updates**\n\n- [`pkg/test.FrameworkClient`](https://github.com/operator-framework/operator-sdk/blob/947a464/pkg/test/client.go#L33) `List()` and `Delete()` method invocations should be updated to match those of `Client.List()` and `Client.Delete()`, described above.\n- The annotation to assign a scope to your CRD has changed. For the following changes, note that `<resource>` is the plural lower-case CRD Kind found at `spec.names.plural`.\n    - For `Namespaced`-scoped operators, add a `+kubebuilder:resource:path=<resource>,scope=Namespaced` comment above your kind type in `pkg/apis/<group>/<version>/<kind>_types.go`.\n    - For `Cluster`-scoped operators, replace the `+genclient:nonNamespaced` comment above your kind type in `pkg/apis/<group>/<version>/<kind>_types.go` with `+kubebuilder:resource:path=<resource>,scope=Cluster`.\n- CRD file names now have the form `<full group>_<resource>_crd.yaml`, and CR file names now have the form `<full group>_<version>_<kind>_cr.yaml`. `<full group>` is the full group name of your CRD found at `spec.group`, and `<resource>` is the plural lower-case CRD Kind found at `spec.names.plural`. To migrate:\n    - Run `operator-sdk generate openapi`. CRD manifest files with new names containing versioned validation and subresource blocks will be generated.\n    - Delete the old CRD manifest files.\n    - Rename CR manifest file names from `<group>_<version>_<kind>_cr.yaml` to `<full group>_<version>_<kind>_cr.yaml`.\n\n## `v0.12.x`\n\n**Go version**\n\n- Ensure that you are using a go version 1.13+\n\n**dep**\n\nUsing `dep` is no longer supported. Follow [Go's official blog post about migrating to modules](https://blog.golang.org/migrating-to-go-modules) to learn how to migrate your project.\n\n**modules**\n\n- Ensure the following `require` modules and `replace` directives with the specific versions are present in your `go.mod` file:\n\n```\nrequire (\n    github.com/go-openapi/spec v0.19.0\n    github.com/operator-framework/operator-sdk v0.12.1-0.20191112211508-82fc57de5e5b\n    github.com/spf13/pflag v1.0.3\n    k8s.io/api v0.0.0\n    k8s.io/apimachinery v0.0.0\n    k8s.io/client-go v11.0.0+incompatible\n    k8s.io/kube-openapi v0.0.0-20190918143330-0270cf2f1c1d\n    sigs.k8s.io/controller-runtime v0.3.0\n)\n\n// Pinned to kubernetes-1.15.4\nreplace (\n    k8s.io/api => k8s.io/api v0.0.0-20190918195907-bd6ac527cfd2\n    k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.0.0-20190918201827-3de75813f604\n    k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20190817020851-f2f3a405f61d\n    k8s.io/apiserver => k8s.io/apiserver v0.0.0-20190918200908-1e17798da8c1\n    k8s.io/cli-runtime => k8s.io/cli-runtime v0.0.0-20190918202139-0b14c719ca62\n    k8s.io/client-go => k8s.io/client-go v0.0.0-20190918200256-06eb1244587a\n    k8s.io/cloud-provider => k8s.io/cloud-provider v0.0.0-20190918203125-ae665f80358a\n    k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.0.0-20190918202959-c340507a5d48\n    k8s.io/code-generator => k8s.io/code-generator v0.0.0-20190612205613-18da4a14b22b\n    k8s.io/component-base => k8s.io/component-base v0.0.0-20190918200425-ed2f0867c778\n    k8s.io/cri-api => k8s.io/cri-api v0.0.0-20190817025403-3ae76f584e79\n    k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.0.0-20190918203248-97c07dcbb623\n    k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.0.0-20190918201136-c3a845f1fbb2\n    k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.0.0-20190918202837-c54ce30c680e\n    k8s.io/kube-proxy => k8s.io/kube-proxy v0.0.0-20190918202429-08c8357f8e2d\n    k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.0.0-20190918202713-c34a54b3ec8e\n    k8s.io/kubelet => k8s.io/kubelet v0.0.0-20190918202550-958285cf3eef\n    k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.0.0-20190918203421-225f0541b3ea\n    k8s.io/metrics => k8s.io/metrics v0.0.0-20190918202012-3c1ca76f5bda\n    k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.0.0-20190918201353-5cc279503896\n)\n```\n\n**NOTE**: Check [here](https://github.com/operator-framework/operator-sdk-samples/pull/90/files#diff-e15cac8b95d260726ca9db9fb25d9230) an example of this upgrade to see the changes from the version `0.11.0` to `0.12.0`.\n\n- Run `go mod tidy` to update the project modules\n- Run the command `operator-sdk generate k8s` to ensure that your resources will be updated\n- Run the command `operator-sdk generate openapi` and ensure that no errors such as `API rule violation` are raised. For further information see the [API rules][api-rules] documentation.\n\n**(Optional) Update your operator to print its version**\n\nIn v0.12.0, the SDK team updated the scaffold for `cmd/manager/main.go` to include the operator's version in the output produced by the `printVersion()` function. See [#1953](https://github.com/operator-framework/operator-sdk/pull/1953)\n\nTo add this feature to your operator, add the following lines in `<project>/cmd/manager/main.go`:\n\n```go\nimport (\n\t...\n\t\"<your_module_path>/version\"\n\t...\n)\n\nfunc printVersion() {\n\tlog.Info(fmt.Sprintf(\"Operator Version: %s\", version.Version))\n\t...\n}\n```\n\n## `v0.13.x`\n\n**modules**\n\n- Ensure the following `require` modules and `replace` directives with the specific versions are present in your `go.mod` file:\n\n```\nrequire (\n\tgithub.com/operator-framework/operator-sdk v0.13.0\n\tsigs.k8s.io/controller-runtime v0.4.0\n)\n\n// Pinned to kubernetes-1.16.2\nreplace (\n\tk8s.io/api => k8s.io/api v0.0.0-20191016110408-35e52d86657a\n\tk8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.0.0-20191016113550-5357c4baaf65\n\tk8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20191004115801-a2eda9f80ab8\n\tk8s.io/apiserver => k8s.io/apiserver v0.0.0-20191016112112-5190913f932d\n\tk8s.io/cli-runtime => k8s.io/cli-runtime v0.0.0-20191016114015-74ad18325ed5\n\tk8s.io/client-go => k8s.io/client-go v0.0.0-20191016111102-bec269661e48\n\tk8s.io/cloud-provider => k8s.io/cloud-provider v0.0.0-20191016115326-20453efc2458\n\tk8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.0.0-20191016115129-c07a134afb42\n\tk8s.io/code-generator => k8s.io/code-generator v0.0.0-20191004115455-8e001e5d1894\n\tk8s.io/component-base => k8s.io/component-base v0.0.0-20191016111319-039242c015a9\n\tk8s.io/cri-api => k8s.io/cri-api v0.0.0-20190828162817-608eb1dad4ac\n\tk8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.0.0-20191016115521-756ffa5af0bd\n\tk8s.io/kube-aggregator => k8s.io/kube-aggregator v0.0.0-20191016112429-9587704a8ad4\n\tk8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.0.0-20191016114939-2b2b218dc1df\n\tk8s.io/kube-proxy => k8s.io/kube-proxy v0.0.0-20191016114407-2e83b6f20229\n\tk8s.io/kube-scheduler => k8s.io/kube-scheduler v0.0.0-20191016114748-65049c67a58b\n\tk8s.io/kubectl => k8s.io/kubectl v0.0.0-20191016120415-2ed914427d51\n\tk8s.io/kubelet => k8s.io/kubelet v0.0.0-20191016114556-7841ed97f1b2\n\tk8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.0.0-20191016115753-cf0698c3a16b\n\tk8s.io/metrics => k8s.io/metrics v0.0.0-20191016113814-3b1a734dba6e\n\tk8s.io/sample-apiserver => k8s.io/sample-apiserver v0.0.0-20191016112829-06bb3c9d77c9\n)\n```\n\n- Run `go mod tidy` to update the project modules\n- Run the command `operator-sdk generate k8s` to ensure that your resources will be updated\n- Run the command `operator-sdk generate crds` to regenerate CRDs\n\n**(Optional) Update the roles.yaml file**\n\nReplace `*` per verbs in order to solve the issue [671](https://github.com/operator-framework/operator-sdk/issues/671) and make clear the permissions used.\n\n**Example**\n\n```\n  verbs:\n  - create\n  - delete\n  - get\n  - list\n  - patch\n  - update\n  - watch\n```\n\n**Notable changes**\n\n- **Deprecated:** Deprecated the `operator-sdk generate openapi` command. CRD generation is still supported with `operator-sdk generate crds`. It is now recommended to use [openapi-gen](https://github.com/kubernetes/kube-openapi/tree/master/cmd/openapi-gen) directly for OpenAPI code generation. The `generate openapi` subcommand will be removed in a future release.\n- **Breaking change:** An existing CSV's `spec.customresourcedefinitions.owned` is now always overwritten except for each name, version, and kind on invoking olm-catalog gen-csv when Go API code annotations are present.\n- **Potentially Breaking change:** Be aware that there are potentially other breaking changes due to the controller-runtime and Kubernetes version be upgraded from `v0.4.0` to `v1.16.2`, respectively. There may be breaking changes to Go client code due to both of those changes.\n\nFor further detailed information see [CHANGELOG](https://github.com/operator-framework/operator-sdk/blob/v0.14.0/CHANGELOG.md#v0130)\n\n## `v0.14.x`\n\n**modules**\n\n- Ensure the following `require` modules and `replace` directives with the specific versions are present in your `go.mod` file:\n\n```\nrequire (\n\tgithub.com/operator-framework/operator-sdk v0.14.1\n\tsigs.k8s.io/controller-runtime v0.4.0\n)\n// Pinned to kubernetes-1.16.2\nreplace (\n\tk8s.io/api => k8s.io/api v0.0.0-20191016110408-35e52d86657a\n\tk8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.0.0-20191016113550-5357c4baaf65\n\tk8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20191004115801-a2eda9f80ab8\n\tk8s.io/apiserver => k8s.io/apiserver v0.0.0-20191016112112-5190913f932d\n\tk8s.io/cli-runtime => k8s.io/cli-runtime v0.0.0-20191016114015-74ad18325ed5\n\tk8s.io/client-go => k8s.io/client-go v0.0.0-20191016111102-bec269661e48\n\tk8s.io/cloud-provider => k8s.io/cloud-provider v0.0.0-20191016115326-20453efc2458\n\tk8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.0.0-20191016115129-c07a134afb42\n\tk8s.io/code-generator => k8s.io/code-generator v0.0.0-20191004115455-8e001e5d1894\n\tk8s.io/component-base => k8s.io/component-base v0.0.0-20191016111319-039242c015a9\n\tk8s.io/cri-api => k8s.io/cri-api v0.0.0-20190828162817-608eb1dad4ac\n\tk8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.0.0-20191016115521-756ffa5af0bd\n\tk8s.io/kube-aggregator => k8s.io/kube-aggregator v0.0.0-20191016112429-9587704a8ad4\n\tk8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.0.0-20191016114939-2b2b218dc1df\n\tk8s.io/kube-proxy => k8s.io/kube-proxy v0.0.0-20191016114407-2e83b6f20229\n\tk8s.io/kube-scheduler => k8s.io/kube-scheduler v0.0.0-20191016114748-65049c67a58b\n\tk8s.io/kubectl => k8s.io/kubectl v0.0.0-20191016120415-2ed914427d51\n\tk8s.io/kubelet => k8s.io/kubelet v0.0.0-20191016114556-7841ed97f1b2\n\tk8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.0.0-20191016115753-cf0698c3a16b\n\tk8s.io/metrics => k8s.io/metrics v0.0.0-20191016113814-3b1a734dba6e\n\tk8s.io/sample-apiserver => k8s.io/sample-apiserver v0.0.0-20191016112829-06bb3c9d77c9\n)\nreplace github.com/docker/docker => github.com/moby/moby v0.7.3-0.20190826074503-38ab9da00309 // Required by Helm\n```\n\n- Run `go mod tidy` to update the project modules\n- Run the command `operator-sdk generate k8s` to ensure that your resources will be updated\n- Run the command `operator-sdk generate crds` to regenerate CRDs\n\n**(Optional) Skip metrics logs when the operator is running locally**\n\nThere are changes to the default implementation of the metrics export. These changes require `cmd/manager/main.go` to be updated as follows.\n\nUpdate imports:\n\n```go\nimport (\n\t...\n\t\"errors\"\n\t...\n)\n```\n\nReplace:\n\n```go\nfunc main() {\n\t...\n\tif err = serveCRMetrics(cfg); err != nil {\n\t\tlog.Info(\"Could not generate and serve custom resource metrics\", \"error\", err.Error())\n\t}\n\n\t// Add to the below struct any other metrics ports you want to expose.\n\tservicePorts := []v1.ServicePort{\n\t\t{Port: metricsPort, Name: metrics.OperatorPortName, Protocol: v1.ProtocolTCP, TargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: metricsPort}},\n\t\t{Port: operatorMetricsPort, Name: metrics.CRPortName, Protocol: v1.ProtocolTCP, TargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: operatorMetricsPort}},\n\t}\n\t// Create Service object to expose the metrics port(s).\n\tservice, err := metrics.CreateMetricsService(ctx, cfg, servicePorts)\n\tif err != nil {\n\t\tlog.Info(\"Could not create metrics Service\", \"error\", err.Error())\n\t}\n\n\t// CreateServiceMonitors will automatically create the prometheus-operator ServiceMonitor resources\n\t// necessary to configure Prometheus to scrape metrics from this operator.\n\tservices := []*v1.Service{service}\n\t_, err = metrics.CreateServiceMonitors(cfg, namespace, services)\n\tif err != nil {\n\t\tlog.Info(\"Could not create ServiceMonitor object\", \"error\", err.Error())\n\t\t// If this operator is deployed to a cluster without the prometheus-operator running, it will return\n\t\t// ErrServiceMonitorNotPresent, which can be used to safely skip ServiceMonitor creation.\n\t\tif err == metrics.ErrServiceMonitorNotPresent {\n\t\t\tlog.Info(\"Install prometheus-operator in your cluster to create ServiceMonitor objects\", \"error\", err.Error())\n\t\t}\n\t}\n  ...\n}\n```\n\nWith:\n\n```go\nfunc main() {\n\t...\n\t// Add the Metrics Service\n\taddMetrics(ctx, cfg, namespace)\n  ...\n}\n```\n\nAnd then, add implementation for `addMetrics`:\n\n```go\n// addMetrics will create the Services and Service Monitors to allow the operator export the metrics by using\n// the Prometheus operator\nfunc addMetrics(ctx context.Context, cfg *rest.Config, namespace string) {\n\tif err := serveCRMetrics(cfg); err != nil {\n\t\tif errors.Is(err, k8sutil.ErrRunLocal) {\n\t\t\tlog.Info(\"Skipping CR metrics server creation; not running in a cluster.\")\n\t\t\treturn\n\t\t}\n\t\tlog.Info(\"Could not generate and serve custom resource metrics\", \"error\", err.Error())\n\t}\n\n\t// Add to the below struct any other metrics ports you want to expose.\n\tservicePorts := []v1.ServicePort{\n\t\t{Port: metricsPort, Name: metrics.OperatorPortName, Protocol: v1.ProtocolTCP, TargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: metricsPort}},\n\t\t{Port: operatorMetricsPort, Name: metrics.CRPortName, Protocol: v1.ProtocolTCP, TargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: operatorMetricsPort}},\n\t}\n\n\t// Create Service object to expose the metrics port(s).\n\tservice, err := metrics.CreateMetricsService(ctx, cfg, servicePorts)\n\tif err != nil {\n\t\tlog.Info(\"Could not create metrics Service\", \"error\", err.Error())\n\t}\n\n\t// CreateServiceMonitors will automatically create the prometheus-operator ServiceMonitor resources\n\t// necessary to configure Prometheus to scrape metrics from this operator.\n\tservices := []*v1.Service{service}\n\t_, err = metrics.CreateServiceMonitors(cfg, namespace, services)\n\tif err != nil {\n\t\tlog.Info(\"Could not create ServiceMonitor object\", \"error\", err.Error())\n\t\t// If this operator is deployed to a cluster without the prometheus-operator running, it will return\n\t\t// ErrServiceMonitorNotPresent, which can be used to safely skip ServiceMonitor creation.\n\t\tif err == metrics.ErrServiceMonitorNotPresent {\n\t\t\tlog.Info(\"Install prometheus-operator in your cluster to create ServiceMonitor objects\", \"error\", err.Error())\n\t\t}\n\t}\n}\n```\n\n**NOTE**: For more information check the PR which is responsible for the above changes [#2190](https://github.com/operator-framework/operator-sdk/pull/2190).\n\n**Deprecations**\n\nThe `github.com/operator-framework/operator-sdk/pkg/restmapper` package was deprecated in favor of the `DynamicRESTMapper` implementation in [controller-runtime](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/client/apiutil#NewDiscoveryRESTMapper). Users should migrate to controller-runtime's implementation, which is a drop-in replacement.\n\nReplace:\n```\ngithub.com/operator-framework/operator-sdk/pkg/restmapper.DynamicRESTMapper\n```\n\nWith:\n\n```\nsigs.k8s.io/controller-runtime/pkg/client/apiutil.DynamicRESTMapper\n```\n\n**Breaking Changes**\n\n**Add `operator_sdk.util` Ansible collection**\n\nThe Ansible module `k8s_status` was extracted and is now provided by the `operator_sdk.util` Ansible collection. See [developer_guide](/docs/building-operators/ansible/development-tips/#custom-resource-status-management) for new usage.\n\nTo use the collection in a role, declare it at the root level in `meta/main.yaml`:\n```yaml\ncollections:\n- operator_sdk.util\n```\n\nTo use it in a playbook, declare it in the play:\n```yaml\n- hosts: all\n  collections:\n   - operator_sdk.util\n  tasks:\n   - k8s_status:\n       api_version: app.example.com/v1\n       kind: Foo\n       name: \"{{ meta.name }}\"\n       namespace: \"{{ meta.namespace }}\"\n       status:\n         foo: bar\n```\n\nYou can also use the fully-qualified name without declaring the collection:\n```yaml\n   - operator_sdk.util.k8s_status:\n       api_version: app.example.com/v1\n       kind: Foo\n       name: \"{{ meta.name }}\"\n       namespace: \"{{ meta.namespace }}\"\n       status:\n         foo: bar\n```\n\n**Notable Changes**\n\nThese notable changes contain just the most important user-facing changes. See the [CHANGELOG](https://github.com/operator-framework/operator-sdk/blob/v0.15.0/CHANGELOG.md#v0141) for details of the release.\n\n**Ansible version update**\n\nThe Ansible version in the init projects was upgraded from `2.6` to `2.9` for collections support. Update the `meta/main.yaml` file.\n\nReplace:\n```yaml\n...\n min_ansible_version: 2.6\n...\n```\n\nWith:\n```yaml\n...\n min_ansible_version: 2.9\n...\n```\n\n**Helm Upgrade to V3**\n\nThe Helm operator packages and base image were upgraded from Helm v2 to Helm v3. Note that cluster state for pre-existing CRs using Helm v2-based operators will be automatically migrated to Helm v3's new release storage format, and existing releases may be upgraded due to changes in Helm v3's label injection.\n\nIf you are using any external helm v2 tooling with the your helm operator-managed releases, you will need to upgrade to the equivalent helm v3 tooling.\n\n## `v0.15.x`\n\n**modules**\n\n- Ensure the following `require` modules and `replace` directives with the specific versions are present in your `go.mod` file:\n\n```\nrequire (\n\tgithub.com/operator-framework/operator-sdk v0.15.2\n\tsigs.k8s.io/controller-runtime v0.4.0\n)\n// Pinned to kubernetes-1.16.2\nreplace (\n\tk8s.io/api => k8s.io/api v0.0.0-20191016110408-35e52d86657a\n\tk8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.0.0-20191016113550-5357c4baaf65\n\tk8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20191004115801-a2eda9f80ab8\n\tk8s.io/apiserver => k8s.io/apiserver v0.0.0-20191016112112-5190913f932d\n\tk8s.io/cli-runtime => k8s.io/cli-runtime v0.0.0-20191016114015-74ad18325ed5\n\tk8s.io/client-go => k8s.io/client-go v0.0.0-20191016111102-bec269661e48\n\tk8s.io/cloud-provider => k8s.io/cloud-provider v0.0.0-20191016115326-20453efc2458\n\tk8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.0.0-20191016115129-c07a134afb42\n\tk8s.io/code-generator => k8s.io/code-generator v0.0.0-20191004115455-8e001e5d1894\n\tk8s.io/component-base => k8s.io/component-base v0.0.0-20191016111319-039242c015a9\n\tk8s.io/cri-api => k8s.io/cri-api v0.0.0-20190828162817-608eb1dad4ac\n\tk8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.0.0-20191016115521-756ffa5af0bd\n\tk8s.io/kube-aggregator => k8s.io/kube-aggregator v0.0.0-20191016112429-9587704a8ad4\n\tk8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.0.0-20191016114939-2b2b218dc1df\n\tk8s.io/kube-proxy => k8s.io/kube-proxy v0.0.0-20191016114407-2e83b6f20229\n\tk8s.io/kube-scheduler => k8s.io/kube-scheduler v0.0.0-20191016114748-65049c67a58b\n\tk8s.io/kubectl => k8s.io/kubectl v0.0.0-20191016120415-2ed914427d51\n\tk8s.io/kubelet => k8s.io/kubelet v0.0.0-20191016114556-7841ed97f1b2\n\tk8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.0.0-20191016115753-cf0698c3a16b\n\tk8s.io/metrics => k8s.io/metrics v0.0.0-20191016113814-3b1a734dba6e\n\tk8s.io/sample-apiserver => k8s.io/sample-apiserver v0.0.0-20191016112829-06bb3c9d77c9\n)\nreplace github.com/docker/docker => github.com/moby/moby v0.7.3-0.20190826074503-38ab9da00309 // Required by Helm\nreplace github.com/openshift/api => github.com/openshift/api v0.0.0-20190924102528-32369d4db2ad // Required until https://github.com/operator-framework/operator-lifecycle-manager/pull/1241 is resolved\n```\n\n- Run `go mod tidy` to update the project modules\n- Run the command `operator-sdk generate k8s` to ensure that your resources will be updated\n- Run the command `operator-sdk generate crds` to regenerate CRDs\n\n**Breaking Changes on Commands**\n\nThis release contains breaking changes in some commands.\n\n- The `operator-sdk olm-catalog gen-csv` was replaced by `operator-sdk generate csv`\n- The `operator-sdk up local` is now `operator-sdk run --local`. However, all functionality of this command is retained.\n- And then, the `operator-sdk alpha olm [sub-commands] [flags]` was moved from `alpha` to its own sub-command. However, all functionality of this command is retained. To check run; `operator-sdk olm --help`.\n\n**Breaking Changes for Helm and Ansible**\n\nThe `operator-sdk run ansible/helm` are now hidden commands in `exec-entrypoint ansible/helm`. However, all functionality of each sub-command is still the same. If you are using this feature then you will need to replace the `run` for `exec-entrypoint` as the following examples.\n\nReplace:\n\n```\noprator-sdk run ansible --watches-file=/opt/ansible/watches.yaml\n```\n\nWith:\n\n```\noprator-sdk exec-entrypoint ansible --watches-file=/opt/ansible/watches.yaml\n```\n\n\nReplace:\n\n```\noprator-sdk run helm --watches-file=$HOME/watches.yaml\n```\n\nWith:\n\n```\noprator-sdk run exec-entrypoint helm --watches-file=$HOME/watches.yaml\n```\n\nSee the [CHANGELOG](https://github.com/operator-framework/operator-sdk/blob/v0.16.0/CHANGELOG.md#v0151) for details of the release.\n\n## v0.16.x\n\n**modules**\n\n- Ensure that the following `require` modules and `replace` directives with the specific versions are present in your `go.mod` file:\n\n```\nrequire (\n\tgithub.com/operator-framework/operator-sdk v0.16.0\n\tsigs.k8s.io/controller-runtime v0.4.0\n)\n\n// Pinned to kubernetes-1.16.2\nreplace (\n\tk8s.io/api => k8s.io/api v0.0.0-20191016110408-35e52d86657a\n\tk8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.0.0-20191016113550-5357c4baaf65\n\tk8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20191004115801-a2eda9f80ab8\n\tk8s.io/apiserver => k8s.io/apiserver v0.0.0-20191016112112-5190913f932d\n\tk8s.io/cli-runtime => k8s.io/cli-runtime v0.0.0-20191016114015-74ad18325ed5\n\tk8s.io/client-go => k8s.io/client-go v0.0.0-20191016111102-bec269661e48\n\tk8s.io/cloud-provider => k8s.io/cloud-provider v0.0.0-20191016115326-20453efc2458\n\tk8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.0.0-20191016115129-c07a134afb42\n\tk8s.io/code-generator => k8s.io/code-generator v0.0.0-20191004115455-8e001e5d1894\n\tk8s.io/component-base => k8s.io/component-base v0.0.0-20191016111319-039242c015a9\n\tk8s.io/cri-api => k8s.io/cri-api v0.0.0-20190828162817-608eb1dad4ac\n\tk8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.0.0-20191016115521-756ffa5af0bd\n\tk8s.io/kube-aggregator => k8s.io/kube-aggregator v0.0.0-20191016112429-9587704a8ad4\n\tk8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.0.0-20191016114939-2b2b218dc1df\n\tk8s.io/kube-proxy => k8s.io/kube-proxy v0.0.0-20191016114407-2e83b6f20229\n\tk8s.io/kube-scheduler => k8s.io/kube-scheduler v0.0.0-20191016114748-65049c67a58b\n\tk8s.io/kubectl => k8s.io/kubectl v0.0.0-20191016120415-2ed914427d51\n\tk8s.io/kubelet => k8s.io/kubelet v0.0.0-20191016114556-7841ed97f1b2\n\tk8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.0.0-20191016115753-cf0698c3a16b\n\tk8s.io/metrics => k8s.io/metrics v0.0.0-20191016113814-3b1a734dba6e\n\tk8s.io/sample-apiserver => k8s.io/sample-apiserver v0.0.0-20191016112829-06bb3c9d77c9\n)\n\nreplace github.com/docker/docker => github.com/moby/moby v0.7.3-0.20190826074503-38ab9da00309 // Required by Helm\nreplace github.com/openshift/api => github.com/openshift/api v0.0.0-20190924102528-32369d4db2ad // Required until https://github.com/operator-framework/operator-lifecycle-manager/pull/1241 is resolved\n```\n\n- Run `go mod tidy` to update the project modules\n- Run the command `operator-sdk generate k8s` to ensure that your resources will be updated\n- Run the command `operator-sdk generate crds` to regenerate CRDs\n\n**Bug Fixes and Improvements for Metrics**\n\nThere are changes to the default implementation of the metrics export. These changes require `cmd/manager/main.go` to be updated as follows.\n\nReplace:\n\n```go\nfunc main() {\n  ...\n  // Add the Metrics Service\n\taddMetrics(ctx, cfg, namespace)\n  ...\n}\n```\n\nWith:\n\n```go\nfunc main() {\n  ...\n\t// Add the Metrics Service\n\taddMetrics(ctx, cfg)\n  ...\n}\n```\n\nAnd then, update the default implementation of `addMetrics` and `serveCRMetrics` with:\n\n```go\n// addMetrics will create the Services and Service Monitors to allow the operator export the metrics by using\n// the Prometheus operator\nfunc addMetrics(ctx context.Context, cfg *rest.Config) {\n\t// Get the namespace the operator is currently deployed in.\n\toperatorNs, err := k8sutil.GetOperatorNamespace()\n\tif err != nil {\n\t\tif errors.Is(err, k8sutil.ErrRunLocal) {\n\t\t\tlog.Info(\"Skipping CR metrics server creation; not running in a cluster.\")\n\t\t\treturn\n\t\t}\n\t}\n\n\tif err := serveCRMetrics(cfg, operatorNs); err != nil {\n\t\tlog.Info(\"Could not generate and serve custom resource metrics\", \"error\", err.Error())\n\t}\n\n\t// Add to the below struct any other metrics ports you want to expose.\n\tservicePorts := []v1.ServicePort{\n\t\t{Port: metricsPort, Name: metrics.OperatorPortName, Protocol: v1.ProtocolTCP, TargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: metricsPort}},\n\t\t{Port: operatorMetricsPort, Name: metrics.CRPortName, Protocol: v1.ProtocolTCP, TargetPort: intstr.IntOrString{Type: intstr.Int, IntVal: operatorMetricsPort}},\n\t}\n\n\t// Create Service object to expose the metrics port(s).\n\tservice, err := metrics.CreateMetricsService(ctx, cfg, servicePorts)\n\tif err != nil {\n\t\tlog.Info(\"Could not create metrics Service\", \"error\", err.Error())\n\t}\n\n\t// CreateServiceMonitors will automatically create the prometheus-operator ServiceMonitor resources\n\t// necessary to configure Prometheus to scrape metrics from this operator.\n\tservices := []*v1.Service{service}\n\n\t// The ServiceMonitor is created in the same namespace where the operator is deployed\n\t_, err = metrics.CreateServiceMonitors(cfg, operatorNs, services)\n\tif err != nil {\n\t\tlog.Info(\"Could not create ServiceMonitor object\", \"error\", err.Error())\n\t\t// If this operator is deployed to a cluster without the prometheus-operator running, it will return\n\t\t// ErrServiceMonitorNotPresent, which can be used to safely skip ServiceMonitor creation.\n\t\tif err == metrics.ErrServiceMonitorNotPresent {\n\t\t\tlog.Info(\"Install prometheus-operator in your cluster to create ServiceMonitor objects\", \"error\", err.Error())\n\t\t}\n\t}\n}\n\n// serveCRMetrics gets the Operator/CustomResource GVKs and generates metrics based on those types.\n// It serves those metrics on \"http://metricsHost:operatorMetricsPort\".\nfunc serveCRMetrics(cfg *rest.Config, operatorNs string) error {\n\t// The function below returns a list of filtered operator/CR specific GVKs. For more control, override the GVK list below\n\t// with your own custom logic. Note that if you are adding third party API schemas, probably you will need to\n\t// customize this implementation to avoid permissions issues.\n\tfilteredGVK, err := k8sutil.GetGVKsFromAddToScheme(apis.AddToScheme)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// The metrics will be generated from the namespaces which are returned here.\n\t// NOTE that passing nil or an empty list of namespaces in GenerateAndServeCRMetrics will result in an error.\n\tns, err := kubemetrics.GetNamespacesForMetrics(operatorNs)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Generate and serve custom resource specific metrics.\n\terr = kubemetrics.GenerateAndServeCRMetrics(cfg, ns, filteredGVK, metricsHost, operatorMetricsPort)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n```\n\n**NOTE**: For more information check the PRs which are responsible for the above changes [#2606](https://github.com/operator-framework/operator-sdk/pull/2606),[#2603](https://github.com/operator-framework/operator-sdk/pull/2603) and [#2601](https://github.com/operator-framework/operator-sdk/pull/2601).\n\n**(Optional) Support for watching multiple namespaces**\n\nThere are changes to add support for watching multiple namespaces. These changes require `cmd/manager/main.go` to be updated as follows.\n\nUpdate imports:\n\n```go\nimport (\n\t...\n\t\"strings\"\n\n\t...\n\t\"sigs.k8s.io/controller-runtime/pkg/cache\"\n\t...\n)\n```\n\nReplace:\n\n```go\nfunc main() {\n\t...\n\t// Create a new Cmd to provide shared dependencies and start components\n\tmgr, err := manager.New(cfg, manager.Options{\n\t\tNamespace:          namespace,\n\t\tMetricsBindAddress: fmt.Sprintf(\"%s:%d\", metricsHost, metricsPort),\n\t})\n\tif err != nil {\n\t\tlog.Error(err, \"\")\n\t\tos.Exit(1)\n\t}\n  ...\n}\n```\n\nWith:\n\n```go\nfunc main() {\n\t...\n\t// Set default manager options\n\toptions := manager.Options{\n\t\tNamespace:          namespace,\n\t\tMetricsBindAddress: fmt.Sprintf(\"%s:%d\", metricsHost, metricsPort),\n\t}\n\n\t// Add support for MultiNamespace set in WATCH_NAMESPACE (e.g ns1,ns2)\n\t// Note that this is not intended to be used for excluding namespaces, this is better done via a Predicate\n\t// Also note that you may face performance issues when using this with a high number of namespaces.\n\t// More Info: https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/cache#MultiNamespacedCacheBuilder\n\tif strings.Contains(namespace, \",\") {\n\t\toptions.Namespace = \"\"\n\t\toptions.NewCache = cache.MultiNamespacedCacheBuilder(strings.Split(namespace, \",\"))\n\t}\n\n\t// Create a new manager to provide shared dependencies and start components\n\tmgr, err := manager.New(cfg, options)\n\tif err != nil {\n\t\tlog.Error(err, \"\")\n\t\tos.Exit(1)\n\t}\n  ...\n}\n```\n\n**NOTE**: For more information check the PR which is responsible for the above changes [#2522](https://github.com/operator-framework/operator-sdk/pull/2522).\n\n**Breaking changes**\n\n**`TestCtx` in `pkg/test` has been deprecated**\n\n The type name `TestCtx` in `pkg/test` has been deprecated and renamed to `Context`. Users of the e2e framework should do the following:\n\n - Replace `TestCtx` with `Context`\n - Replace `NewTestCtx` with `NewContext`\n\n**Scorecard only supports YAML config files**\n\nThe scorecard feature now only supports YAML config files. Config files with other extensions are no longer supported and should be changed to the YAML format. For further information see [`scorecard config file`](https://github.com/operator-framework/operator-sdk/blob/v0.16.x/doc/test-framework/scorecard.md#config-file)\n\n**Breaking Changes for Ansible**\n\n**Remove Ansible container sidecar**\n\nThe Ansible logs are now output in the operator container, so there is no longer a need for the Ansible container sidecar. To reflect this change, update the `deploy/operator.yaml` file as follows.\n\nRemove:\n\n```\n- name: ansible\n  command:\n    - /usr/local/bin/ao-logs\n    - /tmp/ansible-operator/runner\n    - stdout\n  # Replace this with the built image name**\n  image: \"REPLACE_IMAGE\"\n  imagePullPolicy: \"Always\"\n  volumeMounts:\n    - mountPath: /tmp/ansible-operator/runner\n    name: runner\n    readOnly: true\n```\n\nReplace:\n\n```yaml\n- name: operator\n```\n\nWith:\n\n```yaml\n- name: {{your operator name which is the value of metadata.name in this file}}\n```\n\nBy default the full Ansible logs will not be output, however, you can setup it via the `ANSIBLE_DEBUG_LOGS` environment variable in the `deploy/operator.yaml` file. See:\n\n```\n...\n- name: ANSIBLE_DEBUG_LOGS\n  value: \"True\"\n...\n```\n\n**Migration to Ansible collections**\n\nThe core Ansible Kubernetes modules have been moved to the [`community.kubernetes` Ansible collection][kubernetes-ansible-collection]. Future development of the modules will occur there, with only critical bugfixes going into the modules in core. Additionally, the `operator_sdk.util` collection is no longer installed by default in the base image. Instead, users should add a `requirements.yml` to their project root, with the following content:\n\n```yaml\ncollections:\n  - kubernetes.core\n  - operator_sdk.util\n  - cloud.common\n```\n\nUsers should then add the following stages to their `build/Dockerfile`:\n\n```\nCOPY requirements.yml ${HOME}/requirements.yml\nRUN ansible-galaxy collection install -r ${HOME}/requirements.yml \\\n && chmod -R ug+rwx ${HOME}/.ansible\n```\n\n## v0.17.x\n\n**modules**\n\n- Ensure that the following `require` modules and `replace` directives with the specific versions are present in your `go.mod` file:\n\n```\nrequire (\n\tgithub.com/operator-framework/operator-sdk v0.17.2\n\tsigs.k8s.io/controller-runtime v0.5.2\n)\n\nreplace (\n  k8s.io/client-go => k8s.io/client-go v0.17.4 // Required by prometheus-operator\n  github.com/Azure/go-autorest => github.com/Azure/go-autorest v13.3.2+incompatible // Required by OLM\n)\n```\n\n- Run `go mod tidy` to update the project modules\n- Run the command `operator-sdk generate k8s` to ensure that your resources will be updated\n- Run the command `operator-sdk generate crds` to regenerate CRDs\n\n**Breaking Changes**\n\n**OpenAPI generation**\n\n- The deprecated `operator-sdk generate openapi` command has been removed. This command generated CRDs and\n  `zz_generated.openapi` files for operator APIs.\n\nTo generate CRDs, use `operator-sdk generate crds`.\n\nTo generate Go OpenAPI code, use `openapi-gen` directly. For example:\n\n```bash\n# Build the latest openapi-gen from source\nwhich ./bin/openapi-gen > /dev/null || go build -o ./bin/openapi-gen k8s.io/kube-openapi/cmd/openapi-gen\n\n# Run openapi-gen for each of your API group/version packages\n./bin/openapi-gen --logtostderr=true \\\n                  -i ./pkg/apis/<group>/<version> \\\n                  -o \"\" \\\n                  -O zz_generated.openapi \\\n                  -p ./pkg/apis/<group>/<version> \\\n                  -h ./hack/boilerplate.go.txt \\\n                  -r \"-\"\n```\n\n**Molecule Upgrade for Ansible based-operators**\n\nThe Molecule version for Ansible based-operators was upgraded from `2.22` to `3.0.2`. The following changes are required in the default scaffold files.\n\n- Remove the `scenario.name` from `molecule.yaml` and then, ensure that any condition with will look for the folder name which determines the scenario name from now on\n- Replace the lint with newer syntax from [documentation](https://molecule.readthedocs.io/contributing/#linting). See:\n\nReplace:\n\n```yaml\nlint:\n  name: yamllint\n  options:\n    config-data:\n      line-length:\n        max: 120\n```\n\nWith:\n\n```yaml\nlint: |\n  set -e\n  yamllint -d \"{extends: relaxed, rules: {line-length: {max: 120}}}\" .\n```\n\nReplace:\n\n```yaml\nlint:\n  name: ansible-lint\n```\n\nWith:\n\n```yaml\nlint: |\n  set -e\n  ansible-lint\n```\n\n- Rename `molecule/$SCENARIO/playbook.yml` to `molecule/$SCENARIO/converge.yml` to avoid a deprecation message.\n- Update the `.travis.yml` file to install the supported lints as follows.\n\nReplace:\n\n```yaml\ninstall:\n  - pip3 install docker molecule openshift jmespath\n```\n\nWith:\n\n```yaml\ninstall:\n  - pip3 install docker molecule ansible-lint yamllint flake8 openshift jmespath\n```\n\n**NOTE** To know more about how to upgrade your project to use the V3 Molecule version see [here](https://github.com/ansible-community/molecule/issues/2560).\n\n**Deprecations**\n\n**Test Framework**\n\n- The methods `ctx.GetOperatorNamespace()` and `ctx.GetWatchNamespace()` were added to `pkg/test` in order to replace\n`ctx.GetNamespace()` which is deprecated. In this way, replace the use of `ctx.GetNamespace()` in your project with\n`ctx.GetOperatorNamespace()`.\n- The `--namespace` flag from `operator-sdk run --local`, `operator-sdk test --local`, and `operator-sdk cleanup` was\ndeprecated and is replaced by `--watch-namespace` and `--operator-namespace`.\n\n    The `--operator-namespace` flag can be used to set the namespace where the operator will be deployed. It will set the\n    environment variable `OPERATOR_NAMESPACE`. If this value is not set, then it will be the namespace defined as in your\n    current kubeconfig context.\n\n    The `--watch-namespace` flag can be used to set the namespace(s) which the operator will watch for changes. It will set\n    the environment variable `WATCH_NAMESPACE`. Use an explicit empty string to watch all namespaces or a comma-separated\n    list of namespaces (e.g. \"ns1,ns2\") to watch multiple namespace when the operator is cluster-scoped. If using a list,\n    then it should contain the namespace where the operator is deployed since the default metrics implementation will\n    manage resources in the Operator's namespace. By default, `--watch-namespace` will be set to the operator namespace.\n\n- If you've run `operator-sdk bundle create --generate-only`, move your bundle Dockerfile at\n`<project-root>/deploy/olm-catalog/<operator-name>/Dockerfile` to `<project-root>/bundle.Dockerfile` and update the\nfirst `COPY` from `COPY /*.yaml manifests/` to `COPY deploy/olm-catalog/<operator-name>/manifests manifests/`.\n\n[legacy-kubebuilder-doc-crd]: https://book-v1.book.kubebuilder.io/beyond_basics/generating_crd.html\n[v0.8.2-go-mod]: https://github.com/operator-framework/operator-sdk/blob/28bd2b0d4fd25aa68e15d928ae09d3c18c3b51da/internal/pkg/scaffold/go_mod.go#L40-L94\n[activating-modules]: https://github.com/golang/go/wiki/Modules#how-to-install-and-activate-module-support\n[mercurial]: https://www.mercurial-scm.org/downloads\n[migrating-to-modules]: https://github.com/golang/go/wiki/Modules#migrating-to-modules\n[modules-wiki]: https://github.com/golang/go/wiki/Modules#migrating-to-modules\n[print-deps-cli]: https://github.com/operator-framework/operator-sdk/blob/v0.19.x/website/content/en/docs/cli/operator-sdk_print-deps.md\n[changelog]: https://github.com/operator-framework/operator-sdk/blob/v1.3.0/CHANGELOG.md\n[release-notes]: https://github.com/operator-framework/operator-sdk/releases\n[v0.1.0-migration-guide]: ../v0.1.0-migration-guide\n[manifest-format]: https://github.com/operator-framework/operator-registry#manifest-format\n[client-doc]: https://github.com/operator-framework/operator-sdk/blob/v0.19.x/website/content/en/docs/golang/references/client.md\n[api-rules]: https://github.com/kubernetes/kubernetes/tree/36981002246682ed7dc4de54ccc2a96c1a0cbbdb/api/api-rules\n[generating-crd]: https://book.kubebuilder.io/reference/generating-crd.html\n[markers]: https://book.kubebuilder.io/reference/markers.html\n[kubernetes-ansible-collection]: https://github.com/ansible-collections/kubernetes\n"
  },
  {
    "path": "website/content/en/search.md",
    "content": "---\ntitle: Search Results\nlayout: search\n---\n"
  },
  {
    "path": "website/layouts/404.html",
    "content": "{{ define \"main\"}}\n    <main id=\"main\">\n      <div>\n       <h1 id=\"title\">Not found</h1>\n       <p>Oops! This page doesn't exist. Try going back to our <a href=\"{{ \"/\" | relURL }}\">home page</a>.</p>\n\n       <p>You can learn how to make a 404 page like this in <a href=\"https://gohugo.io/templates/404/\">Custom 404 Pages</a>.</p>      \n      </div>\n    </main>\n{{ end }}\n"
  },
  {
    "path": "website/layouts/_default/baseof.html",
    "content": "<!doctype html>\n<html lang=\"{{ .Site.Language.Lang }}\" class=\"no-js\">\n  <head>\n    {{ partial \"head.html\" . }}\n  </head>\n  <body class=\"td-{{ .Kind }}\">\n      {{ partial \"navbar.html\" . }}\n      {{ block \"main\" . }}\n      {{ end }}\n      {{ partial \"footer.html\" . }}\n  </body>\n</html>"
  },
  {
    "path": "website/layouts/_default/single.html",
    "content": "{{ define \"main\" }}\n{{ .Render \"content\" }}\n{{ end }}"
  },
  {
    "path": "website/layouts/build/single.html",
    "content": "{{ define \"main\" }}\n{{ .Render \"content\" }}\n{{ end }}"
  },
  {
    "path": "website/layouts/docs/baseof.html",
    "content": "<!doctype html>\n<html lang=\"{{ .Site.Language.Lang }}\" class=\"no-js\">\n  <head>\n    {{ partial \"head.html\" . }}\n  </head>\n  <body class=\"td-{{ .Kind }}\">\n    <header>\n      {{ partial \"navbar.html\" . }}\n    </header>\n    <div class=\"container-fluid td-outer\">\n      <div class=\"td-main\">\n        <div class=\"row flex-xl-nowrap\">\n          <div class=\"col-12 col-md-3 col-xl-2 td-sidebar d-print-none\">\n            {{ partial \"sidebar.html\" . }}\n          </div>\n          <div class=\"d-none d-xl-block col-xl-2 td-toc d-print-none\">\n            {{ partial \"toc.html\" . }}\n          </div>\n          <main class=\"col-12 col-md-9 col-xl-8 pl-md-5 of-docs__wrapper\" role=\"main\">\n            {{ partial \"version-banner.html\" . }}\n            {{ if not .Site.Params.ui.breadcrumb_disable }}{{ partial \"breadcrumb.html\" . }}{{ end }}\n            {{ block \"main\" . }}{{ end }}\n          </main>\n        </div>\n      </div>\n      <div class=\"row flex-xl-nowrap\">\n        {{ partial \"footer.html\" . }}\n      </div>\n    </div>\n    {{ partial \"scripts.html\" . }}\n  </body>\n</html>"
  },
  {
    "path": "website/layouts/docs/list.html",
    "content": "{{ define \"main\" }}\n<div class=\"td-content\">\n\t<h1>{{ .Title }}</h1>\n\t{{ with .Params.description }}<div class=\"lead\">{{ . | markdownify }}</div>{{ end }}\n\t{{ .Content }}\n        {{ partial \"section-index.html\" . }}\n\t{{ if (and (not .Params.hide_feedback) (.Site.Params.ui.feedback.enable) (.Site.GoogleAnalytics)) }}\n\t\t{{ partial \"feedback.html\" .Site.Params.ui.feedback }}\n\t\t<br />\n\t{{ end }}\n\t{{ if (.Site.DisqusShortname) }}\n\t\t<br />\n\t\t{{ partial \"disqus-comment.html\" . }}\n\t{{ end }}\n\t<div class=\"text-muted mt-5 pt-3 border-top\">{{ partial \"page-meta-lastmod.html\" . }}</div>\n</div>\n{{ end }}\n"
  },
  {
    "path": "website/layouts/docs/single.html",
    "content": "{{ define \"main\" }}\n{{ .Render \"content\" }}\n{{ end }}"
  },
  {
    "path": "website/layouts/faq/baseof.html",
    "content": "<!doctype html>\n<html lang=\"{{ .Site.Language.Lang }}\" class=\"no-js\">\n  <head>\n    {{ partial \"head.html\" . }}\n  </head>\n  <body class=\"td-{{ .Kind }}\">\n      {{ partial \"navbar.html\" . }}\n      <section class=\"of-masthead of-masthead--subpage\">\n      <h1 class=\"of-heading of-heading--xl\">Frequently asked questions</h1>\n    </section>\n    <section class=\"of-section-page-intro\">\n      <header class=\"of-section-page-intro__header\">\n        <h2 class=\"of-heading of-heading--md\">Frequently asked questions</h1>\n      <p>If you are a community member, builder, consumer of applications, or a user of Kubernetes overall, the Operator SDK offers a number of benefits.</p>\n      </header>\n    </section>\n    \n         <main role=\"main\">\n          <section class=\"of-section-page-intro__content of-page--faq\">\n            {{ .Content }}\n          </section>\n          </main>       \n        {{ partial \"footer.html\" . }}\n  </body>\n</html>"
  },
  {
    "path": "website/layouts/index.html",
    "content": "<!doctype html>\n<html lang=\"{{ .Site.Language.Lang }}\" class=\"no-js\">\n  <head>\n    {{ partial \"head.html\" . }}\n  </head>\n  <body class=\"td-{{ .Kind }}\">\n    <header>\n      {{ partial \"navbar.html\" . }}\n    </header>\n    \n      <main role=\"main\" class=\"td-main\">\n        <section class=\"of-masthead of-masthead--home\">\n          <h1 class=\"of-heading of-masthead--home__title\"><span>Operator</span><span>SDK</span></h1>\n          <h2 class=\"of-heading of-heading--md of-masthead--home__content\">The Operator SDK makes it easier to build Kubernetes native applications, a process that can require deep, application-specific operational knowledge.</h2>\n          <a href=\"/build\" class=\"of-button of-button--primary of-masthead--home__action1\">Build an Operator</a>\n          <!-- <a href=\"#\" class=\"of-button of-button--secondary of-masthead--home__action2\" aria-label=\"how can I build an operator\">How can I build one?</a> -->\n        </section>\n        \n          <section class=\"of-section-page-intro \">\n            <header class=\"of-section-page-intro__header\">\n              <h2 class=\"of-heading of-heading--md\">WHAT IS OPERATOR SDK?</h2>\n            <p>This project is a component of the <a href=\"https://github.com/operator-framework\">Operator Framework</a>, an open source toolkit to manage Kubernetes native applications, called Operators, in an effective, automated, and scalable way.</p>\n            </header>\n          </section>\n          <section class=\"of-section of-section-whats-operator of-section-separator\">\n            <aside class=\"of-section-whats-operator__video\"></aside> \n           <div class=\"of-section-whats-operator__content\">\n            <h2 class=\"of-heading of-heading--md\">WHAT CAN I DO WITH OPERATOR SDK?</h2>\n            <p>The Operator SDK provides the tools to build, test, and package Operators. Initially, the SDK facilitates the marriage of an application’s business logic (for example, how to scale, upgrade, or backup) with the Kubernetes API to execute those operations. Over time, the SDK can allow engineers to make applications smarter and have the user experience of cloud services. Leading practices and code patterns that are shared across Operators are included in the SDK to help prevent reinventing the wheel.</p>\n        <p>The Operator SDK is a framework that uses the controller-runtime library to make writing operators easier by providing:</p>\n        <ul class=\"of-list\">\n          <li>High level APIs and abstractions to write the operational logic more intuitively</li>\n          <li>Tools for scaffolding and code generation to bootstrap a new project fast</li>\n          <li>Extensions to cover common Operator use cases</li>\n        </ul>    \n        <a href=\"/build\" class=\"of-button of-button--tertiary\">\n              Build an Operator\n              <svg class=\"of-button__icon\" enable-background=\"new 0 0 22 22\" version=\"1.1\" viewBox=\"0 0 22 22\" xml:space=\"preserve\" xmlns=\"http://www.w3.org/2000/svg\">\n                <path d=\"M19.5,8l-7.3-7.6c-0.4-0.4-1.1-0.4-1.5,0L9.3,1.8c-0.4,0.4-0.4,1.1,0,1.6l5.2,5.5H1.1C0.5,8.9,0,9.3,0,10V12  c0,0.6,0.5,1.1,1.1,1.1h13.5l-5.2,5.5c-0.4,0.4-0.4,1.1,0,1.6l1.4,1.5c0.4,0.4,1.1,0.4,1.5,0l9.4-9.9c0.4-0.4,0.4-1.1,0-1.6L19.5,8z  \"/>\n                </svg>\n            </a>\n           </div>\n          </section>\n          <section class=\"of-section-page-develop\">\n              <h1 class=\"of-heading of-heading--md\">Develop in Go, Ansible, or Helm</h1>\n            <div class=\"of-section-page-intro__items\">\n              <div class=\"of-section-page-intro__item of-section-page-intro__item__build\">\n                  <h3 class=\"of-heading of-heading--lg\">Go</h3>\n                  <div class=\"of-section-page-intro__item__content\">\n                  <ol>\n                    <li>Create a new operator project using the SDK Command Line Interface (CLI)</li>\n                    <li>Define new resource APIs by adding Custom Resource Definitions (CRD)</li>\n                    <li>Define Controllers to watch and reconcile resources</li>\n                    <li>Write the reconciling logic for your Controller using the SDK and controller-runtime APIs</li>\n                    <li>Use the SDK CLI to build and generate the operator deployment manifests</li>\n                  </ol>\n           \n                  <a href=\"/docs/building-operators/golang/quickstart/\" class=\"of-button of-button--tertiary\">\n                    Develop with Go\n                  <svg class=\"of-button__icon\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\" width=\"22px\"\n                  height=\"22px\" viewBox=\"0 0 22 22\" style=\"enable-background:new 0 0 22 22;\" xml:space=\"preserve\">\n                  <path  d=\"M19.5,8l-7.3-7.6c-0.4-0.4-1.1-0.4-1.5,0L9.3,1.8c-0.4,0.4-0.4,1.1,0,1.6l5.2,5.5H1.1C0.5,8.9,0,9.3,0,10V12  c0,0.6,0.5,1.1,1.1,1.1h13.5l-5.2,5.5c-0.4,0.4-0.4,1.1,0,1.6l1.4,1.5c0.4,0.4,1.1,0.4,1.5,0l9.4-9.9c0.4-0.4,0.4-1.1,0-1.6L19.5,8z  \"/>\n                  </svg>\n                </a>  \n                </div>\n              </div>\n              <div class=\"of-section-page-intro__item of-section-page-intro__item__manage\">\n                  <h3 class=\"of-heading of-heading--lg\">Ansible</h3>\n                  <div class=\"of-section-page-intro__item__content\">\n                    <ol>\n                      <li>Create a new operator project using the SDK Command Line Interface (CLI)</li>\n                      <li>Write the reconciling logic for your object using ansible playbooks and roles</li>\n                      <li>Use the SDK CLI to build and generate the operator deployment manifests</li>\n                      <li>Optionally add additional CRD's using the SDK CLI and repeat steps 2 and 3</li>\n                    </ol>\t\n                <a href=\"/docs/building-operators/ansible/quickstart/\" class=\"of-button of-button--tertiary\">\n                  Develop with Ansible\n                  <svg class=\"of-button__icon\" enable-background=\"new 0 0 22 22\" version=\"1.1\" viewBox=\"0 0 22 22\" xml:space=\"preserve\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <path d=\"M19.5,8l-7.3-7.6c-0.4-0.4-1.1-0.4-1.5,0L9.3,1.8c-0.4,0.4-0.4,1.1,0,1.6l5.2,5.5H1.1C0.5,8.9,0,9.3,0,10V12  c0,0.6,0.5,1.1,1.1,1.1h13.5l-5.2,5.5c-0.4,0.4-0.4,1.1,0,1.6l1.4,1.5c0.4,0.4,1.1,0.4,1.5,0l9.4-9.9c0.4-0.4,0.4-1.1,0-1.6L19.5,8z  \"/>\n                  </svg>\n                </a>\n                </div>\n              </div>\n              <div class=\"of-section-page-intro__item of-section-page-intro__item__discover\">\n                  <h3 class=\"of-heading of-heading--lg\">Helm</h3>\n                  <div class=\"of-section-page-intro__item__content\">\n                  <ol>\n                    <li>Create a new operator project using the SDK Command Line Interface (CLI)</li>\n                    <li>Create a new (or add your existing) Helm chart for use by the operator’s reconciling logic</li>\n                    <li>Use the SDK CLI to build and generate the operator deployment manifests</li>\n                    <li>Optionally add additional CRD’s using the SDK CLI and repeat steps 2 and 3</li>\n                  </ol>\t\n                    <a href=\"/docs/building-operators/helm/quickstart/\" class=\"of-button of-button--tertiary\">\n                  Develop with Helm\n                  <svg class=\"of-button__icon\" enable-background=\"new 0 0 22 22\" version=\"1.1\" viewBox=\"0 0 22 22\" xml:space=\"preserve\" xmlns=\"http://www.w3.org/2000/svg\">\n                  <path d=\"M19.5,8l-7.3-7.6c-0.4-0.4-1.1-0.4-1.5,0L9.3,1.8c-0.4,0.4-0.4,1.1,0,1.6l5.2,5.5H1.1C0.5,8.9,0,9.3,0,10V12  c0,0.6,0.5,1.1,1.1,1.1h13.5l-5.2,5.5c-0.4,0.4-0.4,1.1,0,1.6l1.4,1.5c0.4,0.4,1.1,0.4,1.5,0l9.4-9.9c0.4-0.4,0.4-1.1,0-1.6L19.5,8z  \"/>\n                  </svg>\n                </a>  \n                </div>\n              </div>\n            </div>\n          </section>\n          <section class=\"of-section of-section__contribute\">\n            <header class=\"of-section__contribute__header\">\n              <h2 class=\"of-heading of-heading--lg\">Contribute!</h2>\n              <svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\" width=\"26px\"\n        height=\"18px\" viewBox=\"0 0 26 18\" style=\"enable-background:new 0 0 26 18;\" xml:space=\"preserve\">\n        <style type=\"text/css\">\n        .st3{fill:#002032;}\n        </style>\n        <path class=\"st3\" d=\"M14.9,11.5l11-9C25.8,1.1,24.6,0,23.2,0H2.8C1.4,0,0.2,1.1,0,2.5l11,9C12.2,12.4,13.8,12.4,14.9,11.5z\"/>\n        <path class=\"st3\" d=\"M15.9,12.6c-0.8,0.7-1.8,1-2.9,1s-2-0.3-2.9-1L0,4.4v10.8C0,16.7,1.3,18,2.8,18h20.3c1.6,0,2.8-1.3,2.8-2.8\n         V4.4L15.9,12.6z\"/>\n        </svg>\n        <svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\" width=\"25px\"\n           height=\"25px\" viewBox=\"0 0 25 25\" style=\"enable-background:new 0 0 25 25;\" xml:space=\"preserve\">\n        <style type=\"text/css\">\n          .st2{fill-rule:evenodd;clip-rule:evenodd;fill:#002032;}\n        </style>\n        <path class=\"st2\" d=\"M12.5,0C5.6,0,0,5.7,0,12.8C0,18.5,3.6,23.3,8.5,25c0.6,0.1,0.9-0.3,0.9-0.6c0-0.3,0-1.3,0-2.4\n          c-3.1,0.6-4-0.8-4.2-1.5C5,20.1,4.4,19,3.9,18.7c-0.4-0.2-1.1-0.8,0-0.8c1,0,1.7,0.9,1.9,1.3c1.1,1.9,2.9,1.4,3.6,1.1\n          c0.1-0.8,0.4-1.4,0.8-1.7c-2.8-0.3-5.7-1.4-5.7-6.3c0-1.4,0.5-2.5,1.3-3.4C5.7,8.4,5.3,7.1,6,5.3c0,0,1-0.3,3.4,1.3\n          c1-0.3,2.1-0.4,3.1-0.4c1.1,0,2.1,0.1,3.1,0.4C18,5,19.1,5.3,19.1,5.3c0.7,1.8,0.2,3.1,0.1,3.4c0.8,0.9,1.3,2,1.3,3.4\n          c0,4.9-2.9,6-5.7,6.3c0.5,0.4,0.8,1.2,0.8,2.4c0,1.7,0,3.1,0,3.5c0,0.3,0.2,0.7,0.9,0.6c4.9-1.7,8.5-6.5,8.5-12.2\n          C25,5.7,19.4,0,12.5,0z\"/>\n        </svg>\n            </header>\n            \n            <p class=\"of-section__contribute__content\">The Operator SDK and its components are open source, so please feel encouraged to jump into each individually and learn what else you can do. If you want to discuss your experience, have questions, or want to get involved, join the <a href=\"https://groups.google.com/forum/#!forum/operator-framework\" class=\"of-link of-link--inline\">Operator SDK forum</a> and visit us on <a href=\"https://github.com/operator-framework/operator-sdk\" class=\"of-link of-link--inline\">GitHub</a>.</p>\n          </section>\n      </main>\n      {{ partial \"footer.html\" . }}\n    {{ partialCached \"scripts.html\" . }}\n  </body>\n</html>\n"
  },
  {
    "path": "website/layouts/partials/footer.html",
    "content": "{{ $links := .Site.Params.links }}\n<footer class=\"of-footer-main\">\n  <div class=\"of-footer-main__meta\">\n    <img src=\"/build/images/logo.svg\" alt=\"\">\n    <p class=\"of-footer-main__meta__text\">The Operator Framework is an open source toolkit to manage Kubernetes native applications, called Operators, in an effective, automated, and scalable way.</p>\n    <ul class=\"of-link-list of-link-list--secondary\">\n      <li class=\"of-link-list__li\"><a class=\"of-link-list__a\" href=\"https://github.com/operator-framework\">Operator Framework</a></li>\n      <li class=\"of-link-list__li\"><a class=\"of-link-list__a\" href=\"https://github.com/operator-framework/operator-lifecycle-manager\">Operator Lifecycle Manager</a></li>\n      <li class=\"of-link-list__li\"><a class=\"of-link-list__a\" class=\"of-link of-link--external\" href=\"https://operatorhub.io/\">OperatorHub</a></li>\n    </ul>\n  </div>\n  <div class=\"of-footer-main__social\">\n    <h4 class=\"of-heading of-heading--sm\">Connect with us!</h4>\n      {{ with $links }}\n        {{ with index . \"social\"}}\n        {{ template \"footer-links-block\"  . }}\n      {{ end }}\n    {{ end }}\n  </div>\n  <div class=\"of-footer-main__copyright\">\n    <p>Copyright &copy; 2020</p>\n    <a class=\"of-footer-main__badge\" href=\"https://www.netlify.com\">\n      <img src=\"https://www.netlify.com/v3/img/components/netlify-color-accent.svg\" alt=\"Deploys by Netlify\" />\n    </a>\n  </div>\n</footer>\n</body>\n</html>\n{{ define \"footer-links-block\" }}\n    <ul class=\"of-link-list\">\n      {{ range . }}\n        <li class=\"of-link-list__li\">\n          <a class=\"of-link-list__a\" href=\"{{ .url }}\" aria-label=\"{{ .name }}\">\n            <i class=\"{{ .icon }}\"></i>\n          </a>\n        </li>\n      {{ end }}\n</ul>\n{{ end }}\n"
  },
  {
    "path": "website/layouts/partials/head.html",
    "content": "<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n{{ hugo.Generator }}\n{{ if eq (getenv \"HUGO_ENV\") \"production\" }}\n<META NAME=\"ROBOTS\" CONTENT=\"INDEX, FOLLOW\">\n{{ else }}\n<META NAME=\"ROBOTS\" CONTENT=\"NOINDEX, NOFOLLOW\">\n{{ end }}\n{{ range .AlternativeOutputFormats -}}\n<link rel=\"{{ .Rel }}\" type=\"{{ .MediaType.Type }}\" href=\"{{ .Permalink | safeURL }}\">\n{{ end -}}\n{{ partialCached \"favicons.html\" . }}\n<title>{{ if .IsHome }}{{ .Site.Title }}{{ else }}{{ with .Title }}{{ . }} | {{ end }}{{ .Site.Title }}{{ end }}</title>\n{{- template \"_internal/opengraph.html\" . -}}\n{{- template \"_internal/schema.html\" . -}}\n{{- template \"_internal/twitter_cards.html\" . -}}\n{{ if eq (getenv \"HUGO_ENV\") \"production\" }}\n{{ template \"_internal/google_analytics_async.html\" . }}\n{{ end }}\n{{ partialCached \"head-css.html\" . \"asdf\" }}\n<script\n  src=\"https://code.jquery.com/jquery-3.3.1.min.js\"\n  integrity=\"sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=\"\n  crossorigin=\"anonymous\"></script>\n{{ if .Site.Params.offlineSearch }}\n<script\n  src=\"https://unpkg.com/lunr@2.3.8/lunr.min.js\"\n  integrity=\"sha384-vRQ9bDyE0Wnu+lMfm57BlYLO0/XauFuKpVsZPs7KEDwYKktWi5+Kz3MP8++DFlRY\"\n  crossorigin=\"anonymous\"></script>\n{{end}}\n{{ partial \"hooks/head-end.html\" . }}"
  },
  {
    "path": "website/layouts/partials/hooks/body-end.html",
    "content": "{{ with .Site.Params.algolia_docsearch }}\n<script type=\"text/javascript\" src=\"https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.js\"></script>\n<script type=\"text/javascript\"> docsearch({\napiKey: '265a4e0c97efa2f55b1f8a95a20335d9',\nindexName: 'sdk-operatorframework',\ninputSelector: '.td-search-input',\ndebug: false // Set debug to true if you want to inspect the dropdown\n});\n</script>\n{{ end }}\n"
  },
  {
    "path": "website/layouts/partials/hooks/head-end.html",
    "content": "{{ with .Site.Params.algolia_docsearch }}\n<link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.css\" />\n{{ end }}\n"
  },
  {
    "path": "website/layouts/partials/navbar-version-selector.html",
    "content": "<a class=\"of-link-list__a nav-link dropdown-toggle\" href=\"#\" id=\"navbarDropdown\" role=\"button\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\">\n\t{{ .Site.Params.version_menu }}\n</a>\n<div class=\"dropdown-menu\" aria-labelledby=\"navbarDropdownMenuLink\">\n\t{{ range .Site.Params.versions }}\n\t<a class=\"dropdown-item\" href=\"{{ .url }}\">{{ .version }}</a>\n\t{{ end }}\n</div>\n"
  },
  {
    "path": "website/layouts/partials/navbar.html",
    "content": "<header class=\"of-header-main\">\n    <a href=\"/\" class=\"of-brand\">\n      <picture class=\"of-brand__picture\">\n        <source srcset=\"/build/images/logo.svg\" media=\"(min-width: 992px)\">\n        <img src=\"/build/images/logo-sm.svg\" alt=\"\">\n      </picture>\n        </a>\n    <nav class=\"of-nav-main nav-collapse\">\n      <ul class=\"of-nav-main__items menu-items\">\n        <li class=\"of-nav-main__item\"><a class=\"of-link-list__a {{ if eq .Permalink \"/\" }} of-m-active {{end}}\" href=\"/\">Home</a></li>\n        {{ $currentPage := . }}\n        {{ range .Site.Menus.main }}\n        <li class=\"of-nav-main__item\"><a class=\"of-link-list__a{{if or ($currentPage.IsMenuCurrent \"main\" .) ($currentPage.HasMenuCurrent \"main\" .) }} of-m-active{{end}}\" href=\"{{ .URL }}\" title=\"{{ .Title }}\">{{ .Name }}</a></li>\n        {{ end }}\n        {{ if  .Site.Params.versions }}\n        <li class=\"of-nav-main__item\">\n        {{ partial \"navbar-version-selector.html\" . }}\n        </li>\n        {{ end }}\n      </ul>\n    </nav>\n    <div class=\"of-header-main__search\">\n\t\t{{ partial \"search-input.html\" . }}\n    </div>\n  </header>\n"
  },
  {
    "path": "website/layouts/partials/scripts.html",
    "content": "<script src=\"https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js\" integrity=\"sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49\" crossorigin=\"anonymous\"></script>\n<script src=\"https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js\" integrity=\"sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy\" crossorigin=\"anonymous\"></script>\n{{ $jsBase := resources.Get \"js/base.js\" }}\n{{ $jsAnchor := resources.Get \"js/anchor.js\" }}\n{{ $jsSearch := resources.Get \"js/search.js\" | resources.ExecuteAsTemplate \"js/search.js\" .Site.Home }}\n{{ if .Site.Params.offlineSearch }}\n{{ $jsSearch = resources.Get \"js/offline-search.js\" }}\n{{ end }}\n{{ $js := (slice $jsBase $jsAnchor $jsSearch) | resources.Concat \"js/main.js\" }}\n{{ if .Site.IsServer }}\n<script src=\"{{ $js.RelPermalink }}\"></script>\n{{ else }}\n{{ $js := $js | minify | fingerprint }}\n<script src=\"{{ $js.RelPermalink }}\" integrity=\"{{ $js.Data.Integrity }}\" crossorigin=\"anonymous\"></script>\n{{ end }}\n<script type=\"text/javascript\">\n    if ((\"undefined\" !== typeof _satellite) && (\"function\" === typeof _satellite.pageBottom)) {\n        _satellite.pageBottom();\n    }\n</script>\n{{ partial \"hooks/body-end.html\" . }}\n"
  },
  {
    "path": "website/layouts/partials/section-index.html",
    "content": "<div class=\"section-index\">\n    {{ $pages := (where .Site.Pages \"Section\" .Section).ByWeight }}\n    {{ $parent := .Page }}\n    {{ if $parent.Params.no_list }}\n    {{/* If no_list is true we don't show a list of subpages */}}\n    {{ else if $parent.Params.simple_list }}\n    {{/* If simple_list is true we show a bulleted list of subpages */}}\n        <ul>\n            {{ range $pages }}\n                {{ if eq .Parent $parent }}\n                    <li><a href=\"{{ .RelPermalink }}\">{{- .Title -}}</a></li>\n                {{ end }}\n            {{ end }}\n        </ul>\n    {{ else }}\n    {{/* Otherwise we show a nice formatted list of subpages with page descriptions */}}\n    <hr class=\"panel-line\">\n        {{ range $pages }}\n            {{ if eq .Parent $parent }}\n                <div class=\"entry\">\n                    <h3>\n                        <a href=\"{{ .RelPermalink }}\">{{- .Title -}}</a>\n                    </h3>\n                    <p>{{ .Description | markdownify }}</p>\n                </div>\n            {{ end }}\n        {{ end }}\n    {{ end }}\n</div>\n"
  },
  {
    "path": "website/layouts/shortcodes/client-go-version.html",
    "content": "{{- $siteURL := .Page.Site.BaseURL -}}\n{{- $done := false -}}\n{{- range .Page.Site.Params.versions -}}\n    {{- $verUrl := printf \"%s/\" .url -}}\n    {{- if eq  $verUrl $siteURL -}}\n        {{- $done = true -}}\n        <code>{{- .client_go_version -}}</code>\n    {{- end -}}\n{{- end -}}\n{{- if eq $done false -}}\n    {{- range where .Page.Site.Params.versions \"version\" \"Latest Release\" -}}\n        <code>{{- .client_go_version -}}</code> \n    {{- end -}}\n{{- end -}}"
  },
  {
    "path": "website/layouts/shortcodes/kube-version.html",
    "content": "{{- $siteURL := .Page.Site.BaseURL -}}\n{{- $done := false -}}\n{{- range .Page.Site.Params.versions -}}\n    {{- $verUrl := printf \"%s/\" .url -}}\n    {{- if eq  $verUrl $siteURL -}}\n        {{- $done = true -}}\n        <code>{{- .kube_version -}}</code>\n    {{- end -}}\n{{- end -}}\n{{- if eq $done false -}}\n    {{- range where .Page.Site.Params.versions \"version\" \"Latest Release\" -}}\n        <code>{{- .kube_version -}}</code> \n    {{- end -}}\n{{- end -}}\n"
  },
  {
    "path": "website/layouts/shortcodes/table.html",
    "content": "{{ $htmlTable := .Inner | markdownify }}\n{{ $class := .Get 0 }}\n{{ $old := \"<table>\" }}\n{{ $new := printf \"<table class=\\\"%s\\\">\" $class }}\n{{ $htmlTable := replace $htmlTable $old $new }}\n{{ $htmlTable | safeHTML }}\n"
  },
  {
    "path": "website/scripts/set_menu_version.sh",
    "content": "#!/usr/bin/env bash\n\n# This script updates the hugo config's \"version_menu\" param\n# to the current ${MAJOR}.${MINOR} string.\n\nDIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" >/dev/null 2>&1 && pwd)\"\nCONFIG_PATH=\"${DIR}/../config.toml\"\n\nBRANCH_NAME=\"$(git rev-parse --abbrev-ref HEAD)\"\nif [[ \"$BRANCH_NAME\" =~ v[0-9]+\\.[0-9]+\\.x ]]; then\n  VERSION_MENU=\"$(echo $BRANCH_NAME | awk -F. '{ print v$1\".\"$2 }')\"\n  sed -i -E 's/version_menu = \".+\"/version_menu = \"'${VERSION_MENU}'\"/g' \"$CONFIG_PATH\"\n\n  # Ensure config.toml was updated.\n  if ! grep -q \"version_menu = \\\"${VERSION_MENU}\\\"\" \"$CONFIG_PATH\"; then\n    echo \"$0 failed to update config.toml\"\n    exit 1\n  fi\nfi\n"
  },
  {
    "path": "website/scripts/update_branch_mappings.sh",
    "content": "#!/usr/bin/env bash\n\n# This script writes a branch-to-subdomain mapping for the previously created\n# release branch to the hugo config. This change should be committed in the prerelease commit.\n\nDIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" >/dev/null 2>&1 && pwd)\"\nCONFIG_PATH=\"${DIR}/../config.toml\"\n\nVERSION=\"${1?\"A Version is required\"}\"\nVERSION_PATCHLESS=\"$(echo $VERSION | awk -F. '{ print v$1\".\"$2 }')\"\nVERSION_X_DOMAIN=\"$(echo $VERSION | awk -F. '{ print v$1\"-\"$2\"-x\" }')\"\n\nif grep -C 1 \"\\[\\[params\\.versions\\]\\]\" website/config.toml | grep -q \"version = \\\"${VERSION_PATCHLESS}\\\"\"; then\n  echo \"Version mapping ${VERSION_PATCHLESS} already exists, skipping\"\n  exit 0\nfi\n\nKUBE_VERSION=\"$(cat Makefile | grep \"export K8S_VERSION\" | awk -F= '{ gsub(/ /,\"\"); print $2 }')\"\nCLIENT_GO_VERSION=\"$(cat go.mod | grep \"k8s.io/client-go\" | awk -F\" \" '{ print $2 }')\"\n\nMARKER=\"##RELEASE_ADDME##\"\nPARAMS_VERSION=\"[[params.versions]]\\\\n  version = \\\"${VERSION_PATCHLESS}\\\"\\\\n  url = \\\"https://${VERSION_X_DOMAIN}.sdk.operatorframework.io\\\"\\\\n  kube_version = \\\"${KUBE_VERSION}\\\"\\\\n  client_go_version = \\\"${CLIENT_GO_VERSION}\\\"\"\n\nsed -i -E $'s@'${MARKER}'@'\"${MARKER}\\\\n\\\\n${PARAMS_VERSION}\"'@g' \"$CONFIG_PATH\"\n\n# Ensure config.toml was updated.\nif ! grep -q \"url = \\\"https://${VERSION_X_DOMAIN}.sdk.operatorframework.io\\\"\" \"$CONFIG_PATH\"; then\n  echo \"$0 failed to update config.toml\"\n  exit 1\nfi\n"
  },
  {
    "path": "website/scripts/update_download_url.sh",
    "content": "#!/usr/bin/env bash\n\n# This script updates the operator-sdk download link with the current release version.\n# This change should be committed in the prerelease commit.\n\nset -e\n\nDIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" >/dev/null 2>&1 && pwd)\"\nDOC_PATH=\"${DIR}/../content/en/docs/installation/_index.md\"\n\nVERSION=\"${1?\"A Version is required\"}\"\n\nTARGET=\"export OPERATOR_SDK_DL_URL=https://github.com/operator-framework/operator-sdk/releases/download/\"\n\nsed -i -E 's@('\"${TARGET}\"').+@\\1'\"${VERSION}\"'@g' \"$DOC_PATH\"\n\n# Ensure the file was updated.\nif ! grep -q \"${TARGET}${VERSION}\" \"$DOC_PATH\"; then\n  echo \"$0 failed to update ${DOC_PATH}\"\n  exit 1\nfi\n"
  },
  {
    "path": "website/scripts/update_latest_release_compat.sh",
    "content": "#!/usr/bin/env bash\n\n# This script updates the latest release version's `kube_version` and `client_go_version`\n# variable to be up to date. This change should be committed in the prerelease commit.\n\nDIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" >/dev/null 2>&1 && pwd)\"\nCONFIG_PATH=\"${DIR}/../config.toml\"\n\nKUBE_VERSION=\"$(cat Makefile | grep \"export K8S_VERSION\" | awk -F= '{ gsub(/ /,\"\"); print $2 }')\"\nCLIENT_GO_VERSION=\"$(cat go.mod | grep \"k8s.io/client-go\" | awk -F\" \" '{ print $2 }')\"\n\nKUBE_MARKER=\"##LATEST_RELEASE_KUBE_VERSION##\"\nCLIENT_GO_MARKER=\"##LATEST_RELEASE_CLIENT_GO_VERSION##\"\n\nperl -0777 -pi -e $'s@'\"${KUBE_MARKER}\\\\n  kube_version = \".+'@'\"${KUBE_MARKER}\\\\n  kube_version = \\\"${KUBE_VERSION}\\\"\"'@g' ${CONFIG_PATH}\nperl -0777 -pi -e $'s@'\"${CLIENT_GO_MARKER}\\\\n  client_go_version = \".+'@'\"${CLIENT_GO_MARKER}\\\\n  client_go_version = \\\"${CLIENT_GO_VERSION}\\\"\"'@g' ${CONFIG_PATH}"
  }
]