terraform-routeros / terraform-provider-routeros

Terraform Provider for Mikrotik RouterOS
Mozilla Public License 2.0
187 stars 53 forks source link

Package installation #301

Closed rgl closed 1 month ago

rgl commented 10 months ago

Is your feature request related to a problem? Please describe.

I would like to be able to (un)install packages.

Describe the solution you'd like

For example, to enable containers, one has to download the packages .zip, extract the containers-7.12.npk file, upload it, install it, and remove it.

Have a resource to install packages.

Something like:

resource "routeros_package" "container" {
  url       = "https://download.mikrotik.com/routeros/7.12/chr-7.12.img.zip"
  file_name = "container-7.12.npk"
}
vaerh commented 10 months ago

Hi! The functionality of the provider is limited to the set of commands available in the MT console. I've always installed packages using winbox and don't have that experience in the console. Do you have a script with MT commands to implement such an idea?

rgl commented 10 months ago

I'm still looking into it. So far, the procedure to install the package that I've found is:

  1. using sftp, upload the .npk file to the router root directory.
  2. using ssh (maybe can be done using the api), reboot the router using the /system/reboot command . 2.1. at boot time, routeros will install the .npk file and remove it from the router root directory.
  3. wait for the router to reboot, and ensure the .npk file is not longer at the router root, and the package is installed.
vaerh commented 10 months ago

:) it's not much different than updating via winbox.

Schwitzd commented 1 month ago

I have the same needs.. I created a bash script to download the extra packages on my local computer then with this code I upload the package on the router:

locals {
  container_npk_name = "container-${local.system_version}-${local.system_architecture}.npk"
}

# Container - Install package
resource "null_resource" "download_container_npk" {
  provisioner "local-exec" {
    command = <<EOT
      ./helper/download_routeros_packages.sh ${local.system_architecture} "${local.system_version}" "container"
    EOT
  }
}

resource "null_resource" "upload_container_npk" {
  provisioner "local-exec" {
    command = "scp \"/tmp/routeros_packages/${local.container_npk_name}\" ${local.router_user}@${var.router_ip}:/${local.container_npk_name}"
  }

  depends_on = [ null_resource.download_container_npk ]
}

I know it sounds really complicated... but it is the only solution I had in mind to automate as much as possible... Then I'm also blocked at the manual reboot :(

vaerh commented 1 month ago

The solution from stackoverflow won't work?

Schwitzd commented 1 month ago

Interesting I will try! thx for sharing :)

vaerh commented 1 month ago

If you have a working script for installing packages please post it. I would put it in the example files.

Schwitzd commented 1 month ago

No is not a full script to install packages.. This is my script https://github.com/Schwitzd/IaC-HomeRouter/blob/main/helper%2Fdownload_routeros_packages.sh

Takes care to download the extra-packages unzip the needed package. Then with the code on the above post I upload it to MikroTik via scp.

I spent a lot of times trying use routeros_file to upload the npk package, but I only was able to upload the empty file name 😭 From the Web Interface you can upload the .npk and I'm pretty sure is using an API.. Is calling an sproxy and upload the file in form-octect format but is too deep for me..

vaerh commented 1 month ago

People on the forum talked about uploading via scp/ftp. It seems to be true, because uploading a file (only in base64) via API is interrupted by the error returned response code: 413, message: 'Payload Too Large'.

Schwitzd commented 1 month ago

But behind the hood routeros_file is not uploading a file using the API? Because I'm able to use it to upload the .npk but only the file name and not the content

vaerh commented 1 month ago

I was not able to upload via API.Webfig uses a different mechanism.

Schwitzd commented 1 month ago

ok! I have improved the code to install a package and handle the reboot time @vaerh your stackoverflow link was the key. Here the code, in this specific context I'm installing the container package

# Container - Install package
resource "null_resource" "download_container_npk" {
  provisioner "local-exec" {
    command = <<EOT
      chmod +x ./helper/download_routeros_packages.sh
      ./helper/download_routeros_packages.sh ${local.system_architecture} "${local.system_version}" "container"
    EOT
  }
}

resource "null_resource" "upload_container_npk" {
  provisioner "local-exec" {
    command = "scp -i ${local.router_ssh_key} \"/tmp/routeros_packages/${local.container_npk_name}\" ${local.router_user}@${var.router_ip}:/${local.container_npk_name}"
  }

  depends_on = [ null_resource.download_container_npk ]
}

resource "null_resource" "install_container_npk" {
  provisioner "local-exec" {
      command = <<EOT
        ssh -i ${local.router_ssh_key} ${local.router_user}@${var.router_ip} '/system reboot'; sleep 3
        until ssh -i ${local.router_ssh_key} -o ConnectTimeout=2 ${local.router_user}@${var.router_ip} ':put True' 2> /dev/null
        do
          echo "Waiting for router to reboot and become available..."
          sleep 10
        done
      EOT
  }

  depends_on = [ null_resource.upload_container_npk ]
}

Hope can be useful to some else :)

vaerh commented 1 month ago

:tada: This issue has been resolved in version 1.59.1 :tada:

The release is available on GitHub release

Your semantic-release bot :package::rocket: