Kubernetes ImagePolicyWebhook与ValidatingAdmissionWebhook【2】Image_Policy.go源码解析(2)

简介: Kubernetes ImagePolicyWebhook与ValidatingAdmissionWebhook【2】Image_Policy.go源码解析(2)
splitDockerDomain(s)

splitDockerDomain(s)在第90行,通过字段其实大概就能明白它的意思。字段切分。具体怎么实现的呢?

1035234-20181020215539574-213176954.png

strings.IndexRune(name, '/')方法,可以参考go strings方法IndexRune返回字符/在字符串s中第一次出现的位置,如果找不到,则返回-1。domain就等于docker.io,在代码中已初始化好,name等于remainder

1035234-20181020215539574-213176954.png

如果镜像中有‘/’呢,例如:kainlite/kube-image-bouncer:latest,domain取kainlite,remainder取kube-image-bouncer:latest


假如domain等于index.docker.io,就重定义为docker.io


假如domain等于docker.io,并且再次确认remainder不包含‘/’,就将remainder再次重新定义 officialRepoName + "/" + remainder


splitDockerDomain(s)函数分析完毕。继续ParseNormalizedNamed(s string) (Named, error)的分析:


定义个remoteName


tagSep := strings.IndexRune(remainder, ‘:’),即确认:的位置,如果>-1,即如果存在,则

tagSep等于镜像的标签,否则,就等于镜像的名字


strings.ToLower将s中的所有字符修改为其小写格式,如果remotename存在大写的话则不符合仓库名字规范。

parse

Parse(domain + "/" + remainder)是什么意思呢?

1035234-20181020215539574-213176954.png

又是好大的一个函数。

那我们慢慢来分析吧

referenceRegexp.FindStringSubmatch(s)

referenceRegexp.FindStringSubmatch(s)是啥意思?翻译过来就是ReferenceRegexp是完全支持的引用格式。regexp被锚定,并具有名称、标记和摘要组件的捕获组。描述看不懂。还是具体代码逻辑吧

1035234-20181020215539574-213176954.png

anchored大体明白了,就是通过添加开始和结束分隔符锚定正则表达式并作为返回值。

1035234-20181020215539574-213176954.png

正则表达式字符的字符串转换字符串形式。

capture函数与anchored大同小异,只是将含有正则表达式字符的字符串转换数组形式并作为返回值。

1035234-20181020215539574-213176954.png

optional似乎是对字符串可有可无的一种设定,并且optional字面意思是可选的。

1035234-20181020215539574-213176954.png

1035234-20181020215539574-213176954.png

literal函数是什么意思?翻译是将文本编译为文本正则表达式,转义任何regexp保留字符。字面非常容易理解。

1035234-20181020215539574-213176954.png

  • QuoteMeta返回一个字符串,该字符串转义参数文本中的所有正则表达式元字符;返回的字符串是与文本匹配的正则表达式。
  • var match = regexp.MustCompile
  • re := regexp.MustCompile(正则字符串)
  • re就是单纯的正则表达式了。

1035234-20181020215539574-213176954.png

LiteralPrefix返回一个字面值字符串,该字符串必须以正则表达式re的任何匹配项开始。如果字面值字符串包含整个正则表达式,则返回布尔值true。

1035234-20181020215539574-213176954.png

后面的函数方法其实大同小异,这里不一一拆解。

回到函数ReferenceRegexp.FindStringSubmatch(s),FindStringSubmatch(s)是regexp的方法FindStringSubmatch返回一个字符串切片,其中包含正则表达式在s中最左匹配的文本,以及它的子表达式的匹配(如果有的话),如包注释中的’Submatch’描述中定义的那样。返回值为nil表示没有匹配。


ReferenceRegexp函数其实设定了一个正则表达式,使字符串s能够通过我们希望的分割的方式,形成一个切片。它的关键之处是获取s的正则表达式,融入到设定的规则之中。


假如matches为nil,报错

假如matches[1]长度>255,也会报错

nameMatch := anchoredNameRegexp.FindStringSubmatch(matches[1])

这段代码其实是对domain的再度切片,如果它较多的递级目录,那我们就要对目录与仓库名称做出区分。

这里定义了一个关于镜像仓库名与标签的结构体,这是非常重要的一步。

ref := reference{
  namedRepository: repo,
  tag:             matches[2],
}

matches[3]是什么? matches[2]是镜像的版本标签,在这之后,又是通过@分割当然是一个哈希字符串的内容,是可有可无的。所以有下面的一个判断。

if matches[3] != "" {
  var err error
  ref.digest, err = digest.Parse(matches[3])
  if err != nil {
    return nil, err
  }
}

digest包正是处理哈希字符串的。

1035234-20181020215539574-213176954.png

1035234-20181020215539574-213176954.png

对包含镜像的仓库、标签、哈希值的ref结构体再次检查判断,有什么输出什么。并重构还有该特性的结构体。一共有三类结构体。如下:

1035234-20181020215539574-213176954.png

到这里,关于parse的函数分析已经结束了,这一路下来学到了不少方法,不能说全盘了解,但调用的机理已经摸透。

named, isNamed := ref.(Named)是个非常有趣的值得摸索记住的。我不懂,结构体跟点跟括号。后续研究。,但根据下面的代码逻辑推理,可能:

  r.Name() + ":" + r.tag + "@" + r.digest.String()

Named是管道,ref是结构体reference结构体的定义,那么自然会承接Reference管道中的refenceString()

1035234-20181020215539574-213176954.png

1035234-20181020215539574-213176954.png

1035234-20181020215539574-213176954.png

1035234-20181020215539574-213176954.png

1035234-20181020215539574-213176954.png

剩下要做的就是看看这个parse函数返回值被如何用了,自然可以推理出来,如下

1035234-20181020215539574-213176954.png

strings.HasSuffix判断字符串s是否以某个字符串结尾,

1035234-20181020215539574-213176954.png

TagNameOnly函数很好理解,就是判断镜像有没有标签,如果没有标签就添加默认"latest"。

那我们来看看他怎么实现的吧。

IsNameOnly函数在helpers.go

1035234-20181020215539574-213176954.png

来到这里我们又遇到了ref.(NamedTagged),看到这里,也许有一丝明白过来,这个对ref的结构体属性的判断,根据结构体中的属性是否包含值,通过接口组合成一个判断类型。之前,named, isNamed := ref.(Named)代表返回一个完整的镜像+标签的内容,并判断是否正常返回,这里代表是否只返回标签,也就是只判断是否有标签。下面的ref.(Canonical)则是判断标签是否有哈希值。

1035234-20181020215539574-213176954.png

1035234-20181020215539574-213176954.png

最后,如果没有任何标签,即为true,继续执行namedTagged, err := WithTag(ref, defaultTag)

1035234-20181020215539574-213176954.png

withtag函数传递两个函数,获取的镜像的信息,和latest标签。

1035234-20181020215539574-213176954.png

这个对已经获取的Named的对象重新进行定义,目的是为了把默认没有标签的镜像打上latest标签。


当withtag函数执行结束,TagNameOnly(named)也就返回新的镜像结构体,然后通过String()方法,字符串化,Strings.HasSuffix方法判断这个字符串是否以:latest结尾。根据正确与否返回true或false。


IsUsingLatestTag函数的逻辑终于也就结束了。


回到我们的image_policy代码中来。


下面就是根据判断是否有latest做出终端日志输出判断,并且打个是否allow的标签。


我们完成了哪些部分的代码分析呢?真的是九牛一毛。

1035234-20181020215539574-213176954.png

4. echo包

下面只需要分析明白如下内容。

1035234-20181020215539574-213176954.png

echo web框架是go语言开发的一种高性能,可扩展,轻量级的web框架。

echo框架真的非常简单,几行代码就可以启动一个高性能的http服务端。

echo.Context表示当前 HTTP 请求的上下文。它保存请求和响应引用、路径、路径参数、数据、注册处理程序和 API 以读取请求和写入响应。由于 Context 是一个接口,因此很容易使用自定义 API 对其进行扩展。

handlerFunc定义http请求,匿名函数像变量一样返回给echo.HandlerFunc

1035234-20181020215539574-213176954.png

c.bind(&imageReview)意思是通过将请求参数绑定到一个名叫imageReview的struct对象的方式获取数据。这种方式获取请求参数支持json、xml、k/v键值对等多种方式。


该函数最终返回一个json格式的pod拉去一个镜像的属性信息,并伴随http请求状态。


分析到这里,我们完成了对Image_Policy.go的步步分析,也深刻的体会到读源码的重要性。

5. 总结

我对go有了以下感悟:


go的logo是一只土拨鼠,土拨鼠的习性是挖地洞,因此,我们在学习go的时候要有土拨鼠的挖洞精神,在每个包、每个函数、每个方法、每个接口、每个结构体找到它最真实的面孔。

echo web框架的使用,请参考这篇文章

匿名函数作为返回值的使用

匿名函数由一个不带函数名的函数声明和函数体组成。匿名函数的优越性在于可以直接使用函数内的变量,不必申明。这是它最大的特点。这里将一个函数当做一个变量一样的操作作为函数的返回值输出给echo.HandlerFunc


依赖包的结构体具体特性进行变量声明,方便简化代码的逻辑。例如:var imageReview v1alpha1.ImageReview

谁在调用image_policy.go ,是main.go,在下一篇接文章,我们慢慢分析它的逻辑是什么。


相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
2月前
|
Cloud Native 安全 Java
Go语言深度解析:从入门到精通的完整指南
🌟蒋星熠Jaxonic,Go语言探索者。深耕云计算、微服务与并发编程,以代码为笔,在二进制星河中书写极客诗篇。分享Go核心原理、性能优化与实战架构,助力开发者掌握云原生时代利器。#Go语言 #并发编程 #性能优化
445 43
Go语言深度解析:从入门到精通的完整指南
|
4月前
|
数据采集 数据挖掘 测试技术
Go与Python爬虫实战对比:从开发效率到性能瓶颈的深度解析
本文对比了Python与Go在爬虫开发中的特点。Python凭借Scrapy等框架在开发效率和易用性上占优,适合快速开发与中小型项目;而Go凭借高并发和高性能优势,适用于大规模、长期运行的爬虫服务。文章通过代码示例和性能测试,分析了两者在并发能力、错误处理、部署维护等方面的差异,并探讨了未来融合发展的趋势。
377 0
|
3月前
|
Cloud Native 安全 Java
Go语言深度解析:从入门到精通的完整指南
🌟 蒋星熠Jaxonic,执着的星际旅人,用Go语言编写代码诗篇。🚀 Go语言以简洁、高效、并发为核心,助力云计算与微服务革新。📚 本文详解Go语法、并发模型、性能优化与实战案例,助你掌握现代编程精髓。🌌 从goroutine到channel,从内存优化到高并发架构,全面解析Go的强大力量。🔧 实战构建高性能Web服务,展现Go在云原生时代的无限可能。✨ 附技术对比、最佳实践与生态全景,带你踏上Go语言的星辰征途。#Go语言 #并发编程 #云原生 #性能优化
|
4月前
|
缓存 监控 安全
告别缓存击穿!Go 语言中的防并发神器:singleflight 包深度解析
在高并发场景中,多个请求同时访问同一资源易导致缓存击穿、数据库压力过大。Go 语言提供的 `singleflight` 包可将相同 key 的请求合并,仅执行一次实际操作,其余请求共享结果,有效降低系统负载。本文详解其原理、实现及典型应用场景,并附示例代码,助你掌握高并发优化技巧。
354 0
|
4月前
|
数据采集 JSON Go
Go语言实战案例:实现HTTP客户端请求并解析响应
本文是 Go 网络与并发实战系列的第 2 篇,详细介绍如何使用 Go 构建 HTTP 客户端,涵盖请求发送、响应解析、错误处理、Header 与 Body 提取等流程,并通过实战代码演示如何并发请求多个 URL,适合希望掌握 Go 网络编程基础的开发者。
|
6月前
|
存储 设计模式 安全
Go 语言单例模式全解析:从青铜到王者段位的实现方案
单例模式确保一个类只有一个实例,并提供全局访问点,适用于日志、配置管理、数据库连接池等场景。在 Go 中,常用实现方式包括懒汉模式、饿汉模式、双重检查锁定,最佳实践是使用 `sync.Once`,它并发安全、简洁高效。本文详解各种实现方式的优缺点,并提供代码示例与最佳应用建议。
212 5
|
7月前
|
存储 算法 Go
【LeetCode 热题100】17:电话号码的字母组合(详细解析)(Go语言版)
LeetCode 17题解题思路采用回溯算法,通过递归构建所有可能的组合。关键点包括:每位数字对应多个字母,依次尝试;递归构建下一个字符;递归出口为组合长度等于输入数字长度。Go语言实现中,使用map存储数字到字母的映射,通过回溯函数递归生成组合。时间复杂度为O(3^n * 4^m),空间复杂度为O(n)。类似题目包括括号生成、组合、全排列等。掌握回溯法的核心思想,能够解决多种排列组合问题。
315 11
|
7月前
|
Go
【LeetCode 热题100】155:最小栈(详细解析)(Go语言版)
本文详细解析了力扣热题155:最小栈的解题思路与实现方法。题目要求设计一个支持 push、核心思路是使用辅助栈法,通过两个栈(主栈和辅助栈)来维护当前栈中的最小值。具体操作包括:push 时同步更新辅助栈,pop 时检查是否需要弹出辅助栈的栈顶,getMin 时直接返回辅助栈的栈顶。文章还提供了 Go 语言的实现代码,并对复杂度进行了分析。此外,还介绍了单栈 + 差值记录法的进阶思路,并总结了常见易错点,如 pop 操作时忘记同步弹出辅助栈等。
263 6
|
7月前
|
Go 索引
【LeetCode 热题100】739:每日温度(详细解析)(Go语言版)
这篇文章详细解析了 LeetCode 第 739 题“每日温度”,探讨了如何通过单调栈高效解决问题。题目要求根据每日温度数组,计算出等待更高温度的天数。文中推荐使用单调递减栈,时间复杂度为 O(n),优于暴力解法的 O(n²)。通过实例模拟和代码实现(如 Go 语言版本),清晰展示了栈的操作逻辑。此外,还提供了思维拓展及相关题目推荐,帮助深入理解单调栈的应用场景。
316 6
|
8月前
|
存储 算法 物联网
解析局域网内控制电脑机制:基于 Go 语言链表算法的隐秘通信技术探究
数字化办公与物联网蓬勃发展的时代背景下,局域网内计算机控制已成为提升工作效率、达成设备协同管理的重要途径。无论是企业远程办公时的设备统一调度,还是智能家居系统中多设备间的联动控制,高效的数据传输与管理机制均构成实现局域网内计算机控制功能的核心要素。本文将深入探究 Go 语言中的链表数据结构,剖析其在局域网内计算机控制过程中,如何达成数据的有序存储与高效传输,并通过完整的 Go 语言代码示例展示其应用流程。
158 0

热门文章

最新文章

推荐镜像

更多