text:
# Use an image to create a stateful application

You can use an image to create a stateful application. This topic describes how to use an image to create a stateful NGINX application in the Container Service for Kubernetes \(ACK\) console. This topic also describes the features of StatefulSets.

Before you deploy the NGINX application, perform the following steps:

-   [Create a cluster of ACK Managed Edition](/intl.en-US/User Guide for Kubernetes Clusters/Cluster management/Create Kubernetes clusters/Create a cluster of ACK Managed Edition.md)
-   [Create a Persistent Volume Claim](/intl.en-US/User Guide for Kubernetes Clusters/Storage management-Flexvolume/Create a Persistent Volume Claim.md)
-   [Use kubectl to connect to an ACK cluster](/intl.en-US/User Guide for Kubernetes Clusters/Cluster management/Access clusters/Use kubectl to connect to an ACK cluster.md)

StatefulSets provide the following features:

|Scenario|Description|
|--------|-----------|
|Pod consistency|Pod consistency is used. This allows you to make sure that pods are launched and terminated in the defined order. This also allows you to make sure that the consistency of networks is high. Pod consistency is based on pod configurations, regardless of the node to which a pod is scheduled.|
|Stable and persistent storage|VolumeClaimTemplate allows you to mount persistent volumes \(PVs\) to pods. Mounted PVs are not deleted if pod replicas are deleted or scaled in.|
|Stable network identifiers|Each pod in a StatefulSet derives its hostname from the name of the StatefulSet and the ordinal of the pod. The pattern for the hostname is `StatefulSet name-pod ordinal`.|
|Ordinal pod indexes|For a StatefulSet with N pod replicas, each pod is assigned an integer ordinal from 0 to N-1. The ordinals assigned to pods within the StatefulSet are unique.|

## Procedure

1.  Log on to the [ACK console](https://cs.console.aliyun.com).

2.  In the left-side navigation pane, click **Clusters**.

3.  On the Clusters page, click the name of a cluster or click **Details** in the **Actions** column. The details page of the cluster appears.

4.  In the left-side navigation pane, click **Workload**.

5.  Click the **StatefulSets** tab. On the **StatefulSets** tab, click **Create from Image**.

6.  On the **Basic Information** wizard page, configure the basic settings.

    In this example, an application of the **StatefulSet** type is created.

    |Parameter|Description|
    |---------|-----------|
    |Name|The name of the application.|
    |Namespace|The namespace in which the application is deployed. The default namespace is automatically selected. You can select another namespace.|
    |Replicas|The number of replicated pods that are provisioned for the application.|
    |Type|The type of the application. You can select **Deployments**, **StatefulSets**, **Jobs**, **Cron Jobs**, or **DaemonSets**.****|
    |Labels|Add labels to the application.|
    |Annotations|Add annotations to the application.|
    |Synchronize Timezone|Specify whether to synchronize the timezone from nodes to containers.|

7.  Click **Next** to proceed to the **Container** wizard page.

8.  Configure the containers.

    **Note:** At the top of the **Container** wizard page, click **Add Container** to add more containers for the application.

    The following parameters are required to configure the containers.

    -   Basic settings

        ![Basic settings](https://static-aliyun-doc.oss-cn-hangzhou.aliyuncs.com/assets/img/en-US/7045359951/p12305.png)

        |Parameter|Description|
        |---------|-----------|
        |Image Name|        -   To use a Docker image or an image from Container Registry \(ACR\), click **Select Image**. In the dialog box that appears, select an image and click **OK**. In this example, the NGINX image is selected. In the Select Image dialog box, click the **Search** tab, select **Docker Images** from the drop-down list, enter NGINX in the search bar, and then click Search.
            -   Select an image from Alibaba Cloud Container Registry \(ACR\): In the Select Image dialog box, click the **Alibaba Cloud Container Registry** tab and select an image. You must first select a region and an ACR instance. For more information about ACR, see [What is Container Registry Enterprise Edition?]().

**Note:** On the **Alibaba Cloud Container Registry** tab, you can search for an image from ACR by name.

            -   Select a Docker image: In the Select Image dialog box, click the **Docker Official Images** tab and select a Docker image.
            -   Select a favorite image: In the Select Image dialog box, click the **Favorite Images** tab and select a favorite image.
            -   Search for a Docker image or an image from ACR: In the Select Image dialog box, click the **Search** tab and search for a Docker image or an image in a specified region from ACR by name.
        -   To use a private image, enter the address of a private image registry. The registry address must be in the `domainname/namespace/imagename:tag` format. |
        |Image Version

|        -   Click **Select Image Version** and select an image version. If you do not specify an image version, the latest image version is used.
        -   You can select the following image pull policies:

            -   **ifNotPresent**: If the image you want to pull is found in the region where the cluster is deployed, the local image is used. Otherwise, ACK pulls the image from the corresponding repository.
            -   **Always**: ACK pulls the image from the repository each time the application is deployed or expanded.
            -   **Never**: ACK uses only local images.
**Note:** If you select **Image Pull Policy**, no image pull policy is applied for the deployment of the application.

        -   To pull the image without a secret, click **Set Image Pull Secret** to set a secret for pulling images. For more information, see [Use aliyun-acr-credential-helper to pull images without a password](/intl.en-US/User Guide for Kubernetes Clusters/Application management/Use aliyun-acr-credential-helper to pull images without a password.md). |
        |Resource Limit|You can specify an upper limit for the CPU, memory, and ephemeral storage space that the container can consume. This allows you to make sure that the container does not occupy unnecessary resources. The CPU resource is measured in millicores \(one thousandth of one core\). The memory resource is measured in MiB. The ephemeral storage resource is measured in GiB.|
        |Required Resources|The amount of CPU and memory resources that are reserved for this application. These resources are exclusive to the container. This allows you to make sure that the application is still available when other services or processes occupy these resources.|
        |Container Start Parameter|        -   stdin: specifies that start parameters defined in the ACK console are imported to the Linux system.
        -   tty: specifies that start parameters defined in a virtual terminal are imported to the ACK console. |
        |Privileged Container|        -   If you select Privileged Container, privileged=true is set for the container and the privilege mode is enabled.
        -   If you do not select Privileged Container, privileged=false is set for the container and the privilege mode is disabled. |
        |Init Container|If you select Init Container, an init container is created. An init container provides tools to manage pods. For more information, see [Init Containers](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/?spm=a2c4g.111866<IP_ADDRESS>fdd30dfnyevPx).|

    -   Ports

        Specify the container ports.

        -   Name: Enter a name for a port.
        -   Port: the container port that you want to open. Enter a port number from 1 to 65535.
        -   Protocol: Select TCP or UDP.
    -   Environments

        You can use key-value pairs to set environment variables for pods. Environment variables are used to apply pod configurations to containers. For more information, see [Expose Pod Information to Containers Through Environment Variables](https://kubernetes.io/docs/tasks/inject-data-application/environment-variable-expose-pod-information/?spm=<IP_ADDRESS>.8VJbrE).

        -   Type: the type of the environment variable. You can select **Custom**, **ConfigMaps**, **Secret**, or **Value/ValueFrom**. If you select ConfigMaps or Secret as the type of the environment variable, all values in the selected ConfigMap or Secret are passed to the container environment variables. In this example, Secret is selected.

            Select **Secret** from the Name drop-down list and select a Secret from the **Value/ValueFrom** drop-down list. All values in the selected Secret are passed to the environment variable.

            In this case, the YAML file that is used to deploy the application contains the required settings. These settings are used to reference all values in the specified Secret.

        -   Variable Key: Specify the key of the environment variable.
        -   Value/ValueFrom: This is the reference that is used to define the environment variable.
    -   Health check

        Health check settings include liveness and readiness probes. Liveness probes determine when to restart the container. Readiness probes indicate whether the container is ready to accept traffic. For more information about health checks, see [Configure Liveness, Readiness, and Startup Probes](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/).

        |Request type|Description|
        |------------|-----------|
        |HTTP request|Sends an HTTP GET request to the container. You can set the following parameters:        -   Protocol: HTTP or HTTPS.
        -   Path: the requested path on the server.
        -   Port: the container port that you want to open. Enter a port number from 1 to 65535.
        -   HTTP Header: the custom headers in the HTTP request. Duplicate headers are allowed. Key-value pairs are supported.
        -   Initial Delay \(s\): the initialDelaySeconds field in the YAML file. This field specifies the wait time \(in seconds\) before the first probe is performed after the container is started. Default value: 15.
        -   Period \(s\): the periodSeconds field in the YAML file. This field specifies the frequency \(in seconds\) that the probe is performed. Default value: 10. Minimum value: 1.
        -   Timeout \(s\): the timeoutSeconds field in the YAML file. This field specifies the time \(in seconds\) after which the probe times out. Default value: 1. Minimum value: 1.
        -   Healthy Threshold: the minimum number of consecutive successful probes that must occur for a container to be considered healthy after a failed probe. Default value: 1. Minimum value: 1. For liveness probes, this parameter must be set to 1.
        -   Unhealthy Threshold: the minimum number of consecutive failed probes that must occur for a container to be considered unhealthy after a successful probe. Default value: 3. Minimum value: 1. |
        |TCP connection|Opens a TCP socket to the container. The kubelet attempts to open the socket on the specified port. If the connection can be established, the container is considered healthy. Otherwise, it is considered unhealthy. You can set the following parameters:        -   Port: the container port that you want to open. Enter a port number from 1 to 65535.
        -   Initial Delay \(s\): the initialDelaySeconds field in the YAML file. This field specifies the wait time \(in seconds\) before the first probe is performed after the container is started. Default value: 15.
        -   Period \(s\): the periodSeconds field in the YAML file. This field specifies the frequency \(in seconds\) that the probe is performed. Default value: 10. Minimum value: 1.
        -   Timeout \(s\): the timeoutSeconds field in the YAML file. This field specifies the time \(in seconds\) after which the probe times out. Default value: 1. Minimum value: 1.
        -   Healthy Threshold: the minimum number of consecutive successful probes that must occur for a container to be considered healthy after a failed probe. Default value: 1. Minimum value: 1. For liveness probes, this parameter must be set to 1.
        -   Unhealthy Threshold: the minimum number of consecutive failed probes that must occur for a container to be considered unhealthy after a successful probe. Default value: 3. Minimum value: 1. |
        |Command|Runs a probe command in the container to check the health status. You can set the following parameters:        -   Command: the probe command that is run to check the health status of the container.
        -   Initial Delay \(s\): the initialDelaySeconds field in the YAML file. This field specifies the wait time \(in seconds\) before the first probe is performed after the container is started. Default value: 5.
        -   Period \(s\): the periodSeconds field in the YAML file. This field specifies the frequency \(in seconds\) that the probe is performed. Default value: 10. Minimum value: 1.
        -   Timeout \(s\): the timeoutSeconds field in the YAML file. This field specifies the time \(in seconds\) after which the probe times out. Default value: 1. Minimum value: 1.
        -   Healthy Threshold: the minimum number of consecutive successful probes that must occur for a container to be considered healthy after a failed probe. Default value: 1. Minimum value: 1. For liveness probes, this parameter must be set to 1.
        -   Unhealthy Threshold: the minimum number of consecutive failed probes that must occur for a container to be considered unhealthy after a successful probe. Default value: 3. Minimum value: 1. |

    -   Lifecycle

        You can set the following parameters to configure the lifecycle of the container: Start, Post Start, and Pre Stop. For more information, see [Attach Handlers to Container Lifecycle Events](https://kubernetes.io/docs/tasks/configure-pod-container/attach-handler-lifecycle-event/).

        -   **Start**: Set the command and parameter that take effect before the container starts.
        -   **Post Start**: Set the command that takes effect after the container starts.
        -   **Pre Stop**: Set the command that takes effect before the container starts.
    -   Volume

        You can mount local storage volumes and persistent volume claims \(PVCs\) to the container.

        -   **Local Storage**: You can select hostPath, ConfigMap, Secret, and EmptyDir. The source directory or file is mounted to a path in the container. For more information, see [Volumes](https://kubernetes.io/docs/concepts/storage/volumes/?spm=<IP_ADDRESS>.8VJbrE).
        -   **PVC**: Select Cloud Storage.
        In this example, a PVC named disk-ssd is mounted to the /tmp path of the container.

        ![Configure volumes](https://static-aliyun-doc.oss-cn-hangzhou.aliyuncs.com/assets/img/en-US/8045359951/p12307.png)

    -   Log configuration

        Configure **Log Service**. You can specify collection methods and custom tags.

        **Note:** Make sure that the Log Service agent has been installed for the cluster.

        |Parameter|Description|
        |---------|-----------|
        |Collection configuration|Logstore: Create a Logstore in Log Service to store log data.|
        |Log Path: Specify stdout or a path to collect logs.

        -   stdout: specifies that the stdout files are collected.
        -   Text Logs: specifies that logs in the specified path of the container are collected. In this example, /var/log/nginx is specified as the path. Wildcard characters can be used in the path. |
        |Custom tags|You can also set custom tags. Custom tags are added to the logs of the container when the logs are collected. Custom tags provide an easy method to filter collected logs and perform statistical analytics.|

9.  Set the preceding parameters based on your business requirements and click **Next**.

10. Configure advanced settings

    -   Access Control

        **Note:**

        You can configure the following access control settings based on your business requirements:

        -   Internal applications: For applications that run inside the cluster, you can create a service of the Cluster IP or Node Port type to enable internal communication.
        -   External applications: For applications that are open to the Internet, you can configure the access control by using one of the following methods:
            -   Create a service of the LoadBalancer type and enable access to your application over the Internet by using a Server Load Balancer \(SLB\) instance.
            -   Create an Ingress to route external access to a service inside a cluster. For more information, see [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/?spm=a2c4g.111866<IP_ADDRESS>fdd30dfnyevPx).
        Configure the access control settings to enable access to pods that run the application. In this example, a Cluster IP service and an Ingress are created to enable access to the NGINX application over the Internet.

        |Parameter|Description|
        |---------|-----------|
        |Service|Click **Create** on the right side of **Service**. In the **Create Service** dialog box, set the parameters. For more information about the parameters that are required to create a service, see [Create a service](/intl.en-US/User Guide for Kubernetes Clusters/Network management/Service Management/Create a service.md). Select **Cluster IP**.|
        |Ingress|Click **Create** on the right side of **Ingress**. In the Create dialog box, set the parameters. For more information about the parameters that are required to create an Ingress, see [Ingress configurations](/intl.en-US/User Guide for Kubernetes Clusters/Network management/Ingress management/Ingress configurations.md).**Note:** When you deploy an application from an image, you can create an Ingress for only one service. In this example, a virtual host name is used as the test domain name. You must add the following entry to the hosts file to map the domain name to the IP address of the Ingress. In actual scenarios, use a domain name that has obtained an ICP number.

        ```
<IP_ADDRESS>   foo.bar.com    #The IP address of the Ingress.
        ``` |

        You can find the newly created service and Ingress in the **Access Control** section. Click **Update** or **Delete** to modify the settings.

        ![Update and delete the Ingress](https://static-aliyun-doc.oss-cn-hangzhou.aliyuncs.com/assets/img/en-US/0665359951/p10982.png)

    -   Scaling settings

        Specify whether to enable **HPA** to automatically scale the number of pods based on the CPU and memory usage. This enables the application to run as expected at different load levels.

        ![](https://static-aliyun-doc.oss-cn-hangzhou.aliyuncs.com/assets/img/en-US/0665359951/p10978.png)

        **Note:** To enable Horizontal Pod Autoscaler \(HPA\), you must configure resources that support scaling for the container. Otherwise, HPA does not take effect.

        -   **Metric**: Select CPU Usage or Memory Usage. The selected resource type must be the same as the one you have specified in the Required Resources field.
        -   **Condition**: Specify the resource usage threshold. HPA triggers scaling events when the threshold is exceeded.
        -   **Max. Replicas**: Specify the maximum number of replicated pods to which the application can be scaled.
        -   **Min. Replicas**: Specify the minimum number of replicated pods that must run.
    -   Scheduling settings

        You can set the following parameters: Update Method, Node Affinity, Pod Affinity, Pod Anti Affinity, and Toleration. For more information, see [Affinity and anti-affinity](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/?spm=a2c4g.111866<IP_ADDRESS>fdd30dfnyevPx#affinity-and-anti-affinity).

        **Note:** Node affinity and pod affinity affect pod scheduling based on node labels and pod labels. You can add node labels and pod labels that are provided by Kubernetes to node affinity and pod affinity. You can also add custom labels to nodes and pods, and then configure node affinity and pod affinity based on these custom labels.

        |Parameter|Description|
        |---------|-----------|
        |Update Method|Select Rolling Update or OnDelete. For more information, see [Deployments](https://kubernetes.io/zh/docs/concepts/workloads/controllers/deployment/?spm=a2c4g.111866<IP_ADDRESS>fdd30dfnyevPx). |
        |Node Affinity|Add labels to worker nodes to set the node affinity.****Node Affinity supports required and preferred rules, and various operators, such as In, NotIn, Exists, DoesNotExist, Gt, and Lt.

        -   **Required**: Set node labels that must be matched for pod scheduling. In the YAML file, these rules are defined by the requiredDuringSchedulingIgnoredDuringExecution field of the nodeAffinity parameter. These rules have the same effect as the `NodeSelector` parameter. In this example, pods can be scheduled to only nodes with the specified labels. You can create multiple required rules. However, only one of the rules must be met.
        -   **Preferred**: Specify the node weight and node labels that are not required to be matched for pod scheduling. Pods are scheduled to a node that matches the preferred rules when multiple nodes match the required rules. In the YAML file, these rules are defined by the preferredDuringSchedulingIgnoredDuringExecution field of the nodeAffinity parameter. In this example, the scheduler attempts to schedule the pod to a node that matches the preferred rules. You can set node weights in preferred rules. If multiple nodes match the required and preferred rules, the node with the highest weight is preferred for pod scheduling. You can create multiple preferred rules. However, all of the rules must be met before the pods are scheduled. |
        |Pod Affinity|Pod affinity specifies that pods can be scheduled to nodes or topological domains where pods with matching labels are deployed. For example, you can use pod affinity to deploy services that communicate with each other to the same topology domain, such as a host. This reduces the network latency between these services.Pod affinity enables you to specify which node pods can be scheduled based on the labels on other running pods. Pod affinity supports required and preferred rules, and various operators, such as `In, NotIn, Exists, and DoesNotExist`.

        -   **Required**: Specify rules that must be matched for pod scheduling. In the YAML file, these rules are defined by the requiredDuringSchedulingIgnoredDuringExecution field of the podAffinity parameter. A node must match the required rules before pods can be scheduled to the node.
            -   **Namespace**: Specify the namespace to apply the required rule. Pod affinity rules are defined based on the labels that are added to pods. In this case, labels are limited by namespace constraints.
            -   **Topological Domain**: Set the topologyKey. This specifies the key for the node label that the system uses to denote the topology domain. For example, if you set the parameter to `kubernetes.io/hostname`, nodes are used to define topologies. If you set the parameter to `beta.kubernetes.io/os`, the operating systems of nodes are used to determine topologies.
            -   **Selector**: Click Add to add pod labels.
            -   **View Applications**: Click **View Applications** and set the namespace and application in the dialog box that appears. You can view the pod labels on the selected application and add the labels as selectors.
            -   Required rules: Specify labels on existing applications, the operator, and the label value. In this example, the required rule specifies that the application to be created is scheduled to a host that runs applications with the `app: nginx` label.
        -   **Preferred**: Specify rules that are not required to be matched for pod scheduling. In the YAML file, preferred rules are defined by the preferredDuringSchedulingIgnoredDuringExecution field of the podAffinity parameter. The scheduler attempts to schedule the pod to a node that matches the preferred rules. You can set node weights in preferred rules. Set the other parameters as described in the preceding settings.

**Note:** **Weight**: Set the weight of a preferred rule to a value from 1 to 100. The scheduler calculates the weight of each node that meets the preferred rule based on an algorithm, and schedules the pod to the node with the highest weight. |
        |Pod Anti Affinity|Pod anti-affinity rules specify that pods are not scheduled to topology domains where pods with matching labels are deployed. Pod anti-affinity rules apply to the following scenarios:

        -   Schedule the pods of an application to different topology domains, such as multiple hosts. This allows you to enhance the stability of the service.
        -   Grant a pod exclusive access to a node. This enables resource isolation and ensures that no other pod can share the specified node.
        -   To ensure that these pods do not interfere with each other, we recommend that you schedule the pods of an application to different hosts.
**Note:** The parameters of pod anti-affinity rules are the same as those of pod affinity rules. You can create the rules for different scenarios. |
        |Toleration|Set toleration rules to allow pods to be scheduled to nodes with matching taints.|
        |Schedule to Virtual Nodes|Specify whether to schedule pods to virtual nodes. This option is unavailable if the cluster does not contain a virtual node.|

    -   Labels and annotations
        -   Pod Labels: Add labels to the pod.
        -   Pod Annotations: Add annotations to the pod.
11. Click **Create**.

12. After the application is created, you are directed to the Complete page. You can find the resource objects for the application and click **View Details** to view application details.

    The details page of the created StatefulSet appears.

13. In the upper-left corner of the page, click **Back** to return to the StatefulSets tab. On the StatefulSets tab, you can find the created application.

14. Click **Scale** in the Actions column to scale the application.

    1.  In the dialog box that appears, set Desired Number of Pods to 3 and click OK. After you scale out the application, you can find that all pods are listed in ascending order of ordinal indexes. If you scale in the application, pods are deleted in descending order of ordinal indexes. This ensures that all pods follow a specific order.

        ![Scale the application](https://static-aliyun-doc.oss-cn-hangzhou.aliyuncs.com/assets/img/en-US/9045359951/p12438.png)

    2.  In the left-side navigation pane, click Persistent Volumes. On the **Persistent Volume Claims** \> **Persistent Volumes** tab, you can find that a PV and a PVC are created for the newly added pod. However, if the application is scaled in, existing PVs and PVCs are not deleted.

## Related operations

In the left-side navigation pane of the ACK console, click **Clusters**. On the Clusters page, click the name of the cluster or click **Applications** in the **Actions** column. In the left-side navigation pane, click **Workload**. Click the **StatefulSets** tab. On the StatefulSets tab, click the name of the application or click **Details** in the **Actions** column. On the details page, you can edit, scale, redploy, and refresh the application. You can also view the YAML file of the application.

-   Edit: On the details page of the application, click **Edit** in the Actions column of the application to modify the configurations of the application.
-   Scale: On the details page of the application, click **Scale** in the Actions column of the application to scale the application to a required number of pods.
-   View the YAML file: On the details page of the application, click **View in YAML** in the Actions column of the application to update, and download the YAML file of the application. You can also save the YAML file as a template.
-   Redeploy: On the details page of the application, click **Redeploy** in the Actions column of the application to redeploy the application.
-   Refresh: On the details page of the application, click **Refresh** to refresh the application information.

Log on to a master node and perform the following steps to test the persistent storage.

1.  Create a test file in the cloud disk that is mounted to pod nginx-1:

    ```
    kubectl exec nginx-1 ls /tmp            # Query files in the /tmp directory.

    kubectl exec nginx-1 touch /tmp/statefulset         # Create a file named statefulset.

    kubectl exec nginx-1 ls /tmp
    lost+found
    statefulset
    ```

2.  Delete pod nginx-1:

    ```
    kubectl delete pod nginx-1
    pod"nginx-1" deleted
    ```

3.  After the system recreates and starts pod nginx-1, query the files in the /tmp directory. The following result shows that the statefulset file still exists. This ensures the high availability of the application that runs on the StatefulSet.

    ```
    kubectl exec nginx-1 ls /tmp                         # Query files in the /tmp directory.
    statefulset
    ```

url: https://raw.githubusercontent.com/hglakfs/csk/2feaad43acc89e31ae769da934f0976ce85658ef/intl.en-US/Quick Start/Basic operations/Use an image to create a stateful application.md

repository: hglakfs/csk

repo_name: hglakfs/csk


text:
# Requirements

````bash
 sudo apt-get --no-install-recommends install gettext
 sudo apt-get --no-install-recommends install language-pack-en-base
 sudo apt-get --no-install-recommends install language-pack-es-base
 sudo apt-get --no-install-recommends install language-pack-de-base
 sudo apt-get --no-install-recommends install language-pack-fr-base
 sudo apt-get --no-install-recommends install language-pack-ru-base
 sudo apt-get --no-install-recommends install language-pack-gr-base
 sudo apt-get --no-install-recommends install language-pack-ko-base
 sudo apt-get --no-install-recommends install language-pack-ja-base
 sudo apt-get --no-install-recommends install language-pack-id-base
 sudo apt-get --no-install-recommends install language-pack-zh-hant-base
 sudo apt-get --no-install-recommends install language-pack-zh-hans-base
````

to compile from .po to .mo files
there is a custom task

````
sake dev/tasks/CompilePO2MOTask
````

check system language support

```
locale -a
```

download po files from zanata server

```
sake dev/tasks/ZanataServerPOFilesDownloaderTask
```

# Workflow

once that a .pot file is updated, should be uploaded to zanata
for new translations

repository: OpenStackweb/openstack-org

branch_name: refs/heads/master

extension: md

gha_language: PHP

license_type: permissive

repo_name: OpenStackweb/openstack-org


text:
# IoTThingBicycle

```text
aws-20210131/Resource/LoT/IoTThingBicycle
```

```text
include('aws-20210131/Resource/LoT/IoTThingBicycle')
```

| Illustration | IoTThingBicycle | IoTThingBicycleCard | IoTThingBicycleGroup |
| :---: | :---: | :---: | :---: |
| ![illustration for Illustration](../../../aws-20210131/Resource/LoT/IoTThingBicycle.png) | ![illustration for IoTThingBicycle](../../../aws-20210131/Resource/LoT/IoTThingBicycle.Local.png) | ![illustration for IoTThingBicycleCard](../../../aws-20210131/Resource/LoT/IoTThingBicycleCard.Local.png) | ![illustration for IoTThingBicycleGroup](../../../aws-20210131/Resource/LoT/IoTThingBicycleGroup.Local.png) |

## IoTThingBicycle

### Load remotely
```plantuml
@startuml
' configures the library
!global $LIB_BASE_LOCATION="https://github.com/tmorin/plantuml-libs/distribution"

' loads the library's bootstrap
!include $LIB_BASE_LOCATION/bootstrap.puml

' loads the package bootstrap
include('aws-20210131/bootstrap')

' loads the Item which embeds the element IoTThingBicycle
include('aws-20210131/Resource/LoT/IoTThingBicycle')

' renders the element
IoTThingBicycle('IoTThingBicycle', 'Io T Thing Bicycle', 'an optional tech label')
@enduml
```

### Load locally
```plantuml
@startuml
' configures the library
!global $INCLUSION_MODE="local"
!global $LIB_BASE_LOCATION="../../.."

' loads the library's bootstrap
!include $LIB_BASE_LOCATION/bootstrap.puml

' loads the package bootstrap
include('aws-20210131/bootstrap')

' loads the Item which embeds the element IoTThingBicycle
include('aws-20210131/Resource/LoT/IoTThingBicycle')

' renders the element
IoTThingBicycle('IoTThingBicycle', 'Io T Thing Bicycle', 'an optional tech label')
@enduml
```

## IoTThingBicycleCard

### Load remotely
```plantuml
@startuml
' configures the library
!global $LIB_BASE_LOCATION="https://github.com/tmorin/plantuml-libs/distribution"

' loads the library's bootstrap
!include $LIB_BASE_LOCATION/bootstrap.puml

' loads the package bootstrap
include('aws-20210131/bootstrap')

' loads the Item which embeds the element IoTThingBicycleCard
include('aws-20210131/Resource/LoT/IoTThingBicycle')

' renders the element
IoTThingBicycleCard('IoTThingBicycleCard', 'Io T Thing Bicycle Card', 'an optional description')
@enduml
```

### Load locally
```plantuml
@startuml
' configures the library
!global $INCLUSION_MODE="local"
!global $LIB_BASE_LOCATION="../../.."

' loads the library's bootstrap
!include $LIB_BASE_LOCATION/bootstrap.puml

' loads the package bootstrap
include('aws-20210131/bootstrap')

' loads the Item which embeds the element IoTThingBicycleCard
include('aws-20210131/Resource/LoT/IoTThingBicycle')

' renders the element
IoTThingBicycleCard('IoTThingBicycleCard', 'Io T Thing Bicycle Card', 'an optional description')
@enduml
```

## IoTThingBicycleGroup

### Load remotely
```plantuml
@startuml
' configures the library
!global $LIB_BASE_LOCATION="https://github.com/tmorin/plantuml-libs/distribution"

' loads the library's bootstrap
!include $LIB_BASE_LOCATION/bootstrap.puml

' loads the package bootstrap
include('aws-20210131/bootstrap')

' loads the Item which embeds the element IoTThingBicycleGroup
include('aws-20210131/Resource/LoT/IoTThingBicycle')

' renders the element
IoTThingBicycleGroup('IoTThingBicycleGroup', 'Io T Thing Bicycle Group', 'an optional tech label') {
    note as note
        the content of the group
    end note
}
@enduml
```

### Load locally
```plantuml
@startuml
' configures the library
!global $INCLUSION_MODE="local"
!global $LIB_BASE_LOCATION="../../.."

' loads the library's bootstrap
!include $LIB_BASE_LOCATION/bootstrap.puml

' loads the package bootstrap
include('aws-20210131/bootstrap')

' loads the Item which embeds the element IoTThingBicycleGroup
include('aws-20210131/Resource/LoT/IoTThingBicycle')

' renders the element
IoTThingBicycleGroup('IoTThingBicycleGroup', 'Io T Thing Bicycle Group', 'an optional tech label') {
    note as note
        the content of the group
    end note
}
@enduml
```

license: MIT

repository: VinayaSathyanarayana/plantuml-libs

repo_name: VinayaSathyanarayana/plantuml-libs


text:
---
title: jidejs/ui
template: chapter.html
---

# jidejs/ui Introduction

The jidejs/ui package contains many of the most commonly used visual components required by web applications. It has
been created on top of the jidejs/base package and the concept of observable properties and lists.

When using the jidejs/ui package, you can choose between different types of components:
{@link module:jidejs/ui/layout/Pane panes} and {@link module:jidejs/ui/Control controls}. Panes are used for arranging
other components in a certain layout while controls are directly used by the user of the application. Prominent examples
for controls are {@link module:jidejs/ui/control/Button} and {@link module:jidejs/ui/control/Label}.

## Initializing controls

If you have already taken a look at the API documentation of some of the classes in the `jidejs/ui/control` package,
you may have noticed that most of their constructors expects a `config` object to be passed in.

These `config` objects are copied to the created control using {@link module:jidejs/ui/Component.applyConfiguration}.
Thus, by providing a suitable `config` object, you can set any property of the control or the controls it extends.
You can also specify children, if there are any, event handlers, CSS styles and classes.

```javascript
require(['jidejs/ui/control/Button'], function(Button) {
    var myButton = new Button({
        // the configuration for the button goes here
        text: "Click me", // "text" is a property of Labeled, that is an ancestor type of Button
        classList: ['my-really-cool-button'], // add a custom CSS class
        on: {
            // specify event handlers here
            'action': function() {
                // handle the 'action' event here
            }
        }
    });
});
```

## Adding components to the DOM

At the moment, jide.js doesn't offer an automatic way to insert your component structure into the DOM. Thus, you have two
options, that both work equally well.

**Add {@link module:jidejs/ui/Component~element} to the DOM**

```javascript
// given the 'myButton' object created above
document.getElementById('myButton_container').appendChild(myButton.element);
```

**Use an existing element as the components element**
Your HTML needs to contain a `div` element with the ID `myButton`.

```javascript
require(['jidejs/ui/control/Button'], function(Button) {
    var myButton = new Button({
        element: document.getElementById('myButton'),
        // ... same as before
    });
});
```

Note that at this time it is often necessary that the element is empty when it is used for a component.

## Creating a simple application

In this part of the tutorial, we will explore the creation of a simple contact management application. It will
allow its user to create, read, update and delete contacts and will teach you the basics of setting up the UI structure
and the simplicity of creating advanced data bindings.

Start with the simple HTML file:

```xml
<!DOCTYPE html>
<html>
<head>
    <title>Contacts application demo</title>
    <link rel="stylesheet" type="text/css" href="../../../controls/style/default.css">
</head>
<body>
    <h1>A simple contact management application</h1>
    <div id="approot"></div>
    <script src="../../lib/require.js" data-main="main.js"></script>
</body>
</html>
```

And continue with an appropriate Javascript file, in this case we call it *main.js* and locate it directly next to
the HTML file.

**Important:** If you've placed your **jide.js** download in some path you need to configure _require.js_ (or whatever AMD loader you're
using) so that it can find the **jide.js** files.

Then start your application code by importing all used modules:

```javascript
require([
	'jidejs/base/Class',
	'jidejs/base/ObservableProperty',
	'jidejs/base/ObservableList',
	'jidejs/ui/layout/GridPane',
	'jidejs/ui/control/ListView',
	'jidejs/ui/control/TextField',
	'jidejs/ui/control/Button'
], function(
	Class, ObservableProperty, ObservableList,
	GridPane,
	ListView, TextField, Button
) {
```

Our contact model will only need two properties: first name and phonenumber, so just define a simple constructor
that sets up the appropriate, observable, properties. Using {@link module:jidejs/base/ObservableProperty} allows us to
bind its data to UI controls and back:

```javascript
function Contact(firstName, phoneNumber) {
    // define and initialize the contact properties
    installer(this);
    this.firstName = firstName;
    this.phoneNumber = phoneNumber;
}
var installer = ObservableProperty.install(Contact, 'firstName', 'phoneNumber');
```

In practice, you'd now import the data from some other source, i.e. using XHR or similar, however, for the purpose of
this demo, we'll define the data inline, using an {@link module:jidejs/base/ObservableList} which will allow us to add
and remove data even easier:

```javascript
var contacts = ObservableList([
    new Contact('Sarah', randomPhoneNumber()),
    new Contact('Jane', randomPhoneNumber()),
    new Contact('Joe', randomPhoneNumber()),
    new Contact('Paul', randomPhoneNumber()),
    new Contact('George', randomPhoneNumber()),
    new Contact('Sam', randomPhoneNumber()),
    new Contact('Dean', randomPhoneNumber())
]);
```

Next we define the UI for our application. We will store some of the controls in variables so that we can use them
for our data bindings later on:

```javascript
var contactList, nameField, phoneNumberField;
var root = new GridPane({
    // create a GridPane and use the #approot element as its base
    element: document.getElementById('approot'),
    // define the grid, 3x3
    grid: [
        // 'list' spans five rows, name and phone span two columns
        'list new   delete',
        'list .     .',
        'list name  name',
        'list phone phone',
        'list .     call'
    ],
    // define rows, use automatic sizing (each will be as high as needed) but set the second row to be 25px high, it is
    // used to visually separate the new/delete buttons from the textfields
    rowDefinition: 'auto 25px auto auto auto',
    // define columns, set fixed width for the list, use automatic sizing for the others (each will be as wide as needed)
    columnDefinition: '200px auto auto',
    // now add the children
    children: [
        // add contact list
        contactList = new ListView({
            // specify area
            'GridPane.area': 'list',
            // make it take the full width within its parent
            width: '100%',
            // set the contacts list as its items
            items: contacts,
            // use the first name of the contact as its representation in the list
            converter: function(contact) {
                return contact.firstNameProperty;
            }
        }),
        // add name field
        nameField = new TextField({
            'GridPane.area': 'name'
        }),
        // add phone number field
        phoneNumberField = new TextField({
            'GridPane.area': 'phone'
        }),
        // add the call button
        new Button({
            'GridPane.area': 'call',
            text: 'Call',
            on: {
                // react to its click
                action: function() {
                    // get the currently selected contact
                    var contact = contactList.selectionModel.selectedItem;
                    if(contact) {
                        alert('Calling '+contact.firstName+' at '+contact.phoneNumber);
                    } else {
                        alert('No contact selected!');
                    }
                }
            }
        }),
        new Button({
            'GridPane.area': 'new',
            text: 'New',
            on: {
                action: function() {
                    // create a new contact
                    var newContact = new Contact('New Contact', '');
                    // add it to the original contacts list, updates the ListView automatically
                    contacts.add(newContact);
                    // select the new contact
                    contactList.selectionModel.clearAndSelect(newContact);
                }
            }
        }),
        new Button({
            'GridPane.area': 'delete',
            text: 'Delete',
            on: {
                'action': function() {
                    // delete the currently selected item from the list, updates the ListView automatically
                    contacts.remove(contactList.selectionModel.selectedItem);
                }
            }
        })
    ]
});
```

The {@link module:jidejs/ui/layout/GridPane} is the most complex but also most powerful layout pane in *jide.js*. By
mastering this layout pane, there is almost no layout you cannot create. By using its *grid* template, we
significantly simplify its usage as is shown in the above code sample.

At this stage, the demo will display several {@link module:jidejs/ui/control/TextField textfields} and
{@link module:jidejs/ui/control/Button buttons}. The buttons will already work, allowing the user of the application
to create and delete contacts as well as "calling" them. The textfields, however, are without function.

For this demo we will want to use one the most complex use cases of textfields. Whenever the user selects an item from the
list, we want the textfields to display that contacts information. When the user changes the text within the textfields,
we want the list cell to update and change the data within the contact object.

In traditional UI frameworks, we'd have to add event listeners to the ListView and both textfields and update the data of
each when the user interacts with it. Thankfully, **jide.js** doesn't require such boilerplate and allows us to achieve the
expected behaviour with just two data bindings:

```javascript
var selectedItemProperty = contactList.selectionModel.selectedItemProperty;
nameField.textProperty.bindBidirectional(selectedItemProperty.select('firstNameProperty'));
phoneNumberField.textProperty.bindBidirectional(selectedItemProperty.select('phoneNumberProperty'));
```

Since the `selectedItemProperty` of the {@link module:jidejs/ui/control/SelectionModel} is a property, we can easily
store it in a variable for shorter access. The `select` method creates a writable
{@link module:jidejs/base/DependencyProperty} that depends on both, the `selectedItemProperty` and the `firstNameProperty`
(or the `phoneNumberProperty` respectivly). It will contain the firstName (or phoneNumber) of the selected contact.

And that was all that is required for our simple demo application (minus a function that creates a fake phonenumber and
closing the _require_ call).

You can take a look at the full demo [here](../demo/apps/contacts/index.html).

repository: mattiapazienti/jidejs

repo_name: mattiapazienti/jidejs


text:
title: Lean backends using functional Kotlin
class: animation-fade
layout: true

<!-- This slide will serve as the base layout for all your slides -->

---

class: impact full-width
background-image: url(images/background1.jpg)

.impact-wrapper[
# {{title}}
]

???

Elevator pitch

- using kotlin
- backend services
- applying functional concepts

ultimate goal: to make code that is testable, maintainable and easy to understand

---

class: center middle

## What to expect from this talk

???

Content

- code examples that run in production
- introducing some concepts of FP
- not a FP tutorial, not a Kotlin tutorial

---

class: transition

## Mario Fernandez
## Andrei Bechet

 **Thought**Works

---

class: center middle

## Let's start with some context

---

class: center middle big-image

![overview-architecture](images/overview-architecture.png)

???

- this is how it looks like in many of our clients, big german corporations
- for most web app products, there is a big ecosystem, with many teams involved
- also, legacy systems are usually involved

---

class: center middle big-image

![overview-architecture-highlight](images/overview-architecture-highlight.png)

???

- we don't want to talk about this architecture, or about microservices
- we want to focus on single APIs

---

class: center middle big-image

![backend-architecture](images/backend-architecture.png)

???

- typical architecture is simple, a controller, a layer of services that orchestrate things and a series of clients
- receives REST requests, gives and outputs JSON
- JSON is also used to communicate with other APIs
- it could be a DB as well

---

class: center middle

## Technologies that we will be mentioning

---

class: center middle

.image-grid[
.img[![kotlin](images/kotlin.png)]
.img[![strikt](images/strikt.png)]
.img[![arrow](images/arrow.jpeg)]
.img[![spring-boot](images/spring-boot.png)]
]

???

- kotlin: already mentioned
- strikt: a library to write kotlin native assertions
- spring boot: the web framework we usually take to build services
- arrow: a wonderful functional library for kotlin

---

class: transition

# Our pain points

???

- These are pain points that we have observed over and over in our last projects

---

class: middle

### I don't know the state of my data

--

### Half of my time I'm just dealing with *null* values

--

### The other half I'm debugging the **500s** thrown by our application

---

class: center middle big-image

![pains-1](images/pains-1.png)

---

class: center middle big-image

![immutable-change](images/immutable-change.png)

???

- typical scenario: our business domain data goes through multiple stages, and is changed (incorrectly) at some point
- painfully backtrack to debug where things went wrong

---

class: center middle

## Immutability

???

- What is immutability: Not changing objects after initialization
- preaching using immutable data

---

class: center middle

```kotlin
data class TokenAuthentication(
        val id: Id,
        val firstName: FirstName,
        val lastName: LastName,
        val scopes: List<Scope>,
        val expiresAt: LocalDateTime
)
```

???

- Explain we use tokens as the example throughout the presentation
- kotlin brings immutability with data classes and read-only properties out of the box

---

class: center middle

```kotlin
val scopes: List<Scope> = buildScopes(token)

// List is immutable, it won't compile
scopes.removeAt(1) ❌

// Creates a new list
scopes.filter { it.isAdmin } ✅
```

???

- immutability is useful/important for collections as well
- alternative in Java: Guava
- standard collection interfaces are immutable by default in Kotlin

---

class: center middle

## JSON

???

- most of the work is producing/consuming json
- converting that JSON directly into the business domain, avoiding ugly beans

---

class: center middle

```kotlin
@JsonIgnoreProperties(ignoreUnknown = true)
data class TokenAuthentication(
        val id: Id,
        @JsonAlias("name_first")
        val firstName: FirstName,
        @JsonAlias("name_last")
        val lastName: LastName,
        @JsonDeserialize(converter = ListSanitizer::class)
        val scopes: List<Scope>,
        val expiresAt: LocalDateTime
)
```

???

- leveraging jackson, little overhead

---

class: center middle

## Dealing with change

???

- domain is not always static. Change inside a service is also possible
- we don't want to lose the immutability

---

class: center middle

```kotlin
// Will create a new object
fun TokenAuthentication.clearScopes() = copy(scopes = emptyList())
```

???

- copy method is a convenient way of cloning an object
- we can overwrite the fields that we want

---

class: center middle

## A simple test

???

- we want to show some tests to give you an idea of how we test all this

---

class: center middle

```kotlin
expectThat(token) {
    get { name }.isEqualTo("google-oauth2|3234123")
    get { authorities.map { it.authority } }.contains("create:recipes")
}
```

```console
org.opentest4j.AssertionFailedError:
▼ Expect that Some(TokenAuthentication@52789c41):
  ▼ TokenAuthentication@52789c41:
    Authenticated: true;
    Authorities: profile, create:recipes:
    ▼ name:
      ✗ is equal to "google-oauth2|3234123" : found "google-oauth2|dude"
```

???

- testing immutable objects can be tricky if they are big and have many members
- we want to test single attributes while retaining meaningful and expressive error messages

---

class: center middle benefits

# Why Immutability?

## Easier to reason
## Always in a valid state
## Can be shared freely

---

class: center middle big-image

![pains-2](images/pains-2.png)

---

class: center middle

```java
public static boolean isAdmin(List<Scope> scopes) {
    if(scopes == null) {
      return false;
    }

    Scope adminScope = findAdminScope(scopes);

    if(adminScope == null) {
      return false;
    }

    return adminScope.isValid();
  }
```

???

- typical java code
- every single thing can be null, if we don't test we might get NullPointerException's at runtime

---

class: middle

## The billion dollar mistake

> I call it my billion-dollar mistake. It was the invention of the null reference in 1965. At that time, I was designing the first comprehensive type system for references in an object oriented language (ALGOL W). My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn't resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.

???

- From Tony Hoare
- A significant amount of our issues in one of my teams caused by things being null and not being checked

---

class: center middle

## Nullable types
![kotlin-logo](images/kotlin-logo.png)

???

- This is what Kotlin offers us out of the box
- Forces a decision: Can it be null or not?

---

class: center middle

 ```
Authorization: Bearer bGciOi...JIUzI1NiIs
```

???

- back to the example: Our service is authenticated, it requires an Authorization header with a Bearer Token

--

```kotlin
fun String.extractToken(): String? = if (startsWith("Bearer"))
    split(" ").last()
else
    null
```

???

- type is explicitly nullable, as the token might or might not be there

--

```kotlin
header.extractToken()
  ?.let { token -> doStuff(token) }
```

???

- safe call operator
- consumer is forced to deal with the null case
- compiler enforced

---

class: center middle

## It can get messy

---

class: center middle big-image

![jwt-flow](images/jwt-flow.png)

???

- flow is composed of multiple steps, each of those can have an absence of a result (aka null)

---

class: center middle

```kotlin
request.getHeader(Headers.AUTHORIZATION)
  ?.let { header ->
    header.extractToken()
      ?.let { jwt ->
        verifier.verify(jwt)
          ?.let { token ->
            SecurityContextHolder.getContext().authentication = token
          }
      }
  }
```

???

- so much indentation not very readable anymore

---
class: center middle big-image

![callback-hell](images/callback-hell.jpeg)

???

- reminds of callback hell in javascript

---

class: center middle
## Option Datatype
![arrow-logo](images/arrow-logo.png)

???

- arrow presents an alternative, which is the option datatype

---

class: center middle

# Datatype? 🤔

.bottom-right[
A digression about Functional Programming
]

???

- A bit of FP theory comingm, without getting in too many details

--

class: center middle

## A datatype is an abstraction that encapsulates one reusable coding pattern.

???

- Basically a design pattern or a container that can abstract some functionality

---

class: center middle big-image

![option](images/option.png)

???

- It is implemented with sealed classes
- Can be either something (with a type) or nothing

---

class: center middle

```kotlin
fun String.extractToken(): String? = if (startsWith("Bearer"))
    split(" ").last()
else
    null
```

```kotlin
fun String.extractToken(): Option<String> = startsWith("Bearer ")
        .maybe { split(" ").last() }
```

???

- Arrow has plenty of helpers to aid with constructing these types

---

class: center middle

```kotlin
interface Operations {
    fun <A, B> Option<A>.map(f: (A) -> B): Option<B>
    fun <A, B> Option<A>.flatMap(f: (A) -> Option<B>): Option<B>
}
```

.bottom-right[
A digression about Functional Programming
]

???

- Option is a container
- We can operate on it as well, to transform its value
- For that, we have map for the simple case and flatMap for when the result might be an option itself -> Avoid nesting

---

class: center middle

### hackernoon.com/kotlin-functors-applicatives-and-monads-in-pictures-part-1-3-c47a1b1ce251

.bottom-right[
A digression about Functional Programming
]

???

- Nice resource to dig deeper

---

class: center middle

## Let's try our previous example with *Option*

---

class: center middle

```kotlin
request.getHeader(Headers.AUTHORIZATION)
  .toOption()
  .flatMap { header ->
    header.extractToken()
      .flatMap { jwt ->
        verifier
          .verify(jwt)
          .map { token ->
            SecurityContextHolder.getContext().authentication = token
        }
      }
  }
```

???

- still a lot of nesting

---

class: center middle

## Not much of an improvement 😔

---

class: center middle

## Non-nested syntax thanks to arrow

???

- Similar to await/async in JS

---

class: center middle

```kotlin
Option.fx {
    val (header) = request.getHeader(Headers.AUTHORIZATION).toOption()
    val (jwt) = header.extractToken()
    val (token) = verifier.verify(jwt)
    SecurityContextHolder.getContext().authentication = token
}
```

???

- less nesting
- some people actually prefer the flatMap stuff

---

class: center middle

```kotlin
@Test
fun `verify does not work with a invalid jwt token`() {
    expectThat(
      RemoteVerifier(keySet).verify(jwt)
*   ).isEmpty()
}
```

???

- with a nice little helper we can easily test what our method returns

---

class: center middle benefits

# Why Option?
## Explicit about what can be null
## Avoid if-null litter
## Compile time checks
## Save a billion dollars 🤓

???

- Arguably, both nullable types and options fulfill these conditions
- However, Option integrates nicely with other types that we will present in a minute

---

class: center middle big-image

![pains-3](images/pains-3.png)

---

class: center middle

```console
com.auth0.jwt.exceptions.JWTDecodeException:
  The string '{"typ":"JWT","alg":"RS256"}' is not a valid token.
      at com.auth0.jwt.impl.JWTParser.convertFromJSON(JWTParser.java:52)
      at com.auth0.jwt.impl.JWTParser.parseHeader(JWTParser.java:33)
      at com.auth0.jwt.JWTDecoder.<init>(JWTDecoder.java:37)
      at com.auth0.jwt.JWT.decode(JWT.java:21)
      at com.auth0.jwt.JWTVerifier.verify(JWTVerifier.java:352)
```

???

- an example of an exception
- kind of fake, a real one would be like three pages of text to get the full stacktrace

---

class: center middle

## Verifying our token

---

class: center middle big-image

![jwt-flow-highlight](images/jwt-flow-highlight.png)

???

- let's zoom in. We are going to focus on just one part of our flow, the verification

---

class: center middle

```kotlin
interface Verifier {
    fun verify(token: String): TokenAuthentication
}
```

???

- you pass a token as a string, get back a processed token with certain decoded properties

---

class: center middle

## That signature is not quite telling the truth

---

class: center middle

```java
/**
 * Perform the verification against the given Token
 *
 * @param token to verify.
 * @return a verified and decoded JWT.
 * @throws AlgorithmMismatchException
 * @throws SignatureVerificationException
 * @throws TokenExpiredException
 * @throws InvalidClaimException
 */
public DecodedJWT verifyByCallingExternalApi(String token);
```

???

- if we dig deep in the implementation, we'll see that we are calling an external api
- everything that can go wrong is represented as an exception

---

class: center middle big-image

![exception](images/exception.png)

???

- verify will throw an exception whenever it is not successful
- the exception will bubble up right to our controller

---

class: center middle

## Exceptions make the flow implicit

???

- the error case will ignore the path we defined before
- there is one path for the happy case, and a completely different one for the error

---

class: center middle

## Exceptions force you to be aware of the internal implementation

.bottom-right[
kotlinlang.org/docs/reference/exceptions.html
]

???

- you cannot know that unless you inspect the implementation
- encapsulation is broken

---

class: center middle

```kotlin
@ExceptionHandler(JWTVerificationException::class)
fun handleException(exception: JWTVerificationException):
  ResponseEntity<ErrorMessage> {
    return ResponseEntity
      .status(HttpStatus.BAD_GATEWAY)
      .body(ErrorMessage.fromException(exception))
}
```

???

- a way of dealing with exceptions at the controller level in Kotlin
- avoid throwing 500's
- runtime check, if we forget the compiler won't help us catching the error

---

class: center middle

## Either DataType
![arrow-logo](images/arrow-logo.png)

???

- another datatype from the arrow library as an alternative

---

class: center middle

## Option and Either are quite similar

.bottom-right[
A digression about Functional Programming
]

???

- They behave quite similarly, they just model different containers

---

class: center middle big-image

![either](images/either.png)

???

- Either is a disjoint union. It means the result can be either one or the other, but not both

---

class: center middle

```kotlin
interface Operations {
    fun <T, A, B> Either<T, A>.map(f: (A) -> B): Either<T, B>
    fun <T, A, B> Either<T, A>.flatMap(f: (A) -> Either<T, B>):
      Either<T, B>
}
```

.bottom-right[
A digression about Functional Programming
]

???

- again map and flatMap

---

class: center middle

```kotlin
interface Verifier {
    fun verify(token: String):
      Either<JWTVerificationException, TokenAuthentication>
}
```

???

- now our interface is explicit about the fact that things can go wrong

---

class: center middle

## Isolating the problematic code

---

class: center middle

```kotlin
private fun JWTVerifier.unsafeVerify(token: String) = try {
    verifyByCallingExternalApi(token).right()
} catch (e: JWTVerificationException) {
    e.left()
}
```

???

- with this code this method returns an either, and won't throw anymore
- we use the exception to model the error domain, not to throw them around

---

class: center middle

## Operating with Either

---

class: center middle

```kotlin
override fun verify(token: String)
       : Either<JWTVerificationException, TokenAuthentication> {
    val key = key(keySet)
    val algorithm = algorithm(key)
    val verifier = verifier(algorithm, leeway)
    return verifier
*           .unsafeVerify(token)
*           .map { it.asToken() }
}
```

???

- you can operate on an either without having to care whether the error happened or not
- either is right biased: If something went wrong, further operations will be ignored

---

class: center middle

```kotlin
Either.fx<JWTVerificationException, TokenAuthentication> {
    // Either<Throwable, ResponseEntity<UnprocessedResponse>>
    val response = unsafeRequest()
    val (body) = response
*          .mapLeft { JWTVerificationException(it) }
    body.map()
}
```

???

- mapLeft helps us converting a generic exception into our domain model

---

class: center middle

```kotlin
@GetMapping("{id}")
fun recipe(@PathVariable id: Int): ResponseEntity<RecipeDetails> {
    return when (val result = repository.find(id)) {
        is Either.Left -> ResponseEntity.status(result.a).build()
        is Either.Right -> ResponseEntity.ok(result.b)
    }
}
```

???

- now instead of a handler we deal with both possibilities in the controller
- using sealed classes mean that the compiler will complain if we don't handle every case

---

class: center middle

```kotlin
@Test
fun `verify works if the expiration is not taken into account`() {
    val hundredYears = 3600L * 24 * 365 * 100
    val verifier = RemoteVerifier(keySet, hundredYears)

    expectThat(verifier.verify(jwt)).isRight().and {
        get { name }
          .isEqualTo("google-oauth2|111460419457288935787")
        get { authorities.map { it.authority } }
          .contains("create:recipes")
    }
}
```

???

- we can test that the value is correct (Right), and also chain other assertions easily

---

class: center middle

## Result
### kotlin-stdlib

---

class: center middle

```kotlin
fun unsafeOp() =
        runCatching {
            doStuff()
        }.getOrElse { exception -> handle(exception) }
```

???

- alternative from the kotlin standard library, cannot be used as of now in interfaces

---

class: center middle benefits

# Why Either?
## Makes flow explicit
## Interface tells the whole truth
## Compile time checks

---

class: center middle big-image

![pains-end](images/pains-end.png)

---

class: transition

# What comes next?

???

- if you have adopted the three things mentioned before, you are already quite far ahead
- some of my teams barely could take the immutability
- but maybe you want to know what can come next

---

class: center middle

## Purely functional code

???

- some our examples are not truly functional, as they are triggering side effects

---

class: center middle full-width white
background-image: url(images/edge-world.jpg)

# Edge of the World

???

- purely functional means that the code is not truly evaluated until the very end
- in the functional programming world, the edge of the world is the place just before finishing execution where you trigger all side effects

---

class: center middle big-image

![edge-world-controller](images/edge-world-controller.png)

???

- for our backend, that would be the controller, just before returning to the caller

---

class: center middle

## IO

???

- IO is another datatype, just like option and either
- is a way of modeling side effects in a safe way

---

class: center middle

`IO<Either<JWTVerificationException, TokenAuthentication>>`

???

- given that our verifier is triggering a side effect, it should be an IO of an Either
- already a pretty long type

---

class: center middle

## We are hitting the limit of what's convenient to do with Kotlin and Arrow here

???

- not very convenient to use right now
- there is active development in arrow to make this better. Could come soon

---

class: transition

# Wrap Up

---

class: center middle big-image

![journey](images/journey.png)

???

- this is a journey, from immutability to option to either
- not necessarily following the same path

---

class: center middle big-image

![kotlin-fp-server](images/kotlin-fp-server.png)

???

- combining kotlin and fp has helped us write simpler code that we can maintain more easily

---

class: center middle

# At your own pace!

???

- No blueprint for everybody
- Every team has different needs

---

class: impact full-width
background-image: url(images/background5.jpg)

.impact-wrapper[
## JOIN OUR COMMUNITY

<br />

### *26 years* experience
### *42 offices* in 13 countries
### *Thought leader* in agile software development and continuous delivery
### *6000+* thoughtworkers worldwide
### *300+* thoughtworkers in Germany

<br />

####<EMAIL_ADDRESS>]

---


text:
# Sudoku Solver
Solve any Sudoku 9x9 Puzzle no matter how complicated or the difficulty level!

## Usage
* Download the [Sudoku Solver](https://github.com/amakvana/Sudoku-Solver/releases/download/v1.0/Sudoku.Solver.exe) executable
* Run it
* Type in the numbers into the 9x9 Sudoku grid and press solve

repository: amakvana/Sudoku-Solver

repo_name: amakvana/Sudoku-Solver


text:
---
layout: post
title: "Fall 2019"
date: 2019-12-10 08:34:25
categories: Drexel School
tags: featured
image: /assets/article_images/philly.jpg
---

Tuesday concluded the Fall quarter of my senior year at Drexel University. I will run through some of the interesting classes I took this term and provide links to the code I wrote for them.

## CS375 - Application Development

This class begins by teaching the basics of the web. Halfway through it switches to JavaScript, Node.JS, and MYSQL. For the final project, my team and I created a web application that allows programmers to find projects they might be interested in working on. The Github link for this can be found [here](https://github.com/owen-brooks/project-connect).

## ECE487 - Pattern Recognition

This class attempted to teach many of the machine learning algorithms starting with linear classifiers and ending with things like CNNs and ensemble learners. For the final project, my partner and I obtained a UFC fights dataset. We set out to do a comparison of models for the task of sports prediction. Our notebooks, as well as the papers we wrote, can be found [here](https://github.com/owen-brooks/ufc-fight-predictor).

## CS472 - Computer Networks

This class, similar to some I have had in the past, teaches different aspects of computer networking. For the assignments, we had to implement the FTP protocol in python. This gave me more experience with sockets programming and threading. The code for the FTP client and server can be found [here](https://github.com/owen-brooks/ftp-server) and [here](https://github.com/owen-brooks/ftp-client).

Looking ahead to next term, I will only be taking two classes: senior design and computational photography. To fill my extra time, I accepted a job as a Junior Software Developer at CRED iQ. CRED iQ is a real estate analytics startup that focuses primarily on commercial real estate evaluation. You can check out their web site [here](https://www.cred-iq.com/).

extension: markdown

gha_language: HTML

gha_license_id: NOASSERTION


text:
## Patterns

<center>
<img
  src="https://raw.githubusercontent.com/creativecommons/cc-vocabulary/master/src/assets/icons/ds_nomenclature/pattern.svg?sanitize=true"
  width="64px"/>
</center>

An element on its own has very little utility. A pattern on the other hand,
places elements together in meaningful ways using various layouts to make
reusable chunks of code that can be easily used in various scenarios.

Patterns are UI components similar to elements, except that they fall on the
more complex side of the spectrum. Patterns utilize elements, layouts and
tokens in that they place elements inside layouts and style them with tokens.

### Working with patterns

Patterns are nothing but Vue components and consequently live in eponymous
folders containing `Pattern.vue`, `Pattern.md` and `Pattern.styl` files. If a
pattern brings along its translations it may also contain a `lang.json` file.

Patterns import elements and may import other patterns, although ideologically,
dependence on other patterns would be minimal.

### Examples

So while `Container` is a cool component to have and `Headings` allow us to
write structured content, they need some real-world use. Consider components
like the `Header` and the `Footer` that use these components. As mentioned above
a pattern like the `Footer` can bring along its translations (try playing with
the locale switcher).

Here are some available patterns. You should probably
[isolate](#!/Patterns) this view for clarity. In isolated mode already? Go
[back to normal](#/Patterns).

```jsx { "props": { "className": "i18n-enabled contain-content" } }
<Header
  appName="Search"
  color="blue">
  <InputField
    type="text"
    color="blue"
    shade="dark"
    :icon-set="['keyboard', '']"
    placeholder="Search..."/>
  <Navigation
    is-inverted
    :linkList="[{text: 'About', href:'#1'}, {text: 'Browse', href:'#2'}, {text: 'Feedback', href:'#3'}]"/>
</Header>
<Footer/>
```

repository: restaurant-wan/cc-vocabulary

gha_license_id: MIT

repo_name: restaurant-wan/cc-vocabulary


text:
# Data Binding

[Data Binding](https://en.wikipedia.org/wiki/Data_binding), or [Property Binding](https://doc.qt.io/qt-5/qtqml-syntax-propertybinding.html) in Qt terminology, is a programming paradigm that allows binding of data sources to their respective consumers.
That means that if a value depends on another, it will automatically be updated whenever the input value changes.

## Basic Data Binding in KDBindings
The basis for Data Binding in KDBindings is formed by [Properties](properties.md).

They can be combined using arithmetic operators or just plain functions, to create new properties that are bound to the input properties.
This means the result of the calculation will be updated automatically every time the input of the calculation changes.

To create a binding, use the free [makeBoundProperty](../Namespaces/namespaceKDBindings.md#function-makeboundproperty) function in the KDBindings namespace.

### Example
``` cpp
#include <kdbindings/binding.h>

using namespace KDBindings;

Property<int> width(2);
Property<int> height(3);
Property<int> area = makeBoundProperty(width * height);

std::cout << area << std::endl; // will print 6
width = 5;
std::cout << area << std::endl; // will print 15
```

Pretty much all arithmetic operators are supported, as well as combinations of Properties with constant values.

## Declaring functions for use in data binding
KDBindings also allows you to declare arbitrary functions as usable in the context of data binding.
See the [`node_functions.h`](../Files/node__functions_8h.md) file for documentation on the associated macros.

This is already done for some of the `std` arithmetic functions, like abs and floor.
You can use the KDBINDINGS_DECLARE_STD_FUNCTION macro to declare more of these when necessary.

### Example
``` cpp
#include <kdbindings/binding.h>

using namespace KDBindings;

Property<int> value(-1);
Property<int> positiveValue = makeBoundProperty(abs(value));
```

## Binding arbitrary functions
[makeBoundProperty](../Namespaces/namespaceKDBindings.md#function-makeboundproperty) also accepts functions as binding, so arbitrary code can be executed to produce the new property value.

### Example
``` cpp
#include <kdbindings/binding.h>

using namespace KDBindings;

Property<std::string> text;
Property<std::string> lowerCase = makeBoundProperty(
  [](std::string value) {
    std::transform(value.begin(), value.end(), value.begin(),
      [](unsigned char c) { return std::tolower(c); });
      return value;
  },
  text /*don't forget to pass in the source property*/);

text = "Hello World!";
std::cout << lowerCase.get() << std::endl;
```

## No more broken bindings
A common mistake in data binding is accidentally breaking a binding by assigning a value to it.

With KDBindings this is no longer possible.
Assigning a value to a property that is the result of a data binding will result in an error!

### Example
``` cpp
#include <kdbindings/binding.h>

using namespace KDBindings;

Property<int> value;
Property<int> result = makeBoundProperty(2 * value);

result = 5; // this will throw a KDBindings::ReadOnlyProperty error!
```

To intentionally remove a binding from a property, use it's [`reset`](../../Classes/classKDBindings_1_1Property/#function-reset) function.

### Reassigning a Binding
Even though KDBindings prevents you from accidentally overriding a binding with a concrete value, assigning a
new binding to a Property with an existing binding is possible.

For this, use the [makeBinding](../Namespaces/namespaceKDBindings.md#function-makebinding) function instead of [makeBoundProperty](../Namespaces/namespaceKDBindings.md#function-makeboundproperty) to create the binding.

It is also possible to use makeBoundProperty, which will move-assign a new Property into the existing one, therefore completely replacing the existing Property with a new one.
This means that all signals of the old property will be disconnected (see [signals & slots](signals-slots.md)) and any existing data bindings that depended on the property will be removed, which might not be what you want!

Rule of thumb: If you want to create a new property, use makeBoundProperty, if you want to add a new binding to an
existing Property, use makeBinding.

#### Example
``` cpp
#include <kdbindings/binding.h>

using namespace KDBindings;

Property<int> value;
auto result = makeBoundProperty(value);

result = makeBinding(2 * value); // This does not throw any exceptions.
result = makeBoundProperty(3 * value); // This works too, but will override all existing connections to result.
```

## Deferred evaluation
KDBindings optionally offers data bindings with controlled, deferred evaluation.

This feature is enabled by passing a [KDBindings::BindingEvaluator](../Classes/classKDBindings_1_1BindingEvaluator.md) to makeBoundProperty.
The binding will then only be evaluated when [`evaluateAll()`](../Classes/classKDBindings_1_1BindingEvaluator.md#function-evaluateall) is called on the evaluator instance.

Deferred evaluation is useful to avoid unnecessary reevaluation of a binding, as well as controlling the frequency of binding evaluation.
Especially in UI applications, only updating the displayed values once per second can help in making them readable, compared to a bunch of values updating at 60Hz.

See the [06-lazy-property-bindings](../Examples/06-lazy-property-bindings_2main_8cpp-example.md) example for more details on how to use deferred evaluation.

## Further reading
Classes involved in data binding are [KDBindings::Property](../Classes/classKDBindings_1_1Property.md), [KDBindings::Binding](../Classes/classKDBindings_1_1Binding.md), and [KDBindings::BindingEvaluator](../Classes/classKDBindings_1_1BindingEvaluator.md).

See [KDBindings::makeBoundProperty](../Namespaces/namespaceKDBindings.md#function-makeboundproperty) for the different ways to create a binding.

We also recommend you take a look at our [examples](../examples.md).

repository: frankosterfeld/KDBindings

branch_name: refs/heads/main

repo_name: frankosterfeld/KDBindings


text:
Build a secure [K3s](https://github.com/k3s-io/k3s) cluster over public network with [Kilo](https://github.com/squat/kilo)
===========================================

Straightforward playbooks, for reference, not production-ready

---

 * https://blog.tpdn.kim/entry/build-a-secure-k3s-cluster-over-public-network-ja (ja)

System requirements
-------------------
* Ansible 2.10.5+
* Ubuntu 20.04 hosts
  * Maybe it works on ubuntu 18.04
* A server(master) node
  * Not support multiple server(master) nodes
* One or more agent(worker) nodes
* Passwordless SSH access

Usage
===========
Edit configurations
-------------
* hosts.ini
* group_vars/all.yml
* id_rsa

Run ansible-playbook
---------------------
Start provisioning of the cluster using the following command:
```
ansible-playbook playbook.yml -i hosts.ini
```

See if it worked
===============
```
KUBECONFIG=files/k3s.yaml kubectl get nodes
```
```
# Log into your server node
server-node:~# wg
```

Example of expected results
------------------------
```
(ansible-venv) tpdn@tpdn-VirtualBox:~/k3s-kilo-playbook-example$ KUBECONFIG=files/k3s.yaml kubectl get nodes
NAME           STATUS   ROLES                  AGE   VERSION
agent-node-3   Ready    <none>                 25h   v1.20.2+k3s1
agent-node-1   Ready    <none>                 25h   v1.20.2+k3s1
agent-node-2   Ready    <none>                 25h   v1.20.2+k3s1
agent-node-4   Ready    <none>                 25h   v1.20.2+k3s1
server-node    Ready    control-plane,master   25h   v1.20.2+k3s1
agent-node-5   Ready    <none>                 25h   v1.20.2+k3s1
```
```
root@server-node:~# wg
interface: kilo0
  public key: 0kKfArnPxNBblekTLPHm1BMhzrAbVcTqbh9EudDa51k=
  private key: (hidden)
  listening port: 51820

peer: Jddm35Ig1PsX2RwI3i2bYvDzSAZ3kVjmqJexbnY4Dp8=
  endpoint: agent-node-1.example.com:51820
  allowed ips: <IP_ADDRESS>/24, <IP_ADDRESS>/32
  latest handshake: 1 minute, 9 seconds ago
  transfer: 319.90 KiB received, 480.49 KiB sent

peer: N7GH4CO4BNmwcInVDC3TNWbV7/gd3UuriDHgV75LqVR=
  endpoint: agent-node-2.example.com:51820
  allowed ips: <IP_ADDRESS>/24, <IP_ADDRESS>/32
  latest handshake: 2 hours, 47 minutes, 46 seconds ago
  transfer: 1.35 MiB received, 83.46 KiB sent

peer: RrCuDQhtxPr20tbR3qPmVvWFvbG9QrME5vRFWAL+0nh=
  endpoint: agent-node-3.example.com:51820
  allowed ips: <IP_ADDRESS>/24, <IP_ADDRESS>/32

peer: e1dsyWfUyz2PnCwKF7s2NJM5RoSP1s8b2cCM78VuguU=
  endpoint: agent-node-4.example.com:51820
  allowed ips: <IP_ADDRESS>/24, <IP_ADDRESS>/32

peer: TxZuEMbIXsKy07jhf3LfaSjTSEvSqEw1q67QD3uGIKx=
  endpoint: agent-node-5.example.com:51820
  allowed ips: <IP_ADDRESS>/24, <IP_ADDRESS>/32
```


text:
# OSS-Fuzz - Continuous Fuzzing for Open Source Software

> *Status*: Beta. We are now accepting applications from widely-used open source projects.

[FAQ](docs/faq.md)
| [Ideal Fuzzing Integration](docs/ideal_integration.md)
| [New Project Guide](docs/new_project_guide.md)
| [Reproducing Bugs](docs/reproducing.md)
| [Projects](projects)
| [Projects Issue Tracker](https://bugs.chromium.org/p/oss-fuzz/issues/list)
| [Glossary](docs/glossary.md)

[Create New Issue](https://github.com/google/oss-fuzz/issues/new) for questions or feedback about OSS-Fuzz.

## Introduction

[Fuzz testing](https://en.wikipedia.org/wiki/Fuzz_testing) is a well-known
technique for uncovering various kinds of programming errors in software.
Many of these detectable errors (e.g. [buffer overflow](https://en.wikipedia.org/wiki/Buffer_overflow)) can have serious security implications.

We successfully deployed
[guided in-process fuzzing of Chrome components](https://security.googleblog.com/2016/08/guided-in-process-fuzzing-of-chrome.html)
and found [hundreds](https://bugs.chromium.org/p/chromium/issues/list?can=1&q=label%3AStability-LibFuzzer+-status%3ADuplicate%2CWontFix) of security vulnerabilities and stability bugs. We now want to share the experience and the service with the open source community.

In cooperation with the [Core Infrastructure Initiative](https://www.coreinfrastructure.org/),
OSS-Fuzz aims to make common open source software more secure and stable by
combining modern fuzzing techniques and scalable
distributed execution.

At the first stage of the project we use
[libFuzzer](http://llvm.org/docs/LibFuzzer.html) with
[Sanitizers](https://github.com/google/sanitizers). More fuzzing engines will be added later.
[ClusterFuzz](docs/clusterfuzz.md)
provides a distributed fuzzer execution environment and reporting.

Currently OSS-Fuzz supports C and C++ code (other languages supported by [LLVM](http://llvm.org) may work too).

## Process Overview

![diagram](docs/images/process.png?raw=true)

The following process is used for projects in OSS-Fuzz:

- A maintainer of an opensource project or an outside volunteer creates
one or more [fuzz targets](http://libfuzzer.info/#fuzz-target)
and [integrates](docs/ideal_integration.md) them with the project's build and test system.
- The project is [accepted to OSS-Fuzz](#accepting-new-projects).
- When [ClusterFuzz](docs/clusterfuzz.md) finds a bug, an issue is automatically
  reported in the OSS-Fuzz [issue tracker](https://bugs.chromium.org/p/oss-fuzz/issues/list)
  ([example](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9)).
  ([Why use a different tracker?](docs/faq.md#why-do-you-use-a-different-issue-tracker-for-reporting-bugs-in-oss-projects)).
  Project owners are CC-ed to the bug report.
- The project developer fixes the bug upstream and credits OSS-Fuzz for the discovery (commit message should contain
  the string **'Credit to OSS-Fuzz'**).
- [ClusterFuzz](docs/clusterfuzz.md) automatically verifies the fix, adds a comment and closes the issue ([example](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=53#c3)).
- 30 days after the fix is verified or 90 days after reporting (whichever is earlier), the issue becomes *public*
  ([guidelines](#bug-disclosure-guidelines)).

<!-- NOTE: this anchor is referenced by oss-fuzz blog post -->
## Accepting New Projects

To be accepted to OSS-Fuzz, an open-source project must
have a significant user base and/or be critical to the global IT infrastructure.
To submit a new project:
- [Create a pull request](https://help.github.com/articles/creating-a-pull-request/) with new
`projects/<project_name>/project.yaml` file ([example](projects/libarchive/project.yaml)) giving at least the following information:
  * project homepage.
  * e-mail of the engineering contact person to be CCed on new issues. This
    email should be
    [linked to a Google Account](https://support.google.com/accounts/answer/176347?hl=en)
    ([why?](docs/faq.md#why-we-require-an-e-mail-associated-with-a-google-account))
    and belong to an established project committer (according to VCS logs).
    If this is not you or the email address differs from VCS, an informal e-mail verification will be required.
  * Note that `project_name` can only contain alphanumeric characters, underscores(_) or dashes(-).
- Once accepted by an OSS-Fuzz project member, follow the [New Project Guide](docs/new_project_guide.md)
  to configure your project.

## Bug Disclosure Guidelines

Following [Google's standard disclosure policy](https://googleprojectzero.blogspot.com/2015/02/feedback-and-data-driven-updates-to.html)
OSS-Fuzz will adhere to following disclosure principles:
  - **Deadline**. After notifying project authors, we will open reported
    issues to the public in 90 days, or 30 days after the fix is released
    (whichever comes earlier).
  - **Weekends and holidays**. If a deadline is due to expire on a weekend,
    the deadline will be moved to the next normal work day.
  - **Grace period**. We have a 14-day grace period. If a 90-day deadline
    expires but the upstream engineers let us know before the deadline that a
    patch is scheduled for release on a specific day within 14 days following
    the deadline, the public disclosure will be delayed until the availability
    of the patch.

## More Documentation

* [Glossary](docs/glossary.md) describes the common terms used in OSS-Fuzz.
* [New Project Guide](docs/new_project_guide.md) walks through the steps necessary to add new projects to OSS-Fuzz.
* [Ideal Integration](docs/ideal_integration.md) describes the steps to integrate fuzz targets with your project.
* [Accessing corpora](docs/corpora.md) describes how to access the corpora we use for fuzzing.
* [Fuzzer execution environment](docs/fuzzer_environment.md) documents the
  environment under which your fuzzers will be run.
* [Projects](projects) lists OSS projects currently analyzed by OSS-Fuzz.
* [Chrome's Efficient Fuzzer Guide](https://chromium.googlesource.com/chromium/src/testing/libfuzzer/+/HEAD/efficient_fuzzer.md)
  while containing some Chrome-specific bits, is an excellent guide to making your fuzzer better.
* Blog posts: 2016-12-01 ([1](https://opensource.googleblog.com/2016/12/announcing-oss-fuzz-continuous-fuzzing.html),
[2](https://testing.googleblog.com/2016/12/announcing-oss-fuzz-continuous-fuzzing.html),
[3](https://security.googleblog.com/2016/12/announcing-oss-fuzz-continuous-fuzzing.html))

## Build Status
[This page](https://oss-fuzz-build-logs.storage.googleapis.com/status.html)
gives the latest build logs for each project.

## Trophies

[This page](https://bugs.chromium.org/p/oss-fuzz/issues/list?can=1&q=status%3AFixed%2CVerified+Type%3ABug%2CBug-Security+-component%3AInfra+)
gives a list of publicly-viewable fixed bugs found by OSS-Fuzz.

## References
* [libFuzzer documentation](http://libfuzzer.info)
* [libFuzzer tutorial](http://tutorial.libfuzzer.info)
* [libFuzzer workshop](https://github.com/Dor1s/libfuzzer-workshop)
* [Chromium Fuzzing Page](https://chromium.googlesource.com/chromium/src/testing/libfuzzer/)
* [ClusterFuzz](https://blog.chromium.org/2012/04/fuzzing-for-security.html)

repository: oliverchang/oss-fuzz

repo_name: oliverchang/oss-fuzz


text:
Pull Request Notifier
=====================

WARNING! This project is not maintained anymore.

You want to follow some pull requests and get notified when they are merged? Here is a GitHub Pull Request Notifier!

* Sign in with your GitHub account
* Paste the URL of the pull request you want to follow
* Get a daily mail with a list of the pull requests that have been merged

A sample Rails app
------------------

This is a sample Rails app for the [Gemnasium workshop](http://www.dotrb.eu/workshops#gemnasium) at [dotRB2013](http://www.dotrb.eu/).

Warning! This app has been written for the workshop and is not production-ready!

Requirements
------------

The app is known to work with:

* ruby 1.9.3
* bundler 1.3.5
* postgresql 9.1
* redis 2.2

Here are the packages you need to make it run on ubuntu 12.04 "precise":

```
sudo apt-get install ruby1.9.1 \
  ruby1.9.1-dev build-essential \
  libpq-dev libv8-dev libsqlite3-dev \
  postgresql-9.1 postgresql-contrib-9.1 postgresql-client-9.1 \
  redis-server
```

Remember that `ruby1.9.1` ubuntu package contains ruby 1.9.3.

You then need to install bundler:

```
sudo gem install bundler
```

Install
-------

1. clone this project
1. run `bundle install`
1. setup the database
1. configure the mailer
1. export GitHub client credentials
1. run the `./start` script

`ActionMailer` is used to send emails to the users, so you may have to set `config.action_mailer` in your `config/environments/development.rb` and `config/environments/production.rb` config files.

When in development mode, we suggest you deliver the emails using [mailtrap.io](http://mailtrap.io):

1. create a mailtrap account
1. create a mailtrap inbox for this rails app
1. setup mailtrap SMTP delivery in `development.rb` config file

Go to [gemnasium/dotrb2013-docker](https://github.com/gemnasium/dotrb2013-docker) if you want to install with [docker](http://docker.io).

GitHub application
------------------

You need credentials for your GitHub client:

1. go to the [GitHub applications settings](https://github.com/settings/applications)
1. register your application with name, homepage and callback URL
1. export your credentials

If your homepage URL is `http://localhost:3000/`, then the callback URL must be set to `http://localhost:3000/auth/github/callback`.

Export your credentials:

```
GITHUB_CLIENT_ID="1337"
GITHUB_CLIENT_SECRET="secret"

export GITHUB_CLIENT_ID
export GITHUB_CLIENT_SECRET

rails server
```

The app also looks for a `.env` file when running in development environment.

Usage
-----

Normal user

1. visit the root URL
1. sign in using GitHub
1. manage your subscriptions

There is no sign up: user account is automatically created from GitHub account.

Admin interface

* `/admin` for activeadmin
* `/admin/resque` for resque-web

Default admin user

* login is<EMAIL_ADDRESS>* password is `password`

How it works
------------

Data model:

* User: a normal user, comes from GitHub
* PullRequest - mirrors GitHub Pull Request object
* Subscription - relation b/w a user and a pull request she watches
* Notification - relation b/w a merged pull request and a user that will be notified about it
* AdminUser - to access the admin interface only, not bound to GitHub, works with the devise gem

Resque elementary jobs:

* connect to GitHub and fetch pull request metadata: title, body, etc.
* connect to GitHub and update the "merged" status
* notify one user about the pull requests that have been merged

Resque scheduled jobs (every day):

* update all the open pull requests
* notify all the users

Licence
-------

MIT Licence.

gha_language: Ruby


text:
# Make unpaid WHMCS Users Inactive

Since WHMCS changed their pricing structure to increase prices greatly I wrote this small python script to set users that have not paid and are not affiliate to inactive.

## What It does
The script uses the WHMCS api to query your users in a loop, if they have not generated any revenue and are not an affiliate, they are set inactive.

## License
**MIT**

## About Us

dh42 is a PrestaShop and Shopify development and support agency based out of Nashville. You can visit us on the web at [dh42 e-ecommerce support](https://dh42.com)


text:
## Javascript Sticky Scroll
Created for personal use but everyone is welcome to use this in any project.

### Usage
Add the class `.sticky` to any element and it should follow the user down by
setting `position: fixed` on the element.

### Known issues
1. "Stacking" two sticky elements is not supported, work-around by grouping
multiple elements in one `.sticky` container.

### Known limitations
1. No stop point is supported. Planned for implementation.
2. No "real" configuration is supported. Planned for implementation. (Check demo for a simple work-around configuration)

### Demo
Demo is located at [https://codepen.io/didair/pen/XxjvXx](https://codepen.io/didair/pen/XxjvXx).

repository: didair/js-sticky-scroll

repo_name: didair/js-sticky-scroll


text:
# curl examples

## post to create a new environment named foo

curl -i -X POST -H "Content-Type: application/json" http://localhost:9393/environment/foo/create -d '{"puppetfile_repo":"git@github.com:ghoneycutt/puppet-modules.git","puppetfile_ref":"master","hiera_repo":"git@github.com:ghoneycutt/hiera-data.git","hiera_ref":"master","manifests_repo":"git@github.com:ghoneycutt/puppet-manifests.git","manifests_ref":"master","primary_name":"Garrett Honeycutt","primary_email":"code@garretthoneycutt.com","secondary_name":"Secondary<EMAIL_ADDRESS>

repository: ghoneycutt/highrise

repo_name: ghoneycutt/highrise