exoframejs / exoframe

Exoframe is a self-hosted tool that allows simple one-command deployments using Docker
https://exoframejs.github.io/exoframe/
1.13k stars 56 forks source link

docker-compose list labels vs lists #297

Closed Harjot1Singh closed 4 years ago

Harjot1Singh commented 4 years ago

Description

When you specify label arguments as a list in docker-compose.yml, you end up with them being cast to object notation incorrectly. I logged the transformed docker.compose.yaml in the deployments folder to confirm this:

Minimal Test Case

Input:

  uploads:
    labels:
      - traefik.http.routers.uploads.rule=Host(`x.test.me`) && PathPrefix(`/api/uploads`)
      - traefik.http.routers.uploads.middlewares=uploads--stripprefix
      - traefik.http.middlewares.uploads--stripprefix.stripprefix.prefixes=/api/uploads

Output:

 uploads:
    container_name: exo-harjot-test-uploads-71c4bd50
    restart: 'on-failure:2'
    build: *ref_14
    environment: *ref_15
    ports: *ref_16
    labels:
      '0': >-
        traefik.http.routers.uploads.rule=Host(`x.test.me`) &&
        PathPrefix(`/api/uploads`)
      '1': traefik.http.routers.uploads.middlewares=uploads--stripprefix
      '2': >-
        traefik.http.middlewares.uploads--stripprefix.stripprefix.prefixes=/api/uploads
      exoframe.name: exo-harjot-test-uploads-71c4bd50
      exoframe.deployment: exo-harjot-test-uploads-71c4bd50
      exoframe.user: harjot
      exoframe.project: exo-harjot-test
      traefik.docker.network: exoframe
      traefik.enable: 'true'
    networks:
      - exoframe

Expected Output

You can see that the input labels are instead mapped to array indices, and it instead should be anything before the first =.

Proposed Solution

When mapping docker-compose labels that are supplied as an array, first parse them into an object. Something like:

const parsedLabels = Array.isArray(labels)
  ? labels.reduce((acc, [label, ...value]) => {
      // Split at =, but only retain first value
      const [label, ...values] = label.split('=')
      const value = values.join('=')

      return { ...acc, [label]: value }
    }, {})
  : labels
yamalight commented 4 years ago

@Harjot1Singh haven't considered that case - would be a nice improvement! I'll try to update this once I have time. In the mean time - PRs welcome as usual :)

Relevant bit of code: https://github.com/exoframejs/exoframe-server/blob/master/src/docker/templates/compose.js#L45-L54

Harjot1Singh commented 4 years ago

Done ;)