Merge pull request #61 from akshaymankar/integration-tests

Add Integration tests
This commit is contained in:
Kubernetes Prow Robot
2020-09-01 07:53:50 -07:00
committed by GitHub
12 changed files with 461 additions and 78 deletions

View File

@@ -11,6 +11,9 @@
# Do not choose a language; we provide our own build tools.
language: generic
services:
- docker
# Caching so the next build will be fast too.
cache:
directories:
@@ -18,6 +21,7 @@ cache:
- $HOME/.cabal
- $HOME/.stack
- $TRAVIS_BUILD_DIR/.stack-work
- $TRAVIS_BUILD_DIR/examples/.stack-work
# The different configurations we want to test. We have BUILD=cabal which uses
# cabal-install, and BUILD=stack which uses Stack. More documentation on each
@@ -31,38 +35,26 @@ cache:
# addons: {apt: {packages: [libfcgi-dev,libgmp-dev]}}
matrix:
include:
# We grab the appropriate GHC and cabal-install versions from hvr's PPA. See:
# https://github.com/hvr/multi-ghc-travis
#- env: BUILD=cabal GHCVER=7.0.4 CABALVER=1.16 HAPPYVER=1.19.5 ALEXVER=3.1.7
# compiler: ": #GHC 7.0.4"
# addons: {apt: {packages: [cabal-install-1.16,ghc-7.0.4,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
#- env: BUILD=cabal GHCVER=7.2.2 CABALVER=1.16 HAPPYVER=1.19.5 ALEXVER=3.1.7
# compiler: ": #GHC 7.2.2"
# addons: {apt: {packages: [cabal-install-1.16,ghc-7.2.2,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
#- env: BUILD=cabal GHCVER=7.4.2 CABALVER=1.16 HAPPYVER=1.19.5 ALEXVER=3.1.7
# compiler: ": #GHC 7.4.2"
# addons: {apt: {packages: [cabal-install-1.16,ghc-7.4.2,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
#- env: BUILD=cabal GHCVER=7.6.3 CABALVER=1.16 HAPPYVER=1.19.5 ALEXVER=3.1.7
# compiler: ": #GHC 7.6.3"
# addons: {apt: {packages: [cabal-install-1.16,ghc-7.6.3,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
#- env: BUILD=cabal GHCVER=7.8.4 CABALVER=1.18 HAPPYVER=1.19.5 ALEXVER=3.1.7
# compiler: ": #GHC 7.8.4"
# addons: {apt: {packages: [cabal-install-1.18,ghc-7.8.4,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
#- env: BUILD=cabal GHCVER=7.10.3 CABALVER=1.22 HAPPYVER=1.19.5 ALEXVER=3.1.7
# compiler: ": #GHC 7.10.3"
# addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.3,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
- env: BUILD=cabal GHCVER=8.0.2 CABALVER=1.24 HAPPYVER=1.19.5 ALEXVER=3.1.7
compiler: ": #GHC 8.0.2"
addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.2,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
- env: BUILD=integration-tests
compiler: ": #integration-tests"
addons: {apt: {packages: [libgmp-dev]}}
- env: BUILD=stack ARGS=""
compiler: ": #stack default"
addons: {apt: {packages: [libgmp-dev]}}
# - env: BUILD=cabal GHCVER=8.0.2 CABALVER=1.24 HAPPYVER=1.19.5 ALEXVER=3.1.7
# compiler: ": #GHC 8.0.2"
# addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.2,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
- env: BUILD=cabal GHCVER=8.2.2 CABALVER=2.0 HAPPYVER=1.19.5 ALEXVER=3.1.7
compiler: ": #GHC 8.2.2"
addons: {apt: {packages: [cabal-install-2.0,ghc-8.2.2,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
- env: BUILD=cabal GHCVER=8.4.4 CABALVER=2.2 HAPPYVER=1.19.5 ALEXVER=3.1.7
compiler: ": #GHC 8.4.4"
addons: {apt: {packages: [cabal-install-2.2,ghc-8.4.4,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
- env: BUILD=cabal GHCVER=8.6.3 CABALVER=2.4 HAPPYVER=1.19.5 ALEXVER=3.1.7
compiler: ": #GHC 8.6.3"
addons: {apt: {packages: [cabal-install-2.4,ghc-8.6.3,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
- env: BUILD=cabal GHCVER=8.6.5 CABALVER=2.4 HAPPYVER=1.19.5 ALEXVER=3.1.7
compiler: ": #GHC 8.6.5"
addons: {apt: {packages: [cabal-install-2.4,ghc-8.6.5,happy-1.19.5,alex-3.1.7], sources: [hvr-ghc]}}
# Build with the newest GHC and cabal-install. This is an accepted failure,
# see below.
@@ -72,30 +64,6 @@ matrix:
# The Stack builds. We can pass in arbitrary Stack arguments via the ARGS
# variable, such as using --stack-yaml to point to a different file.
- env: BUILD=stack ARGS=""
compiler: ": #stack default"
addons: {apt: {packages: [libgmp-dev]}}
#- env: BUILD=stack ARGS="--resolver lts-2"
# compiler: ": #stack 7.8.4"
# addons: {apt: {packages: [libgmp-dev]}}
#- env: BUILD=stack ARGS="--resolver lts-3"
# compiler: ": #stack 7.10.2"
# addons: {apt: {packages: [libgmp-dev]}}
#- env: BUILD=stack ARGS="--resolver lts-6"
# compiler: ": #stack 7.10.3"
# addons: {apt: {packages: [libgmp-dev]}}
#- env: BUILD=stack ARGS="--resolver lts-7"
# compiler: ": #stack 8.0.1"
# addons: {apt: {packages: [libgmp-dev]}}
#- env: BUILD=stack ARGS="--resolver lts-9"
# compiler: ": #stack 8.0.2"
# addons: {apt: {packages: [libgmp-dev]}}
- env: BUILD=stack ARGS="--resolver lts-11 --stack-yaml stack-8.2.2.yaml"
compiler: ": #stack 8.2.2"
addons: {apt: {packages: [libgmp-dev]}}
@@ -104,8 +72,8 @@ matrix:
compiler: ": #stack 8.4.4"
addons: {apt: {packages: [libgmp-dev]}}
- env: BUILD=stack ARGS="--resolver lts-13"
compiler: ": #stack 8.6.3"
- env: BUILD=stack ARGS="--resolver lts-14"
compiler: ": #stack 8.6.5"
addons: {apt: {packages: [libgmp-dev]}}
# Nightly builds are allowed to fail
@@ -118,27 +86,6 @@ matrix:
compiler: ": #stack default osx"
os: osx
# Travis includes an macOS which is incompatible with GHC 7.8.4
#- env: BUILD=stack ARGS="--resolver lts-2"
# compiler: ": #stack 7.8.4 osx"
# os: osx
#- env: BUILD=stack ARGS="--resolver lts-3"
# compiler: ": #stack 7.10.2 osx"
# os: osx
#- env: BUILD=stack ARGS="--resolver lts-6"
# compiler: ": #stack 7.10.3 osx"
# os: osx
#- env: BUILD=stack ARGS="--resolver lts-7"
# compiler: ": #stack 8.0.1 osx"
# os: osx
#- env: BUILD=stack ARGS="--resolver lts-9"
# compiler: ": #stack 8.0.2 osx"
# os: osx
- env: BUILD=stack ARGS="--resolver lts-11 --stack-yaml stack-8.2.2.yaml"
compiler: ": #stack 8.2.2 osx"
os: osx
@@ -147,8 +94,8 @@ matrix:
compiler: ": #stack 8.4.4 osx"
os: osx
- env: BUILD=stack ARGS="--resolver lts-13"
compiler: ": #stack 8.6.3 osx"
- env: BUILD=stack ARGS="--resolver lts-14"
compiler: ": #stack 8.6.5 osx"
os: osx
- env: BUILD=stack ARGS="--resolver nightly"
@@ -202,7 +149,7 @@ install:
# stack --no-terminal $ARGS solver --update-config)
# Build the dependencies
stack --no-terminal --install-ghc $ARGS test --bench --only-dependencies
stack --no-terminal --install-ghc $ARGS test --bench --only-dependencies --fast
;;
cabal)
cabal --version
@@ -211,10 +158,22 @@ install:
# Get the list of packages from the stack.yaml file. Note that
# this will also implicitly run hpack as necessary to generate
# the .cabal files needed by cabal-install.
PACKAGES=$(stack --install-ghc query locals | grep '^ *path' | sed 's@^ *path:@@')
PACKAGES=$(stack --system-ghc query locals | grep '^ *path' | sed 's@^ *path:@@')
cabal install --only-dependencies --enable-tests --enable-benchmarks --force-reinstalls --ghc-options=-O0 --reorder-goals --max-backjumps=-1 $CABALARGS $PACKAGES
;;
integration-tests)
curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin/
# Download and install kind
curl -LO https://github.com/kubernetes-sigs/kind/releases/download/v0.5.1/kind-linux-amd64 && chmod +x kind-linux-amd64 && sudo mv kind-linux-amd64 /usr/local/bin/kind
# Create a new Kubernetes cluster using KinD
kind create cluster
# Set KUBECONFIG environment variable
export KUBECONFIG="$(kind get kubeconfig-path)"
stack --no-terminal --install-ghc --stack-yaml ./examples/stack.yaml --work-dir .stack-work build --only-dependencies --fast
;;
esac
set +ex
@@ -223,7 +182,7 @@ script:
set -ex
case "$BUILD" in
stack)
stack --no-terminal $ARGS test --bench --no-run-benchmarks --haddock --no-haddock-deps
stack --no-terminal $ARGS test --bench --no-run-benchmarks --haddock --no-haddock-deps --fast
;;
cabal)
cabal install --enable-tests --enable-benchmarks --force-reinstalls --ghc-options=-O0 --reorder-goals --max-backjumps=-1 $CABALARGS $PACKAGES
@@ -249,5 +208,23 @@ script:
cd $ORIGDIR
done
;;
integration-tests)
EXAMPLE_ARGS="--no-terminal --install-ghc --stack-yaml ./examples/stack.yaml --work-dir .stack-work"
stack $EXAMPLE_ARGS build --fast
# Run simple test
stack $EXAMPLE_ARGS exec simple
# Build and load the in-cluster-example image
cp "$(stack $EXAMPLE_ARGS exec which in-cluster)" in-cluster-example
docker build . -f ./examples/in-cluster/Dockerfile -t in-cluster-example:latest
kind load docker-image in-cluster-example:latest
# Wait for kind node to be ready
kubectl wait --for=condition=Ready node --all
# Run the test pod
./examples/in-cluster/run-test.sh
;;
esac
set +ex

4
examples/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
dist
dist-newstyle
*.cabal
.stack-work

1
examples/LICENSE Symbolic link
View File

@@ -0,0 +1 @@
../LICENSE

View File

@@ -0,0 +1,5 @@
FROM ubuntu:xenial
RUN apt-get update && apt-get install -y libgmp3-dev
COPY in-cluster-example /usr/local/bin

View File

@@ -0,0 +1,85 @@
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Control.Concurrent.STM
import Control.Exception.Safe
import Kubernetes.Client
import Kubernetes.OpenAPI
import Kubernetes.OpenAPI.API.CoreV1
import Network.HTTP.Client
import Network.HTTP.Types.Status
import qualified Data.Map as Map
import qualified Data.Text as T
import qualified Data.Text.IO as T
main :: IO ()
main = do
oidcCache <- newTVarIO $ Map.fromList []
(manager, cfg) <- mkKubeClientConfig oidcCache KubeConfigCluster
let createNamespaceRequest =
createNamespace (ContentType MimeJSON) (Accept MimeJSON) testNamespace
createdNS <- assertMimeSuccess =<< dispatchMime manager cfg createNamespaceRequest
nsName <- assertJust "Expected K8s to generate name for namespace, but it didn't"
$ (v1ObjectMetaName =<< v1NamespaceMetadata createdNS)
T.putStrLn $ "Created Namespace: " <> nsName
-- NOTE: We cannot use dispatchMime due to this issue: https://github.com/kubernetes/kubernetes/issues/59501
let deleteNamespaceRequest =
deleteNamespace (ContentType MimeJSON) (Accept MimeJSON) (Name nsName)
deleteNamespaceResponse <- dispatchLbs manager cfg deleteNamespaceRequest
if responseStatus deleteNamespaceResponse /= status200
then throwM $ AssertionFailure
$ "Failed to cleanup namespace: " <> T.unpack nsName
<> "\nStatus Code: " <> show (responseStatus deleteNamespaceResponse)
<> "\nBody: " <> show (responseBody deleteNamespaceResponse)
else return ()
putStrLn "Clenaup complete!"
testDeployment :: V1Deployment
testDeployment =
let labelSelector =
mkV1LabelSelector
{ v1LabelSelectorMatchLabels =
Just $ Map.fromList [("app", "test")] }
container =
(mkV1Container "container-name")
{ v1ContainerImage = Just $ "nginx" }
podTemplate =
mkV1PodTemplateSpec
{ v1PodTemplateSpecMetadata =
Just $ mkV1ObjectMeta
{ v1ObjectMetaLabels = Just $ Map.fromList [("app", "test")] }
, v1PodTemplateSpecSpec =
Just $
mkV1PodSpec [container]
}
in mkV1Deployment
{ v1DeploymentMetadata =
Just $ mkV1ObjectMeta { v1ObjectMetaName = Just "test-deployment" }
, v1DeploymentSpec =
Just
$ (mkV1DeploymentSpec labelSelector podTemplate)
}
testNamespace :: V1Namespace
testNamespace =
let nsMetadata =
mkV1ObjectMeta
{ v1ObjectMetaGenerateName = Just "haskell-client-test-" }
in mkV1Namespace
{ v1NamespaceMetadata = Just nsMetadata }
assertMimeSuccess :: MonadThrow m => MimeResult a -> m a
assertMimeSuccess (MimeResult (Right res) _) = pure res
assertMimeSuccess (MimeResult (Left err) _) =
throwM $ AssertionFailure $ "Unexpected MimeError: " ++ show err
assertJust :: MonadThrow m => String -> Maybe a -> m a
assertJust err Nothing = throwM $ AssertionFailure err
assertJust _ (Just x) = return x
data AssertionFailure = AssertionFailure String
deriving Show
instance Exception AssertionFailure

68
examples/in-cluster/run-test.sh Executable file
View File

@@ -0,0 +1,68 @@
#!/bin/bash
set -euo pipefail
SCRIPT_DIR="$( cd "$(dirname "$0")" ; pwd -P )"
MAX_SECONDS=20
main(){
kubectl apply -f "$SCRIPT_DIR/test-pod.yaml"
start_time="$(date +%s)"
while true; do
phase="$(get-pod-phase in-cluster-example)"
consumed_seconds="$(seconds-since $start_time)"
if [[ "$phase" == "Succeeded" ]]; then
echo "------------------------------"
echo "Test passed!"
echo "------------------------------"
echo
echo "------------------------------"
echo "Logs from test:"
echo "------------------------------"
kubectl logs in-cluster-example
exit 0
elif [[ "$phase" == "Failed" ]]; then
echo "------------------------------"
echo "Test failed!"
echo "------------------------------"
print-failure in-cluster-example
exit 1
elif (( consumed_seconds > MAX_SECONDS )); then
echo "------------------------------"
echo "Test timed out after $MAX_SECONDS seconds!"
echo "------------------------------"
print-failure in-cluster-example
exit 2
else
echo "Test still running, pod phase = $phase"
sleep 0.5
fi
done
}
get-pod-phase() {
kubectl get pod $1 -o 'jsonpath={.status.phase}'
}
print-failure() {
echo
echo "------------------------------"
echo "Pod Description:"
echo "------------------------------"
kubectl describe pod $1
echo
echo "------------------------------"
echo "Logs from test:"
echo "------------------------------"
kubectl logs $1
}
# Takes epoch time
seconds-since() {
local start=$1
local end=$(date +%s)
echo $(( end - start))
}
main

View File

@@ -0,0 +1,34 @@
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: in-cluster-example
namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: in-cluster-example
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: in-cluster-example
namespace: default
---
apiVersion: v1
kind: Pod
metadata:
name: in-cluster-example
namespace: default
spec:
restartPolicy: Never
serviceAccountName: in-cluster-example
containers:
- name: in-cluster-example
image: in-cluster-example:latest
imagePullPolicy: Never
command:
- in-cluster-example

33
examples/package.yaml Normal file
View File

@@ -0,0 +1,33 @@
name: kubernetes-examples
version: 0.1.0.1
description: |
Examples to interact with Kubernetes using kubernetes-client and kubernetes-client-core
synopsis: Kubernetes examples with Haskell
maintainer:
- Shimin Guo <smguo2001@gmail.com>
- Akshay Mankar <itsakshaymankar@gmail.com>
category: Examples, Kubernetes
license: Apache-2.0
license-file: LICENSE
executables:
simple:
main: Main.hs
source-dirs: simple
ghc-options:
- -Wall
in-cluster:
main: Main.hs
source-dirs: in-cluster
ghc-options:
- -Wall
dependencies:
- base
- containers
- http-client
- http-types
- kubernetes-client
- kubernetes-client-core
- safe-exceptions
- stm
- text

102
examples/simple/Main.hs Normal file
View File

@@ -0,0 +1,102 @@
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Control.Concurrent.STM
import Control.Exception.Safe
import Kubernetes.Client
import Kubernetes.OpenAPI
import Kubernetes.OpenAPI.API.AppsV1
import Kubernetes.OpenAPI.API.CoreV1
import Network.HTTP.Client
import Network.HTTP.Types.Status
import System.Environment
import qualified Data.Map as Map
import qualified Data.Text as T
import qualified Data.Text.IO as T
main :: IO ()
main = do
kubeConfigFile <- getEnv "KUBECONFIG"
oidcCache <- newTVarIO $ Map.fromList []
(manager, cfg) <- mkKubeClientConfig oidcCache
$ KubeConfigFile kubeConfigFile
let createNamespaceRequest =
createNamespace (ContentType MimeJSON) (Accept MimeJSON) testNamespace
createdNS <- assertMimeSuccess =<< dispatchMime manager cfg createNamespaceRequest
nsName <- assertJust "Expected K8s to generate name for namespace, but it didn't"
$ (v1ObjectMetaName =<< v1NamespaceMetadata createdNS)
T.putStrLn $ "Created Namespace: " <> nsName
let createDeploymentRequest =
createNamespacedDeployment (ContentType MimeJSON) (Accept MimeJSON) testDeployment (Namespace nsName)
deployment <- assertMimeSuccess =<< dispatchMime manager cfg createDeploymentRequest
T.putStrLn $ "Created Deployment: " <> maybe "No name!?" id (v1DeploymentMetadata deployment >>= v1ObjectMetaName)
let listDeploymentsRequest =
listNamespacedDeployment (Accept MimeJSON) (Namespace nsName)
listedDeployments <- assertMimeSuccess =<< dispatchMime manager cfg listDeploymentsRequest
let numberOfDeployments = length $ v1DeploymentListItems listedDeployments
if numberOfDeployments /= 1
then throwM $ AssertionFailure $ "Expected 1 deployment, found: " <> show numberOfDeployments
else putStrLn "Test successful!"
-- NOTE: We cannot use dispatchMime due to this issue: https://github.com/kubernetes/kubernetes/issues/59501
let deleteNamespaceRequest =
deleteNamespace (ContentType MimeJSON) (Accept MimeJSON) (Name nsName)
deleteNamespaceResponse <- dispatchLbs manager cfg deleteNamespaceRequest
if responseStatus deleteNamespaceResponse /= status200
then throwM $ AssertionFailure
$ "Failed to cleanup namespace: " <> T.unpack nsName
<> "\nStatus Code: " <> show (responseStatus deleteNamespaceResponse)
<> "\nBody: " <> show (responseBody deleteNamespaceResponse)
else return ()
putStrLn "Clenaup complete!"
testDeployment :: V1Deployment
testDeployment =
let labelSelector =
mkV1LabelSelector
{ v1LabelSelectorMatchLabels =
Just $ Map.fromList [("app", "test")] }
container =
(mkV1Container "container-name")
{ v1ContainerImage = Just $ "nginx" }
podTemplate =
mkV1PodTemplateSpec
{ v1PodTemplateSpecMetadata =
Just $ mkV1ObjectMeta
{ v1ObjectMetaLabels = Just $ Map.fromList [("app", "test")] }
, v1PodTemplateSpecSpec =
Just $
mkV1PodSpec [container]
}
in mkV1Deployment
{ v1DeploymentMetadata =
Just $ mkV1ObjectMeta { v1ObjectMetaName = Just "test-deployment" }
, v1DeploymentSpec =
Just
$ (mkV1DeploymentSpec labelSelector podTemplate)
}
testNamespace :: V1Namespace
testNamespace =
let nsMetadata =
mkV1ObjectMeta
{ v1ObjectMetaGenerateName = Just "haskell-client-test-" }
in mkV1Namespace
{ v1NamespaceMetadata = Just nsMetadata }
assertMimeSuccess :: MonadThrow m => MimeResult a -> m a
assertMimeSuccess (MimeResult (Right res) _) = pure res
assertMimeSuccess (MimeResult (Left err) _) =
throwM $ AssertionFailure $ "Unexpected MimeError: " ++ show err
assertJust :: MonadThrow m => String -> Maybe a -> m a
assertJust err Nothing = throwM $ AssertionFailure err
assertJust _ (Just x) = return x
data AssertionFailure = AssertionFailure String
deriving Show
instance Exception AssertionFailure

13
examples/stack.yaml Normal file
View File

@@ -0,0 +1,13 @@
resolver: lts-14.7
packages:
- .
- ../kubernetes-client
- ../kubernetes
extra-deps:
- jsonpath-0.1.0.1
- jwt-0.10.0
- oidc-client-0.4.0.0
- git: https://github.com/akshaymankar/hs-certificate.git
commit: 2a71b5271b83e87a1fd14c53cc5987bef6e07a06
subdirs:
- x509-validation

49
examples/stack.yaml.lock Normal file
View File

@@ -0,0 +1,49 @@
# This file was autogenerated by Stack.
# You should not edit this file by hand.
# For more information, please see the documentation at:
# https://docs.haskellstack.org/en/stable/lock_files
packages:
- completed:
hackage: jsonpath-0.1.0.1@sha256:55718ac52b25cd8ce80fbdc9079a112344f032b056cfaf30737a29b6bd1a5c12,2377
pantry-tree:
size: 1097
sha256: 027749c943abaa6a78adc58e5abd4b3f42644c17c5fb7edf816557424a79448b
original:
hackage: jsonpath-0.1.0.1
- completed:
hackage: jwt-0.10.0@sha256:d14551b0c357424fb9441ec9a7a9d5b90b13f805fcc9327ba49db548cd64fc29,4180
pantry-tree:
size: 1027
sha256: e0cf95e834d99768ad8a3f7e99246948f0cdd2cfa18813517f540144aea6c3e5
original:
hackage: jwt-0.10.0
- completed:
hackage: oidc-client-0.4.0.0@sha256:f72a496ab27d9a5071be44e750718c539118ac52c2f1535a5fb3dde7f9874a55,3306
pantry-tree:
size: 1153
sha256: 68c285c6365360975d50bbb18cb07755d5ef19af8bf0e998d3ea46d35ef4a4e1
original:
hackage: oidc-client-0.4.0.0
- completed:
subdir: x509-validation
cabal-file:
size: 2211
sha256: 141d15544dacf1aa3278ba40d622ce78b7caaf523c3ff8c537a70ef902ae6596
name: x509-validation
version: 1.6.11
git: https://github.com/akshaymankar/hs-certificate.git
pantry-tree:
size: 631
sha256: 19855a414ea47001945b06f6b108a80b8ba3378c3ed585026215acd307d809db
commit: 2a71b5271b83e87a1fd14c53cc5987bef6e07a06
original:
subdir: x509-validation
git: https://github.com/akshaymankar/hs-certificate.git
commit: 2a71b5271b83e87a1fd14c53cc5987bef6e07a06
snapshots:
- completed:
size: 523700
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/14/7.yaml
sha256: 8e3f3c894be74d71fa4bf085e0a8baae7e4d7622d07ea31a52736b80f8b9bb1a
original: lts-14.7

View File

@@ -0,0 +1,12 @@
# This file was autogenerated by Stack.
# You should not edit this file by hand.
# For more information, please see the documentation at:
# https://docs.haskellstack.org/en/stable/lock_files
packages: []
snapshots:
- completed:
size: 523700
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/14/7.yaml
sha256: 8e3f3c894be74d71fa4bf085e0a8baae7e4d7622d07ea31a52736b80f8b9bb1a
original: lts-14.7