예제 #1
0
        public async override Task RunAsync()
        {
            if (DryRun)
            {
                ColoredConsole.WriteLine(KubernetesHelper.GetKedaResources(Namespace));
                if (!KedaOnly)
                {
                    ColoredConsole.WriteLine(KubernetesHelper.GetOsirisResources(Namespace));
                }
            }
            else
            {
                var sb = new StringBuilder();
                sb.AppendLine(KubernetesHelper.GetKedaResources(Namespace));
                if (!KedaOnly)
                {
                    sb.AppendLine(KubernetesHelper.GetOsirisResources(Namespace));
                }

                if (!await KubernetesHelper.NamespaceExists(Namespace))
                {
                    await KubernetesHelper.CreateNamespace(Namespace);
                }

                await KubectlHelper.KubectlApply(sb.ToString(), showOutput : true);
            }
        }
 private async Task CreateNamespace(string name)
 {
     if (!await KubernetesHelper.NamespaceExists(name))
     {
         await KubernetesHelper.CreateNamespace(name);
     }
 }
 public override ICommandLineParserResult ParseArgs(string[] args)
 {
     SetFlag <string>("name", "The name used for the deployment and other artifacts in kubernetes", n =>
     {
         KubernetesHelper.ValidateKubernetesName(n);
         Name = n;
     }, isRequired: true);
     SetFlag <string>("image-name", "Image to use for the pod deployment and to read functions from", n => ImageName = n);
     SetFlag <string>("registry", "When set, a docker build is run and the image is pushed to that registry/name. This is mutually exclusive with --image-name. For docker hub, use username.", r => Registry = r);
     SetFlag <string>("namespace", "Kubernetes namespace to deploy to. Default: default", ns => Namespace = ns);
     SetFlag <string>("pull-secret", "The secret holding a private registry credentials", s => PullSecret = s);
     SetFlag <int>("polling-interval", "The polling interval for checking non-http triggers. Default: 30 (seconds)", p => PollingInterval = p);
     SetFlag <int>("cooldown-period", "The cooldown period for the deployment before scaling back to 0 after all triggers are no longer active. Default: 300 (seconds)", p => CooldownPeriod = p);
     SetFlag <int>("min-replicas", "Minimum replica count", m => MinReplicaCount = m);
     SetFlag <int>("max-replicas", "Maximum replica count to scale to by HPA", m => MaxReplicaCount = m);
     SetFlag <string>("keys-secret-name", "The name of a kubernetes secret collection to use for the function app keys (host keys, function keys etc.)", ksn => KeysSecretCollectionName = ksn);
     SetFlag <bool>("mount-funckeys-as-containervolume", "The flag indicating to mount the func app keys as container volume", kmv => MountFuncKeysAsContainerVolume = kmv);
     SetFlag <string>("secret-name", "The name of an existing kubernetes secret collection, containing func app settings, to use in the deployment instead of creating new a new one based upon local.settings.json", sn => SecretsCollectionName = sn);
     SetFlag <string>("config-map-name", "The name of an existing config map with func app settings to use in the deployment", cm => ConfigMapName = cm);
     SetFlag <string>("service-type", "Kubernetes Service Type. Default LoadBalancer  Valid options: " + string.Join(",", ServiceTypes), s =>
     {
         if (!string.IsNullOrEmpty(s) && !ServiceTypes.Contains(s))
         {
             throw new CliArgumentsException($"serviceType {ServiceType} is not supported. Valid options are: {string.Join(",", ServiceTypes)}");
         }
         ServiceType = s;
     });
     SetFlag <bool>("no-docker", "With --image-name, the core-tools will inspect the functions inside the image. This will require mounting the image filesystem. Passing --no-docker uses current directory for functions.", nd => NoDocker = nd);
     SetFlag <bool>("use-config-map", "Use a ConfigMap/V1 instead of a Secret/V1 object for function app settings configurations", c => UseConfigMap = c);
     SetFlag <bool>("dry-run", "Show the deployment template", f => DryRun = f);
     SetFlag <bool>("ignore-errors", "Proceed with the deployment if a resource returns an error. Default: false", f => IgnoreErrors = f);
     return(base.ParseArgs(args));
 }
        private async Task CreateAutoscaler(string deploymentName, string nameSpace, int minInstances, int maxInstances, int cpuPercentage = 60)
        {
            var cmd = $"autoscale deploy {deploymentName} --cpu-percent={cpuPercentage} --max={maxInstances} --min={minInstances} --namespace={nameSpace}";

            if (!string.IsNullOrEmpty(configFile))
            {
                cmd += $" --kubeconfig {configFile}";
            }

            await KubernetesHelper.RunKubectl(cmd);
        }
 public void ValidateKubernetesNames(string name, bool isValid)
 {
     try
     {
         KubernetesHelper.ValidateKubernetesName(name);
     }
     catch
     {
         if (isValid)
         {
             throw;
         }
     }
 }
예제 #6
0
        public async override Task RunAsync()
        {
            if (DryRun)
            {
                ColoredConsole.WriteLine(KubernetesHelper.GetKedaResources(Namespace));
            }
            else
            {
                if (!await KubernetesHelper.NamespaceExists(Namespace))
                {
                    await KubernetesHelper.CreateNamespace(Namespace);
                }

                await KubectlHelper.KubectlApply(KubernetesHelper.GetKedaResources(Namespace), showOutput : true);
            }
        }
예제 #7
0
        private async Task Deploy(string name, string image, string nameSpace, int min, int max)
        {
            var isHTTP = IsHTTPTrigger(name);

            await CreateNamespace(nameSpace);

            client.DefaultNamespace = nameSpace;

            ColoredConsole.WriteLine();
            ColoredConsole.WriteLine("Deploying function to Knative...");

            var knativeService = GetKnativeService(name, image, nameSpace, min, max, isHTTP);
            var json           = Newtonsoft.Json.JsonConvert.SerializeObject(knativeService,
                                                                             Newtonsoft.Json.Formatting.None,
                                                                             new Newtonsoft.Json.JsonSerializerSettings
            {
                NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore
            });

            File.WriteAllText("deployment.json", json);
            await KubernetesHelper.RunKubectl($"apply -f deployment.json");

            File.Delete("deployment.json");

            var endpoint = await GetIstioClusterIngressEndpoint();

            var host = GetFunctionHost(name, nameSpace);

            ColoredConsole.WriteLine();
            ColoredConsole.WriteLine("Function deployed successfully!");
            ColoredConsole.WriteLine();
            if (string.IsNullOrEmpty(endpoint))
            {
                ColoredConsole.WriteLine($"Function URL: http://{endpoint}");
            }
            else
            {
                ColoredConsole.WriteLine("Couldn't identify Function URL: Couldn't find Istio Cluster Ingress endpoint");
            }
            ColoredConsole.WriteLine($"Function Host: {host}");
            ColoredConsole.WriteLine();
            ColoredConsole.WriteLine("Plese note: it may take a few minutes for the knative service to be reachable");
        }
예제 #8
0
        public void PopulateMetadataDictionary_CorrectlyPopulatesRabbitMQMetadata()
        {
            string jsonText = @"
            {
                ""type"": ""rabbitMQTrigger"",
                ""connectionStringSetting"": ""RabbitMQConnection"",
                ""queueName"": ""myQueue"",
                ""name"": ""message""
            }";

            JToken jsonObj = JToken.Parse(jsonText);

            IDictionary <string, string> metadata = KubernetesHelper.PopulateMetadataDictionary(jsonObj);

            Assert.Equal(4, metadata.Count);
            Assert.True(metadata.ContainsKey("type"));
            Assert.True(metadata.ContainsKey("host"));
            Assert.True(metadata.ContainsKey("name"));
            Assert.True(metadata.ContainsKey("queueName"));
            Assert.Equal("rabbitMQTrigger", metadata["type"]);
            Assert.Equal("RabbitMQConnection", metadata["host"]);
            Assert.Equal("message", metadata["name"]);
            Assert.Equal("myQueue", metadata["queueName"]);
        }
        private async Task Deploy(string name, string image, string nameSpace, int min, int max, double cpu = 0.1, int memory = 128, string port = "80")
        {
            await CreateNamespace(nameSpace);

            client.DefaultNamespace = nameSpace;

            var deploymentName = $"{name}-deployment";

            await DeleteDeploymentIfExists(deploymentName, nameSpace);

            ColoredConsole.WriteLine("Deploying function to Kubernetes...");

            var deployment = GetDeployment(deploymentName, image, cpu, memory, port, nameSpace, min);
            var json       = Newtonsoft.Json.JsonConvert.SerializeObject(deployment,
                                                                         Newtonsoft.Json.Formatting.None,
                                                                         new Newtonsoft.Json.JsonSerializerSettings
            {
                NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore
            });

            File.WriteAllText("deployment.json", json);
            KubernetesHelper.RunKubectl($"apply -f deployment.json");

            ColoredConsole.WriteLine("Deployment successful");

            var service = GetService(deploymentName, nameSpace, port);

            try
            {
                // we can safely ignore the error here
                await client.ServicesV1().Create(service);
            }
            catch { }

            await TryRemoveAutoscaler(deploymentName, nameSpace);
            await CreateAutoscaler(deploymentName, nameSpace, min, max);

            var externalIP = "";

            ColoredConsole.WriteLine("Waiting for External IP...");

            while (string.IsNullOrEmpty(externalIP))
            {
                var svc = await client.ServicesV1().Get($"{deploymentName}-service", nameSpace);

                if (svc != null)
                {
                    if (svc.Status.LoadBalancer.Ingress.Count > 0)
                    {
                        externalIP = svc.Status.LoadBalancer.Ingress[0].Ip;
                    }
                }
            }

            File.Delete("deployment.json");

            ColoredConsole.WriteLine("");

            ColoredConsole.WriteLine("Function deployed successfully!");
            ColoredConsole.WriteLine($"Function IP: {externalIP}");
        }
        public override async Task RunAsync()
        {
            (var resolvedImageName, var shouldBuild) = ResolveImageName();
            TriggersPayload triggers = null;

            if (DryRun)
            {
                if (shouldBuild)
                {
                    // don't build on a --dry-run.
                    // read files from the local dir
                    triggers = await GetTriggersLocalFiles();
                }
                else
                {
                    triggers = await DockerHelpers.GetTriggersFromDockerImage(resolvedImageName);
                }
            }
            else
            {
                if (shouldBuild)
                {
                    await DockerHelpers.DockerBuild(resolvedImageName, Environment.CurrentDirectory);
                }
                triggers = await DockerHelpers.GetTriggersFromDockerImage(resolvedImageName);
            }

            (var resources, var funcKeys) = await KubernetesHelper.GetFunctionsDeploymentResources(
                Name,
                resolvedImageName,
                Namespace,
                triggers,
                _secretsManager.GetSecrets(),
                PullSecret,
                SecretsCollectionName,
                ConfigMapName,
                UseConfigMap,
                PollingInterval,
                CooldownPeriod,
                ServiceType,
                MinReplicaCount,
                MaxReplicaCount,
                KeysSecretCollectionName,
                MountFuncKeysAsContainerVolume);

            if (DryRun)
            {
                ColoredConsole.WriteLine(KubernetesHelper.SerializeResources(resources, OutputSerializationOptions.Yaml));
            }
            else
            {
                if (!await KubernetesHelper.NamespaceExists(Namespace))
                {
                    await KubernetesHelper.CreateNamespace(Namespace);
                }

                if (shouldBuild)
                {
                    await DockerHelpers.DockerPush(resolvedImageName);
                }

                foreach (var resource in resources)
                {
                    await KubectlHelper.KubectlApply(resource, showOutput : true, ignoreError : IgnoreErrors, @namespace : Namespace);
                }

                //Print the function keys message to the console
                await KubernetesHelper.PrintFunctionsInfo($"{Name}-http", Namespace, funcKeys, triggers);
            }
        }
 /// <summary>
 /// Constructer used by unit tests
 /// </summary>
 /// <param name="kubernetesHelper">Kubernetes Helper class instance to use</param>
 internal NamespaceCountHandler(KubernetesHelper kubernetesHelper)
 {
     this.kubernetesHelper = kubernetesHelper;
 }
예제 #12
0
 /// <summary>
 /// Constructer used by unit tests
 /// </summary>
 /// <param name="kubernetesHelper">Kubernetes Helper class instance to use</param>
 internal PodCountHandler(KubernetesHelper kubernetesHelper)
 {
     this.kubernetesHelper = kubernetesHelper;
 }
예제 #13
0
 public async override Task RunAsync()
 {
     await KubernetesHelper.RemoveKeda(Namespace);
 }
 /// <summary>
 /// Constructer used by unit tests
 /// </summary>
 /// <param name="kubernetesHelper">Kubernetes Helper class instance to use</param>
 internal NodeRamUsageHandler(KubernetesHelper kubernetesHelper)
 {
     this.kubernetesHelper = kubernetesHelper;
 }
예제 #15
0
 private async Task CreateNamespace(string name)
 {
     await KubernetesHelper.RunKubectl($"create ns {name}");
 }
예제 #16
0
 /// <summary>
 /// Constructer used by unit tests
 /// </summary>
 /// <param name="kubernetesHelper">Kubernetes Helper class instance to use</param>
 internal PodCPUUsageHandler(KubernetesHelper kubernetesHelper)
 {
     this.kubernetesHelper = kubernetesHelper;
 }
예제 #17
0
 public async Task GetKubernetesFunctionLogs(string functionName)
 {
     string nameSpace = KUBERNETES_DEFAULT_NAMESPACE;
     await KubernetesHelper.RunKubectl($"logs -l app={functionName}-deployment -n {nameSpace}", true);
 }
 private async Task TryRemoveAutoscaler(string deploymentName, string nameSpace)
 {
     await KubernetesHelper.RunKubectl($"delete hpa {deploymentName} -n {nameSpace}");
 }