skip to Main Content
def make_file():
    
    read_file = r'C:Users~Desktopsample.yml'
    write_file = r'C:Users~Desktopsample_out.yml'    
    
    f = open(read_file, 'r')
    lst = [line for line in f]            
    f.close()

    ports = 'ports:n'
    for index in range(len(lst)):
        if "system_frontend:" in lst[index]:            
            count_spaces = len(lst[index+1]) - len(lst[index+1].lstrip(' '))
            
            lst.insert(index+1, ports)
            lst[index+1] = lst[index+1].rjust(count_spaces)            
            # lst.insert(index+1, " "*count_spaces + ports + " "*count_spaces + "- "0.0.0.0:5000:80"n") ## Did it this way, but it's not the best option.

    with open(write_file, 'w', encoding='utf-8') as file:
        for line in lst:
            file.write(line) 

The task is to place a certain amount of spaces in needed line(before str ‘ports:’, so it would look like ‘ ports:’).

fragment from .yml

services:
  system_frontend:
    image: ${DOCKER_REGISTRY}/frontend:${CONTAINER_VERSION}
    logging: *id001
    environment:
      SSL_CERTIFICATE: ${SSL_CERTIFICATE:-}
      SSL_CERTIFICATE_KEY: ${SSL_CERTIFICATE_KEY:-}
      ENABLE_CORS: ${ENABLE_CORS:-}
      FRONTEND_URL: ${FRONTEND_URL:-}
      METRICS_PUSHGATEWAY: ${METRICS_PUSHGATEWAY:-}
    volumes:
      - ssl-volume:/etc/nginx/ssl
    networks:
      system_network: null
    restart: unless-stopped
    depends_on:
      - webapi

Can’t succeed.

3

Answers


  1. I think this is what you are trying to achieve. The main difference between your code and this is I added a break statement so the loop doesn’t keep performing actions after the target line has been found.

    def make_file():
    
        read_file = r'sample.yml'
        write_file = r'sample_out.yml'
        f = open(read_file, 'r')
        lst = [line for line in f]
        f.close()
        ports = 'ports:n'
        spaces = 0
        for index in range(len(lst)):
            if "system_frontend:" in lst[index]:
                spaces += lst[index+1].count(" ") - 1
                break
        lst.insert(index + 1, (" "* spaces) + ports)
        with open(write_file, 'w', encoding='utf-8') as file:
            for line in lst:
                file.write(line)
    make_file()
    

    Please note that there are better ways to work with yaml files. Check out pyyaml in PyPi.

    output

    services:
      system_frontend:
        ports:
        image: ${DOCKER_REGISTRY}/frontend:${CONTAINER_VERSION}
        logging: *id001
        environment:
          SSL_CERTIFICATE: ${SSL_CERTIFICATE:-}
          SSL_CERTIFICATE_KEY: ${SSL_CERTIFICATE_KEY:-}
          ENABLE_CORS: ${ENABLE_CORS:-}
          FRONTEND_URL: ${FRONTEND_URL:-}
          METRICS_PUSHGATEWAY: ${METRICS_PUSHGATEWAY:-}
        volumes:
          - ssl-volume:/etc/nginx/ssl
        networks:
          bimeister_network: null
        restart: unless-stopped
        depends_on:
          - webapi
    
    Login or Signup to reply.
  2. I’m guessing that you are trying to alter docker-compose.yaml to add ports.
    There’s 2 options, you can either do it the hard way by processing text, or use yaml.safe_load to process the content

    Here’s my take on how you can do it. Give it a try and see if it fits your needs

    import yaml
    
    
    # manually processing text file
    def update_port_value_manual(read_file: str, write_file: str, ports: list):
        f = open(read_file, 'r')
        lst = [line for line in f]
        f.close()
    
        for index in range(len(lst)):
            if "system_frontend:" in lst[index]:
                count_spaces = len(lst[index + 1]) - len(lst[index + 1].lstrip(" "))
                inserted_content = count_spaces * " " + "ports:n"
                inserted_content += "".join([f"{' ' * count_spaces}- {host_port}:{container_port}n"
                                             for host_port, container_port in ports])
                lst.insert(index + 1, inserted_content)
                break
    
        with open(write_file, 'w', encoding='utf-8') as file:
            for line in lst:
                file.write(line)
    
    
    # use yaml for easier processing
    def update_port_value_yaml(read_file: str, write_file: str, ports: list):
        with open(read_file, "r") as read_yml:
            content = yaml.safe_load(read_yml)
    
        content.get("services").get("system_frontend").update(ports=[f"{host_port}:{container_port}"
                                                                     for host_port, container_port in ports])
    
        with open(write_file, "w") as write_yml:
            yaml.dump(content, write_yml)
    
    
    def main():
        read_file = "sample.yml"
        write_file = "sample_out.yaml"
    
        ports = [(8081, 8081), (8080, 8080)]
    
        update_port_value_manual(read_file, write_file, ports)
        # update_port_value_yaml(read_file, write_file, ports)
    
    Login or Signup to reply.
  3. You insert a line while loop through it, you should leave the original lines intact and use another list to store output, this is what I would do:

    def make_file():
        read_file = r'sample.yml.txt'
        write_file = r'output.yml.txt'    
        
        ports = 'ports:n'
    
        with open(read_file, 'r', encoding='UTF-8') as f, open(write_file, 'w', encoding='utf-8') as o:
            while (line := f.readline()):
    
                o.write( line )
    
                if "system_frontend:" in line:
                    next_line = f.readline()
                    count_spaces = next_line.count(" ") - 1
                    next_line = next_line.rjust(count_spaces)
                    
                    o.write(ports)
                    o.write(next_line)
    
    make_file()
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search