From 3bc51b5ef3912d37e74aabba59b30267d316f6de Mon Sep 17 00:00:00 2001
From: Dominic Burkart <1351120+DominicBurkart@users.noreply.github.com>
Date: Tue, 6 Oct 2020 14:05:48 +0200
Subject: [PATCH] implement setup_repo for k8s

---
 README.md                             |  2 ++
 turbolift_internals/Cargo.toml        |  2 ++
 turbolift_internals/src/kubernetes.rs | 42 +++++++++++++++++++++++----
 3 files changed, 41 insertions(+), 5 deletions(-)

diff --git a/README.md b/README.md
index 40b14830..6af37bff 100644
--- a/README.md
+++ b/README.md
@@ -53,6 +53,8 @@ should not have relative local dependencies prone to breaking.
 - if your program produces side effects when initialized, for example when 
 global constants are initialized, those side effects may be triggered 
 for each function call.
+- currently, turbolift does not guarantee that the target operating system for a 
+program will also be used with its microservices.
 
 ## Current Project Goals
 - [ ] support kubernetes ([pr](https://github.com/DominicBurkart/turbolift/pull/2)).
diff --git a/turbolift_internals/Cargo.toml b/turbolift_internals/Cargo.toml
index 890ba5cf..1a00f9e1 100644
--- a/turbolift_internals/Cargo.toml
+++ b/turbolift_internals/Cargo.toml
@@ -29,6 +29,8 @@ anyhow = "1"
 cached = "0.19"
 async-std = "1.6"
 async-trait = "0.1"
+base64 = "0.13"
+machine-ip = "0.2"
 
 # kubernetes-specific requirements
 kube = "0.42.0"
diff --git a/turbolift_internals/src/kubernetes.rs b/turbolift_internals/src/kubernetes.rs
index 3b083749..6b7595e2 100644
--- a/turbolift_internals/src/kubernetes.rs
+++ b/turbolift_internals/src/kubernetes.rs
@@ -1,8 +1,12 @@
+use std::collections::HashMap;
+use std::process::Command;
+use std::str::FromStr;
+
 use async_trait::async_trait;
+use base64::encode;
 use k8s_openapi::api::core::v1::Pod;
 use kube::api::{Api, PostParams};
 use kube::Client;
-use std::collections::HashMap;
 use url::Url;
 
 use crate::distributed_platform::{
@@ -75,12 +79,40 @@ impl DistributionPlatform for K8s {
     }
 }
 
-fn setup_repo(_function_name: &str, _project_tar: &[u8]) -> DistributionResult<Url> {
-    unimplemented!()
+fn setup_repo(_function_name: &str, _project_tar: &[u8]) -> anyhow::Result<Url> {
+    let status = Command::new("docker")
+        .args("run -d -p 5000:5000 --restart=always --name registry registry:2".split(' '))
+        .status()?; // todo choose an open port
+    if !status.success() {
+        return Err(anyhow::anyhow!("repo setup failed"));
+    }
+    let address = machine_ip::get().unwrap();
+    Ok(Url::from_str(&(address.to_string() + ":5000"))?)
 }
 
-fn make_image(_function_name: &str, _project_tar: &[u8]) -> DistributionResult<ImageTag> {
-    unimplemented!()
+fn make_image(function_name: &str, project_tar: &[u8]) -> anyhow::Result<ImageTag> {
+    let tar_base64 = encode(project_tar);
+    let mut docker_file = format!(
+        "\
+FROM rustlang/rust:nightly
+RUN  apt-get update \
+  && apt-get install -y coreutils \
+  && rm -rf /var/lib/apt/lists/*
+base64 --decode {} > f.tar
+tar xvf f.tar
+",
+        tar_base64
+    );
+    docker_file.insert(0, '\'');
+    docker_file.push('\'');
+    let tag_flag = "-t ".to_string() + function_name;
+    let status = Command::new("docker")
+        .args(&["build", &tag_flag, "-", &docker_file])
+        .status()?;
+    if status.success() {
+        return Err(anyhow::anyhow!("docker image build failure"));
+    }
+    Ok(function_name.to_string())
 }
 
 fn add_image_to_repo(_local_tag: ImageTag) -> DistributionResult<ImageTag> {