|
| 1 | +Developer Containers |
| 2 | +==================== |
| 3 | + |
| 4 | +.. _ioc_change_types: |
| 5 | + |
| 6 | +Types of Changes |
| 7 | +---------------- |
| 8 | + |
| 9 | +Containerized IOCs can be modified in 3 distinct places (in order of decreasing |
| 10 | +frequency of change but increasing complexity): |
| 11 | + |
| 12 | +#. The IOC instance: this means making changes to the IOC instance folders |
| 13 | + which appear in the ``iocs`` folder of a domain repository. e.g.: |
| 14 | + |
| 15 | + - changing the EPICS DB (or the ``ibek`` files that generate it) |
| 16 | + - altering the IOC boot script (or the ``ibek`` files that generate it) |
| 17 | + - changing the version of the Generic IOC used in values.yaml |
| 18 | + - for Kubernetes: the values.yaml can override any settings used by helm |
| 19 | + so these can also be adjusted on a per IOC instance basis. |
| 20 | + - for Kubernetes: changes to the global values.yaml |
| 21 | + file found in ``beamline-chart``, these affect all IOCs in the domain. |
| 22 | + |
| 23 | +#. The Generic IOC: i.e. altering how the Generic IOC container image |
| 24 | + is built. This means making changes to an ``ioc-XXX`` |
| 25 | + source repo and publishing a new version of the container image. |
| 26 | + Types of changes include: |
| 27 | + |
| 28 | + - changing the EPICS base version |
| 29 | + - changing the versions of EPICS support modules compiled into the IOC binary |
| 30 | + - adding new support modules |
| 31 | + - altering the system dependencies installed into the container image |
| 32 | + |
| 33 | +#. The dependencies - Support modules used by the Generic IOC. Changes to support |
| 34 | + module repos. To make use of these changes would require: |
| 35 | + |
| 36 | + - publishing a new release of the support module, |
| 37 | + - updating and publishing the Generic IOC |
| 38 | + - updating and publishing the IOC instance |
| 39 | + |
| 40 | +For all of the above, the epics-containers approach allows |
| 41 | +local testing of the changes before going through the publishing cycle. |
| 42 | +This allows us to have a fast 'inner loop' of development and testing. |
| 43 | + |
| 44 | +Also, epics-containers provides a mechanism for creating a separate workspace for |
| 45 | +working on all of the above elements in one place. |
| 46 | + |
| 47 | +Need for a Developer Container |
| 48 | +------------------------------ |
| 49 | + |
| 50 | +The earlier tutorials were firmly in the realm of ``1`` above. |
| 51 | +It was adequate for us to install a container platform, IDE and python |
| 52 | +and that is all we needed. |
| 53 | + |
| 54 | +Once you get to level ``2`` changes you need to have compilers and build tools |
| 55 | +installed. You might also require system level dependencies. AreaDetector, |
| 56 | +that we used earlier has a long list of system dependencies that need to be |
| 57 | +installed in order to compile it. Traditionally we have installed all of these |
| 58 | +onto developer workstations or separately compiled the dependencies as part of |
| 59 | +the build. |
| 60 | + |
| 61 | +These tools and dependencies will differ from one Generic IOC to the next. |
| 62 | + |
| 63 | +When using epics-containers we don't need to install any of these tools or |
| 64 | +dependencies on our local machine. Instead we can use a developer container, |
| 65 | +and in fact our Generic IOC *is* our developer container. |
| 66 | + |
| 67 | +When the CI builds a Generic IOC it creates |
| 68 | +`two targets <https://github.com/orgs/epics-containers/packages?repo_name=ioc-adsimdetector>`_: |
| 69 | + |
| 70 | +:developer: this target installs all the build tools and build time dependencies |
| 71 | + into the container image. It then compiles the support modules and IOC. |
| 72 | + |
| 73 | +:runtime: this target installs only the runtime dependencies into the container. |
| 74 | + It also extracts the built runtime assets from the developer target. |
| 75 | + |
| 76 | +The developer stage of the build is a necessary step in order to get a |
| 77 | +working runtime container. However, we choose to keep this stage as an additional |
| 78 | +build target and it then becomes a perfect candidate for a developer container. |
| 79 | + |
| 80 | +VSCode has excellent support for using a container as a development environment. |
| 81 | +The next section will show you how to use this feature. Note that you can use |
| 82 | +any IDE that supports remote development in a container, you could also |
| 83 | +simply launch the developer container in a shell and use it via CLI only. |
| 84 | + |
| 85 | +Starting a Developer Container |
| 86 | +------------------------------ |
| 87 | + |
| 88 | +For this section we will work with the ADSimDetector Generic IOC that we |
| 89 | +used in previous tutorials. Let's go and fetch a version of the Generic IOC |
| 90 | +source and build it locally. |
| 91 | + |
| 92 | +For the purposes of this tutorial we will place the source in a folder right |
| 93 | +next to your test beamline ``bl01t`` folder. We will also be getting a |
| 94 | +specific version of the Generic IOC source so that future changes don't break |
| 95 | +this tutorial: |
| 96 | + |
| 97 | +.. code-block:: bash |
| 98 | +
|
| 99 | + # starting from folder bl01t so that the clone is next to bl01t |
| 100 | + cd .. |
| 101 | + git clone --recursive [email protected]:epics-containers/ioc-adsimdetector.git -b 2023.10.6b1 |
| 102 | + cd ioc-adsimdetector |
| 103 | + ec dev build |
| 104 | +
|
| 105 | +The last step uses one of the ``ec dev`` sub commands to build the developer |
| 106 | +target of the container to your local container cache. This will take a few |
| 107 | +minutes to complete. A philosophy of epics-containers is that Generic IOCs |
| 108 | +build all of their own support. This is to avoid problematic dependency trees. |
| 109 | +For this reason building something as complex as AreaDetector will take a |
| 110 | +few minutes when you first build it. |
| 111 | + |
| 112 | +A nice thing about containers is that the build is |
| 113 | +cached so that a second build will be almost instant unless you have changed |
| 114 | +something that requires some steps to be rebuilt. |
| 115 | + |
| 116 | +The ``ec dev`` commands are a set of convenience commands |
| 117 | +for working on Generic IOCs from *outside* of the container. These commands |
| 118 | +are useful for debugging container builds: although most work is done inside |
| 119 | +the container, you will need these commands if it fails to build. |
| 120 | + |
| 121 | +Once built, open the project in VSCode: |
| 122 | + |
| 123 | +.. code-block:: bash |
| 124 | +
|
| 125 | + code . |
| 126 | +
|
| 127 | +When it opens, VSCode may prompt you to open in a devcontainer. If not then click |
| 128 | +the green icon in the bottom left of the VSCode window and select |
| 129 | +``Reopen in Container``. |
| 130 | + |
| 131 | +You should now be *inside* the container. All terminals started in VSCode will |
| 132 | +be inside the container. Every file that you open with the VSCode editor |
| 133 | +will be inside the container. |
| 134 | + |
| 135 | +There are some caveats because some folders are mounted from the host file |
| 136 | +system. For example, the ``ioc-adsimdetector`` project folder |
| 137 | +is mounted into the container as a volume. It is mounted under |
| 138 | +``/epics/ioc-adsimdetector``. This means that you can edit the source code |
| 139 | +from your local machine and the changes will be visible inside the container and |
| 140 | +outside the container. This is a good thing as you should consider the container |
| 141 | +filesystem to be a temporary filesystem that will be destroyed when the container |
| 142 | +deleted. |
| 143 | + |
| 144 | +Now that you are *inside* the container you have access to the tools built into |
| 145 | +it, this includes ``ibek``. The first command you should run is: |
| 146 | + |
| 147 | +.. code-block:: bash |
| 148 | +
|
| 149 | + ibek ioc build |
| 150 | +
|
| 151 | +This generates an IOC source tree in the ``ioc`` folder under your |
| 152 | +``ioc-adsimdetector`` folder and compiles it. Note that the IOC code is |
| 153 | +boilerplate, but that the ``src/Makefile`` is generated according to the |
| 154 | +support modules this Generic IOC contains. You can go and take a look at |
| 155 | +the Makefile and see that it contains ``dbd`` and ``lib`` references for each |
| 156 | +of the support modules in the container. |
| 157 | +See ``/epics/ioc-adsimdetector/ioc/iocApp/src/Makefile`` |
| 158 | + |
| 159 | +You will note that the ``ioc`` folder is greyed out in the VSCode explorer. This |
| 160 | +is because it is in ``.gitignore`` and it is purely generated code. If you |
| 161 | +particularly needed to customize the contents of the ioc source tree then |
| 162 | +you can remove it from ``.gitignore`` and commit your changes to the repo. These |
| 163 | +changes would then always get loaded for every instance of the Generic IOC. |
| 164 | + |
| 165 | +The Generic IOC should now be ready to run inside of the container. To do this: |
| 166 | + |
| 167 | +.. code-block:: bash |
| 168 | +
|
| 169 | + cd ioc |
| 170 | + ./start.sh |
| 171 | +
|
| 172 | +You will just see the default output of a Generic IOC that has no Instance |
| 173 | +configuration. Next we will add some instance configuration from one of the |
| 174 | +IOC instances in the ``bl01t`` beamline. |
| 175 | + |
| 176 | +Let's now add some other folders to our VSCode workspace to make it easier to |
| 177 | +work with ``bl01t`` and to investigate the container. |
| 178 | + |
| 179 | +Adding the Beamline to the Workspace |
| 180 | +------------------------------------ |
| 181 | + |
| 182 | +To meaningfully test the Generic IOC we will need an instance to test it |
| 183 | +against. We will use the ``bl01t`` beamline that you already made. |
| 184 | + |
| 185 | +In VSCode click the ``File`` menu and select ``Add Folder to Workspace``. |
| 186 | +Navigate to ``/repos`` and you will see all the peers of your ``ioc-adsimdetector`` |
| 187 | +folder (see `container-layout` below) . Choose the ``bl01t`` folder and add it to the |
| 188 | +workspace - you may see an error but if so clicking "reload window" will |
| 189 | +clear it. |
| 190 | + |
| 191 | +Also take this opportunity to add the folder ``/epics`` to the workspace. |
| 192 | + |
| 193 | +You can now easily browse around the ``/epics`` folder and see all the |
| 194 | +support modules and epics-base. This will give you a feel for the layout of |
| 195 | +files in the container. Here is a summary (where WS is the root |
| 196 | +of your host folders): |
| 197 | + |
| 198 | +.. _container-layout: |
| 199 | + |
| 200 | +.. list-table:: Developer Container Layout |
| 201 | + :widths: 25 35 45 |
| 202 | + :header-rows: 1 |
| 203 | + |
| 204 | + * - Path Inside Container |
| 205 | + - Host Mount Path |
| 206 | + - Description |
| 207 | + |
| 208 | + * - /epics/support |
| 209 | + - N/A |
| 210 | + - root of compiled support modules |
| 211 | + |
| 212 | + * - /epics/epics-base |
| 213 | + - N/A |
| 214 | + - compiled epics-base |
| 215 | + |
| 216 | + * - /epics/ioc-adsimdetector |
| 217 | + - WS/ioc-adsimdetector |
| 218 | + - Source repository for the Generic IOC |
| 219 | + |
| 220 | + * - /epics/ioc |
| 221 | + - WS/ioc-adsimdetector/ioc |
| 222 | + - soft link to IOC source tree |
| 223 | + |
| 224 | + * - /epics/ibek |
| 225 | + - N/A |
| 226 | + - All ibek *Support yaml* files |
| 227 | + |
| 228 | + * - /epics/pvi |
| 229 | + - N/A |
| 230 | + - all PVI definitions from support modules |
| 231 | + |
| 232 | + * - /epics/opi |
| 233 | + - N/A |
| 234 | + - all OPI files (generated or copied from support) |
| 235 | + |
| 236 | + * - /repos |
| 237 | + - WS |
| 238 | + - all peers to Generic IOC source repo |
| 239 | + |
| 240 | + |
| 241 | +Now that we have the beamline repo visible in our container we can |
| 242 | +easily supply some instance configuration to the Generic IOC. |
| 243 | +Try the following: |
| 244 | + |
| 245 | +.. code:: |
| 246 | +
|
| 247 | + cd /epics/ioc-adsimdetector |
| 248 | + rm -r ioc/config |
| 249 | + ln -s /repos/bl01t/iocs/bl01t-ea-ioc-02/config ioc |
| 250 | + ioc/start.sh |
| 251 | +
|
| 252 | +This removed the boilerplate config and replaced it with the config from |
| 253 | +the IOC instance bl01t-ea-ioc-02. Note that we used a soft link, this |
| 254 | +means we can edit the config, restart the IOC to test it and the changes |
| 255 | +will already be in place in the beamline repo. You can even open a shell |
| 256 | +onto the beamline repo and commit and push the changes. |
| 257 | + |
| 258 | +Wrapping Up |
| 259 | +----------- |
| 260 | + |
| 261 | +We now have a tidy development environment for working on the Generic IOC, |
| 262 | +IOC Instances and even the support modules inside the Generic IOC, all in one |
| 263 | +place. We can easily test our changes in place too. In particular note that |
| 264 | +we are able to test changes without having to go through a container build |
| 265 | +cycle. |
| 266 | + |
| 267 | +In the following tutorials we will look at how to make changes at each of the |
| 268 | +3 levels listed in `ioc_change_types`. |
0 commit comments